X-Git-Url: http://git.maemo.org/git/?p=modest;a=blobdiff_plain;f=src%2Fwidgets%2Fmodest-window-mgr.c;h=fa3258608549c129e5871a108d5c6695357170cf;hp=d66cc14adbb898278947fff868bd6c0a75b757f4;hb=aab537f6ce755830767baa7260d7879449ceeb38;hpb=87596c5aa5517ac7ba37e50664a969fcaaea72f9 diff --git a/src/widgets/modest-window-mgr.c b/src/widgets/modest-window-mgr.c index d66cc14..fa32586 100644 --- a/src/widgets/modest-window-mgr.c +++ b/src/widgets/modest-window-mgr.c @@ -36,18 +36,19 @@ #include "widgets/modest-main-window.h" #include "widgets/modest-msg-edit-window.h" #include "widgets/modest-msg-view-window.h" -/* include other impl specific header files */ + /* 'private'/'protected' functions */ 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); +static gboolean on_window_destroy (ModestWindow *window, + GdkEvent *event, + ModestWindowMgr *self); + +static const gchar* get_show_toolbar_key (GType window_type, + gboolean fullscreen); /* list my signals */ enum { @@ -59,15 +60,18 @@ enum { typedef struct _ModestWindowMgrPrivate ModestWindowMgrPrivate; struct _ModestWindowMgrPrivate { GList *window_list; + ModestWindow *main_window; + GtkDialog *easysetup_dialog; + gboolean fullscreen_mode; - gboolean show_toolbars; - gboolean show_toolbars_fullscreen; GSList *windows_that_prevent_hibernation; GSList *preregistered_uids; GHashTable *destroy_handlers; GHashTable *viewer_handlers; + + guint closing_time; }; #define MODEST_WINDOW_MGR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ MODEST_TYPE_WINDOW_MGR, \ @@ -123,15 +127,16 @@ modest_window_mgr_init (ModestWindowMgr *obj) priv->window_list = NULL; priv->main_window = NULL; priv->fullscreen_mode = FALSE; - + priv->easysetup_dialog = NULL; + priv->preregistered_uids = NULL; /* Could not initialize it from gconf, singletons are not ready yet */ - priv->show_toolbars = FALSE; - priv->show_toolbars_fullscreen = FALSE; 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; } static void @@ -166,9 +171,17 @@ modest_window_mgr_finalize (GObject *obj) priv->viewer_handlers = NULL; } + if (priv->easysetup_dialog) { + g_warning ("%s: forgot to destroy an easysetup dialog somewhere", + __FUNCTION__); + gtk_widget_destroy (GTK_WIDGET(priv->easysetup_dialog)); + priv->easysetup_dialog = NULL; + } + /* Do not unref priv->main_window because it does not hold a new reference */ + G_OBJECT_CLASS(parent_class)->finalize (obj); } @@ -285,11 +298,17 @@ compare_msguids (ModestWindow *win, { const gchar *msg_uid; - if (!MODEST_IS_MSG_VIEW_WINDOW (win)) + if ((!MODEST_IS_MSG_EDIT_WINDOW (win)) && (!MODEST_IS_MSG_VIEW_WINDOW (win))) return 1; /* Get message uid from msg window */ - msg_uid = modest_msg_view_window_get_message_uid (MODEST_MSG_VIEW_WINDOW (win)); + 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; @@ -298,13 +317,33 @@ compare_msguids (ModestWindow *win, } +void +modest_window_mgr_close_all_windows (ModestWindowMgr *self) +{ + ModestWindowMgrPrivate *priv = NULL; + GList *wins = NULL; + gboolean ret_value = FALSE; + + g_return_if_fail (MODEST_IS_WINDOW_MGR (self)); + priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); + + /* delete-event handler already removes window_list item, */ + /* so no next its required on this loop */ + wins = priv->window_list; + while (wins) { + g_signal_emit_by_name (G_OBJECT (wins->data), "delete-event", NULL, &ret_value); + + wins = priv->window_list; + } +} + gboolean modest_window_mgr_find_registered_header (ModestWindowMgr *self, TnyHeader *header, ModestWindow **win) { - ModestWindowMgrPrivate *priv; - gchar* uid; + ModestWindowMgrPrivate *priv = NULL; + gchar* uid = NULL; gboolean has_header, has_window = FALSE; GList *item = NULL; @@ -318,16 +357,14 @@ 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)); - 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)) + 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"); @@ -340,33 +377,56 @@ modest_window_mgr_find_registered_header (ModestWindowMgr *self, TnyHeader *head 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; +} void modest_window_mgr_register_window (ModestWindowMgr *self, ModestWindow *window) { - static gboolean first_time = TRUE; GList *win; - gboolean show; ModestWindowMgrPrivate *priv; gint *handler_id; + const gchar *key; g_return_if_fail (MODEST_IS_WINDOW_MGR (self)); - g_return_if_fail (MODEST_IS_WINDOW (window)); + g_return_if_fail (GTK_IS_WINDOW (window)); priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); win = g_list_find (priv->window_list, window); if (win) { - g_warning ("Trying to register an already registered window"); + g_warning ("%s: trying to re-register a window", + __FUNCTION__); return; } /* Check that it's not a second main window */ if (MODEST_IS_MAIN_WINDOW (window)) { if (priv->main_window) { - g_warning ("Trying to register a second main window"); + g_warning ("%s: trying to register a second main window", + __FUNCTION__); return; } else { priv->main_window = window; @@ -377,16 +437,27 @@ modest_window_mgr_register_window (ModestWindowMgr *self, if (MODEST_IS_MSG_VIEW_WINDOW(window)) { const gchar *uid = modest_msg_view_window_get_message_uid (MODEST_MSG_VIEW_WINDOW (window)); - - g_debug ("registering window for %s", uid); - + if (!has_uid (priv->preregistered_uids, uid)) g_debug ("weird: no uid for window (%s)", uid); + + 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))); + + } else if (MODEST_IS_MSG_EDIT_WINDOW(window)) { + const gchar *uid = modest_msg_edit_window_get_message_uid + (MODEST_MSG_EDIT_WINDOW (window)); + + g_debug ("registering window for %s", uid); + + priv->preregistered_uids = + remove_uid (priv->preregistered_uids, + modest_msg_edit_window_get_message_uid + (MODEST_MSG_EDIT_WINDOW (window))); } /* Add to list. Keep a reference to the window */ @@ -412,26 +483,11 @@ modest_window_mgr_register_window (ModestWindowMgr *self, if (priv->fullscreen_mode) gtk_window_fullscreen (GTK_WINDOW (window)); - /* Fill caches */ - if (first_time) { - ModestConf *conf = modest_runtime_get_conf (); - priv->show_toolbars = - modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR, NULL); - priv->show_toolbars_fullscreen = - modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR_FULLSCREEN, NULL); - first_time = FALSE; - } - - /* Show/hide toolbar */ - if (priv->fullscreen_mode) - show = priv->show_toolbars_fullscreen; - else - show = priv->show_toolbars; - modest_window_show_toolbar (window, show); + /* 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 void */ -/* on_window_destroy (ModestWindow *window, ModestWindowMgr *self) */ static gboolean on_window_destroy (ModestWindow *window, GdkEvent *event, @@ -475,17 +531,11 @@ on_window_destroy (ModestWindow *window, _("mcen_nc_no_email_message_modified_save_changes")); /* Save to drafts */ if (response != GTK_RESPONSE_CANCEL) - modest_ui_actions_on_save_to_drafts (NULL, MODEST_MSG_EDIT_WINDOW (window)); - + modest_ui_actions_on_save_to_drafts (NULL, MODEST_MSG_EDIT_WINDOW (window)); } } } - /* Save configuration state (TODO: why edit window does not require this function ?) */ - if (!MODEST_IS_MSG_EDIT_WINDOW (window)) - modest_window_save_state (MODEST_WINDOW(window)); - - /* Unregister window */ modest_window_mgr_unregister_window (self, window); @@ -504,13 +554,68 @@ disconnect_msg_changed (gpointer key, } + +/* interval before retrying to close the application */ +#define CLOSING_RETRY_INTERVAL 3000 +/* interval before cancel whatever is left in the queue, and closing anyway */ +#define MAX_WAIT_FOR_CLOSING 30 * 1000 + +static gboolean +on_quit_maybe (ModestWindowMgr *self) +{ + ModestWindowMgrPrivate *priv; + guint queue_num; + + priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); + + /* it seems, in the meantime some windows were + * created. in that case, stop 'on_quit_maybe' */ + if (priv->window_list) { + priv->closing_time = 0; + return FALSE; + } + + if (priv->closing_time >= MAX_WAIT_FOR_CLOSING) { + /* we waited long enough: cancel all remaining operations */ + g_debug ("%s: we waited long enough (%ds), cancelling queue and quiting", + __FUNCTION__, priv->closing_time/1000); + /* FIXME: below gives me a lot of: + * GLIB CRITICAL ** default - modest_mail_operation_cancel: + * assertion `priv->account' failed + * which means there is no account for the given operation + * so, we're not trying to be nice, we're just quiting. + */ + //modest_mail_operation_queue_cancel_all + // (modest_runtime_get_mail_operation_queue()); + } else { + + /* if there is anything left in our operation queue, + * wait another round + */ + queue_num = modest_mail_operation_queue_num_elements + (modest_runtime_get_mail_operation_queue()); + if (queue_num > 0) { + g_debug ("%s: waiting, there are still %d operation(s) queued", + __FUNCTION__, queue_num); + priv->closing_time += CLOSING_RETRY_INTERVAL; + return TRUE; + } + } + + /* so: no windows left, nothing in the queue: quit */ + priv->closing_time = 0; + gtk_main_quit (); + return FALSE; +} + + void modest_window_mgr_unregister_window (ModestWindowMgr *self, ModestWindow *window) { 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)); @@ -528,11 +633,22 @@ modest_window_mgr_unregister_window (ModestWindowMgr *self, priv->main_window = NULL; /* Disconnect all emissions of msg-changed */ - g_hash_table_foreach (priv->viewer_handlers, - disconnect_msg_changed, - NULL); - g_hash_table_destroy (priv->viewer_handlers); - priv->viewer_handlers = NULL; + 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); + g_signal_handler_disconnect (window, *tmp); + g_hash_table_remove (priv->viewer_handlers, window); } /* Save state */ @@ -547,32 +663,27 @@ 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); - + /* If there are no more windows registered then exit program */ - if (priv->window_list == NULL) { - ModestConf *conf = modest_runtime_get_conf (); - - /* Save show toolbar status */ - modest_conf_set_bool (conf, MODEST_CONF_SHOW_TOOLBAR_FULLSCREEN, - priv->show_toolbars_fullscreen, NULL); - modest_conf_set_bool (conf, MODEST_CONF_SHOW_TOOLBAR, - priv->show_toolbars, NULL); - - /* Quit main loop */ - /* FIXME: do we ever need to do this here? */ - if (gtk_main_level() > 0) - gtk_main_quit (); - } + if (priv->window_list == NULL) + g_timeout_add (CLOSING_RETRY_INTERVAL, + (GSourceFunc)on_quit_maybe, self); } + + 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)); @@ -584,18 +695,28 @@ modest_window_mgr_set_fullscreen_mode (ModestWindowMgr *self, priv->fullscreen_mode = on; + conf = modest_runtime_get_conf (); + /* Update windows */ win = priv->window_list; while (win) { - if (on) { + 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)); - modest_window_show_toolbar (MODEST_WINDOW (win->data), - priv->show_toolbars_fullscreen); - } else { + else gtk_window_unfullscreen (GTK_WINDOW (win->data)); - modest_window_show_toolbar (MODEST_WINDOW (win->data), - priv->show_toolbars); - } + + /* Show/Hide toolbar */ + modest_window_show_toolbar (MODEST_WINDOW (win->data), show); + win = g_list_next (win); } } @@ -614,30 +735,27 @@ modest_window_mgr_get_fullscreen_mode (ModestWindowMgr *self) void modest_window_mgr_show_toolbars (ModestWindowMgr *self, + GType window_type, gboolean show_toolbars, gboolean fullscreen) { ModestWindowMgrPrivate *priv; + ModestConf *conf; + const gchar *key = NULL; 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. Otherwise cache it, do not - save to GConf for the moment, it will be done when all - windows become unregistered in order to avoid unnecessary - ModestConf calls */ - if (fullscreen) { - if (priv->show_toolbars_fullscreen == show_toolbars) - return; - else - priv->show_toolbars_fullscreen = show_toolbars; - } else { - if (priv->show_toolbars == show_toolbars) - return; - else - priv->show_toolbars = show_toolbars; - } + /* 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) || @@ -646,8 +764,9 @@ modest_window_mgr_show_toolbars (ModestWindowMgr *self, GList *win = priv->window_list; while (win) { - modest_window_show_toolbar (MODEST_WINDOW (win->data), - show_toolbars); + if (G_TYPE_FROM_INSTANCE (win->data) == window_type) + modest_window_show_toolbar (MODEST_WINDOW (win->data), + show_toolbars); win = g_list_next (win); } } @@ -657,14 +776,45 @@ ModestWindow* modest_window_mgr_get_main_window (ModestWindowMgr *self) { 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) { + /* modest_window_mgr_register_window will set priv->main_window */ + modest_window_mgr_register_window (self, modest_main_window_new ()); + g_debug ("%s: created main window: %p\n", __FUNCTION__, priv->main_window); + } + + return priv->main_window; +} + +GtkDialog* +modest_window_mgr_get_easysetup_dialog (ModestWindowMgr *self) +{ + ModestWindowMgrPrivate *priv; + g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), NULL); + priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); + + return priv->easysetup_dialog; +} + +GtkDialog* +modest_window_mgr_set_easysetup_dialog (ModestWindowMgr *self, GtkDialog *dialog) +{ + ModestWindowMgrPrivate *priv; + + g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), NULL); priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); - return priv->main_window; + return priv->easysetup_dialog = dialog; } + static void on_nonhibernating_window_hide(GtkWidget *widget, gpointer user_data) { @@ -693,7 +843,8 @@ on_nonhibernating_window_show(GtkWidget *widget, gpointer user_data) G_CALLBACK (on_nonhibernating_window_hide), self); } -void modest_window_mgr_prevent_hibernation_while_window_is_shown (ModestWindowMgr *self, +void +modest_window_mgr_prevent_hibernation_while_window_is_shown (ModestWindowMgr *self, GtkWindow *window) { g_return_if_fail (MODEST_IS_WINDOW_MGR (self)); @@ -707,7 +858,8 @@ void modest_window_mgr_prevent_hibernation_while_window_is_shown (ModestWindowMg } } -gboolean modest_window_mgr_get_hibernation_is_prevented (ModestWindowMgr *self) +gboolean +modest_window_mgr_get_hibernation_is_prevented (ModestWindowMgr *self) { g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), FALSE); @@ -719,7 +871,8 @@ gboolean modest_window_mgr_get_hibernation_is_prevented (ModestWindowMgr *self) } -void modest_window_mgr_save_state_for_all_windows (ModestWindowMgr *self) +void +modest_window_mgr_save_state_for_all_windows (ModestWindowMgr *self) { g_return_if_fail (MODEST_IS_WINDOW_MGR (self));