2007-11-07 [colin] 3.0.2cvs124
[claws.git] / src / mimeview.c
index 6d087b36f67c7e56ace54302d639c93377591be8..35aa0ccc29d6fad0996a8707ac341ffa9686cf05 100644 (file)
@@ -4,7 +4,7 @@
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
@@ -13,8 +13,8 @@
  * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * 
  */
 
 #ifdef HAVE_CONFIG_H
@@ -41,6 +41,8 @@
 #include <gtk/gtkcontainer.h>
 #include <gtk/gtkbutton.h>
 #include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 
 #ifndef HAVE_APACHE_FNMATCH
 /* kludge: apache's fnmatch clashes with <regex.h>, don't include
 #include "gtk/logwindow.h"
 #include "timing.h"
 
+#ifdef MAEMO
+//#include <hildon-widgets/hildon-program.h>
+//#include <gtk/gtkmain.h>
+#include <libosso.h>
+#include <osso-mime.h>
+#endif
+
 typedef enum
 {
        COL_MIMETYPE = 0,
@@ -126,6 +135,7 @@ static void mimeview_open_part_with (MimeView       *mimeview,
                                         MimeInfo       *partinfo,
                                         gboolean        automatic);
 static void mimeview_select_next_part  (MimeView       *mimeview);
+static void mimeview_select_prev_part  (MimeView       *mimeview);
 static void mimeview_view_file         (const gchar    *filename,
                                         MimeInfo       *partinfo,
                                         const gchar    *cmd,
@@ -139,8 +149,6 @@ static void icon_selected               (MimeView       *mimeview,
 static gint icon_key_pressed            (GtkWidget      *button, 
                                         GdkEventKey    *event,
                                         MimeView       *mimeview);
-static void toggle_icon                        (GtkToggleButton *button,
-                                        MimeView       *mimeview);
 static void icon_list_append_icon      (MimeView       *mimeview, 
                                         MimeInfo       *mimeinfo);
 static void icon_list_create           (MimeView       *mimeview, 
@@ -148,10 +156,8 @@ static void icon_list_create               (MimeView       *mimeview,
 static void icon_list_clear            (MimeView       *mimeview);
 static void icon_list_toggle_by_mime_info (MimeView    *mimeview,
                                           MimeInfo     *mimeinfo);
-static gboolean icon_list_select_by_number(MimeView    *mimeview,
-                                          gint          number);
-static void mime_toggle_button_cb      (GtkWidget      *button,
-                                        MimeView       *mimeview);
+static gint mime_toggle_button_cb(GtkWidget *button, GdkEventButton *event,
+                                   MimeView *mimeview);
 static gboolean part_button_pressed    (MimeView       *mimeview, 
                                         GdkEventButton *event, 
                                         MimeInfo       *partinfo);
@@ -167,7 +173,9 @@ static void mimeview_launch_cb(MimeView *mimeview)
 static GtkItemFactoryEntry mimeview_popup_entries[] =
 {
        {N_("/_Open (l)"),                NULL, mimeview_launch_cb,       0, NULL},
+#ifndef MAEMO
        {N_("/Open _with (o)..."),        NULL, mimeview_open_with,       0, NULL},
+#endif
        {N_("/_Display as text (t)"),     NULL, mimeview_display_as_text, 0, NULL},
        {N_("/_Save as (y)..."),          NULL, mimeview_save_as,         0, NULL},
        {N_("/Save _all..."),             NULL, mimeview_save_all,        0, NULL},
@@ -182,6 +190,32 @@ static GtkTargetEntry mimeview_mime_types[] =
 GSList *mimeviewer_factories;
 GSList *mimeviews;
 
+static GdkCursor *hand_cursor = NULL;
+
+static gboolean mimeview_visi_notify(GtkWidget *widget,
+                                      GdkEventVisibility *event,
+                                      MimeView *mimeview)
+{
+       gdk_window_set_cursor(widget->window, hand_cursor);
+       return FALSE;
+}
+
+static gboolean mimeview_leave_notify(GtkWidget *widget,
+                                     GdkEventCrossing *event,
+                                     MimeView *mimeview)
+{
+       gdk_window_set_cursor(widget->window, NULL);
+       return FALSE;
+}
+
+static gboolean mimeview_enter_notify(GtkWidget *widget,
+                                     GdkEventCrossing *event,
+                                     MimeView *mimeview)
+{
+       gdk_window_set_cursor(widget->window, hand_cursor);
+       return FALSE;
+}
+
 MimeView *mimeview_create(MainWindow *mainwin)
 {
        MimeView *mimeview;
@@ -207,6 +241,9 @@ MimeView *mimeview_create(MainWindow *mainwin)
        gint n_entries;
        gint i;
 
+       if (!hand_cursor)
+               hand_cursor = gdk_cursor_new(GDK_HAND2);
+
        debug_print("Creating MIME view...\n");
        mimeview = g_new0(MimeView, 1);
 
@@ -261,16 +298,30 @@ MimeView *mimeview_create(MainWindow *mainwin)
        g_signal_connect(G_OBJECT(icon_scroll), "scroll_event",
                         G_CALLBACK(mimeview_scrolled), mimeview);
 
-       mime_toggle = gtk_toggle_button_new();
+       mime_toggle = gtk_event_box_new();
+       gtk_event_box_set_visible_window(GTK_EVENT_BOX(mime_toggle), FALSE);
+
+       g_signal_connect(G_OBJECT(mime_toggle), "visibility-notify-event",
+                        G_CALLBACK(mimeview_visi_notify), mimeview);
+       g_signal_connect(G_OBJECT(mime_toggle), "motion-notify-event",
+                        G_CALLBACK(mimeview_visi_notify), mimeview);
+       g_signal_connect(G_OBJECT(mime_toggle), "leave-notify-event",
+                        G_CALLBACK(mimeview_leave_notify), mimeview);
+       g_signal_connect(G_OBJECT(mime_toggle), "enter-notify-event",
+                        G_CALLBACK(mimeview_enter_notify), mimeview);
+
+       gtk_container_set_border_width(GTK_CONTAINER(mime_toggle), 2);
        gtk_widget_show(mime_toggle);
+       mimeview->ctree_mode = FALSE;
        arrow = gtk_arrow_new(GTK_ARROW_LEFT, GTK_SHADOW_NONE);
        gtk_widget_show(arrow);
        gtk_container_add(GTK_CONTAINER(mime_toggle), arrow);
-       g_signal_connect(G_OBJECT(mime_toggle), "toggled", 
+       g_signal_connect(G_OBJECT(mime_toggle), "button_release_event", 
                         G_CALLBACK(mime_toggle_button_cb), mimeview);
 
        icon_mainbox = gtk_vbox_new(FALSE, 0);
        gtk_widget_show(icon_mainbox);
+       gtk_widget_set_size_request(icon_mainbox, 32, -1);
        gtk_box_pack_start(GTK_BOX(icon_mainbox), mime_toggle, FALSE, FALSE, 0);
        gtk_box_pack_start(GTK_BOX(icon_mainbox), icon_scroll, TRUE, TRUE, 3);
        gtk_box_pack_end(GTK_BOX(icon_mainbox), scrollbutton, FALSE, FALSE, 0);
@@ -306,7 +357,9 @@ MimeView *mimeview_create(MainWindow *mainwin)
 
        gtk_widget_show(hbox);
        gtk_widget_hide(ctree_mainbox);
-
+#ifdef MAEMO
+       gtk_widget_set_size_request(mime_toggle, -1, arrow->requisition.height + 8);
+#endif
        mimeview->hbox          = hbox;
        mimeview->paned         = paned;
        mimeview->scrolledwin   = scrolledwin;
@@ -737,7 +790,7 @@ void mimeview_clear(MimeView *mimeview)
 }
 
 static void check_signature_cb(GtkWidget *widget, gpointer user_data);
-void mimeview_check_signature(MimeView *mimeview);
+static void mimeview_check_signature(MimeView *mimeview);
 static void display_full_info_cb(GtkWidget *widget, gpointer user_data);
 
 static void update_signature_noticeview(MimeView *mimeview, MimeInfo *mimeinfo, 
@@ -1008,7 +1061,7 @@ static void check_signature_cb(GtkWidget *widget, gpointer user_data)
 #endif
        noticeview_set_text(mimeview->siginfoview, _("Checking signature..."));
        GTK_EVENTS_FLUSH();
-#if (defined USE_PTHREAD && defined __GLIBC__ && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)))
+#if (defined USE_PTHREAD && ((defined __GLIBC__ && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3))) || !defined __GLIBC__))
        /* let's do it non-blocking */
        mimeview_check_sig_in_thread(mimeview);
        if (!mimeview->check_data) /* let's check syncronously */
@@ -1022,7 +1075,7 @@ static void check_signature_cb(GtkWidget *widget, gpointer user_data)
        }
 }
 
-void mimeview_check_signature(MimeView *mimeview)
+static void mimeview_check_signature(MimeView *mimeview)
 {
        check_signature_cb(NULL, mimeview);     
 }
@@ -1234,39 +1287,43 @@ void mimeview_pass_key_press_event(MimeView *mimeview, GdkEventKey *event)
 
 static void mimeview_select_next_part(MimeView *mimeview)
 {
-       gboolean is_next = FALSE;
+       GtkCTree *ctree = GTK_CTREE(mimeview->ctree);
+       GtkCTreeNode *node = mimeview->opened;
+       MimeInfo *partinfo = NULL;
+       
+skip:
+       node = GTK_CTREE_NODE_NEXT(node);
+       if (!node)
+               node = gtk_ctree_node_nth(GTK_CTREE(ctree), 0);
 
-       GList *child = gtk_container_children(GTK_CONTAINER(mimeview->icon_vbox));
-       for (; child != NULL; child = g_list_next(child)) {
-               if (GTK_IS_TOGGLE_BUTTON(child->data) &&  
-                   gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(child->data))) {
-                       is_next = TRUE;
-               } else if (GTK_IS_TOGGLE_BUTTON(child->data) &&
-                          is_next) {
-                       toggle_icon(GTK_TOGGLE_BUTTON(child->data), mimeview);
-                       gtk_toggle_button_set_active
-                               (GTK_TOGGLE_BUTTON(child->data), TRUE);
-                       icon_selected(mimeview, -1, 
-                               (MimeInfo *)g_object_get_data(G_OBJECT(child->data),
-                                     "partinfo"));
-                       is_next = FALSE;
-                       break;
-               }
+       if (node) {
+               partinfo = gtk_ctree_node_get_row_data(ctree, node);
+               if (partinfo->type == MIMETYPE_MULTIPART)
+                       goto skip;
+               gtk_sctree_unselect_all(GTK_SCTREE(ctree));
+               gtk_sctree_select(GTK_SCTREE(ctree), node);
+               icon_list_toggle_by_mime_info(mimeview, partinfo);
        }
-       if (is_next) {
-               /* we were on the last one, go to first */
-               child = gtk_container_children(GTK_CONTAINER(mimeview->icon_vbox));
-               for (; child != NULL; child = g_list_next(child)) {
-                       if (GTK_IS_TOGGLE_BUTTON(child->data)) {
-                               toggle_icon(GTK_TOGGLE_BUTTON(child->data), mimeview);
-                               gtk_toggle_button_set_active
-                                       (GTK_TOGGLE_BUTTON(child->data), TRUE);
-                               icon_selected(mimeview, -1, 
-                                       (MimeInfo *)g_object_get_data(G_OBJECT(child->data),
-                                               "partinfo"));
-                               break;
-                       }
-               }
+}
+
+static void mimeview_select_prev_part(MimeView *mimeview)
+{
+       GtkCTree *ctree = GTK_CTREE(mimeview->ctree);
+       GtkCTreeNode *node = mimeview->opened;
+       MimeInfo *partinfo = NULL;
+       
+skip:
+       node = GTK_CTREE_NODE_PREV(node);
+       if (!node)
+               node = gtk_ctree_node_nth(GTK_CTREE(ctree), GTK_CLIST(ctree)->rows - 1);
+
+       if (node) {
+               partinfo = gtk_ctree_node_get_row_data(ctree, node);
+               if (partinfo->type == MIMETYPE_MULTIPART)
+                       goto skip;
+               gtk_sctree_unselect_all(GTK_SCTREE(ctree));
+               gtk_sctree_select(GTK_SCTREE(ctree), node);
+               icon_list_toggle_by_mime_info(mimeview, partinfo);
        }
 }
 
@@ -1282,7 +1339,6 @@ static gint mimeview_key_pressed(GtkWidget *widget, GdkEventKey *event,
 {
        SummaryView *summaryview;
        GtkCTree *ctree = GTK_CTREE(widget);
-       GtkCTreeNode *node;
 
        if (!event) return FALSE;
        if (!mimeview->opened) return FALSE;
@@ -1297,13 +1353,9 @@ static gint mimeview_key_pressed(GtkWidget *widget, GdkEventKey *event,
                if (mimeview_scroll_page(mimeview, FALSE))
                        return TRUE;
 
-               node = GTK_CTREE_NODE_NEXT(mimeview->opened);
-               if (node) {
-                       gtk_sctree_unselect_all(GTK_SCTREE(ctree));
-                       gtk_sctree_select(GTK_SCTREE(ctree), node);
-                       return TRUE;
-               }
-               break;
+               mimeview_select_next_part(mimeview);
+               return TRUE;
+
        case GDK_BackSpace:
                mimeview_scroll_page(mimeview, TRUE);
                return TRUE;
@@ -1315,19 +1367,15 @@ static gint mimeview_key_pressed(GtkWidget *widget, GdkEventKey *event,
        case GDK_n:
        case GDK_N:
                BREAK_ON_MODIFIER_KEY();
-               if (!GTK_CTREE_NODE_NEXT(mimeview->opened)) break;
-               KEY_PRESS_EVENT_STOP();
-               g_signal_emit_by_name(G_OBJECT(ctree), "scroll_vertical",
-                                       GTK_SCROLL_STEP_FORWARD, 0.0);
+               mimeview_select_next_part(mimeview);
                return TRUE;
+
        case GDK_p:
        case GDK_P:
                BREAK_ON_MODIFIER_KEY();
-               if (!GTK_CTREE_NODE_PREV(mimeview->opened)) break;
-               KEY_PRESS_EVENT_STOP();
-               g_signal_emit_by_name(G_OBJECT(ctree), "scroll_vertical",
-                                       GTK_SCROLL_STEP_BACKWARD, 0.0);
+               mimeview_select_prev_part(mimeview);
                return TRUE;
+
        case GDK_y:
                BREAK_ON_MODIFIER_KEY();
                KEY_PRESS_EVENT_STOP();
@@ -1728,6 +1776,9 @@ static void mimeview_open_with(MimeView *mimeview)
        mimeview_open_part_with(mimeview, partinfo, FALSE);
 }
 
+#ifdef MAEMO
+osso_context_t *get_osso_context(void);
+#endif
 static void mimeview_open_part_with(MimeView *mimeview, MimeInfo *partinfo, gboolean automatic)
 {
        gchar *filename;
@@ -1735,6 +1786,11 @@ static void mimeview_open_part_with(MimeView *mimeview, MimeInfo *partinfo, gboo
        gchar *mime_command = NULL;
        gchar *content_type = NULL;
        gint err;
+#ifdef MAEMO
+       DBusConnection *dbusconn;
+       gchar *uri;
+       int r = 0;
+#endif
        g_return_if_fail(partinfo != NULL);
 
        filename = procmime_get_tmp_file_name(partinfo);
@@ -1746,7 +1802,7 @@ static void mimeview_open_part_with(MimeView *mimeview, MimeInfo *partinfo, gboo
                g_free(filename);
                return;
        }
-
+       
        if (!prefs_common.mime_open_cmd_history)
                prefs_common.mime_open_cmd_history =
                        add_history(NULL, prefs_common.mime_open_cmd);
@@ -1761,6 +1817,19 @@ static void mimeview_open_part_with(MimeView *mimeview, MimeInfo *partinfo, gboo
                        partinfo->subtype);
        }
        
+#ifdef MAEMO
+       if (content_type != NULL) {
+               uri = g_strconcat ("file://", filename, NULL);
+               dbusconn = osso_get_dbus_connection (get_osso_context());
+               r = osso_mime_open_file_with_mime_type (dbusconn, uri, content_type);
+               g_free(uri);
+       }
+       if (r != 1) {
+               alertpanel_error(_("No registered viewer for this file type."));
+       }
+       goto out;
+#endif
+       
        if ((partinfo->type == MIMETYPE_TEXT && !strcmp(partinfo->subtype, "html"))
        && prefs_common.uri_cmd && prefs_common.uri_cmd[0]) {
                mime_command = g_strdup(prefs_common.uri_cmd);
@@ -1792,16 +1861,14 @@ static void mimeview_open_part_with(MimeView *mimeview, MimeInfo *partinfo, gboo
                                 _("Enter the command line to open file:\n"
                                   "('%s' will be replaced with file name)"),
                                 mime_command ? mime_command : prefs_common.mime_open_cmd,
-                                prefs_common.mime_open_cmd_history,
-                                TRUE, &remember);
+                                prefs_common.mime_open_cmd_history, &remember);
                else
                        cmd = input_dialog_combo
                                (_("Open with"),
                                 _("Enter the command line to open file:\n"
                                   "('%s' will be replaced with file name)"),
                                 mime_command ? mime_command : prefs_common.mime_open_cmd,
-                                prefs_common.mime_open_cmd_history,
-                                TRUE);
+                                prefs_common.mime_open_cmd_history);
                if (cmd && remember) {
                        mailcap_update_default(content_type, cmd);
                }
@@ -1816,6 +1883,9 @@ static void mimeview_open_part_with(MimeView *mimeview, MimeInfo *partinfo, gboo
                prefs_common.mime_open_cmd_history =
                        add_history(prefs_common.mime_open_cmd_history, cmd);
        }
+#ifdef MAEMO
+out:
+#endif
        g_free(content_type);
        g_free(filename);
 }
@@ -1829,14 +1899,21 @@ static void mimeview_view_file(const gchar *filename, MimeInfo *partinfo,
                mimeview_open_part_with(mimeview, partinfo, TRUE);
        else {
                if ((p = strchr(cmd, '%')) && *(p + 1) == 's' &&
-                   !strchr(p + 2, '%'))
+                   !strchr(p + 2, '%')) {
                        g_snprintf(buf, sizeof(buf), cmd, filename);
-               else {
+                       if (!prefs_common.save_parts_readwrite)
+                               g_chmod(filename, S_IRUSR);
+                       else
+                               g_chmod(filename, S_IRUSR|S_IWUSR);
+               } else {
                        g_warning("MIME viewer command line is invalid: '%s'", cmd);
                        mimeview_open_part_with(mimeview, partinfo, FALSE);
                }
-               if (execute_command_line(buf, TRUE) != 0)
+               if (execute_command_line(buf, TRUE) != 0) {
+                       if (!prefs_common.save_parts_readwrite)
+                               g_chmod(filename, S_IRUSR|S_IWUSR);
                        mimeview_open_part_with(mimeview, partinfo, FALSE);
+               }
        }
 }
 
@@ -1884,11 +1961,9 @@ static gboolean icon_clicked_cb (GtkWidget *button, GdkEventButton *event, MimeV
        if (event->button == 1) {
                icon_selected(mimeview, num, partinfo);
                gtk_widget_grab_focus(button);
-               if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button))) {
-                       toggle_icon(GTK_TOGGLE_BUTTON(button), mimeview);
-               }
        }
        part_button_pressed(mimeview, event, partinfo);
+       icon_list_toggle_by_mime_info(mimeview, partinfo);
 
        return FALSE;
 }
@@ -1908,11 +1983,6 @@ void mimeview_select_mimepart_icon(MimeView *mimeview, MimeInfo *partinfo)
        icon_selected(mimeview, -1, partinfo);
 }
 
-#undef  KEY_PRESS_EVENT_STOP
-#define KEY_PRESS_EVENT_STOP() \
-        g_signal_stop_emission_by_name(G_OBJECT(button), \
-                                       "key_press_event");
-
 static gint icon_key_pressed(GtkWidget *button, GdkEventKey *event,
                             MimeView *mimeview)
 {
@@ -1930,19 +2000,11 @@ static gint icon_key_pressed(GtkWidget *button, GdkEventKey *event,
 
        switch (event->keyval) {
        case GDK_space:
-               if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button))) {
-                       /* stop the button being untoggled */
-                       KEY_PRESS_EVENT_STOP();
-                       if (mimeview_scroll_page(mimeview, FALSE))
-                               return TRUE;
-
-                       if (icon_list_select_by_number(mimeview, num + 1))
-                               return TRUE;
-               } else {
-                       icon_selected(mimeview, num, partinfo);
-                       toggle_icon(GTK_TOGGLE_BUTTON(button), mimeview);
+               if (mimeview_scroll_page(mimeview, FALSE))
                        return TRUE;
-               }
+
+               mimeview_select_next_part(mimeview);
+               return TRUE;
 
                break;
        case GDK_BackSpace:
@@ -1950,63 +2012,44 @@ static gint icon_key_pressed(GtkWidget *button, GdkEventKey *event,
                return TRUE;
        case GDK_Return:
        case GDK_KP_Enter:
-               if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button))) {
-                       KEY_PRESS_EVENT_STOP();
-                       mimeview_scroll_one_line(mimeview,
-                                                (event->state & GDK_MOD1_MASK) != 0);
-                       return TRUE;
-               } else {
-                       icon_selected(mimeview, num, partinfo);
-                       toggle_icon(GTK_TOGGLE_BUTTON(button), mimeview);
-                       return TRUE;
-               }
+               mimeview_scroll_one_line(mimeview,
+                                        (event->state & GDK_MOD1_MASK) != 0);
+               return TRUE;
 
        case GDK_n:
        case GDK_N:
                BREAK_ON_MODIFIER_KEY();
-               if (icon_list_select_by_number(mimeview, num + 1)) {
-                       KEY_PRESS_EVENT_STOP();
-                       return TRUE;
-               }
-               break;
+               mimeview_select_next_part(mimeview);
+               return TRUE;
                
        case GDK_p:
        case GDK_P:
                BREAK_ON_MODIFIER_KEY();
-               if (icon_list_select_by_number(mimeview, num - 1)) {
-                       KEY_PRESS_EVENT_STOP();
-                       return TRUE;
-               }
+               mimeview_select_prev_part(mimeview);
                break;
 
        case GDK_y:
                BREAK_ON_MODIFIER_KEY();
-               KEY_PRESS_EVENT_STOP();
                mimeview_save_as(mimeview);
                return TRUE;
        case GDK_t:
                BREAK_ON_MODIFIER_KEY();
-               KEY_PRESS_EVENT_STOP();
                mimeview_display_as_text(mimeview);
                return TRUE;    
        case GDK_l:
                BREAK_ON_MODIFIER_KEY();
-               KEY_PRESS_EVENT_STOP();
                mimeview_launch(mimeview, NULL);
                return TRUE;
        case GDK_o:
                BREAK_ON_MODIFIER_KEY();
-               KEY_PRESS_EVENT_STOP();
                mimeview_open_with(mimeview);
                return TRUE;
        case GDK_c:
                BREAK_ON_MODIFIER_KEY();
-               KEY_PRESS_EVENT_STOP();
                mimeview_check_signature(mimeview);
                return TRUE;
        case GDK_a:
                BREAK_ON_MODIFIER_KEY();
-               KEY_PRESS_EVENT_STOP();
                mimeview_select_next_part(mimeview);
                return TRUE;
        default:
@@ -2018,21 +2061,6 @@ static gint icon_key_pressed(GtkWidget *button, GdkEventKey *event,
        return summary_pass_key_press_event(summaryview, event);
 }
 
-static void toggle_icon(GtkToggleButton *button, MimeView *mimeview)
-{
-       GList *child;
-       
-       child = gtk_container_get_children(GTK_CONTAINER(mimeview->icon_vbox));
-       for (; child != NULL; child = g_list_next(child)) {
-               if (GTK_IS_TOGGLE_BUTTON(child->data) && 
-                   GTK_TOGGLE_BUTTON(child->data) != button &&
-                   gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(child->data)))
-                       gtk_toggle_button_set_active
-                               (GTK_TOGGLE_BUTTON(child->data),
-                                FALSE);
-       }
-}
-
 static gboolean icon_popup_menu(GtkWidget *widget, gpointer data)
 {
        MimeView *mimeview = (MimeView *)data;
@@ -2063,8 +2091,18 @@ static void icon_list_append_icon (MimeView *mimeview, MimeInfo *mimeinfo)
        
        vbox = mimeview->icon_vbox;
        mimeview->icon_count++;
-       button = gtk_toggle_button_new();
-       gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
+       button = gtk_event_box_new();
+
+       g_signal_connect(G_OBJECT(button), "visibility-notify-event",
+                        G_CALLBACK(mimeview_visi_notify), mimeview);
+       g_signal_connect(G_OBJECT(button), "motion-notify-event",
+                        G_CALLBACK(mimeview_visi_notify), mimeview);
+       g_signal_connect(G_OBJECT(button), "leave-notify-event",
+                        G_CALLBACK(mimeview_leave_notify), mimeview);
+       g_signal_connect(G_OBJECT(button), "enter-notify-event",
+                        G_CALLBACK(mimeview_enter_notify), mimeview);
+
+       gtk_container_set_border_width(GTK_CONTAINER(button), 2);
        g_object_set_data(G_OBJECT(button), "icon_number", 
                          GINT_TO_POINTER(mimeview->icon_count));
        g_object_set_data(G_OBJECT(button), "partinfo", 
@@ -2149,7 +2187,6 @@ static void icon_list_append_icon (MimeView *mimeview, MimeInfo *mimeinfo)
                                                          OVERLAY_NONE, 6, 3);
        }
        gtk_container_add(GTK_CONTAINER(button), pixmap);
-       
        if (!desc) {
                if (prefs_common.attach_desc)
                        desc = get_part_description(mimeinfo);
@@ -2203,6 +2240,10 @@ static void icon_list_append_icon (MimeView *mimeview, MimeInfo *mimeinfo)
        g_signal_connect(G_OBJECT(button), "drag_data_get",
                         G_CALLBACK(mimeview_drag_data_get), mimeview);
        gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);
+#ifdef MAEMO
+       gtk_widget_set_size_request(vbox, -1, pixmap->requisition.height + 8);
+       gtk_widget_set_size_request(button, -1, pixmap->requisition.height + 4);
+#endif
 
 }
 
@@ -2221,23 +2262,7 @@ static void icon_list_clear (MimeView *mimeview)
        mimeview->icon_count = 0;
        adj  = gtk_layout_get_vadjustment(GTK_LAYOUT(mimeview->icon_scroll));
        gtk_adjustment_set_value(adj, adj->lower);
-}
-
-static void icon_list_toggle_by_mime_info(MimeView     *mimeview,
-                                         MimeInfo      *mimeinfo)
-{
-       GList *child;
-       
-       child = gtk_container_children(GTK_CONTAINER(mimeview->icon_vbox));
-       for (; child != NULL; child = g_list_next(child)) {
-               if (GTK_IS_TOGGLE_BUTTON(child->data) &&  
-                   g_object_get_data(G_OBJECT(child->data),
-                                     "partinfo") == (gpointer)mimeinfo) {
-                       toggle_icon(GTK_TOGGLE_BUTTON(child->data), mimeview);
-                       gtk_toggle_button_set_active
-                               (GTK_TOGGLE_BUTTON(child->data), TRUE); 
-               }                                
-       }
+       gtk_adjustment_changed(adj);
 }
 
 /*!
@@ -2245,31 +2270,6 @@ static void icon_list_toggle_by_mime_info(MimeView       *mimeview,
  *
  *\return       true if the icon 'number' exists and was selected.
  */
-static gboolean icon_list_select_by_number(MimeView    *mimeview,
-                                          gint          number)
-{
-       GList *child;
-
-       if (number == 0) return FALSE;
-       child = gtk_container_children(GTK_CONTAINER(mimeview->icon_vbox));
-       for (; child != NULL; child = g_list_next(child)) {
-               if (GTK_IS_TOGGLE_BUTTON(child->data) &&  
-                   GPOINTER_TO_INT(g_object_get_data(G_OBJECT(child->data),
-                                       "icon_number")) == number) {
-                       icon_selected(mimeview, number,
-                                     (MimeInfo*)g_object_get_data(G_OBJECT(child->data),
-                                                                  "partinfo"));
-                       toggle_icon(GTK_TOGGLE_BUTTON(child->data), mimeview);
-                       gtk_toggle_button_set_active
-                               (GTK_TOGGLE_BUTTON(child->data), TRUE);
-                       gtk_widget_grab_focus(GTK_WIDGET(child->data));
-               
-                       return TRUE;
-               }                                
-       }
-       return FALSE;
-}
-
 static void icon_scroll_size_allocate_cb(GtkWidget *widget, 
                                         GtkAllocation *size, MimeView *mimeview)
 {
@@ -2311,14 +2311,43 @@ static void icon_list_create(MimeView *mimeview, MimeInfo *mimeinfo)
                gtk_widget_set_size_request(mimeview->icon_mainbox, 
                                            size.width, -1);
        }
+}
 
+static void icon_list_toggle_by_mime_info (MimeView    *mimeview,
+                                          MimeInfo     *mimeinfo)
+{
+       GList *child;
+       
+       child = gtk_container_children(GTK_CONTAINER(mimeview->icon_vbox));
+       for (; child != NULL; child = g_list_next(child)) {
+               if (!GTK_IS_EVENT_BOX(child->data))
+                       continue;
+               if(g_object_get_data(G_OBJECT(child->data),
+                                     "partinfo") == (gpointer)mimeinfo) {
+                       gboolean *highlight = NULL;
+                       GtkWidget *icon = gtk_bin_get_child(GTK_BIN(child->data));
+                       highlight = g_object_get_data(G_OBJECT(icon), "highlight");
+                       *highlight = TRUE;
+                       gtk_widget_queue_draw(icon);
+               } else {
+                       gint *highlight = NULL;
+                       GtkWidget *icon = gtk_bin_get_child(GTK_BIN(child->data));
+                       highlight = g_object_get_data(G_OBJECT(icon), "highlight");
+                       *highlight = FALSE;
+                       gtk_widget_queue_draw(icon);
+               }                        
+       }
 }
 
-static void mime_toggle_button_cb (GtkWidget *button, MimeView *mimeview) 
+static gint mime_toggle_button_cb(GtkWidget *button, GdkEventButton *event,
+                                   MimeView *mimeview)
 {
        gtk_widget_ref(button); 
 
-       if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button))) {
+       mimeview_leave_notify(button, NULL, NULL);
+
+       mimeview->ctree_mode = !mimeview->ctree_mode;
+       if (mimeview->ctree_mode) {
                gtk_arrow_set(GTK_ARROW(GTK_BIN(button)->child), GTK_ARROW_RIGHT, 
                                        GTK_SHADOW_NONE);
                gtk_widget_hide(mimeview->icon_mainbox);
@@ -2350,9 +2379,8 @@ static void mime_toggle_button_cb (GtkWidget *button, MimeView *mimeview)
 
                gtk_paned_set_gutter_size(GTK_PANED(mimeview->paned), 0);
        }
-       gtk_widget_grab_focus(button);
        gtk_widget_unref(button);
-
+       return TRUE;
 }
 
 void mimeview_update (MimeView *mimeview) {