[geary/wip/730682-refine-convo-list] Implement copy and move from ConversationActionBar.
- From: Michael Gratton <mjog src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/wip/730682-refine-convo-list] Implement copy and move from ConversationActionBar.
- Date: Wed, 3 Jan 2018 09:03:26 +0000 (UTC)
commit 130f4ea2b54d032bf8d6ae83de1a176b5d54b7bb
Author: Michael James Gratton <mike vee net>
Date: Thu Dec 28 12:10:21 2017 +1100
Implement copy and move from ConversationActionBar.
* src/client/components/main-window.vala (MainWindow): Add actions for
both showing and activating copy and move ops from the action bar. Add
some uitl methods for converting a folder path to a GVariant and back
so it can be passed via an action param. Add action handlers for the
new ops.
* src/client/components/conversation-action-bar.vala
(ConversationActionBar): Make move and copy menu buttons public so they
can be messaed with. Hook up and update them with the account when it
changes.
* src/client/application/geary-controller.vala (GearyController): Add
internal copy and move functions for MainWindow. Rename existing
move_conversations() method to move_conversations_special() to make way
for "plain" move op, update call sites.
* src/engine/api/geary-account.vala (Account): Add factory method for
constructing native FolderPath instances, so the MainWindow can
deserialise paths serialised as a Variant.
* src/engine/app/app-email-store.vala (EmailStore): Add support for
moving a set of emails across folders.
po/POTFILES.in | 2 +
src/CMakeLists.txt | 1 +
src/client/application/geary-controller.vala | 40 ++++++++-
src/client/components/conversation-action-bar.vala | 77 ++++++++++++++---
src/client/components/main-window.vala | 89 ++++++++++++++++++--
src/engine/api/geary-account.vala | 46 +++++++----
src/engine/app/app-email-store.vala | 14 +++-
src/engine/app/email-store/app-move-operation.vala | 32 +++++++
.../imap-engine/imap-engine-generic-account.vala | 14 +++-
ui/conversation-action-bar.ui | 2 +
10 files changed, 272 insertions(+), 45 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 11bd439..366745e 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -161,6 +161,7 @@ src/engine/app/email-store/app-copy-operation.vala
src/engine/app/email-store/app-fetch-operation.vala
src/engine/app/email-store/app-list-operation.vala
src/engine/app/email-store/app-mark-operation.vala
+src/engine/app/email-store/app-move-operation.vala
src/engine/common/common-message-data.vala
src/engine/db/db-connection.vala
src/engine/db/db-context.vala
@@ -404,6 +405,7 @@ ui/composer-headerbar.ui
ui/composer-link-popover.ui
ui/composer-menus.ui
ui/composer-widget.ui
+ui/conversation-action-bar.ui
ui/conversation-email.ui
ui/conversation-email-attachment-view.ui
ui/conversation-email-menus.ui
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index fb88f9b..fca0df0 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -68,6 +68,7 @@ engine/app/email-store/app-copy-operation.vala
engine/app/email-store/app-fetch-operation.vala
engine/app/email-store/app-list-operation.vala
engine/app/email-store/app-mark-operation.vala
+engine/app/email-store/app-move-operation.vala
engine/common/common-message-data.vala
diff --git a/src/client/application/geary-controller.vala b/src/client/application/geary-controller.vala
index 578eb7d..6d25c6f 100644
--- a/src/client/application/geary-controller.vala
+++ b/src/client/application/geary-controller.vala
@@ -1154,8 +1154,25 @@ public class GearyController : Geary.BaseObject {
/**
* Moves a set of conversations to a special folder.
*/
- internal async void move_conversations(Gee.Collection<Geary.App.Conversation> targets,
- Geary.SpecialFolderType type)
+ internal async void copy_conversations(Gee.Collection<Geary.App.Conversation> targets,
+ Geary.FolderPath destination)
+ throws Error {
+ Gee.List<Geary.EmailIdentifier> ids = get_ids_in_folder(targets);
+ yield this.email_stores.get(this.current_account).copy_email_async(
+ ids, destination, this.cancellable_folder
+ );
+ }
+
+ /**
+ * Moves a set of conversations to a special folder.
+ *
+ * This does some extra work when moving conversations to specific
+ * special folders like archive and trash, and hence should be
+ * used in preference to {@link move_conversation} for special
+ * folders.
+ */
+ internal async void move_conversations_special(Gee.Collection<Geary.App.Conversation> targets,
+ Geary.SpecialFolderType type)
throws Error {
Gee.List<Geary.EmailIdentifier> ids = get_ids_in_folder(targets);
if (type == Geary.SpecialFolderType.ARCHIVE) {
@@ -1174,7 +1191,6 @@ public class GearyController : Geary.BaseObject {
_("Undo archive (Ctrl+Z)")
);
} else {
- Geary.Folder dest = this.current_account.get_special_folder(type);
Geary.FolderSupport.Move? movable =
this.current_folder as Geary.FolderSupport.Move;
if (movable == null) {
@@ -1183,6 +1199,7 @@ public class GearyController : Geary.BaseObject {
this.current_folder.to_string()
);
}
+ Geary.Folder dest = this.current_account.get_special_folder(type);
string tooltip = "";
switch (type) {
case Geary.SpecialFolderType.INBOX:
@@ -1199,6 +1216,9 @@ public class GearyController : Geary.BaseObject {
break;
}
save_revokable(
+ // XXX really should be using
+ // EmailStore.move_email_async here, but it doesn't
+ // return a revokable :<
yield movable.move_email_async(
ids, dest.path, this.cancellable_folder
),
@@ -1208,11 +1228,23 @@ public class GearyController : Geary.BaseObject {
}
/**
+ * Moves a set of conversations to a special folder.
+ */
+ internal async void move_conversations(Gee.Collection<Geary.App.Conversation> targets,
+ Geary.FolderPath destination)
+ throws Error {
+ Gee.List<Geary.EmailIdentifier> ids = get_ids_in_folder(targets);
+ yield this.email_stores.get(this.current_account).move_email_async(
+ ids, destination, this.cancellable_folder
+ );
+ }
+
+ /**
* Restores a set of messages to their original location.
*/
internal async void restore_conversations(Gee.Collection<Geary.App.Conversation> targets)
throws Error {
- yield move_conversations(targets, Geary.SpecialFolderType.INBOX);
+ yield move_conversations_special(targets, Geary.SpecialFolderType.INBOX);
}
/**
diff --git a/src/client/components/conversation-action-bar.vala
b/src/client/components/conversation-action-bar.vala
index 9ceaba6..c3e1d92 100644
--- a/src/client/components/conversation-action-bar.vala
+++ b/src/client/components/conversation-action-bar.vala
@@ -11,14 +11,22 @@
[GtkTemplate (ui = "/org/gnome/Geary/conversation-action-bar.ui")]
public class ConversationActionBar : Gtk.ActionBar {
- private Geary.Account? account = null;
+ /** The folder popover for copying/labelling conversations. */
+ public FolderPopover copy_folder_menu {
+ get; set; default = new FolderPopover();
+ }
+
+ /** The folder popover for moving conversations. */
+ public FolderPopover move_folder_menu {
+ get; set; default = new FolderPopover();
+ }
+
+ private Geary.Account? owner = null;
+ private Geary.Folder? location = null;
private bool has_archive = false;
private bool has_trash = false;
- private FolderPopover copy_folder_menu = new FolderPopover();
- private FolderPopover move_folder_menu = new FolderPopover();
-
[GtkChild]
private Gtk.Grid flag_actions;
[GtkChild]
@@ -57,16 +65,25 @@ public class ConversationActionBar : Gtk.ActionBar {
}
public void set_account(Geary.Account account) {
- if (this.account != null) {
- this.account.folders_special_type.disconnect(on_special_folder_changed);
+ if (this.owner != null) {
+ this.owner.folders_available_unavailable.disconnect(on_folders_changed);
+ this.owner.folders_special_type.disconnect(on_special_folder_changed);
}
- this.account = account;
- this.account.folders_special_type.connect(on_special_folder_changed);
+ this.owner = account;
+ this.owner.folders_available_unavailable.connect(on_folders_changed);
+ this.owner.folders_special_type.connect(on_special_folder_changed);
update_account();
}
public void update_location(Geary.Folder location) {
+ if (this.location != null) {
+ this.copy_folder_menu.enable_disable_folder(this.location, true);
+ this.move_folder_menu.enable_disable_folder(this.location, true);
+ }
+
+ this.location = location;
+
Gtk.Button? primary_action = null;
bool show_flag_actions = false;
bool show_folder_actions = false;
@@ -136,7 +153,9 @@ public class ConversationActionBar : Gtk.ActionBar {
this.archive_action.set_visible(primary_action == this.archive_action);
this.restore_action.set_visible(primary_action == this.restore_action);
this.copy_action.set_visible(show_folder_actions);
+ this.copy_folder_menu.enable_disable_folder(location, false);
this.move_action.set_visible(show_folder_actions);
+ this.move_folder_menu.enable_disable_folder(location, false);
if (show_trash && !this.has_trash) {
show_trash = false;
@@ -153,17 +172,30 @@ public class ConversationActionBar : Gtk.ActionBar {
private void update_account() {
try {
this.has_archive = (
- this.account.get_special_folder(Geary.SpecialFolderType.ARCHIVE) != null
+ this.owner.get_special_folder(Geary.SpecialFolderType.ARCHIVE) != null
);
} catch (Error err) {
- debug("Could not get Archive for account: %s", this.account.to_string());
+ debug("Could not get Archive for account: %s", this.owner.to_string());
}
try {
this.has_trash = (
- this.account.get_special_folder(Geary.SpecialFolderType.TRASH) != null
+ this.owner.get_special_folder(Geary.SpecialFolderType.TRASH) != null
);
} catch (Error err) {
- debug("Could not get Trash for account: %s", this.account.to_string());
+ debug("Could not get Trash for account: %s", this.owner.to_string());
+ }
+
+ this.copy_folder_menu.clear();
+ this.move_folder_menu.clear();
+ try {
+ foreach (Geary.Folder f in this.owner.list_folders()) {
+ this.copy_folder_menu.add_folder(f);
+ this.move_folder_menu.add_folder(f);
+ }
+ } catch (Error err) {
+ debug("Could not list folders for %s: %s",
+ this.owner.to_string(),
+ err.message);
}
}
@@ -184,6 +216,27 @@ public class ConversationActionBar : Gtk.ActionBar {
secondary.set_visible(!show_primary);
}
+ private void on_folders_changed(Gee.List<Geary.Folder>? available,
+ Gee.List<Geary.Folder>? unavailable) {
+ if (available != null) {
+ foreach (Geary.Folder folder in available) {
+ if (!this.copy_folder_menu.has_folder(folder))
+ this.copy_folder_menu.add_folder(folder);
+ if (!this.move_folder_menu.has_folder(folder))
+ this.move_folder_menu.add_folder(folder);
+ }
+ }
+
+ if (unavailable != null) {
+ foreach (Geary.Folder folder in unavailable) {
+ if (this.copy_folder_menu.has_folder(folder))
+ this.copy_folder_menu.remove_folder(folder);
+ if (this.move_folder_menu.has_folder(folder))
+ this.move_folder_menu.remove_folder(folder);
+ }
+ }
+ }
+
private void on_special_folder_changed() {
update_account();
}
diff --git a/src/client/components/main-window.vala b/src/client/components/main-window.vala
index afc9d7a..3d329c0 100644
--- a/src/client/components/main-window.vala
+++ b/src/client/components/main-window.vala
@@ -11,15 +11,20 @@ public class MainWindow : Gtk.ApplicationWindow {
public const string ACTION_ARCHIVE = "conversation-archive";
+ public const string ACTION_COPY = "conversation-copy";
public const string ACTION_DELETE = "conversation-delete";
public const string ACTION_JUNK = "conversation-junk";
public const string ACTION_MARK_READ = "conversation-mark-read";
public const string ACTION_MARK_STARRED = "conversation-mark-starred";
public const string ACTION_MARK_UNREAD = "conversation-mark-unread";
public const string ACTION_MARK_UNSTARRED = "conversation-mark-unstarred";
+ public const string ACTION_MOVE = "conversation-move";
public const string ACTION_RESTORE = "conversation-restore";
public const string ACTION_TRASH = "conversation-trash";
+ public const string ACTION_SHOW_COPY = "show-copy";
+ public const string ACTION_SHOW_MOVE = "show-move";
+
public const string ACTION_SELECTION_MODE_DISABLE = "selection-mode-disable";
public const string ACTION_SELECTION_MODE_ENABLE = "selection-mode-enable";
@@ -29,15 +34,20 @@ public class MainWindow : Gtk.ApplicationWindow {
private const ActionEntry[] action_entries = {
{ ACTION_ARCHIVE, on_conversation_archive },
+ { ACTION_COPY, on_conversation_copy, "as" },
{ ACTION_DELETE, on_conversation_delete },
{ ACTION_JUNK, on_conversation_junk },
{ ACTION_MARK_READ, on_conversation_mark_read },
{ ACTION_MARK_STARRED, on_conversation_mark_starred },
{ ACTION_MARK_UNREAD, on_conversation_mark_unread },
{ ACTION_MARK_UNSTARRED, on_conversation_mark_unstarred },
+ { ACTION_MOVE, on_conversation_move, "as" },
{ ACTION_RESTORE, on_conversation_restore },
{ ACTION_TRASH, on_conversation_trash },
+ { ACTION_SHOW_COPY },
+ { ACTION_SHOW_MOVE },
+
{ ACTION_SELECTION_MODE_DISABLE, on_selection_mode_disabled },
{ ACTION_SELECTION_MODE_ENABLE, on_selection_mode_enabled }
};
@@ -118,6 +128,8 @@ public class MainWindow : Gtk.ApplicationWindow {
this.conversation_list.visible_conversations_changed.connect(on_visible_conversations_changed);
this.conversation_list.load_more.connect(on_load_more);
+ this.conversation_list_actions.copy_folder_menu.folder_selected.connect(on_copy_folder);
+ this.conversation_list_actions.move_folder_menu.folder_selected.connect(on_move_folder);
this.conversation_list_grid.add(this.conversation_list_actions);
load_config(application.config);
@@ -541,17 +553,33 @@ public class MainWindow : Gtk.ApplicationWindow {
this.conversation_viewer.show_none_selected();
}
- private void report_problem(Action action, Variant? param, Error err) {
+ private void report_problem(Action action, Variant? param, Error? err = null) {
// XXX
debug("Client problem reported: %s: %s",
action.get_name(),
- err.message);
+ err != null ? err.message : "no error reported");
}
private inline SimpleAction get_action(string name) {
return (SimpleAction) lookup_action(name);
}
+ private Geary.FolderPath? variant_to_path(Variant? strv) {
+ Geary.FolderPath? path = null;
+ if (this.current_folder != null &&
+ strv != null &&
+ strv.get_type_string() == "as") {
+ path = this.current_folder.account.new_folder_path(
+ new Gee.ArrayList<string>.wrap(strv.get_strv())
+ );
+ }
+ return path;
+ }
+
+ private Variant path_to_variant(Geary.FolderPath path) {
+ return new Variant.strv(path.as_list().to_array());
+ }
+
private void on_folder_selected(Geary.Folder? folder) {
if (folder != null) {
update_folder(folder);
@@ -730,12 +758,12 @@ public class MainWindow : Gtk.ApplicationWindow {
}
private void on_conversation_archive(Action action, Variant? param) {
- this.application.controller.move_conversations.begin(
+ this.application.controller.move_conversations_special.begin(
this.conversation_list.get_highlighted_conversations(),
Geary.SpecialFolderType.ARCHIVE,
(obj, ret) => {
try {
- this.application.controller.move_conversations.end(ret);
+ this.application.controller.move_conversations_special.end(ret);
} catch (Error err) {
report_problem(action, param, err);
}
@@ -743,6 +771,25 @@ public class MainWindow : Gtk.ApplicationWindow {
);
}
+ private void on_conversation_copy(Action action, Variant? param) {
+ Geary.FolderPath? destination = variant_to_path(param);
+ if (path != null) {
+ this.application.controller.copy_conversations.begin(
+ this.conversation_list.get_highlighted_conversations(),
+ destination,
+ (obj, ret) => {
+ try {
+ this.application.controller.copy_conversations.end(ret);
+ } catch (Error err) {
+ report_problem(action, param, err);
+ }
+ }
+ );
+ } else {
+ report_problem(action, param);
+ }
+ }
+
private void on_conversation_delete(Action action, Variant? param) {
if (confirm_delete()) {
this.application.controller.delete_conversations.begin(
@@ -759,12 +806,12 @@ public class MainWindow : Gtk.ApplicationWindow {
}
private void on_conversation_junk(Action action, Variant? param) {
- this.application.controller.move_conversations.begin(
+ this.application.controller.move_conversations_special.begin(
this.conversation_list.get_highlighted_conversations(),
Geary.SpecialFolderType.SPAM,
(obj, ret) => {
try {
- this.application.controller.move_conversations.end(ret);
+ this.application.controller.move_conversations_special.end(ret);
} catch (Error err) {
report_problem(action, param, err);
}
@@ -862,6 +909,25 @@ public class MainWindow : Gtk.ApplicationWindow {
);
}
+ private void on_conversation_move(Action action, Variant? param) {
+ Geary.FolderPath? destination = variant_to_path(param);
+ if (path != null) {
+ this.application.controller.move_conversations.begin(
+ this.conversation_list.get_highlighted_conversations(),
+ destination,
+ (obj, ret) => {
+ try {
+ this.application.controller.move_conversations.end(ret);
+ } catch (Error err) {
+ report_problem(action, param, err);
+ }
+ }
+ );
+ } else {
+ report_problem(action, param);
+ }
+ }
+
private void on_conversation_restore(Action action, Variant? param) {
this.application.controller.restore_conversations.begin(
this.conversation_list.get_highlighted_conversations(),
@@ -876,12 +942,12 @@ public class MainWindow : Gtk.ApplicationWindow {
}
private void on_conversation_trash(Action action, Variant? param) {
- this.application.controller.move_conversations.begin(
+ this.application.controller.move_conversations_special.begin(
this.conversation_list.get_highlighted_conversations(),
Geary.SpecialFolderType.TRASH,
(obj, ret) => {
try {
- this.application.controller.move_conversations.end(ret);
+ this.application.controller.move_conversations_special.end(ret);
} catch (Error err) {
report_problem(action, param, err);
}
@@ -889,6 +955,13 @@ public class MainWindow : Gtk.ApplicationWindow {
);
}
+ public void on_copy_folder(Geary.Folder target) {
+ get_action(ACTION_COPY).activate(path_to_variant(target.path));
+ }
+
+ public void on_move_folder(Geary.Folder target) {
+ get_action(ACTION_MOVE).activate(path_to_variant(target.path));
+ }
private void on_selection_mode_enabled() {
set_selection_mode_enabled(true);
diff --git a/src/engine/api/geary-account.vala b/src/engine/api/geary-account.vala
index a7fd343..6773ed9 100644
--- a/src/engine/api/geary-account.vala
+++ b/src/engine/api/geary-account.vala
@@ -127,22 +127,6 @@ public abstract class Geary.Account : BaseObject {
}
/**
- * A utility method to sort a Gee.Collection of {@link Folder}s by their {@link FolderPath}s
- * to ensure they comport with {@link folders_available_unavailable} and
- * {@link folders_added_removed} signals' contracts.
- */
- protected Gee.List<Geary.Folder> sort_by_path(Gee.Collection<Geary.Folder> folders) {
- Gee.TreeSet<Geary.Folder> sorted = new Gee.TreeSet<Geary.Folder>(folder_path_comparator);
- sorted.add_all(folders);
-
- return Collection.to_array_list<Geary.Folder>(sorted);
- }
-
- private int folder_path_comparator(Geary.Folder a, Geary.Folder b) {
- return a.path.compare_to(b.path);
- }
-
- /**
* Opens the {@link Account} and makes it and its {@link Folder}s available for use.
*
* @throws EngineError.CORRUPT if the local store is corrupt or unusable
@@ -223,7 +207,19 @@ public abstract class Geary.Account : BaseObject {
* list_matching_folders().
*/
public abstract Gee.Collection<Geary.Folder> list_folders() throws Error;
-
+
+ /**
+ * Returns a path for a list of folder names.
+ *
+ * This is useful for converting a string representation of a
+ * folder path back into an actual instance of a folder path. This
+ * does not guarantee that the folder represented by the path will
+ * exist.
+ *
+ * {@see FolderPath.as_list}
+ */
+ public abstract FolderPath new_folder_path(Gee.List<string> name_list);
+
/**
* Gets a perpetually update-to-date collection of autocompletion contacts.
*/
@@ -434,4 +430,20 @@ public abstract class Geary.Account : BaseObject {
report_problem(new ServiceProblemReport(type, this.information, service_type, err));
}
+ /**
+ * A utility method to sort a Gee.Collection of {@link Folder}s by their {@link FolderPath}s
+ * to ensure they comport with {@link folders_available_unavailable} and
+ * {@link folders_added_removed} signals' contracts.
+ */
+ protected Gee.List<Geary.Folder> sort_by_path(Gee.Collection<Geary.Folder> folders) {
+ Gee.TreeSet<Geary.Folder> sorted = new Gee.TreeSet<Geary.Folder>(folder_path_comparator);
+ sorted.add_all(folders);
+
+ return Collection.to_array_list<Geary.Folder>(sorted);
+ }
+
+ private int folder_path_comparator(Geary.Folder a, Geary.Folder b) {
+ return a.path.compare_to(b.path);
+ }
+
}
diff --git a/src/engine/app/app-email-store.vala b/src/engine/app/app-email-store.vala
index 4390dfa..f74ede3 100644
--- a/src/engine/app/app-email-store.vala
+++ b/src/engine/app/app-email-store.vala
@@ -97,7 +97,7 @@ public class Geary.App.EmailStore : BaseObject {
yield do_folder_operation_async(new Geary.App.MarkOperation(flags_to_add, flags_to_remove),
emails, cancellable);
}
-
+
/**
* Copies any set of EmailIdentifiers as if they were all in one
* Geary.FolderSupport.Copy folder.
@@ -107,7 +107,17 @@ public class Geary.App.EmailStore : BaseObject {
yield do_folder_operation_async(new Geary.App.CopyOperation(destination),
emails, cancellable);
}
-
+
+ /**
+ * Moves any set of EmailIdentifiers as if they were all in one
+ * Geary.FolderSupport.Move folder.
+ */
+ public async void move_email_async(Gee.Collection<Geary.EmailIdentifier> emails,
+ Geary.FolderPath destination, Cancellable? cancellable = null) throws Error {
+ yield do_folder_operation_async(new Geary.App.MoveOperation(destination),
+ emails, cancellable);
+ }
+
private async Gee.HashMap<Geary.FolderPath, Geary.Folder> get_folder_instances_async(
Gee.Collection<Geary.FolderPath> paths, Cancellable? cancellable) throws Error {
Gee.HashMap<Geary.FolderPath, Geary.Folder> folders
diff --git a/src/engine/app/email-store/app-move-operation.vala
b/src/engine/app/email-store/app-move-operation.vala
new file mode 100644
index 0000000..63f70bb
--- /dev/null
+++ b/src/engine/app/email-store/app-move-operation.vala
@@ -0,0 +1,32 @@
+/* Copyright 2016 Software Freedom Conservancy Inc.
+ *
+ * This software is licensed under the GNU Lesser General Public License
+ * (version 2.1 or later). See the COPYING file in this distribution.
+ */
+
+private class Geary.App.MoveOperation : Geary.App.AsyncFolderOperation {
+
+ public override Type folder_type {
+ get { return typeof(Geary.FolderSupport.Move); }
+ }
+
+ public Geary.FolderPath destination;
+
+ public MoveOperation(Geary.FolderPath destination) {
+ this.destination = destination;
+ }
+
+ public override async Gee.Collection<Geary.EmailIdentifier>
+ execute_async(Geary.Folder folder,
+ Gee.Collection<Geary.EmailIdentifier> ids,
+ Cancellable? cancellable)
+ throws Error {
+ Geary.FolderSupport.Move? move = folder as Geary.FolderSupport.Move;
+ assert(move != null);
+
+ Gee.List<Geary.EmailIdentifier> list =
+ Geary.Collection.to_array_list<Geary.EmailIdentifier>(ids);
+ yield move.move_email_async(list, destination, cancellable);
+ return ids;
+ }
+}
diff --git a/src/engine/imap-engine/imap-engine-generic-account.vala
b/src/engine/imap-engine/imap-engine-generic-account.vala
index 2ac8e73..6872e0a 100644
--- a/src/engine/imap-engine/imap-engine-generic-account.vala
+++ b/src/engine/imap-engine/imap-engine-generic-account.vala
@@ -367,10 +367,20 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account {
Gee.HashSet<Geary.Folder> all_folders = new Gee.HashSet<Geary.Folder>();
all_folders.add_all(folder_map.values);
all_folders.add_all(local_only.values);
-
+
return all_folders;
}
-
+
+ public override FolderPath new_folder_path(Gee.List<string> name_list) {
+ Gee.Iterator<string> names = name_list.iterator();
+ names.next();
+ Geary.FolderPath path = new Imap.FolderRoot(names.get());
+ while (names.next()) {
+ path = path.get_child(names.get());
+ }
+ return path;
+ }
+
private void reschedule_unseen_update(Geary.Folder folder) {
if (!folder_map.has_key(folder.path))
return;
diff --git a/ui/conversation-action-bar.ui b/ui/conversation-action-bar.ui
index c84cdc6..0cf111d 100644
--- a/ui/conversation-action-bar.ui
+++ b/ui/conversation-action-bar.ui
@@ -127,6 +127,7 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
+ <property name="action_name">win.show-copy</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
@@ -145,6 +146,7 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
+ <property name="action_name">win.show-move</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]