when changing sort_key by clicking column header, preserve sort_type
[claws.git] / src / summaryview.c
index 9ce55586c9f50e40f53d169ab1d566d4f0f9671c..9bf442054fb200b51aa8f09fc40f0ec50abab383 100644 (file)
@@ -193,6 +193,8 @@ static void summary_mark_row_as_read        (SummaryView            *summaryview,
                                         GtkCMCTreeNode         *row);
 static void summary_mark_row_as_unread (SummaryView            *summaryview,
                                         GtkCMCTreeNode         *row);
+static gboolean summary_mark_all_read_confirm(gboolean ask_if_needed);
+static gboolean summary_mark_all_unread_confirm(gboolean ask_if_needed);
 static void summary_delete_row         (SummaryView            *summaryview,
                                         GtkCMCTreeNode         *row);
 static void summary_unmark_row         (SummaryView            *summaryview,
@@ -886,10 +888,10 @@ static void summary_set_fonts(SummaryView *summaryview)
                        }
                }
                bold_marked_style = gtk_style_copy(bold_style);
-               bold_marked_style->fg[GTK_STATE_NORMAL] =
+               bold_marked_style->text[GTK_STATE_NORMAL] =
                        summaryview->color_marked;
                bold_deleted_style = gtk_style_copy(bold_style);
-               bold_deleted_style->fg[GTK_STATE_NORMAL] =
+               bold_deleted_style->text[GTK_STATE_NORMAL] =
                        summaryview->color_dim;
        }
 
@@ -1279,7 +1281,7 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
 
                val = alertpanel(_("Process mark"),
                                 _("Some marks are left. Process them?"),
-                                GTK_STOCK_NO, GTK_STOCK_YES, GTK_STOCK_CANCEL);
+                                GTK_STOCK_NO, GTK_STOCK_YES, GTK_STOCK_CANCEL, ALERTFOCUS_FIRST);
                if (G_ALERTALTERNATE == val) {
                        summary_unlock(summaryview);
                        summary_execute(summaryview);
@@ -1766,7 +1768,11 @@ void summary_set_menu_sensitive(SummaryView *summaryview)
        gboolean sensitive;
        gint i;
 
+#ifndef GENERIC_UMPC
 #define N_ENTRIES 39
+#else
+#define N_ENTRIES 28
+#endif
        static struct {
                const gchar *entry;
                SensitiveCondMask cond;
@@ -1907,7 +1913,7 @@ void summary_select_prev_unread(SummaryView *summaryview)
                                val = alertpanel(_("No more unread messages"),
                                                 _("No unread message found. "
                                                   "Search from the end?"),
-                                                GTK_STOCK_NO, "+"GTK_STOCK_YES, NULL);
+                                                GTK_STOCK_NO, GTK_STOCK_YES, NULL, ALERTFOCUS_SECOND);
                                break;
                        case NEXTUNREADMSGDIALOG_ASSUME_YES:
                                val = G_ALERTALTERNATE;
@@ -1955,7 +1961,7 @@ void summary_select_next_unread(SummaryView *summaryview)
                                val = alertpanel(_("No more unread messages"),
                                                 _("No unread message found. "
                                                   "Go to next folder?"),
-                                                GTK_STOCK_NO, "+"GTK_STOCK_YES, NULL);
+                                                GTK_STOCK_NO, GTK_STOCK_YES, NULL, ALERTFOCUS_SECOND);
                                break;
                        case NEXTUNREADMSGDIALOG_ASSUME_YES:
                                val = G_ALERTALTERNATE;
@@ -1992,7 +1998,7 @@ void summary_select_prev_new(SummaryView *summaryview)
                                val = alertpanel(_("No more new messages"),
                                                 _("No new message found. "
                                                   "Search from the end?"),
-                                                GTK_STOCK_NO, "+"GTK_STOCK_YES, NULL);
+                                                GTK_STOCK_NO, GTK_STOCK_YES, NULL, ALERTFOCUS_SECOND);
                                break;
                        case NEXTUNREADMSGDIALOG_ASSUME_YES:
                                val = G_ALERTALTERNATE;
@@ -2040,7 +2046,7 @@ void summary_select_next_new(SummaryView *summaryview)
                                val = alertpanel(_("No more new messages"),
                                                 _("No new message found. "
                                                   "Go to next folder?"),
-                                                GTK_STOCK_NO, "+"GTK_STOCK_YES, NULL);
+                                                GTK_STOCK_NO, GTK_STOCK_YES, NULL, ALERTFOCUS_SECOND);
                                break;
                        case NEXTUNREADMSGDIALOG_ASSUME_YES:
                                val = G_ALERTALTERNATE;
@@ -2074,7 +2080,7 @@ void summary_select_prev_marked(SummaryView *summaryview)
                val = alertpanel(_("No more marked messages"),
                                 _("No marked message found. "
                                   "Search from the end?"),
-                                GTK_STOCK_NO, "+"GTK_STOCK_YES, NULL);
+                                GTK_STOCK_NO, GTK_STOCK_YES, NULL, ALERTFOCUS_SECOND);
                if (val != G_ALERTALTERNATE) return;
                node = summary_find_prev_flagged_msg(summaryview, NULL,
                                                     MSG_MARKED, TRUE);
@@ -2107,7 +2113,7 @@ void summary_select_next_marked(SummaryView *summaryview)
                                val = alertpanel(_("No more marked messages"),
                                                 _("No marked message found. "
                                                   "Go to next folder?"),
-                                                GTK_STOCK_NO, "+"GTK_STOCK_YES, NULL);
+                                                GTK_STOCK_NO, GTK_STOCK_YES, NULL, ALERTFOCUS_SECOND);
                                break;
                        case NEXTUNREADMSGDIALOG_ASSUME_YES:
                                val = G_ALERTALTERNATE;
@@ -2141,7 +2147,7 @@ void summary_select_prev_labeled(SummaryView *summaryview)
                val = alertpanel(_("No more labeled messages"),
                                 _("No labeled message found. "
                                   "Search from the end?"),
-                                GTK_STOCK_NO, "+"GTK_STOCK_YES, NULL);
+                                GTK_STOCK_NO, GTK_STOCK_YES, NULL, ALERTFOCUS_SECOND);
                if (val != G_ALERTALTERNATE) return;
                node = summary_find_prev_flagged_msg(summaryview, NULL,
                                                     MSG_CLABEL_FLAG_MASK, TRUE);
@@ -2170,7 +2176,7 @@ void summary_select_next_labeled(SummaryView *summaryview)
                val = alertpanel(_("No more labeled messages"),
                                 _("No labeled message found. "
                                   "Search from the beginning?"),
-                                GTK_STOCK_NO, "+"GTK_STOCK_YES, NULL);
+                                GTK_STOCK_NO, GTK_STOCK_YES, NULL, ALERTFOCUS_SECOND);
                if (val != G_ALERTALTERNATE) return;
                if (summaryview->sort_type == SORT_ASCENDING)
                        node = summary_find_next_flagged_msg(summaryview, NULL,
@@ -3468,10 +3474,19 @@ static inline void summary_set_header(SummaryView *summaryview, gchar *text[],
        
        to_text = msginfo->to ? msginfo->to : 
                   (msginfo->cc ? msginfo->cc :
-                    (msginfo->newsgroups ? msginfo->newsgroups : _("(No Recipient)")
+                    (msginfo->newsgroups ? msginfo->newsgroups : NULL
                     )
                   );
 
+       if (!to_text)
+               to_text = _("(No Recipient)");
+       else {
+               if (prefs_common.summary_from_show == SHOW_NAME)
+                       to_text = procheader_get_fromname(to_text);
+               else if (prefs_common.summary_from_show == SHOW_ADDR)
+                       extract_address(to_text);
+       }
+
        text[col_pos[S_COL_TO]] = to_text;
        if (!should_swap) {
                text[col_pos[S_COL_FROM]] = from_text;
@@ -4129,6 +4144,11 @@ void summary_mark_as_read(SummaryView *summaryview)
 
        if (summary_is_locked(summaryview))
                return;
+
+       if ((summaryview->folder_item->total_msgs == (gint)g_list_length(GTK_CMCLIST(ctree)->selection))
+                && !summary_mark_all_read_confirm(TRUE))
+               return;
+
        START_LONG_OPERATION(summaryview, FALSE);
        folder_item_set_batch(summaryview->folder_item, TRUE);
        for (cur = GTK_CMCLIST(ctree)->selection; cur != NULL && cur->data != NULL; cur = cur->next)
@@ -4148,6 +4168,11 @@ void summary_mark_as_unread(SummaryView *summaryview)
 
        if (summary_is_locked(summaryview))
                return;
+
+       if ((summaryview->folder_item->total_msgs == (gint)g_list_length(GTK_CMCLIST(ctree)->selection))
+                && !summary_mark_all_unread_confirm(TRUE))
+               return;
+
        START_LONG_OPERATION(summaryview, FALSE);
        folder_item_set_batch(summaryview->folder_item, TRUE);
        for (cur = GTK_CMCLIST(ctree)->selection; cur != NULL && cur->data != NULL; cur = cur->next)
@@ -4193,29 +4218,36 @@ void summary_msgs_unlock(SummaryView *summaryview)
        summary_status_show(summaryview);
 }
 
-void summary_mark_all_read(SummaryView *summaryview, gboolean ask_if_needed)
+static gboolean summary_mark_all_read_confirm(gboolean ask_if_needed)
 {
-       GtkCMCTree *ctree = GTK_CMCTREE(summaryview->ctree);
-       GtkCMCTreeNode *node;
-       AlertValue val;
-       gboolean froze = FALSE;
-
        /* ask_if_needed is FALSE when user-asking is performed by caller,
           commonly when the caller is a mark-as-read-recursive func */
        if (ask_if_needed && prefs_common.ask_mark_all_read) {
-               val = alertpanel_full(_("Mark all as read"),
+               AlertValue val = alertpanel_full(_("Mark all as read"),
                          _("Do you really want to mark all mails in this folder as read?"),
-                         GTK_STOCK_NO, GTK_STOCK_YES, NULL,
-                         TRUE, NULL, ALERT_QUESTION, G_ALERTDEFAULT);
+                         GTK_STOCK_NO, GTK_STOCK_YES, NULL, ALERTFOCUS_FIRST,
+                         TRUE, NULL, ALERT_QUESTION);
 
                if ((val & ~G_ALERTDISABLE) != G_ALERTALTERNATE)
-                       return;
+                       return FALSE;
                else if (val & G_ALERTDISABLE)
                        prefs_common.ask_mark_all_read = FALSE;
        }
+       return TRUE;
+}
+
+void summary_mark_all_read(SummaryView *summaryview, gboolean ask_if_needed)
+{
+       GtkCMCTree *ctree = GTK_CMCTREE(summaryview->ctree);
+       GtkCMCTreeNode *node;
+       gboolean froze = FALSE;
        
        if (summary_is_locked(summaryview))
                return;
+
+       if (!summary_mark_all_read_confirm(ask_if_needed))
+               return;
+
        START_LONG_OPERATION(summaryview, TRUE);
        folder_item_set_batch(summaryview->folder_item, TRUE);
        for (node = GTK_CMCTREE_NODE(GTK_CMCLIST(ctree)->row_list); node != NULL;
@@ -4232,29 +4264,36 @@ void summary_mark_all_read(SummaryView *summaryview, gboolean ask_if_needed)
        summary_status_show(summaryview);
 }
 
-void summary_mark_all_unread(SummaryView *summaryview, gboolean ask_if_needed)
+static gboolean summary_mark_all_unread_confirm(gboolean ask_if_needed)
 {
-       GtkCMCTree *ctree = GTK_CMCTREE(summaryview->ctree);
-       GtkCMCTreeNode *node;
-       AlertValue val;
-       gboolean froze = FALSE;
-
        /* ask_if_needed is FALSE when user-asking is performed by caller,
           commonly when the caller is a mark-as-unread-recursive func */
        if (ask_if_needed && prefs_common.ask_mark_all_read) {
-               val = alertpanel_full(_("Mark all as unread"),
+               AlertValue val = alertpanel_full(_("Mark all as unread"),
                          _("Do you really want to mark all mails in this folder as unread?"),
-                         GTK_STOCK_NO, GTK_STOCK_YES, NULL,
-                         TRUE, NULL, ALERT_QUESTION, G_ALERTDEFAULT);
+                         GTK_STOCK_NO, GTK_STOCK_YES, NULL, ALERTFOCUS_FIRST,
+                         TRUE, NULL, ALERT_QUESTION);
 
                if ((val & ~G_ALERTDISABLE) != G_ALERTALTERNATE)
-                       return;
+                       return FALSE;
                else if (val & G_ALERTDISABLE)
                        prefs_common.ask_mark_all_read = FALSE;
        }
+       return TRUE;
+}
+
+void summary_mark_all_unread(SummaryView *summaryview, gboolean ask_if_needed)
+{
+       GtkCMCTree *ctree = GTK_CMCTREE(summaryview->ctree);
+       GtkCMCTreeNode *node;
+       gboolean froze = FALSE;
        
        if (summary_is_locked(summaryview))
                return;
+
+       if (!summary_mark_all_unread_confirm(ask_if_needed))
+               return;
+
        START_LONG_OPERATION(summaryview, TRUE);
        folder_item_set_batch(summaryview->folder_item, TRUE);
        for (node = GTK_CMCTREE_NODE(GTK_CMCLIST(ctree)->row_list); node != NULL;
@@ -4377,7 +4416,7 @@ static gboolean check_permission(SummaryView *summaryview, MsgInfo * msginfo)
                }
 
                if (!found) {
-                       alertpanel_error(_("You're not the author of the article.\n"));
+                       alertpanel_error(_("You're not the author of the article."));
                }
                
                return found;
@@ -4465,14 +4504,14 @@ void summary_delete(SummaryView *summaryview)
 
        if (!prefs_common.live_dangerously) {
                gchar *buf = NULL;
-               int num = g_list_length(GTK_CMCLIST(summaryview->ctree)->selection);
+               guint num = g_list_length(GTK_CMCLIST(summaryview->ctree)->selection);
                buf = g_strdup_printf(ngettext(
                        "Do you really want to delete the selected message?",
                        "Do you really want to delete the %d selected messages?", num),
                        num);
                aval = alertpanel(ngettext("Delete message", "Delete messages", num),
                                  buf,
-                                 GTK_STOCK_CANCEL, "+"GTK_STOCK_DELETE, NULL);
+                                 GTK_STOCK_CANCEL, GTK_STOCK_DELETE, NULL, ALERTFOCUS_SECOND);
                g_free(buf);
                if (aval != G_ALERTALTERNATE) {
                        END_LONG_OPERATION(summaryview);
@@ -4819,11 +4858,26 @@ void summary_add_address(SummaryView *summaryview)
 
 void summary_select_all(SummaryView *summaryview)
 {
+       GtkCMCTreeNode *node;
+
        if (!summaryview->folder_item) return;
 
+       if (GTK_CMCLIST(summaryview->ctree)->focus_row < 0) {
+               /* If no row is selected, select (but do not open) the first
+                * row, to get summaryview into correct state for selecting all. */
+               debug_print("summary_select_all: no row selected, selecting first one\n");
+               if (GTK_CMCLIST(summaryview->ctree)->row_list != NULL) {
+                       node = gtk_cmctree_node_nth(GTK_CMCTREE(summaryview->ctree), 0);
+                       summary_select_node(summaryview, node, FALSE);
+               }
+       }
+
+       /* Now select all rows while locking the summaryview for
+        * faster performance. */
        summary_lock(summaryview);
        gtk_cmclist_select_all(GTK_CMCLIST(summaryview->ctree));
        summary_unlock(summaryview);
+
        summary_status_show(summaryview);
 }
 
@@ -4912,8 +4966,8 @@ void summary_save_as(SummaryView *summaryview)
        if (is_file_exist(dest)) {
                aval = alertpanel(_("Append or Overwrite"),
                                  _("Append or overwrite existing file?"),
-                                 _("_Append"), _("_Overwrite"),
-                                 GTK_STOCK_CANCEL);
+                                 _("_Append"), _("_Overwrite"), GTK_STOCK_CANCEL,
+                                       ALERTFOCUS_FIRST);
                if (aval != 0 && aval != 1)
                        return;
        }
@@ -4958,8 +5012,8 @@ void summary_print(SummaryView *summaryview)
                                       "want to continue?"), 
                                       g_list_length(clist->selection));
        if (g_list_length(clist->selection) > 9
-       &&  alertpanel(_("Warning"), msg, GTK_STOCK_CANCEL, "+" GTK_STOCK_YES, NULL)
-           != G_ALERTALTERNATE) {
+       &&  alertpanel(_("Warning"), msg, GTK_STOCK_CANCEL, GTK_STOCK_YES,
+               NULL, ALERTFOCUS_SECOND) != G_ALERTALTERNATE) {
                g_free(msg);
                return;
        }
@@ -5697,7 +5751,8 @@ static gboolean summary_filter_get_mode(void)
                        _("Filtering"),
                        _("There are some filtering rules that belong to an account.\n"
                          "Please choose what to do with these rules:"),
-                       GTK_STOCK_CANCEL, _("_Filter"), NULL, TRUE, G_ALERTALTERNATE, vbox);
+                       GTK_STOCK_CANCEL, _("_Filter"), NULL, ALERTFOCUS_SECOND,
+                       TRUE, vbox);
 
        if ((val & ~G_ALERTDISABLE) != G_ALERTALTERNATE) {
                return FALSE;
@@ -5857,7 +5912,7 @@ static void summary_colorlabel_menu_item_activate_cb(GtkWidget *widget,
 }
 
 /* summary_set_colorlabel_color() - labelcolor parameter is the color *flag*
- * for the messsage; not the color index */
+ * for the message; not the color index */
 void summary_set_colorlabel_color(GtkCMCTree *ctree, GtkCMCTreeNode *node,
                                  guint labelcolor)
 {
@@ -5876,22 +5931,22 @@ void summary_set_colorlabel_color(GtkCMCTree *ctree, GtkCMCTreeNode *node,
        if (color_index < 0 || color_index >= N_COLOR_LABELS) {
                if (!prev_style) return;
                style = gtk_style_copy(prev_style);
-               color = ctree_style->fg[GTK_STATE_NORMAL];
-               style->fg[GTK_STATE_NORMAL] = color;
-               color = ctree_style->fg[GTK_STATE_SELECTED];
-               style->fg[GTK_STATE_SELECTED] = color;
+               color = ctree_style->text[GTK_STATE_NORMAL];
+               style->text[GTK_STATE_NORMAL] = color;
+               color = ctree_style->text[GTK_STATE_SELECTED];
+               style->text[GTK_STATE_SELECTED] = color;
        } else {
                if (prev_style)
                        style = gtk_style_copy(prev_style);
                else
                        style = gtk_style_copy(ctree_style);
                color = colorlabel_get_color(color_index);
-               style->fg[GTK_STATE_NORMAL] = color;
+               style->text[GTK_STATE_NORMAL] = color;
                /* get the average of label color and selected fg color
                   for visibility */
-               style->fg[GTK_STATE_SELECTED].red   = (color.red   + 3*ctree_style->fg[GTK_STATE_SELECTED].red  ) / 4;
-               style->fg[GTK_STATE_SELECTED].green = (color.green + 3*ctree_style->fg[GTK_STATE_SELECTED].green) / 4;
-               style->fg[GTK_STATE_SELECTED].blue  = (color.blue  + 3*ctree_style->fg[GTK_STATE_SELECTED].blue ) / 4;
+               style->text[GTK_STATE_SELECTED].red   = (color.red   + 3*ctree_style->text[GTK_STATE_SELECTED].red  ) / 4;
+               style->text[GTK_STATE_SELECTED].green = (color.green + 3*ctree_style->text[GTK_STATE_SELECTED].green) / 4;
+               style->text[GTK_STATE_SELECTED].blue  = (color.blue  + 3*ctree_style->text[GTK_STATE_SELECTED].blue ) / 4;
        }
 
        gtk_cmctree_node_set_row_style(ctree, node, style);
@@ -5918,6 +5973,54 @@ void summary_set_colorlabel(SummaryView *summaryview, guint labelcolor,
        GList *cur;
        gboolean froze = FALSE;
 
+       if (prefs_common.ask_override_colorlabel) {
+               GtkCMCTree *ctree = GTK_CMCTREE(summaryview->ctree);
+               gboolean ask = FALSE;
+               AlertValue val;
+               guint color;
+               gboolean already_this_color_everywhere = TRUE;
+
+               /* if clearing color labels (applying 'none', 0):
+                   - ask if at least one message has a non-0 color label set
+                  if applying a non-0 color label:
+                   - ask if at least one of the selected messages has a non-0 color label different
+                         from the one we want to apply.
+                   - don't ask if all messages have the same color label as the one we're applying
+               */
+               for (cur = GTK_CMCLIST(ctree)->selection;
+                        !ask && cur != NULL && cur->data != NULL;
+                        cur = cur->next) {
+                       MsgInfo *msginfo = gtk_cmctree_node_get_row_data(ctree, GTK_CMCTREE_NODE(cur->data));
+                       if (msginfo) {
+                               color = MSG_GET_COLORLABEL_VALUE(msginfo->flags);
+                               if (labelcolor == 0) {
+                                       /* clearing color labels */
+                                       ask = (color != 0);
+                               } else {
+                                       already_this_color_everywhere &= (color == labelcolor);
+                                       ask = ((color != 0) && (color != labelcolor)) && !already_this_color_everywhere;
+                               }
+                       }
+               }
+
+               if (ask) {
+                       gchar *msg;
+
+                       if (labelcolor == 0)
+                               msg = _("Do you really want to reset the color label of all selected messages?");
+                       else
+                               msg = _("Do you really want to apply this color label to all selected messages?");
+                       val = alertpanel_full(_("Set color label"), msg,
+                                 GTK_STOCK_NO, GTK_STOCK_YES, NULL, ALERTFOCUS_FIRST,
+                                 TRUE, NULL, ALERT_QUESTION);
+
+                       if ((val & ~G_ALERTDISABLE) != G_ALERTALTERNATE)
+                               return;
+                       else if (val & G_ALERTDISABLE)
+                               prefs_common.ask_override_colorlabel = FALSE;
+               }
+       }
+
        START_LONG_OPERATION(summaryview, FALSE);
        for (cur = GTK_CMCLIST(ctree)->selection; cur != NULL && cur->data != NULL; cur = cur->next)
                summary_set_row_colorlabel(summaryview,
@@ -7188,7 +7291,7 @@ static void summary_sort_by_column_click(SummaryView *summaryview,
                             summaryview->sort_type == SORT_ASCENDING
                             ? SORT_DESCENDING : SORT_ASCENDING);
        else
-               summary_sort(summaryview, sort_key, SORT_ASCENDING);
+               summary_sort(summaryview, sort_key, summaryview->sort_type);
 
        node = GTK_CMCTREE_NODE(GTK_CMCLIST(summaryview->ctree)->row_list);