Add folder avail. signals to Account; closes #6208
Squashed commit of the following:
commit 3b133030800699c2106bfb30a104cd58710cf245
Author: Charles Lindsay <chaz@yorba.org>
Date: Thu Jan 17 12:06:11 2013 -0800
Clean up state on close; ref #6208
commit a4637a49277740b64ac198fa057eb52556c80efa
Author: Charles Lindsay <chaz@yorba.org>
Date: Thu Jan 17 11:58:22 2013 -0800
Simplify build_folder; ref #6208
commit e9afa248ce525f0496220cfbb0d8529e38cbceae
Author: Charles Lindsay <chaz@yorba.org>
Date: Wed Jan 16 18:10:00 2013 -0800
Cleanup; ref #6208
commit 95ee3a2c6fcfd4b9b7e10aae1100fe7a8697c25a
Author: Charles Lindsay <chaz@yorba.org>
Date: Wed Jan 16 18:02:02 2013 -0800
Aggregate building folders; ref #6208
commit 28ee5df718e08c0121b26b1934b619a409fb451a
Author: Charles Lindsay <chaz@yorba.org>
Date: Wed Jan 16 16:49:17 2013 -0800
Make local-only folders available; ref #6208
This also slightly cleans up the special-casing of local-only folders.
commit 19c48fe657fca989fe0b519d39833dd8e0d95cfe
Author: Charles Lindsay <chaz@yorba.org>
Date: Wed Jan 16 15:44:55 2013 -0800
Use new interface; ref #6208
commit f64f82f9362a0081a3e4f7a21dc401f3d4ca320f
Author: Charles Lindsay <chaz@yorba.org>
Date: Mon Jan 14 17:11:04 2013 -0800
Try new interface in Account; ref #6208
This commit is contained in:
parent
1ab3b22d02
commit
13b804eca0
4 changed files with 113 additions and 107 deletions
|
|
@ -6,34 +6,6 @@
|
|||
|
||||
// Primary controller object for Geary.
|
||||
public class GearyController {
|
||||
private class ListFoldersOperation : Geary.NonblockingBatchOperation {
|
||||
public Geary.Account account;
|
||||
public Geary.FolderPath path;
|
||||
|
||||
public ListFoldersOperation(Geary.Account account, Geary.FolderPath path) {
|
||||
this.account = account;
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public override async Object? execute_async(Cancellable? cancellable) throws Error {
|
||||
return yield account.list_folders_async(path, cancellable);
|
||||
}
|
||||
}
|
||||
|
||||
private class FetchFolderOperation : Geary.NonblockingBatchOperation {
|
||||
public Geary.Account account;
|
||||
public Geary.FolderPath folder_path;
|
||||
|
||||
public FetchFolderOperation(Geary.Account account, Geary.FolderPath folder_path) {
|
||||
this.account = account;
|
||||
this.folder_path = folder_path;
|
||||
}
|
||||
|
||||
public override async Object? execute_async(Cancellable? cancellable) throws Error {
|
||||
return yield account.fetch_folder_async(folder_path);
|
||||
}
|
||||
}
|
||||
|
||||
// Named actions.
|
||||
public const string ACTION_HELP = "GearyHelp";
|
||||
public const string ACTION_ABOUT = "GearyAbout";
|
||||
|
|
@ -274,7 +246,7 @@ public class GearyController {
|
|||
cancel_inbox();
|
||||
cancel_message();
|
||||
|
||||
account.folders_added_removed.disconnect(on_folders_added_removed);
|
||||
account.folders_available_unavailable.disconnect(on_folders_available_unavailable);
|
||||
|
||||
main_window.title = GearyApplication.NAME;
|
||||
main_window.conversation_list_store.account_owner_email = null;
|
||||
|
|
@ -312,6 +284,8 @@ public class GearyController {
|
|||
|
||||
// Connect the new account, if any.
|
||||
if (account != null) {
|
||||
account.folders_available_unavailable.connect(on_folders_available_unavailable);
|
||||
|
||||
try {
|
||||
yield account.open_async(cancellable);
|
||||
} catch (Error open_err) {
|
||||
|
|
@ -323,7 +297,6 @@ public class GearyController {
|
|||
GearyApplication.instance.panic();
|
||||
}
|
||||
|
||||
account.folders_added_removed.connect(on_folders_added_removed);
|
||||
account.email_sent.connect(on_sent);
|
||||
|
||||
if (account.settings.service_provider == Geary.ServiceProvider.YAHOO)
|
||||
|
|
@ -331,7 +304,6 @@ public class GearyController {
|
|||
main_window.conversation_list_store.account_owner_email = account.settings.email.address;
|
||||
|
||||
main_window.folder_list.set_user_folders_root_name(_("Labels"));
|
||||
load_folders.begin(cancellable_folder);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -361,19 +333,6 @@ public class GearyController {
|
|||
}
|
||||
}
|
||||
|
||||
private async void load_folders(Cancellable? cancellable) {
|
||||
try {
|
||||
// pull down the root-level user folders and recursively add to sidebar
|
||||
Gee.Collection<Geary.Folder> folders = yield account.list_folders_async(null);
|
||||
if (folders != null)
|
||||
on_folders_added_removed(folders, null);
|
||||
else
|
||||
debug("no folders");
|
||||
} catch (Error err) {
|
||||
message("%s", err.message);
|
||||
}
|
||||
}
|
||||
|
||||
private void on_folder_selected(Geary.Folder? folder) {
|
||||
if (folder == null) {
|
||||
debug("no folder selected");
|
||||
|
|
@ -624,11 +583,11 @@ public class GearyController {
|
|||
main_window.folder_list.add_folder(folder);
|
||||
}
|
||||
|
||||
private void on_folders_added_removed(Gee.Collection<Geary.Folder>? added,
|
||||
Gee.Collection<Geary.Folder>? removed) {
|
||||
private void on_folders_available_unavailable(Gee.Collection<Geary.Folder>? available,
|
||||
Gee.Collection<Geary.Folder>? unavailable) {
|
||||
|
||||
if (added != null && added.size > 0) {
|
||||
foreach (Geary.Folder folder in added) {
|
||||
if (available != null && available.size > 0) {
|
||||
foreach (Geary.Folder folder in available) {
|
||||
main_window.folder_list.add_folder(folder);
|
||||
main_window.main_toolbar.copy_folder_menu.add_folder(folder);
|
||||
main_window.main_toolbar.move_folder_menu.add_folder(folder);
|
||||
|
|
@ -660,49 +619,9 @@ public class GearyController {
|
|||
|
||||
folder.special_folder_type_changed.connect(on_special_folder_type_changed);
|
||||
}
|
||||
|
||||
search_folders_for_children.begin(added);
|
||||
}
|
||||
}
|
||||
|
||||
private async void search_folders_for_children(Gee.Collection<Geary.Folder> folders) {
|
||||
set_busy(true);
|
||||
Geary.NonblockingBatch batch = new Geary.NonblockingBatch();
|
||||
foreach (Geary.Folder folder in folders) {
|
||||
// Search for children unless Folder is absolutely certain it doesn't have any
|
||||
if (folder.has_children().is_possible())
|
||||
batch.add(new ListFoldersOperation(account, folder.get_path()));
|
||||
}
|
||||
|
||||
debug("Listing %d folder children", batch.size);
|
||||
try {
|
||||
yield batch.execute_all_async();
|
||||
} catch (Error err) {
|
||||
debug("Unable to execute batch: %s", err.message);
|
||||
set_busy(false);
|
||||
|
||||
return;
|
||||
}
|
||||
debug("Completed listing folder children");
|
||||
|
||||
Gee.ArrayList<Geary.Folder> accumulator = new Gee.ArrayList<Geary.Folder>();
|
||||
foreach (int id in batch.get_ids()) {
|
||||
ListFoldersOperation op = (ListFoldersOperation) batch.get_operation(id);
|
||||
try {
|
||||
Gee.Collection<Geary.Folder> children = (Gee.Collection<Geary.Folder>)
|
||||
batch.get_result(id);
|
||||
accumulator.add_all(children);
|
||||
} catch (Error err2) {
|
||||
debug("Unable to list children of %s: %s", op.path.to_string(), err2.message);
|
||||
}
|
||||
}
|
||||
|
||||
if (accumulator.size > 0)
|
||||
on_folders_added_removed(accumulator, null);
|
||||
|
||||
set_busy(false);
|
||||
}
|
||||
|
||||
private void cancel_folder() {
|
||||
Cancellable old_cancellable = cancellable_folder;
|
||||
cancellable_folder = new Cancellable();
|
||||
|
|
|
|||
|
|
@ -14,6 +14,11 @@ public abstract class Geary.AbstractAccount : Object, Geary.Account {
|
|||
this.settings = settings;
|
||||
}
|
||||
|
||||
protected virtual void notify_folders_available_unavailable(Gee.Collection<Geary.Folder>? available,
|
||||
Gee.Collection<Geary.Folder>? unavailable) {
|
||||
folders_available_unavailable(available, unavailable);
|
||||
}
|
||||
|
||||
protected virtual void notify_folders_added_removed(Gee.Collection<Geary.Folder>? added,
|
||||
Gee.Collection<Geary.Folder>? removed) {
|
||||
folders_added_removed(added, removed);
|
||||
|
|
|
|||
|
|
@ -24,6 +24,18 @@ public interface Geary.Account : Object {
|
|||
public signal void report_problem(Geary.Account.Problem problem, Geary.AccountSettings settings,
|
||||
Error? err);
|
||||
|
||||
/**
|
||||
* Fired when folders become available or unavailable in the account.
|
||||
* Folders become available when the account is first opened or when
|
||||
* they're created later; they become unavailable when the account is
|
||||
* closed or they're deleted later.
|
||||
*/
|
||||
public signal void folders_available_unavailable(Gee.Collection<Geary.Folder>? available,
|
||||
Gee.Collection<Geary.Folder>? unavailable);
|
||||
|
||||
/**
|
||||
* Fired when folders are created or deleted.
|
||||
*/
|
||||
public signal void folders_added_removed(Gee.Collection<Geary.Folder>? added,
|
||||
Gee.Collection<Geary.Folder>? removed);
|
||||
|
||||
|
|
@ -48,6 +60,12 @@ public interface Geary.Account : Object {
|
|||
protected abstract void notify_report_problem(Geary.Account.Problem problem,
|
||||
Geary.AccountSettings? settings, Error? err);
|
||||
|
||||
/**
|
||||
* Signal notification method for subclasses to use.
|
||||
*/
|
||||
public abstract void notify_folders_available_unavailable(Gee.Collection<Geary.Folder>? available,
|
||||
Gee.Collection<Geary.Folder>? unavailable);
|
||||
|
||||
/**
|
||||
* Signal notification method for subclasses to use.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.AbstractAccount {
|
|||
FolderPath, Imap.FolderProperties>(Hashable.hash_func, Equalable.equal_func);
|
||||
private Gee.HashMap<FolderPath, GenericFolder> existing_folders = new Gee.HashMap<
|
||||
FolderPath, GenericFolder>(Hashable.hash_func, Equalable.equal_func);
|
||||
private Gee.HashSet<FolderPath> local_only = new Gee.HashSet<FolderPath>(
|
||||
private Gee.HashMap<FolderPath, Folder> local_only = new Gee.HashMap<FolderPath, Folder>(
|
||||
Hashable.hash_func, Equalable.equal_func);
|
||||
|
||||
public GenericAccount(string name, Geary.AccountSettings settings, Imap.Account remote,
|
||||
|
|
@ -35,7 +35,6 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.AbstractAccount {
|
|||
|
||||
if (outbox_path == null) {
|
||||
outbox_path = new SmtpOutboxFolderRoot();
|
||||
local_only.add(outbox_path);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -48,6 +47,26 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.AbstractAccount {
|
|||
throw new EngineError.OPEN_REQUIRED("Account %s not opened", to_string());
|
||||
}
|
||||
|
||||
protected override void notify_folders_available_unavailable(Gee.Collection<Geary.Folder>? available,
|
||||
Gee.Collection<Geary.Folder>? unavailable) {
|
||||
base.notify_folders_available_unavailable(available, unavailable);
|
||||
|
||||
if (available != null) {
|
||||
foreach(Folder f in available) {
|
||||
if (f.has_children().is_possible())
|
||||
enumerate_folders_async.begin(f.get_path(), null, on_enumerate_folders_async_complete);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void on_enumerate_folders_async_complete(Object? object, AsyncResult result) {
|
||||
try {
|
||||
enumerate_folders_async.end(result);
|
||||
} catch (Error e) {
|
||||
debug("Error enumerating subfolders: %s", e.message);
|
||||
}
|
||||
}
|
||||
|
||||
public override async void open_async(Cancellable? cancellable = null) throws Error {
|
||||
if (open)
|
||||
throw new EngineError.ALREADY_OPEN("Account %s already opened", to_string());
|
||||
|
|
@ -56,6 +75,7 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.AbstractAccount {
|
|||
|
||||
// outbox is now available
|
||||
local.outbox.report_problem.connect(notify_report_problem);
|
||||
local_only.set(outbox_path, local.outbox);
|
||||
|
||||
// need to back out local.open_async() if remote fails
|
||||
try {
|
||||
|
|
@ -74,11 +94,17 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.AbstractAccount {
|
|||
open = true;
|
||||
|
||||
notify_opened();
|
||||
|
||||
notify_folders_available_unavailable(local_only.values, null);
|
||||
yield enumerate_folders_async(null, cancellable);
|
||||
}
|
||||
|
||||
public override async void close_async(Cancellable? cancellable = null) throws Error {
|
||||
if (!open)
|
||||
return;
|
||||
|
||||
notify_folders_available_unavailable(null, local_only.values);
|
||||
notify_folders_available_unavailable(null, existing_folders.values);
|
||||
|
||||
local.outbox.report_problem.disconnect(notify_report_problem);
|
||||
|
||||
|
|
@ -96,6 +122,10 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.AbstractAccount {
|
|||
} catch (Error rclose_err) {
|
||||
remote_err = rclose_err;
|
||||
}
|
||||
|
||||
properties_map.clear();
|
||||
existing_folders.clear();
|
||||
local_only.clear();
|
||||
|
||||
if (local_err != null)
|
||||
throw local_err;
|
||||
|
|
@ -113,17 +143,48 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.AbstractAccount {
|
|||
ImapDB.Account local_account, ImapDB.Folder local_folder);
|
||||
|
||||
private GenericFolder build_folder(ImapDB.Folder local_folder) {
|
||||
GenericFolder? folder = existing_folders.get(local_folder.get_path());
|
||||
if (folder != null)
|
||||
return folder;
|
||||
|
||||
folder = new_folder(local_folder.get_path(), remote, local, local_folder);
|
||||
existing_folders.set(folder.get_path(), folder);
|
||||
|
||||
return folder;
|
||||
return Geary.Collection.get_first(build_folders(new Geary.Singleton<ImapDB.Folder>(local_folder)));
|
||||
}
|
||||
|
||||
private Gee.Collection<GenericFolder> build_folders(Gee.Collection<ImapDB.Folder> local_folders) {
|
||||
Gee.ArrayList<ImapDB.Folder> folders_to_build = new Gee.ArrayList<ImapDB.Folder>();
|
||||
Gee.ArrayList<GenericFolder> built_folders = new Gee.ArrayList<GenericFolder>();
|
||||
Gee.ArrayList<GenericFolder> return_folders = new Gee.ArrayList<GenericFolder>();
|
||||
|
||||
foreach(ImapDB.Folder local_folder in local_folders) {
|
||||
if (existing_folders.has_key(local_folder.get_path()))
|
||||
return_folders.add(existing_folders.get(local_folder.get_path()));
|
||||
else
|
||||
folders_to_build.add(local_folder);
|
||||
}
|
||||
|
||||
foreach(ImapDB.Folder folder_to_build in folders_to_build) {
|
||||
GenericFolder folder = new_folder(folder_to_build.get_path(), remote, local, folder_to_build);
|
||||
existing_folders.set(folder.get_path(), folder);
|
||||
built_folders.add(folder);
|
||||
return_folders.add(folder);
|
||||
}
|
||||
|
||||
if (built_folders.size > 0)
|
||||
notify_folders_available_unavailable(built_folders, null);
|
||||
return return_folders;
|
||||
}
|
||||
|
||||
public override async Gee.Collection<Geary.Folder> list_folders_async(Geary.FolderPath? parent,
|
||||
Cancellable? cancellable = null) throws Error {
|
||||
Gee.ArrayList<Geary.Folder> matches = new Gee.ArrayList<Geary.Folder>();
|
||||
|
||||
foreach(FolderPath path in existing_folders.keys) {
|
||||
FolderPath? path_parent = path.get_parent();
|
||||
if ((parent == null && path_parent == null) ||
|
||||
(parent != null && path_parent != null && path_parent.equals(parent))) {
|
||||
matches.add(existing_folders.get(path));
|
||||
}
|
||||
}
|
||||
return matches;
|
||||
}
|
||||
|
||||
private async Gee.Collection<Geary.Folder> enumerate_folders_async(Geary.FolderPath? parent,
|
||||
Cancellable? cancellable = null) throws Error {
|
||||
check_open();
|
||||
|
||||
|
|
@ -138,13 +199,12 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.AbstractAccount {
|
|||
|
||||
Gee.Collection<Geary.Folder> engine_list = new Gee.ArrayList<Geary.Folder>();
|
||||
if (local_list != null && local_list.size > 0) {
|
||||
foreach (ImapDB.Folder local_folder in local_list)
|
||||
engine_list.add(build_folder(local_folder));
|
||||
engine_list.add_all(build_folders(local_list));
|
||||
}
|
||||
|
||||
// Add Outbox to root
|
||||
// Add local folders (assume that local-only folders always go in root)
|
||||
if (parent == null)
|
||||
engine_list.add(local.outbox);
|
||||
engine_list.add_all(local_only.values);
|
||||
|
||||
background_update_folders.begin(parent, engine_list, cancellable);
|
||||
|
||||
|
|
@ -170,8 +230,8 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.AbstractAccount {
|
|||
Cancellable? cancellable = null) throws Error {
|
||||
check_open();
|
||||
|
||||
if (path.equals(local.outbox.get_path()))
|
||||
return local.outbox;
|
||||
if (local_only.has_key(path))
|
||||
return local_only.get(path);
|
||||
|
||||
try {
|
||||
return build_folder((ImapDB.Folder) yield local.fetch_folder_async(path, cancellable));
|
||||
|
|
@ -255,7 +315,7 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.AbstractAccount {
|
|||
// it
|
||||
Gee.List<Geary.Folder>? to_remove = new Gee.ArrayList<Geary.Imap.Folder>();
|
||||
foreach (Geary.Folder folder in engine_folders) {
|
||||
if (!remote_paths.contains(folder.get_path()) && !local_only.contains(folder.get_path()))
|
||||
if (!remote_paths.contains(folder.get_path()) && !local_only.keys.contains(folder.get_path()))
|
||||
to_remove.add(folder);
|
||||
}
|
||||
|
||||
|
|
@ -281,10 +341,12 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.AbstractAccount {
|
|||
Gee.Collection<Geary.Folder> engine_added = null;
|
||||
if (to_add != null) {
|
||||
engine_added = new Gee.ArrayList<Geary.Folder>();
|
||||
|
||||
Gee.ArrayList<ImapDB.Folder> folders_to_build = new Gee.ArrayList<ImapDB.Folder>();
|
||||
foreach (Geary.Imap.Folder remote_folder in to_add) {
|
||||
try {
|
||||
engine_added.add(build_folder((ImapDB.Folder) yield local.fetch_folder_async(
|
||||
remote_folder.get_path(), cancellable)));
|
||||
folders_to_build.add((ImapDB.Folder) yield local.fetch_folder_async(
|
||||
remote_folder.get_path(), cancellable));
|
||||
} catch (Error convert_err) {
|
||||
// This isn't fatal, but irksome ... in the future, when local folders are
|
||||
// removed, it's possible for one to disappear between cloning it and fetching
|
||||
|
|
@ -292,6 +354,8 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.AbstractAccount {
|
|||
debug("Unable to fetch local folder after cloning: %s", convert_err.message);
|
||||
}
|
||||
}
|
||||
|
||||
engine_added.add_all(build_folders(folders_to_build));
|
||||
}
|
||||
|
||||
// TODO: Remove local folders no longer available remotely.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue