2007-06-08 Murray Cumming <murrayc@murrayc.com>
+ * src/modest-account-mgr-priv.h: Added a timeout id and a GSList of
+ keys changed in the last X seconds.
+
+ * src/modest-account-mgr.h:
+ * src/modest-account-mgr.c: (on_timeout_notify_changes),
+ (on_key_change), (modest_account_mgr_class_init),
+ (modest_account_mgr_init), (modest_account_mgr_finalize):
+ As the keys are changed, save them in a GSList* and signal that GSList*
+ further every X seconds, to batch changes, to allow us to do just one
+ update per batch. This should fix bug projects.maemo.org bug NB#56472 and
+ bug NB#56941 and other (UI-blocking) delays when changing account settings.
+
+ * src/modest-tny-account-store.c: (on_account_changed): Adapted to
+ changed signal signature.
+
+ * src/modest-conf.c: (modest_conf_set_list),
+ (modest_conf_on_change): Reenable notification.
+
+ (modest_conf_maemo_fake_on_change): Comment out the hack that
+ notified immediately instead of asynchronously.
+
+ * src/widgets/modest-account-view.h:
+ * src/widgets/modest-account-view.c:
+ (update_account_view): Select the previously-selected account ID,
+ if possible. This fixes projects.maemo.org bug NB#56933.
+
+ (on_account_changed), (on_account_removed),
+ (modest_account_view_select_account):
+
+ Remove the block/unblock functions
+ because they were not useful.
+
+ * src/maemo/modest-account-view-window.c:
+ (on_delete_button_clicked), (on_edit_button_clicked),
+ (on_new_button_clicked): Remove the use of the non-working block/unblock.
+
+2007-06-08 Murray Cumming <murrayc@murrayc.com>
+
* src/modest-tny-account-store.c: (modest_tny_account_store_alert):
Improve the error dialog to show Incorrect Account Settings, which seems
clearer, and say that the internal error message (to be removed from the
gboolean removed;
GtkWidget *dialog;
gchar *txt;
-
- /* Freeze updates, so we can do just one update afterwards,
- * instead of responding to every conf key change: */
- modest_account_view_block_conf_updates (priv->account_view);
dialog = gtk_dialog_new_with_buttons (_("Confirmation dialog"),
GTK_WINDOW (self),
gtk_widget_destroy (dialog);
g_free (account_title);
g_free (account_name);
-
- /* Update the view: */
- modest_account_view_unblock_conf_updates (priv->account_view);
}
}
return;
}
- /* Freeze updates, so we can do just one update afterwards,
- * instead of responding to every conf key change: */
- modest_account_view_block_conf_updates (priv->account_view);
-
/* Show the Account Settings window: */
ModestAccountSettingsDialog *dialog = modest_account_settings_dialog_new ();
modest_account_settings_dialog_set_account_name (dialog, account_name);
gtk_widget_destroy (GTK_WIDGET (dialog));
g_free (account_name);
-
- /* Update the view: */
- modest_account_view_unblock_conf_updates (priv->account_view);
-
- /* TODO: Call modest_account_view_select_account() when
- * the view has actually been update. */
}
static void
on_new_button_clicked (GtkWidget *button, ModestAccountViewWindow *self)
{
- ModestAccountViewWindowPrivate *priv = MODEST_ACCOUNT_VIEW_WINDOW_GET_PRIVATE(self);
-
- /* Freeze updates, so we can do just one update afterwards,
- * instead of responding to every conf key change: */
- modest_account_view_block_conf_updates (priv->account_view);
-
/* Show the easy-setup wizard: */
ModestEasysetupWizardDialog *wizard = modest_easysetup_wizard_dialog_new ();
gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (self));
gtk_dialog_run (GTK_DIALOG (wizard));
gtk_widget_destroy (GTK_WIDGET (wizard));
-
- /* Allow updates: */
- modest_account_view_unblock_conf_updates (priv->account_view);
}
typedef struct _ModestAccountMgrPrivate ModestAccountMgrPrivate;
struct _ModestAccountMgrPrivate {
ModestConf *modest_conf;
+
+ /* We store these as they change, and send notifications every X seconds: */
+ GSList *changed_conf_keys;
+ guint timeout;
};
#define MODEST_ACCOUNT_MGR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
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);
+
+ /* 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);
+
+ g_signal_emit (G_OBJECT(self), signals[ACCOUNT_CHANGED_SIGNAL], 0,
+ default_account, priv->changed_conf_keys, FALSE);
+
+ g_free (default_account);
+
+ 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)
{
/* printf("DEBUG: %s: key=%s\n", __FUNCTION__, key); */
ModestAccountMgr *self = MODEST_ACCOUNT_MGR (user_data);
- /* ModestAccountMgrPrivate *priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self); */
+ ModestAccountMgrPrivate *priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
/* 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) {
- gchar *default_account =
- modest_account_mgr_get_default_account (self);
- g_signal_emit (G_OBJECT(self), signals[ACCOUNT_CHANGED_SIGNAL], 0,
- default_account, key, FALSE);
- g_free (default_account);
- return;
+ /* 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 (NULL,
+ (gpointer)key);
}
gboolean is_account_key = FALSE;
*/
if (enabled ||
g_str_has_suffix (key, MODEST_ACCOUNT_ENABLED) ||
- strcmp (key, MODEST_CONF_DEFAULT_ACCOUNT) == 0)
- g_signal_emit (G_OBJECT(self), signals[ACCOUNT_CHANGED_SIGNAL], 0,
- account, key, is_server_account);
+ 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)key);
+ }
g_free (account);
}
G_STRUCT_OFFSET(ModestAccountMgrClass,account_changed),
NULL, NULL,
modest_marshal_VOID__STRING_STRING_BOOLEAN,
- G_TYPE_NONE, 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN);
+ G_TYPE_NONE, 3, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_BOOLEAN);
}
MODEST_ACCOUNT_MGR_GET_PRIVATE (obj);
priv->modest_conf = NULL;
+
+ priv->timeout = g_timeout_add (1000 /* milliseconds */, on_timeout_notify_changes, obj);
}
static void
modest_account_mgr_finalize (GObject * obj)
{
- ModestAccountMgrPrivate *priv =
+ ModestAccountMgrPrivate *priv =
MODEST_ACCOUNT_MGR_GET_PRIVATE (obj);
if (priv->modest_conf) {
g_object_unref (G_OBJECT(priv->modest_conf));
priv->modest_conf = NULL;
}
+
+ if (priv->timeout)
+ g_source_remove (priv->timeout);
+
+ if (priv->changed_conf_keys)
+ g_slist_free (priv->changed_conf_keys);
G_OBJECT_CLASS(parent_class)->finalize (obj);
}
void (* account_removed) (ModestAccountMgr *obj, const gchar* account,
gboolean server_account, gpointer user_data);
void (* account_changed) (ModestAccountMgr *obj, const gchar* account,
- const gchar* key, gboolean server_account,
+ const GSList* keys, gboolean server_account,
gpointer user_data);
};
if(debug_list_length_start != debug_list_length_after)
g_warning("modest_conf_set_list(): The list length after setting is "
- "not the same as the specified list. key=%s", key);
+ "not the same as the specified list. key=%s. "
+ "We think that we fixed this, so tell us if you see this.", key);
g_slist_free(debug_list);
}
modest_conf_on_change (GConfClient *client, guint conn_id, GConfEntry *entry,
gpointer data)
{
- /*
- * on maemo, there's a nasty bug in gconf, which makes it really
- * slow, for updates and notifications. as an ugly hack, we turn off all
- * gconf-based notifications, and send them ourselves, a short time
- * after we do a change. this does not work for non-modest-conf
- * changes of course...
- */
-#ifndef MODEST_PLATFORM_MAEMO
-
ModestConfEvent event;
const gchar* key;
g_signal_emit (G_OBJECT(data),
signals[KEY_CHANGED_SIGNAL], 0,
key, event);
-#endif /*!MODEST_PLATFORM_MAEMO*/
}
////////////////////////////////////////////////////////////////////////////////
/* workaround for the b0rked dbus-gconf on maemo */
-/* fires a fake change notification after 0.3 secs */
+/* 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)
{
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);
(event == MODEST_CONF_EVENT_KEY_CHANGED)
? (GSourceFunc)emit_change_cb : (GSourceFunc)emit_remove_cb,
(gpointer)helper);
-#endif /*MODEST_PLATFORM_MAEMO*/
+#endif /* MODEST_PLATFORM_MAEMO */
+#endif
}
//////////////////////////////////////////////////////////////////////////////////
static void
on_account_changed (ModestAccountMgr *acc_mgr, const gchar *account,
- const gchar *key, gboolean server_account, gpointer user_data)
+ const GSList *keys, gboolean server_account, gpointer user_data)
{
ModestTnyAccountStore *self = MODEST_TNY_ACCOUNT_STORE(user_data);
+ #if 0
/* Ignore the change if it's a change in the last_updated value */
if (g_str_has_suffix (key, MODEST_ACCOUNT_LAST_UPDATED))
return;
+ #endif
/* FIXME: make this more finegrained; changes do not really affect _all_
* accounts, and some do not affect tny accounts at all (such as 'last_update')
static void modest_account_view_init (ModestAccountView *obj);
static void modest_account_view_finalize (GObject *obj);
+static void modest_account_view_select_account (ModestAccountView *account_view,
+ const gchar* account_name);
typedef enum {
MODEST_ACCOUNT_VIEW_NAME_COLUMN,
GSList *account_names, *cursor;
GtkListStore *model;
- model = GTK_LIST_STORE(gtk_tree_view_get_model (GTK_TREE_VIEW(view)));
+ model = GTK_LIST_STORE(gtk_tree_view_get_model (GTK_TREE_VIEW(view)));
+
+ /* Get the ID of the currently-selected account,
+ * so we can select it again after rebuilding the list.
+ * Note that the name doesn't change even when the display name changes.
+ */
+ gchar *selected_name = modest_account_view_get_selected_account (view);
+
gtk_list_store_clear (model);
/* Note: We do not show disabled accounts.
cursor = cursor->next;
}
g_slist_free (account_names);
+
+ /* Try to re-select the same account: */
+ if (selected_name) {
+ modest_account_view_select_account (view, selected_name);
+ g_free (selected_name);
+ }
}
static void
on_account_changed (ModestAccountMgr *account_mgr,
- const gchar* account, const gchar* key,
+ const gchar* account, GSList *keys,
gboolean server_account, ModestAccountView *self)
{
/* Never update the view in response to gconf changes.
* 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)..
*/
- return;
- ModestAccountViewPrivate* priv = MODEST_ACCOUNT_VIEW_GET_PRIVATE(self);
-
- if (!priv->block_conf_updates)
- update_account_view (account_mgr, self);
+ update_account_view (account_mgr, self);
}
const gchar* account, gboolean server_account,
ModestAccountView *self)
{
- ModestAccountViewPrivate* priv = MODEST_ACCOUNT_VIEW_GET_PRIVATE(self);
- if (!priv->block_conf_updates)
- on_account_changed (account_mgr, account, NULL, server_account, self);
+ on_account_changed (account_mgr, account, NULL, server_account, self);
}
return FALSE; /* Keep walking the tree. */
}
-void modest_account_view_select_account (ModestAccountView *account_view,
+static void modest_account_view_select_account (ModestAccountView *account_view,
const gchar* account_name)
{
/* Create a state instance so we can send two items of data to the signal handler: */
g_free (state);
}
-
-
-void modest_account_view_block_conf_updates (ModestAccountView *account_view)
-{
- ModestAccountViewPrivate* priv = MODEST_ACCOUNT_VIEW_GET_PRIVATE(account_view);
- priv->block_conf_updates = TRUE;
-}
-
-void modest_account_view_unblock_conf_updates (ModestAccountView *account_view)
-{
- ModestAccountViewPrivate* priv = MODEST_ACCOUNT_VIEW_GET_PRIVATE(account_view);
- priv->block_conf_updates = FALSE;
-
- update_account_view (modest_runtime_get_account_mgr(), account_view);
-}
*
* Sets the currently selected account.
**/
+/* Not used outside:
void modest_account_view_select_account (ModestAccountView *account_view,
const gchar* account_name);
-
-/**
- * modest_account_view_block_conf_updates
- * @account_view: a #ModestAccountView
- *
- * Stops the widget from updating in response to configuration key changes.
- * This can be a useful optimization when making many configuration changes.
- **/
-void modest_account_view_block_conf_updates (ModestAccountView *account_view);
-
-/**
- * modest_account_view_unblock_conf_updates
- * @account_view: a #ModestAccountView
- *
- * Allows the widget tp update again in response to configuration key changes.
- * When this is called it will cause the widget to immediately update its view from the
- * configuration data.
- **/
-void modest_account_view_unblock_conf_updates (ModestAccountView *account_view);
+*/
G_END_DECLS