Reverted again the gdk_threads_enter/leave sentences:
[modest] / src / widgets / modest-header-view.c
index 297e1cb..acf8f72 100644 (file)
@@ -51,6 +51,7 @@
 static void modest_header_view_class_init  (ModestHeaderViewClass *klass);
 static void modest_header_view_init        (ModestHeaderView *obj);
 static void modest_header_view_finalize    (GObject *obj);
+static void modest_header_view_dispose     (GObject *obj);
 
 static void          on_header_row_activated (GtkTreeView *treeview, GtkTreePath *path,
                                              GtkTreeViewColumn *column, gpointer userdata);
@@ -184,6 +185,7 @@ modest_header_view_class_init (ModestHeaderViewClass *klass)
 
        parent_class            = g_type_class_peek_parent (klass);
        gobject_class->finalize = modest_header_view_finalize;
+       gobject_class->dispose = modest_header_view_dispose;
        
        g_type_class_add_private (gobject_class, sizeof(ModestHeaderViewPrivate));
        
@@ -245,7 +247,7 @@ get_new_column (const gchar *name, GtkCellRenderer *renderer,
        if (resizable) 
                gtk_tree_view_column_set_expand (column, TRUE);
        
-       if (show_as_text) 
+       if (show_as_text)
                gtk_tree_view_column_add_attribute (column, renderer, "text",
                                                    sort_col_id);
        if (sort_col_id >= 0)
@@ -506,6 +508,24 @@ modest_header_view_init (ModestHeaderView *obj)
 }
 
 static void
+modest_header_view_dispose (GObject *obj)
+{
+       ModestHeaderView        *self;
+       ModestHeaderViewPrivate *priv;
+       
+       self = MODEST_HEADER_VIEW(obj);
+       priv = MODEST_HEADER_VIEW_GET_PRIVATE(self);
+
+       if (priv->folder) {
+               tny_folder_remove_observer (priv->folder, TNY_FOLDER_OBSERVER (obj));
+               g_object_unref (G_OBJECT (priv->folder));
+               priv->folder = NULL;
+       }
+
+       G_OBJECT_CLASS(parent_class)->dispose (obj);
+}
+
+static void
 modest_header_view_finalize (GObject *obj)
 {
        ModestHeaderView        *self;
@@ -522,12 +542,6 @@ modest_header_view_finalize (GObject *obj)
        g_mutex_unlock (priv->observers_lock);
        g_mutex_free (priv->observers_lock);
 
-       if (priv->folder) {
-               tny_folder_remove_observer (priv->folder, TNY_FOLDER_OBSERVER (obj));
-               g_object_unref (G_OBJECT (priv->folder));
-               priv->folder   = NULL;
-       }
-
        /* Clear hidding array created by cut operation */
        _clear_hidding_filter (MODEST_HEADER_VIEW (obj));
 
@@ -551,7 +565,7 @@ modest_header_view_new (TnyFolder *folder, ModestHeaderViewStyle style)
        priv = MODEST_HEADER_VIEW_GET_PRIVATE(self);
        
        modest_header_view_set_style   (self, style);
-       modest_header_view_set_folder (self, NULL, NULL, NULL);
+/*     modest_header_view_set_folder (self, NULL, NULL, NULL); */
 
        gtk_tree_view_columns_autosize (GTK_TREE_VIEW(obj));
        gtk_tree_view_set_fixed_height_mode (GTK_TREE_VIEW(obj),TRUE);
@@ -574,6 +588,37 @@ modest_header_view_new (TnyFolder *folder, ModestHeaderViewStyle style)
 }
 
 
+guint
+modest_header_view_count_selected_headers (ModestHeaderView *self)
+{
+       GtkTreeSelection *sel;
+       guint selected_rows;
+
+       g_return_val_if_fail (self, 0);
+       
+       /* Get selection object and check selected rows count */
+       sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(self));
+       selected_rows = gtk_tree_selection_count_selected_rows (sel);
+       
+       return selected_rows;
+}
+
+gboolean
+modest_header_view_has_selected_headers (ModestHeaderView *self)
+{
+       GtkTreeSelection *sel;
+       gboolean empty;
+
+       g_return_val_if_fail (self, FALSE);
+       
+       /* Get selection object and check selected rows count */
+       sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(self));
+       empty = gtk_tree_selection_count_selected_rows (sel) == 0;
+       
+       return !empty;
+}
+
+
 TnyList * 
 modest_header_view_get_selected_headers (ModestHeaderView *self)
 {
@@ -768,25 +813,17 @@ modest_header_view_get_style (ModestHeaderView *self)
 static void
 modest_header_view_set_model (GtkTreeView *header_view, GtkTreeModel *model)
 {
-       GtkTreeModel *old_model_filter = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
-       GtkTreeModel *old_model_sort = NULL;
-
-       if (old_model_filter) 
-               old_model_sort = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER(old_model_filter));
-
-       if (old_model_sort && GTK_IS_TREE_MODEL_SORT (old_model_sort)) { 
-               GtkTreeModel *old_model;
-               ModestHeaderViewPrivate *priv;
-
-               priv = MODEST_HEADER_VIEW_GET_PRIVATE (header_view);
-               old_model = gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT (old_model_sort));
-
-               /* Set new model */
-               gtk_tree_view_set_model (header_view, model);
-       } else
-               gtk_tree_view_set_model (header_view, model);
-
-       return;
+/*     GtkTreeModel *old_model_sort = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)); */
+/*     if (old_model_sort && GTK_IS_TREE_MODEL_SORT (old_model_sort)) { */
+/*             GtkTreeModel *old_model; */
+/*             ModestHeaderViewPrivate *priv; */
+/*             priv = MODEST_HEADER_VIEW_GET_PRIVATE (header_view); */
+/*             old_model = gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT (old_model_sort)); */
+
+/*             /\* Set new model *\/ */
+/*             gtk_tree_view_set_model (header_view, model); */
+/*     } else */
+       gtk_tree_view_set_model (header_view, model);
 }
 
 TnyFolder*
@@ -829,7 +866,6 @@ modest_header_view_set_folder_intern (ModestHeaderView *self, TnyFolder *folder)
        priv->monitor = TNY_FOLDER_MONITOR (tny_folder_monitor_new (folder));
        tny_folder_monitor_add_list (priv->monitor, TNY_LIST (headers));
        tny_folder_monitor_start (priv->monitor);
-       tny_folder_add_observer (folder, TNY_FOLDER_OBSERVER (self));
        g_mutex_unlock (priv->observers_lock);
 
        sortable = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL(headers));
@@ -945,6 +981,40 @@ modest_header_view_get_sort_type (ModestHeaderView *self,
        return priv->sort_type[style][type];
 }
 
+typedef struct {
+       ModestHeaderView *header_view;
+       RefreshAsyncUserCallback cb;
+       gpointer user_data;
+} SetFolderHelper;
+
+static void
+folder_refreshed_cb (const GObject *obj, 
+                    TnyFolder *folder, 
+                    gpointer user_data)
+{
+       ModestHeaderViewPrivate *priv;
+       SetFolderHelper *info;
+       info = (SetFolderHelper*) user_data;
+
+       priv = MODEST_HEADER_VIEW_GET_PRIVATE(info->header_view);
+
+       /* User callback */
+       if (info->cb)
+               info->cb (obj, folder, info->user_data);
+
+       /* Start the folder count changes observer. We do not need it
+          before the refresh. Note that the monitor could still be
+          called for this refresh but now we know that the callback
+          was previously called */
+       g_mutex_lock (priv->observers_lock);
+       tny_folder_add_observer (folder, TNY_FOLDER_OBSERVER (info->header_view));
+       g_mutex_unlock (priv->observers_lock);
+
+       /* Frees */
+       g_free (info);
+}
+
 void
 modest_header_view_set_folder (ModestHeaderView *self, 
                               TnyFolder *folder,
@@ -952,9 +1022,9 @@ modest_header_view_set_folder (ModestHeaderView *self,
                               gpointer user_data)
 {
        ModestHeaderViewPrivate *priv;
-       ModestMailOperation *mail_op = NULL;
        ModestWindowMgr *mgr = NULL;
        GObject *source = NULL;
+       SetFolderHelper *info;
  
        priv = MODEST_HEADER_VIEW_GET_PRIVATE(self);
 
@@ -967,6 +1037,7 @@ modest_header_view_set_folder (ModestHeaderView *self,
        }
 
        if (folder) {
+               ModestMailOperation *mail_op = NULL;
 
                /* Get main window to use it as source of mail operation */
                mgr = modest_runtime_get_window_mgr ();
@@ -981,19 +1052,24 @@ modest_header_view_set_folder (ModestHeaderView *self,
                /* no message selected */
                g_signal_emit (G_OBJECT(self), signals[HEADER_SELECTED_SIGNAL], 0, NULL);
 
+               info = g_malloc0 (sizeof(SetFolderHelper));
+               info->header_view = self;
+               info->cb = callback;
+               info->user_data = user_data;
+
                /* Create the mail operation (source will be the parent widget) */
                mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, source);
                modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
                                                 mail_op);
 
                /* Refresh the folder asynchronously */
-               modest_mail_operation_refresh_folder (mail_op, folder,
-                                                     callback,
-                                                     user_data);
+               modest_mail_operation_refresh_folder (mail_op, 
+                                                     folder,
+                                                     folder_refreshed_cb,
+                                                     info);
 
                /* Free */
                g_object_unref (mail_op);
-
        } else {
                g_mutex_lock (priv->observers_lock);
 
@@ -1073,7 +1149,10 @@ on_selection_changed (GtkTreeSelection *sel, gpointer user_data)
                       0, header);
 
        g_object_unref (G_OBJECT (header));
-       gtk_tree_path_free(path);
+
+       /* free all items in 'selected' */
+       g_list_foreach (selected, (GFunc)gtk_tree_path_free, NULL);
+       g_list_free (selected);
 }
 
 
@@ -1091,6 +1170,16 @@ _modest_header_view_change_selection (GtkTreeSelection *selection,
        on_selection_changed (selection, user_data);
 }
 
+static gint compare_priorities (TnyHeaderFlags p1, TnyHeaderFlags p2)
+{
+       p1 = p1 & TNY_HEADER_FLAG_PRIORITY;
+       p2 = p2 & TNY_HEADER_FLAG_PRIORITY;
+       if (p1 == 0) 
+               p1 = TNY_HEADER_FLAG_LOW_PRIORITY + 1;
+       if (p2 == 0) 
+               p2 = TNY_HEADER_FLAG_LOW_PRIORITY + 1;
+       return p1 - p2;
+}
 
 static gint
 cmp_rows (GtkTreeModel *tree_model, GtkTreeIter *iter1, GtkTreeIter *iter2,
@@ -1105,14 +1194,8 @@ cmp_rows (GtkTreeModel *tree_model, GtkTreeIter *iter1, GtkTreeIter *iter2,
        g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN(user_data), 0);
 /*     col_id = gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (tree_model)); */
        col_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(user_data), MODEST_HEADER_VIEW_FLAG_SORT));
+
        
-/*     if (!(++counter % 100)) { */
-/*             GObject *header_view = g_object_get_data(G_OBJECT(user_data), */
-/*                                                      MODEST_HEADER_VIEW_PTR); */
-/*             g_signal_emit (header_view, */
-/*                            signals[STATUS_UPDATE_SIGNAL], */
-/*                            0, _("Sorting..."), 0, 0); */
-/*     } */
        switch (col_id) {
        case TNY_HEADER_FLAG_ATTACHMENTS:
 
@@ -1134,10 +1217,7 @@ cmp_rows (GtkTreeModel *tree_model, GtkTreeIter *iter1, GtkTreeIter *iter2,
 
                /* This is for making priority values respect the intuitive sort relationship 
                 * as HIGH is 11, LOW is 01, and we put NORMAL AS 10 (2) */
-               if (val1 == 0) val1 = 2;
-               if (val2 == 0) val2 = 2;
-
-               cmp =  (val1 & TNY_HEADER_FLAG_PRIORITY) - (val2 & TNY_HEADER_FLAG_PRIORITY);
+               cmp =  compare_priorities (val1, val2);
 
                return cmp ? cmp : t1 - t2;
 
@@ -1314,17 +1394,11 @@ on_focus_in (GtkWidget     *self,
        return FALSE;
 }
 
-static gboolean
-idle_notify_added_headers (gpointer data)
-{
-       modest_platform_on_new_msg ();
-
-       return FALSE;
-}
-
 static void
 idle_notify_headers_count_changed_destroy (gpointer data)
 {
+       gdk_threads_enter ();
+
        HeadersCountChangedHelper *helper = NULL;
 
        g_return_if_fail (data != NULL);
@@ -1332,11 +1406,15 @@ idle_notify_headers_count_changed_destroy (gpointer data)
 
        g_object_unref (helper->change);
        g_slice_free (HeadersCountChangedHelper, helper);
+
+       gdk_threads_leave ();
 }
 
 static gboolean
 idle_notify_headers_count_changed (gpointer data)
 {
+       gdk_threads_enter ();
+
        TnyFolder *folder = NULL;
        ModestHeaderViewPrivate *priv = NULL;
        HeadersCountChangedHelper *helper = NULL;
@@ -1354,11 +1432,14 @@ idle_notify_headers_count_changed (gpointer data)
        /* Emmit signal to evaluate how headers changes affects to the window view  */
        g_signal_emit (G_OBJECT(helper->self), signals[MSG_COUNT_CHANGED_SIGNAL], 0, folder, helper->change);
                
-       /* Added or removed headers, so data sotred on cliboard are invalid  */
-       modest_email_clipboard_clear (priv->clipboard);
-
+       /* Added or removed headers, so data stored on cliboard are invalid  */
+       if (modest_email_clipboard_check_source_folder (priv->clipboard, folder))
+           modest_email_clipboard_clear (priv->clipboard);
+           
        g_mutex_unlock (priv->observers_lock);
 
+       gdk_threads_leave ();
+
        return FALSE;
 }
 
@@ -1366,17 +1447,19 @@ static void
 folder_monitor_update (TnyFolderObserver *self, 
                       TnyFolderChange *change)
 {
+       ModestHeaderViewPrivate *priv;
        TnyFolderChangeChanged changed;
        HeadersCountChangedHelper *helper = NULL;
 
        changed = tny_folder_change_get_changed (change);
-
-       /* We need an idle because this function is called from within
-          a thread, so it could cause problems if the modest platform
-          code calls dbus for example */
-       if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS)
-               g_idle_add (idle_notify_added_headers, NULL);
        
+       /* Do not notify the observers if the folder of the header
+          view has changed before this call to the observer
+          happens */
+       priv = MODEST_HEADER_VIEW_GET_PRIVATE (MODEST_HEADER_VIEW (self));
+       if (tny_folder_change_get_folder (change) != priv->folder)
+               return;
+
        /* Check folder count */
        if ((changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) ||
            (changed & TNY_FOLDER_CHANGE_CHANGED_REMOVED_HEADERS)) {