aboutsummaryrefslogblamecommitdiffstats
path: root/my-evolution/e-summary-mail.c
blob: aff5061cc8e577f9194545e7f8f3ef46610230d5 (plain) (tree)
1
2
3
4
5
6
7
8

                                                                           


                                  
                                                                
                                                                   
                                                        











                                                                    

   


                    
                          
                                  
 

                                
                                                                   






                                       






                            



                                                    
                                                 
                                 
                                                   
 

                             
                            
                     




                              









                                           





                                    
 
                                                              
                        

                     

                                           

                                               


                     





                                                            





                                             

                                            
                                 
 

                                      
                                                                     
                                                                    












                                                                                                                             
                 
                      
 


                                                  
                             
                                                                             
                                                                        
                                                                                        



                                                                                          
        
                                               
                                                           
         

                                                       

                         
                                 


                     


                                      












                                                   





























                                                                               
                               
 
                                        

                                        
                 
 
                                       
                                                 

                                                                

                       


                                                    
                             
                                                           


                                            
                                  

                                                                            

                                                                
                                                                         
                                                                 
                                                                               

                                                                          
                 
         


           

                                                     
                                   
                                  
 
                                        
                            
                                  

                  


                                                                                 
 


                                                                     
                                               



                                                                              


           

                                                     
                                  
 
                                        

                                        
                 






                                                                








                                                                          
                                                  
                                   













                                                       
                 


                             

                                        








                                                                  
                            
 

                                                                         
                                                          
                                                 

                               
         








                                           

        

                                                   
                                                  
                                                                       

                           
                                                       
                        
                             
 
                             
 






                                                         
 
                                                                      
        







                                                                                
 
                                   
                                                                                 
                              
                                                            

                                                     
                
                              
                             

         
                                   
 


                    








































































                                                                                                  



                                                                    

                                       





                                                             





                                                                                                           
                                           
                             
         
 









                                                                                                   
                             



                                   














                                                       
                          

                                                                          
                                                           
                                                                

                                                     
 


                       

                                   







                                                                           
 
                                                                        


                                                                                         
 



                                              
                       






                                                  
 
                                                                                       


                                           

                                                            



                                                                     
 

                                                                  



                                                                             




                                                                          



                               
                                               

                                 

































                                              
                                                
 














                                                           

 




                                  









                                                     



















                                                       
                                   






                                          
                     


                                             

                                                                    
                                                       
                                         












                                                                                    
                        
                                                                                                 



                             




                                                 




                                                   


                                                                           






















                                                                







































                                                                                    
    
                                             


                                            
                  
 


                                                    




                             


                                                             
 




                                                        
         















                                                                   









                                           











                                                              



                                                                                      






                                                                






                                                                                    


                             
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
/* e-summary-mail.c
 *
 * Copyright (C) 2001 Ximian, Inc.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU General Public
 * License as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * Author: Iain Holmes  <iain@ximian.com>
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <liboaf/liboaf.h>
#include <gal/widgets/e-unicode.h>

#include <libgnome/gnome-defs.h>
#include <libgnome/gnome-i18n.h>
#include <libgnome/gnome-util.h> /* gnome_util_prepend_user_home */
#include <gtk/gtksignal.h>
#include <bonobo/bonobo-exception.h>
#include <bonobo/bonobo-listener.h>

#include <Evolution.h>
#include <evolution-storage-listener.h>

#include "Mail.h"
#include "e-summary.h"
#include "e-summary-mail.h"
#include "e-summary-table.h"

#include "e-util/e-path.h"

#define MAIL_IID "OAFIID:GNOME_Evolution_FolderInfo"

struct _ESummaryMail {
    GNOME_Evolution_FolderInfo folder_info;
    GNOME_Evolution_StorageRegistry registry;
    BonoboListener *listener;
    EvolutionStorageListener *storage_listener;

    GSList *storage_list;
    
    GHashTable *folders;
    GList *shown;
    ESummaryMailMode mode;

    char *html;
};

typedef struct _StorageInfo {
    char *name;
    char *toplevel;
    
    GNOME_Evolution_Storage storage;
    EvolutionStorageListener *listener;
    ESummary *summary;
    GList *folders;
} StorageInfo;

typedef struct _ESummaryMailFolder {
    char *name;
    char *path;

    int count;
    int unread;

    gboolean init; /* Has this folder been initialised? */
    StorageInfo *si;
} ESummaryMailFolder;

/* Work out what to do with folder names */
static char *
make_pretty_foldername (ESummary *summary,
            const char *foldername)
{
    char *pretty;

    if (summary->preferences->show_full_path == FALSE) {
        if ((pretty = strrchr (foldername, '/'))) {
            return g_strdup (pretty + 1);
        } else {
            return g_strdup (foldername);
        }
    } else {
        return g_strdup (foldername);
    }
}

static void
folder_gen_html (ESummary *summary,
         ESummaryMailFolder *folder,
         GString *string)
{
    char *str, *pretty_name, *uri;
    
    pretty_name = make_pretty_foldername (summary, folder->name);
    uri = g_strconcat ("evolution:/local", folder->name, NULL); 
    str = g_strdup_printf ("<tr><td><a href=\"%s\"><pre>%s</pre></a></td><td align=\"Left\"><pre>%d/%d</pre></td></tr>", 
                   uri, pretty_name, folder->unread, folder->count);
    g_free (uri);
    g_string_append (string, str);
    g_free (pretty_name);
    g_free (str);
}

static void
e_summary_mail_generate_html (ESummary *summary)
{
    ESummaryMail *mail;
    GString *string;
    GList *p;
    char *s, *old;

    g_return_if_fail (summary != NULL);
    g_return_if_fail (IS_E_SUMMARY (summary));

    mail = summary->mail;
    string = g_string_new ("<dl><dt><img src=\"myevo-mail-summary.png\" "
                           "align=\"middle\" alt=\"\" width=\"48\" "
                           "height=\"48\"> <b><a href=\"evolution:/local/Inbox\">");
    s = e_utf8_from_locale_string (_("Mail summary"));
    g_string_append (string, s);
    g_free (s);
    g_string_append (string, "</a></b></dt><dd><table numcols=\"2\" width=\"100%\">");
    
    for (p = mail->shown; p; p = p->next) {
        folder_gen_html (summary, p->data, string);
    }

    g_string_append (string, "</table></dd></dl>");

    old = mail->html;
    mail->html = string->str;

    g_free (old);

    g_string_free (string, FALSE);
}

const char *
e_summary_mail_get_html (ESummary *summary)
{
    /* Only regenerate HTML when it's needed */
    e_summary_mail_generate_html (summary);
    
    if (summary->mail == NULL) {
        return NULL;
    }

    return summary->mail->html;
}

static void
e_summary_mail_get_info (ESummaryMail *mail,
             const char *uri,
             BonoboListener *listener)
{
    Bonobo_Listener corba_listener;
    CORBA_Environment ev;

    g_return_if_fail (mail != NULL);
    g_return_if_fail (mail->folder_info != CORBA_OBJECT_NIL);

    corba_listener = bonobo_object_corba_objref (BONOBO_OBJECT (listener));
    CORBA_exception_init (&ev);
    GNOME_Evolution_FolderInfo_getInfo (mail->folder_info, uri ? uri : "",
                        corba_listener, &ev);
    if (BONOBO_EX (&ev)) {
        g_warning ("Error getting info for %s:\n%s", uri,
               CORBA_exception_id (&ev));
        CORBA_exception_free (&ev);
        return;
    }

    CORBA_exception_free (&ev);
    return;
}

static void
new_folder_cb (EvolutionStorageListener *listener,
           const char *path,
           const GNOME_Evolution_Folder *folder,
           StorageInfo *si)
{
    ESummary *summary = si->summary;
    ESummaryMail *mail;
    ESummaryMailFolder *mail_folder;
    GList *p;

    /* Don't care about non mail */
    if (strcmp (folder->type, "mail") != 0 ||
        (strncmp (folder->physicalUri, "file://", 7) != 0 &&
        strncmp (folder->physicalUri, "vfolder", 7) != 0)) {
        return;
    }
    mail = summary->mail;

    mail_folder = g_new (ESummaryMailFolder, 1);
    mail_folder->si = si;
    mail_folder->path = g_strdup (folder->physicalUri);
    mail_folder->name = g_strdup (path);
    mail_folder->count = -1;
    mail_folder->unread = -1;
    mail_folder->init = FALSE;

    g_hash_table_insert (mail->folders, mail_folder->path, mail_folder);
    si->folders = g_list_prepend (si->folders, mail_folder);
    
    for (p = summary->preferences->display_folders; p; p = p->next) {
        if (strcmp (p->data, folder->physicalUri) == 0) {
            mail->shown = g_list_append (mail->shown, mail_folder);
            e_summary_mail_get_info (mail, mail_folder->path, 
                         mail->listener);
        }
    }
}

static void
update_folder_cb (EvolutionStorageListener *listener,
          const char *path,
          int unread_count,
          StorageInfo *si)
{
    ESummary *summary = si->summary;
    char *evolution_dir;
    static char *proto = NULL;
    char *uri;

    /* Make this static, saves having to recompute it each time */
    if (proto == NULL) {
        evolution_dir = gnome_util_prepend_user_home ("evolution/local");

        proto = g_strconcat ("file://", evolution_dir, NULL);
        g_free (evolution_dir);
    }
    uri = e_path_to_physical (proto, path);

    e_summary_mail_get_info (summary->mail, uri, summary->mail->listener);

    g_free (uri);
}

static void
remove_folder_cb (EvolutionStorageListener *listener,
          const char *path,
          StorageInfo *si)
{
    ESummary *summary = si->summary;
    ESummaryMail *mail;
    ESummaryMailFolder *mail_folder;
    GList *p;

    mail = summary->mail;
    mail_folder = g_hash_table_lookup (mail->folders, path);
    if (mail_folder == NULL) {
        return;
    }

    /* Check if we're displaying it, because we can't display it if it
       doesn't exist :) */
    for (p = mail->shown; p; p = p->next) {
        if (p->data == mail_folder) {
            mail->shown = g_list_remove_link (mail->shown, p);
            g_list_free (p);
        }
    }

    g_hash_table_remove (mail->folders, path);
    g_free (mail_folder->name);
    g_free (mail_folder->path);
    g_free (mail_folder);
}

static void
mail_change_notify (BonoboListener *listener,
            const char *name,
            const BonoboArg *arg,
            CORBA_Environment *ev,
            ESummary *summary)
{
    GNOME_Evolution_FolderInfo_MessageCount *count;
    ESummaryMail *mail;
    ESummaryMailFolder *folder;
    GList *p;

    mail = summary->mail;

    g_return_if_fail (mail != NULL);

    count = arg->_value;
    folder = g_hash_table_lookup (mail->folders, count->path);

    if (folder == NULL) {
        return;
    }

    folder->count = count->count;
    folder->unread = count->unread;
    folder->init = TRUE;

    /* Are we displaying this folder? */
    for (p = summary->preferences->display_folders; p; p = p->next) {
        if (strcmp (p->data, folder->path) == 0) {
            e_summary_draw (summary);
            return;
        }
    }
}

static void
e_summary_mail_protocol (ESummary *summary,
             const char *uri,
             void *closure)
{
}

    
    
static gboolean
e_summary_mail_register_storage (ESummary *summary,
                 const char *name,
                 GNOME_Evolution_Storage corba_storage)
{
    ESummaryMail *mail;
    GNOME_Evolution_StorageListener corba_listener;
    StorageInfo *si;
    CORBA_Environment ev;

    mail = summary->mail;

    si = g_new (StorageInfo, 1);
    si->name = g_strdup (name);
    si->toplevel = NULL;
    si->summary = summary;
    si->storage = corba_storage;
    si->listener = evolution_storage_listener_new ();
    si->folders = NULL;

    mail->storage_list = g_slist_prepend (mail->storage_list, si);
    
    gtk_signal_connect (GTK_OBJECT (si->listener), "new-folder",
                GTK_SIGNAL_FUNC (new_folder_cb), si);
    gtk_signal_connect (GTK_OBJECT (si->listener), "removed-folder",
                GTK_SIGNAL_FUNC (remove_folder_cb), si);
    gtk_signal_connect (GTK_OBJECT (si->listener), "update_folder",
                GTK_SIGNAL_FUNC (update_folder_cb), si);
    
    corba_listener = evolution_storage_listener_corba_objref (si->listener);

    CORBA_exception_init (&ev);
    GNOME_Evolution_Storage_addListener (corba_storage, corba_listener, &ev);
    if (BONOBO_EX (&ev)) {
        g_warning ("Exception adding listener: %s", 
               CORBA_exception_id (&ev));
        CORBA_exception_free (&ev);
        
        g_free (mail);
        return FALSE;
    }

    CORBA_exception_free (&ev);

    return TRUE;
}

static void
e_summary_mail_register_local_storage (ESummary *summary)
{
    ESummaryMail *mail;
    GNOME_Evolution_Storage local_storage;
    CORBA_Environment ev;

    mail = summary->mail;

    CORBA_exception_init (&ev);
    local_storage = GNOME_Evolution_Shell_getLocalStorage (summary->shell, &ev);
    if (BONOBO_EX (&ev) || local_storage == CORBA_OBJECT_NIL) {
        g_warning ("Error getting local storage: %s", CORBA_exception_id (&ev));
        CORBA_exception_free (&ev);
        return;
    }
    CORBA_exception_free (&ev);

    e_summary_mail_register_storage (summary, _("Local Folders"), local_storage);
}

static void
storage_notify (BonoboListener *listener,
        const char *name,
        const BonoboArg *arg,
        CORBA_Environment *ev,
        ESummary *summary)
{
    GNOME_Evolution_StorageRegistry_NotifyResult *nr;
    GNOME_Evolution_Storage corba_storage;
    CORBA_Environment ev2;
    ESummaryMail *mail;

    mail = summary->mail;
    g_return_if_fail (mail != NULL);
    
    nr = arg->_value;
    switch (nr->type) {
    case GNOME_Evolution_StorageRegistry_STORAGE_CREATED:
        /* These need to be special cased because they're special */
        if (strcmp (nr->name, "summary") == 0) {
            break;
        }

        if (strcmp (nr->name, "local") == 0) {
            e_summary_mail_register_local_storage (summary);
            break;
        }
        
        CORBA_exception_init (&ev2);
        corba_storage = GNOME_Evolution_StorageRegistry_getStorageByName (mail->registry,
                                          nr->name, &ev2);
        if (BONOBO_EX (&ev2) || corba_storage == CORBA_OBJECT_NIL) {
            g_warning ("Error getting storage %s\n%s", nr->name,
                   CORBA_exception_id (&ev2));
            CORBA_exception_free (&ev2);
            return;
        }

        CORBA_exception_free (&ev2);
        e_summary_mail_register_storage (summary, nr->name, corba_storage);
        break;

    case GNOME_Evolution_StorageRegistry_STORAGE_DESTROYED:
        g_print ("%s removed\n", nr->name);
        break;

    default:
        g_print ("Unknown response %d\n", nr->type);
        break;
    }
}

static gboolean
e_summary_mail_register_storages (ESummary *summary,
                  GNOME_Evolution_Shell corba_shell)
{
    Bonobo_Listener corba_listener;
    BonoboListener *listener;
    CORBA_Environment ev;

    g_return_val_if_fail (summary != NULL, FALSE);
    g_return_val_if_fail (IS_E_SUMMARY (summary), FALSE);

    CORBA_exception_init (&ev);

    summary->mail->registry = Bonobo_Unknown_queryInterface (corba_shell,
                                 "IDL:GNOME/Evolution/StorageRegistry:1.0",
                                 &ev);
    if (BONOBO_EX (&ev) || summary->mail->registry == NULL) {
        g_warning ("No storage registry: %s", CORBA_exception_id (&ev));
        CORBA_exception_free (&ev);
        return FALSE;
    }

    listener = bonobo_listener_new (NULL, NULL);
    gtk_signal_connect (GTK_OBJECT (listener), "event-notify",
                GTK_SIGNAL_FUNC (storage_notify), summary);
    corba_listener = bonobo_object_corba_objref (BONOBO_OBJECT (listener));

    /* Storages will be added whenever the listener gets an event. */
    GNOME_Evolution_StorageRegistry_addListener (summary->mail->registry, corba_listener, &ev);
    if (BONOBO_EX (&ev)) {
        g_warning ("Cannot add listener\n%s", CORBA_exception_id (&ev));
        CORBA_exception_free (&ev);
        return FALSE;
    }
    
    CORBA_exception_free (&ev);
    return TRUE;
}

void
e_summary_mail_init (ESummary *summary,
             GNOME_Evolution_Shell corba_shell)
{
    ESummaryMail *mail;
    CORBA_Environment ev;

    g_return_if_fail (summary != NULL);
    g_return_if_fail (IS_E_SUMMARY (summary));

    mail = g_new0 (ESummaryMail, 1);
    summary->mail = mail;

    mail->html = NULL;
    CORBA_exception_init (&ev);
    mail->folder_info = oaf_activate_from_id (MAIL_IID, 0, NULL, &ev);
    if (BONOBO_EX (&ev) || mail->folder_info == NULL) {
        g_warning ("Exception creating FolderInfo: %s", 
               CORBA_exception_id (&ev));
        CORBA_exception_free (&ev);

        return;
    }

    CORBA_exception_free (&ev);
    
    /* Create a BonoboListener for all the notifies. */
    mail->listener = bonobo_listener_new (NULL, NULL);
    gtk_signal_connect (GTK_OBJECT (mail->listener), "event-notify",
                GTK_SIGNAL_FUNC (mail_change_notify), summary);

    /* Create a hash table for the folders */
    mail->folders = g_hash_table_new (g_str_hash, g_str_equal);
    mail->shown = NULL;

    e_summary_mail_register_storages (summary, corba_shell);    
    e_summary_add_protocol_listener (summary, "mail", e_summary_mail_protocol, mail);
    return;
}

void
e_summary_mail_reconfigure (ESummary *summary)
{
    ESummaryMail *mail;
    GList *old, *p;

    g_return_if_fail (summary != NULL);
    g_return_if_fail (IS_E_SUMMARY (summary));
    
    mail = summary->mail;
    old = mail->shown;
    mail->shown = NULL;

    for (p = g_list_last (summary->preferences->display_folders); p; p = p->prev) {
        ESummaryMailFolder *folder;
        char *uri;

        if (strncmp (p->data, "file://", 7) == 0 ||
            strncmp (p->data, "vfolder:", 8) == 0) {
            uri = g_strdup (p->data);
        } else {
            uri = g_strconcat ("file://", p->data, NULL);
        }

        folder = g_hash_table_lookup (mail->folders, uri);
        if (folder != NULL) {
            if (folder->init == FALSE) {
                e_summary_mail_get_info (mail, folder->path, 
                             mail->listener);
            }
            mail->shown = g_list_append (mail->shown, folder);
        }

        g_free (uri);
    }

    /* Free the old list */
    g_list_free (old);

    e_summary_mail_generate_html (summary);
    e_summary_draw (summary);
}

static void
free_row_data (gpointer data)
{
    ESummaryMailRowData *rd = data;

    g_free (rd->name);
    g_free (rd->uri);
    g_free (rd);
}

static void
hash_to_list (gpointer key,
          gpointer value,
          gpointer data)
{
    ESummaryMailRowData *rd;
    ESummaryMailFolder *folder;
    GList **p;

    p = (GList **) data;
    folder = (ESummaryMailFolder *) value;

    rd = g_new (ESummaryMailRowData, 1);
    rd->name = g_strdup (folder->name);
    rd->uri = g_strdup (key);

    *p = g_list_prepend (*p, rd);
}

static int
str_compare (gconstpointer a,
         gconstpointer b)
{
    ESummaryMailFolder *folder_a, *folder_b;

    folder_a = (ESummaryMailFolder *) a;
    folder_b = (ESummaryMailFolder *) b;
    return strcasecmp (folder_a->name, folder_b->name);
}

static int
sort_storages (gconstpointer a,
           gconstpointer b)
{
    StorageInfo *si_a, *si_b;

    si_a = (StorageInfo *) a;
    si_b = (StorageInfo *) b;

    return strcasecmp (si_a->name, si_b->name);
}

static char *
get_parent_path (const char *path)
{
    char *last;

    if (strncmp (path, "vfolder", 7) == 0) {
        last = strrchr (path, '#');
        if (last == NULL) {
            return g_strdup (path);
        }
        return g_strndup (path, last - path);
    } else {
        last = strrchr (path, '/');
        return g_strndup (path, last - path);
    }
}

static gboolean
is_folder_shown (ESummaryMail *mail,
         const char *path)
{
    GList *p;

    for (p = mail->shown; p; p = p->next) {
        ESummaryMailFolder *folder = p->data;
        if (strcmp (folder->path, path) == 0) {
            return TRUE;
        }
    }
    
    return FALSE;
}

static ETreePath
insert_path_recur (ESummaryTable *est,
           StorageInfo *si,
           GHashTable *hash_table,
           const char *path,
           ESummaryMail *mail)
{
    char *parent_path, *name;
    ETreePath parent_node, node;
    ESummaryTableModelEntry *entry;
    int children;
    
    parent_path = get_parent_path (path);

    parent_node = g_hash_table_lookup (hash_table, parent_path);
    if (parent_node == NULL) {
        if (strcmp (si->toplevel, path) == 0) {
            /* Insert root */
            children = e_summary_table_get_num_children (est, NULL);
            node = e_summary_table_add_node (est, NULL, children, NULL);
            entry = g_new (ESummaryTableModelEntry, 1);
            entry->path = node;
            entry->location = NULL;
            entry->name = g_strdup (si->name);
            entry->editable = FALSE;
            entry->removable = FALSE;
            entry->shown = FALSE;

            g_hash_table_insert (est->model, entry->path, entry);
            g_hash_table_insert (hash_table, g_strdup (path), node);
            return node;
        } else {
            parent_node = insert_path_recur (est, si, hash_table, parent_path, mail);
        }
    }

    g_free (parent_path);
    if (strcmp (si->name, "VFolders") == 0) {
        name = strrchr (path, '#');
    } else {
        name = strrchr (path, '/');
    }

    /* Leave out folders called "subfolder" */
    if (strcmp (name + 1, "subfolders") == 0) {
        return parent_node;
    }

    children = e_summary_table_get_num_children (est, parent_node);
    node = e_summary_table_add_node (est, parent_node, children, NULL);
    entry = g_new (ESummaryTableModelEntry, 1);
    entry->path = node;
    entry->location = g_strdup (path);
    entry->name = g_strdup (name + 1);
    entry->editable = TRUE;
    entry->removable = FALSE;

    /* Check if shown */
    entry->shown = is_folder_shown (mail, path);
    g_hash_table_insert (est->model, entry->path, entry);
    g_hash_table_insert (hash_table, g_strdup (path), node);

    return node;
}

static void
free_path_hash (gpointer key,
        gpointer value,
        gpointer data)
{
    g_free (key);
}

static void
add_storage_to_table (ESummaryTable *est,
              StorageInfo *si,
              ESummary *summary)
{
    GHashTable *path_hash;
    GList *p;
    
    path_hash = g_hash_table_new (g_str_hash, g_str_equal);
        p = g_list_sort (si->folders, str_compare);

    for (; p; p = p->next) {
        ESummaryMailFolder *folder = p->data;

        insert_path_recur (est, si, path_hash, folder->path, summary->mail);
    }

    g_hash_table_foreach (path_hash, free_path_hash, NULL);
    g_hash_table_destroy (path_hash);
}

static void
make_toplevel (StorageInfo *si)
{
    if (si->toplevel != NULL) {
        return;
    }

    if (strcmp (si->name, "VFolders") == 0) {
        si->toplevel = g_strdup_printf ("vfolder:%s/evolution/vfolder",
                        g_get_home_dir ());
    } else if (strcmp (si->name, "Local Folders") == 0) {
        si->toplevel = g_strdup_printf ("file://%s/evolution/local",
                        g_get_home_dir ());
    } else {
        g_warning ("Unknown folder name... EEEEEEKEKEKEKEE!");
        si->toplevel = g_strdup ("Dunno");
    }
}

void
e_summary_mail_fill_list (ESummaryTable *est,
              ESummary *summary)
{
    ESummaryMail *mail;
    GSList *p;

    g_return_if_fail (IS_E_SUMMARY_TABLE (est));
    g_return_if_fail (IS_E_SUMMARY (summary));
    
    mail = summary->mail;
    if (mail == NULL) {
        return;
    }

    p = g_slist_sort (mail->storage_list, sort_storages);
    for (; p; p = p->next) {
        StorageInfo *si = p->data;

        if (si->toplevel == NULL) {
            make_toplevel (si);
        }
        
        add_storage_to_table (est, si, summary);
    }
}

const char *
e_summary_mail_uri_to_name (ESummary *summary,
                const char *uri)
{
    ESummaryMailFolder *folder;

    folder = g_hash_table_lookup (summary->mail->folders, uri);
    if (folder == NULL) {
        return NULL;
    } else {
        return folder->name;
    }
}
    
static void
free_folder (gpointer key,
         gpointer value,
         gpointer data)
{
    ESummaryMailFolder *folder = value;
    
    g_free (folder->name);
    g_free (folder->path);
    g_free (folder);
}

void
e_summary_mail_free (ESummary *summary)
{
    ESummaryMail *mail;

    g_return_if_fail (summary != NULL);
    g_return_if_fail (IS_E_SUMMARY (summary));

    mail = summary->mail;
    bonobo_object_release_unref (mail->folder_info, NULL);
    mail->folder_info = CORBA_OBJECT_NIL;

    gtk_signal_disconnect_by_func (GTK_OBJECT (mail->listener),
                       GTK_SIGNAL_FUNC (mail_change_notify), summary);
    bonobo_object_unref (BONOBO_OBJECT (mail->listener));

    g_hash_table_foreach (mail->folders, free_folder, NULL);
    g_hash_table_destroy (mail->folders);

    g_free (mail->html);

    gtk_signal_disconnect_by_func (GTK_OBJECT (mail->storage_listener),
                       GTK_SIGNAL_FUNC (new_folder_cb), summary);
    gtk_signal_disconnect_by_func (GTK_OBJECT (mail->storage_listener),
                       GTK_SIGNAL_FUNC (remove_folder_cb), summary);
    gtk_signal_disconnect_by_func (GTK_OBJECT (mail->storage_listener),
                       GTK_SIGNAL_FUNC (update_folder_cb), summary);

    g_free (mail);
    summary->mail = NULL;
}