[Xfce4-commits] <postler:master> Move actions into action bar, check via check box

Christian Dywan noreply at xfce.org
Sun Jul 17 05:34:04 CEST 2011


Updating branch refs/heads/master
         to cf5c974efe2a641efa76090d9ac14f3fe3fdacc5 (commit)
       from 373a0c661e31c465957c70f509502189607edc41 (commit)

commit cf5c974efe2a641efa76090d9ac14f3fe3fdacc5
Author: Christian Dywan <christian at twotoasts.de>
Date:   Sun Jul 17 01:26:29 2011 +0200

    Move actions into action bar, check via check box

 postler/postler-bureau.vala             |   85 +++++++++++++++++-------
 postler/postler-cellrenderertoggle.vala |   16 +++++
 postler/postler-messages.vala           |  110 ++++++++++++++++++++++--------
 3 files changed, 157 insertions(+), 54 deletions(-)

diff --git a/postler/postler-bureau.vala b/postler/postler-bureau.vala
index 294bcc2..f46e397 100644
--- a/postler/postler-bureau.vala
+++ b/postler/postler-bureau.vala
@@ -20,6 +20,7 @@ public class Postler.Bureau : Gtk.Window {
 
     Gtk.VBox shelf;
     Gtk.Toolbar toolbar;
+    Gtk.Toolbar message_actions;
     Elementary.SearchEntry search;
     Gtk.Toolbar search_options;
     uint search_timeout = 0;
@@ -54,6 +55,7 @@ public class Postler.Bureau : Gtk.Window {
                     <menuitem action="MessageArchive"/>
                     <menuitem action="MessageJunk"/>
                     <menuitem action="MessageDelete"/>
+                    <menuitem action="CheckedCancel"/>
                     <separator/>
                     <menuitem action="MessageNextUnread"/>
                     <menuitem action="MessagePreviousUnread"/>
@@ -78,9 +80,6 @@ public class Postler.Bureau : Gtk.Window {
                 <toolitem action="MessageNew"/>
                 <separator/>
                 <toolitem action="MessageReplyAll"/>
-                <toolitem action="MessageArchive"/>
-                <toolitem action="MessageJunk"/>
-                <toolitem action="MessageDelete"/>
                 <separator expand="true"/>
             </toolbar>
             <popup name="view">
@@ -90,6 +89,13 @@ public class Postler.Bureau : Gtk.Window {
                 <menuitem action="Shortcuts"/>
                 <menuitem action="About"/>
             </popup>
+            <toolbar name="message_actions">
+                <toolitem action="MessageArchive"/>
+                <toolitem action="MessageJunk"/>
+                <toolitem action="MessageDelete"/>
+                <separator expand="true"/>
+                <toolitem action="CheckedCancel"/>
+            </toolbar>
             <toolbar name="search_options">
                 <toolitem action="SearchAny"/>
                 <toolitem action="SearchSubject"/>
@@ -137,20 +143,24 @@ public class Postler.Bureau : Gtk.Window {
 
     void action_archive () {
         if (messages.selected_folder_type != FolderType.ARCHIVE)
-            messages.move_selected (FolderType.ARCHIVE);
+            messages.move_checked (FolderType.ARCHIVE);
         else
-            messages.move_selected (FolderType.INBOX);
+            messages.move_checked (FolderType.INBOX);
     }
 
     void action_junk () {
         if (messages.selected_folder_type != FolderType.JUNK)
-            messages.move_selected (FolderType.JUNK);
+            messages.move_checked (FolderType.JUNK);
         else
-            messages.move_selected (FolderType.INBOX);
+            messages.move_checked (FolderType.INBOX);
     }
 
     void action_delete () {
-        messages.delete_selected ();
+        messages.delete_checked ();
+    }
+
+    void action_checked_cancel () {
+        messages.uncheck_all ();
     }
 
     void action_previous_unread () {
@@ -184,10 +194,14 @@ public class Postler.Bureau : Gtk.Window {
         assert_not_reached ();
     }
 
+    void context_bar_toggle (Gtk.Widget current) {
+        folders.visible = search_options.visible = message_actions.visible = false;
+        current.show ();
+    }
+
     void search_apply () {
         if (search.get_text () == search.hint_string || search.get_text ().strip () == "") {
-            search_options.hide ();
-            folders.show ();
+            context_bar_toggle (folders);
             var action = actions.get_action ("SearchSubject") as Gtk.RadioAction;
             action.set_current_value (0);
             messages.populate (folders.selected_location);
@@ -195,8 +209,7 @@ public class Postler.Bureau : Gtk.Window {
         }
 
         messages.populate (get_search_uri ());
-        folders.hide ();
-        search_options.show ();
+        context_bar_toggle (search_options);
     }
 
     void action_save_search () {
@@ -354,6 +367,8 @@ public class Postler.Bureau : Gtk.Window {
           N_("Mark message as junk"), action_junk },
         { "MessageDelete", Gtk.STOCK_DELETE, null, "<Ctrl>d",
           N_("Delete message"), action_delete },
+        { "CheckedCancel", Gtk.STOCK_CANCEL, null, "Escape",
+          N_("Cancel operation on messages"), action_checked_cancel },
         { "MessagePreviousUnread", null, N_("_Previous Unread Message"), "<Alt>Up",
           N_("Go to the previous unread message"), action_previous_unread },
         { "MessageNextUnread", null, N_("_Next Unread Message"), "<Alt>Down",
@@ -434,7 +449,7 @@ public class Postler.Bureau : Gtk.Window {
             infobar.response.connect ((response) => {
                 switch (response) {
                 case 1:
-                    messages.move_selected (FolderType.INBOX);
+                    messages.move_checked (FolderType.INBOX);
                     break;
                 case 2:
                     folders.empty_folder (messages.location);
@@ -444,15 +459,15 @@ public class Postler.Bureau : Gtk.Window {
                     assert_not_reached ();
                 }
             });
-            messages.notify["selected-message"].connect ((object, pspec) => {
+            messages.notify["checked-messages"].connect ((object, pspec) => {
                 infobar.set_response_sensitive (1,
-                    messages.get_selection ().count_selected_rows () > 0);
+                    messages.checked_messages.nth_data (0) != null);
             });
             trash_action_infobar = infobar;
         }
 
         trash_action_infobar.set_response_sensitive (1,
-            messages.get_selection ().count_selected_rows () > 0);
+            messages.checked_messages.nth_data (0) != null);
         trash_action_infobar.show ();
     }
 
@@ -713,6 +728,22 @@ public class Postler.Bureau : Gtk.Window {
                 trash_action_infobar.hide ();
         });
 
+        message_actions = ui.get_widget ("/message_actions") as Gtk.Toolbar;
+        message_actions.icon_size = Gtk.IconSize.SMALL_TOOLBAR;
+        #if HAVE_GTK3
+        message_actions.get_style_context ().add_class ("secondary-toolbar");
+        #endif
+        /* Implement mnemonics for search buttons */
+        foreach (var button in message_actions.get_children ()) {
+            if (button is Gtk.ToolButton) {
+                var toolbutton = button as Gtk.ToolButton;
+                toolbutton.is_important = true;
+                var label = new Gtk.Label.with_mnemonic (toolbutton.label);
+                toolbutton.label_widget = label;
+            }
+        }
+        shelf.pack_start (message_actions, false, false, 0);
+
         search_options = ui.get_widget ("/search_options") as Gtk.Toolbar;
         #if HAVE_GTK3
         search_options.get_style_context ().add_class ("secondary-toolbar");
@@ -744,11 +775,19 @@ public class Postler.Bureau : Gtk.Window {
             Postler.Messages messages = object as Postler.Messages;
             bool state = messages.selected_message != null;
             actions.get_action ("MessageFlag").sensitive = state;
+        });
+        messages.notify["checked-messages"].connect ((object, pspec) => {
+            Postler.Messages messages = object as Postler.Messages;
+            bool state = messages.checked_messages.nth_data (0) != null;
             actions.get_action ("MessageArchive").sensitive = state;
-            var action = actions.get_action ("MessageJunk");
-            action.sensitive = state;
-            action = actions.get_action ("MessageDelete");
-            action.sensitive = state;
+            actions.get_action ("MessageJunk").sensitive = state;
+            actions.get_action ("MessageDelete").sensitive = state;
+            if (state)
+                context_bar_toggle (message_actions);
+            else if (search.get_text () == search.hint_string || search.get_text ().strip () == "")
+                context_bar_toggle (folders);
+            else
+                context_bar_toggle (search_options);
         });
         var scrolled = new Postler.ScrolledWindow (messages);
         messages_box.pack_start (scrolled, true, true, 0);
@@ -876,7 +915,6 @@ public class Postler.Bureau : Gtk.Window {
             return false;
         });
         shelf.show_all ();
-        search_options.hide ();
 
         messages.set_headers_visible (false);
         messages.set_rules_hint (true);
@@ -889,11 +927,10 @@ public class Postler.Bureau : Gtk.Window {
         accounts.remove_info.connect_after (account_check);
         account_check (null);
 
+        folders.select_folder ("file://%/INBOX/%");
         /* Never focus hidden widgets: assertion `WIDGET_REALIZED_FOR_EVENT */
-        if (messages.visible) {
+        if (messages.visible)
             messages.grab_focus ();
-            folders.select_folder ("file://%/INBOX/%");
-        }
 
         if (Environment.get_variable ("POSTLER_MOCKUP") != null) {
             progressbar.fraction = 0.7;
diff --git a/postler/postler-cellrenderertoggle.vala b/postler/postler-cellrenderertoggle.vala
index 1e37e8a..a8ec3d8 100644
--- a/postler/postler-cellrenderertoggle.vala
+++ b/postler/postler-cellrenderertoggle.vala
@@ -15,9 +15,15 @@ public class Postler.CellRendererToggle : Gtk.CellRendererToggle {
 
     public CellRendererToggle () {
     }
+
     public override void get_size (Gtk.Widget widget, Gdk.Rectangle? cell_area,
         out int x_offset, out int y_offset, out int width, out int height) {
 
+        if (prelight_stock_id == null && stock_id == null) {
+            base.get_size (widget, cell_area, out x_offset, out y_offset, out width, out height);
+            return;
+        }
+
         int icon_width, icon_height;
         int xpad, ypad;
         Gtk.icon_size_lookup_for_settings (widget.get_settings (),
@@ -55,11 +61,21 @@ public class Postler.CellRendererToggle : Gtk.CellRendererToggle {
         Gdk.Rectangle expose_area, Gdk.Rectangle cell_area,
         Gtk.CellRendererState flags) {
         Gdk.Rectangle background_area = expose_area;
+
+        if (prelight_stock_id == null && stock_id == null) {
+            base.render (context, widget, expose_area, cell_area, flags);
+            return;
+        }
 #else
     public override void render (Gdk.Window window, Gtk.Widget widget,
         Gdk.Rectangle background_area, Gdk.Rectangle cell_area,
         Gdk.Rectangle expose_area, Gtk.CellRendererState flags) {
         var context = Gdk.cairo_create (window);
+
+        if (prelight_stock_id == null && stock_id == null) {
+            base.render (window, widget, background_area, cell_area, expose_area, flags);
+            return;
+        }
 #endif
 
         Gdk.cairo_rectangle (context, expose_area);
diff --git a/postler/postler-messages.vala b/postler/postler-messages.vala
index 4ac847b..7e23168 100644
--- a/postler/postler-messages.vala
+++ b/postler/postler-messages.vala
@@ -20,6 +20,7 @@ public class Postler.Messages : Gtk.TreeView {
     public FolderType selected_folder_type { get; private set; }
     public string? location { get; private set; }
     public Message? selected_message { get; private set; }
+    public unowned GLib.List<Message>? checked_messages { get; private set; }
 
     enum Columns {
         MESSAGE
@@ -54,6 +55,14 @@ public class Postler.Messages : Gtk.TreeView {
         return fallback.str;
     }
 
+    void render_checkbox (Gtk.CellLayout layout, Gtk.CellRenderer cell,
+        Gtk.TreeModel model, Gtk.TreeIter iter) {
+
+        Message message;
+        model.get (iter, Columns.MESSAGE, out message);
+        cell.set ("active", message.get_data<bool> ("checked"));
+    }
+
     void render_flag (Gtk.CellLayout layout, Gtk.CellRenderer cell,
         Gtk.TreeModel model, Gtk.TreeIter iter) {
         Message message;
@@ -110,6 +119,27 @@ public class Postler.Messages : Gtk.TreeView {
         renderer.text = message.excerpt + "…";
     }
 
+    void renderer_checkbox_toggled (Gtk.CellRendererToggle renderer,
+                                    string                 path) {
+        Gtk.TreeIter iter = Gtk.TreeIter ();
+        if (!model.get_iter_from_string (out iter, path))
+            return;
+
+        Message message;
+        model.get (iter, Columns.MESSAGE, out message);
+        if (message.get_data<bool> ("checked")) {
+            checked_messages.remove (message);
+            message.set_data ("checked", false);
+        }
+        else {
+            checked_messages.append (message);
+            message.set_data ("checked", true);
+            message.set_data ("row", new Gtk.TreeRowReference (
+                model, model.get_path (iter)));
+        }
+        notify_property ("checked-messages");
+    }
+
     void renderer_flag_toggled (Gtk.CellRendererToggle renderer,
                                 string                 path) {
         Gtk.TreeIter iter = Gtk.TreeIter ();
@@ -151,13 +181,25 @@ public class Postler.Messages : Gtk.TreeView {
 
         var column = new Gtk.TreeViewColumn ();
         column.set_sizing (Gtk.TreeViewColumnSizing.FIXED);
+        column.set_title (_("Selected"));
+        var renderer_checkbox = new Postler.CellRendererToggle ();
+        column.pack_start (renderer_checkbox, true);
+        column.set_cell_data_func (renderer_checkbox, render_checkbox);
+        renderer_checkbox.toggled.connect (renderer_checkbox_toggled);
+        insert_column (column, -1);
+        int cell_width, xpad;
+        column.cell_get_size (null, null, null, out cell_width, null);
+        Gtk.cell_renderer_get_padding (renderer_checkbox, out xpad, null);
+        column.set_fixed_width (cell_width + xpad * 4);
+
+        column = new Gtk.TreeViewColumn ();
+        column.set_sizing (Gtk.TreeViewColumnSizing.FIXED);
         column.set_title (_("Flagged"));
         var renderer_flag = new Postler.CellRendererToggle ();
         column.pack_start (renderer_flag, true);
         column.set_cell_data_func (renderer_flag, render_flag);
         renderer_flag.toggled.connect (renderer_flag_toggled);
         insert_column (column, -1);
-        int cell_width, xpad;
         column.cell_get_size (null, null, null, out cell_width, null);
         Gtk.cell_renderer_get_padding (renderer_flag, out xpad, null);
         column.set_fixed_width (cell_width + xpad * 4);
@@ -224,7 +266,7 @@ public class Postler.Messages : Gtk.TreeView {
     }
     [Signal (action=true)]
     public virtual signal void delete () {
-        delete_selected ();
+        delete_checked ();
     }
 
     static string decode_piece (string encoded, out string charset) {
@@ -294,9 +336,23 @@ public class Postler.Messages : Gtk.TreeView {
         return fallback_to_utf8 (decoded.str);
     }
 
+    public void uncheck_all () {
+        foreach (var message in checked_messages) {
+            message.set_data<bool> ("checked", false);
+            var reference = message.get_data<Gtk.TreeRowReference> ("row");
+            Gtk.TreePath? path = reference.get_path ();
+            Gtk.TreeIter iter;
+            if (reference.get_model ().get_iter (out iter, path))
+                reference.get_model ().row_changed (path, iter);
+        }
+        checked_messages = new GLib.List<Message> ();
+        notify_property ("checked-messages");
+    }
+
     public void clear () {
         client = null;
         store.clear ();
+        uncheck_all ();
     }
 
     static string flags_from_filename (string filename, out string bare_filename) {
@@ -497,13 +553,6 @@ public class Postler.Messages : Gtk.TreeView {
         return true;
     }
 
-    public void delete_selected () {
-        if (selected_folder_type == FolderType.TRASH)
-            move_selected (null);
-        else
-            move_selected (FolderType.TRASH);
-    }
-
     public static uint32 obtain_uid_sequence (string folder, uint32 fallback_sequence) {
         /* Update .uidvalidity number, also read and updated by mbsync */
         uint32 uid_sequence = fallback_sequence;
@@ -563,26 +612,17 @@ public class Postler.Messages : Gtk.TreeView {
         return new_folder + parts[0] + ",U=" + uid_sequence.to_string () + ":2," + parts[2];
     }
 
-    public void move_selected (FolderType? type) {
-        string? destination_path;
-        if (type == null)
-            destination_path = null;
+    public void delete_checked () {
+        if (selected_folder_type == FolderType.TRASH)
+            move_checked (null);
         else
-            destination_path = "/"; /* Nonsense path, in case of later errors */
-
-        GLib.List<Gtk.TreePath> paths;
-        var references = new GLib.List<Gtk.TreeRowReference> ();
-        paths = get_selection ().get_selected_rows (null);
-        foreach (var path in paths)
-            references.prepend (new Gtk.TreeRowReference (model, path));
+            move_checked (FolderType.TRASH);
+    }
 
-        foreach (var reference in references) {
-            var path = reference.get_path ();
-            Gtk.TreeIter iter;
-            if (model.get_iter (out iter, path)) {
-                Message message;
-                model.get (iter, Columns.MESSAGE, out message);
-                try {
+    public void move_checked (FolderType? type) {
+        foreach (var message in checked_messages) {
+            string? destination_path = null;
+                if (type != null) {
                     AccountInfo account_info = message.get_account (accounts);
                     return_if_fail (account_info != null);
                     string? folder_name = null;
@@ -594,8 +634,17 @@ public class Postler.Messages : Gtk.TreeView {
                     }
                     destination_path = account_info.path + "/" + folder_name;
                     return_if_fail (destination_path != null);
+                }
+                try {
                     message.move (destination_path);
-
+                    /* Remove iter, move on to next row */
+                    var reference = message.get_data<Gtk.TreeRowReference> ("row");
+                    var path = reference.get_path ();
+                    Gtk.TreeIter iter;
+                    if (!model.get_iter (out iter, path)) {
+                        message.from_error ("Message moved: No valid iter");
+                        continue;
+                    }
                     /* Move to next, more recent message row */
                     Gtk.TreePath next_path = model.get_path (iter);
                     content.clear ();
@@ -612,9 +661,10 @@ public class Postler.Messages : Gtk.TreeView {
                         warning = _("Failed to delete message \"%s\": %s");
                     else
                         warning = _("Failed to move message \"%s\": %s");
-                    GLib.critical (warning, location, error.message);
+                    GLib.critical (warning, message.uri, error.message);
                 }
-            }
+            checked_messages.remove (message);
+            message.set_data<bool> ("checked", false);
         }
     }
 



More information about the Xfce4-commits mailing list