Further engine rework: Revised interface to Geary.Folder
Now that the Geary.Folder interface is not tied to the internal SQLite/IMAP folder objects, it is free to offer more data and better information to the client via its signals. This commit makes the "email-removed" signal more useful and removes two list_*() calls that were only useful to the EngineFolder itself when manipulating the internal Folder objects.
This commit is contained in:
parent
6f5f05099e
commit
c6cac07c76
8 changed files with 165 additions and 135 deletions
|
|
@ -276,8 +276,8 @@ public class Geary.Conversations : Object {
|
|||
|
||||
~Conversations() {
|
||||
if (monitor_new) {
|
||||
folder.messages_appended.disconnect(on_folder_messages_appended);
|
||||
folder.message_removed.disconnect(on_folder_message_removed);
|
||||
folder.email_appended.disconnect(on_folder_email_appended);
|
||||
folder.email_removed.disconnect(on_folder_email_removed);
|
||||
}
|
||||
|
||||
// Manually detach all the weak refs in the Conversation objects
|
||||
|
|
@ -335,8 +335,8 @@ public class Geary.Conversations : Object {
|
|||
|
||||
monitor_new = true;
|
||||
cancellable_monitor = cancellable;
|
||||
folder.messages_appended.connect(on_folder_messages_appended);
|
||||
folder.message_removed.connect(on_folder_message_removed);
|
||||
folder.email_appended.connect(on_folder_email_appended);
|
||||
folder.email_removed.connect(on_folder_email_removed);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -709,7 +709,7 @@ public class Geary.Conversations : Object {
|
|||
}
|
||||
}
|
||||
|
||||
private void on_folder_messages_appended() {
|
||||
private void on_folder_email_appended() {
|
||||
// Find highest identifier by ordering
|
||||
// TODO: optimize.
|
||||
Geary.EmailIdentifier? highest = null;
|
||||
|
|
@ -733,8 +733,9 @@ public class Geary.Conversations : Object {
|
|||
lazy_load_by_id(highest, int.MAX, Folder.ListFlags.EXCLUDING_ID, cancellable_monitor);
|
||||
}
|
||||
|
||||
private void on_folder_message_removed(Geary.EmailIdentifier removed_id) {
|
||||
remove_email(removed_id);
|
||||
private void on_folder_email_removed(Gee.Collection<Geary.EmailIdentifier> removed_ids) {
|
||||
foreach (Geary.EmailIdentifier id in removed_ids)
|
||||
remove_email(id);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -65,14 +65,27 @@ public interface Geary.Folder : Object {
|
|||
public signal void closed(CloseReason reason);
|
||||
|
||||
/**
|
||||
* "messages-appended" is fired when new messages have been appended to the list of messages in
|
||||
* "email-appended" is fired when new messages have been appended to the list of messages in
|
||||
* the folder (and therefore old message position numbers remain valid, but the total count of
|
||||
* the messages in the folder has changed).
|
||||
*/
|
||||
public signal void messages_appended(int total);
|
||||
public signal void email_appended(Gee.Collection<Geary.EmailIdentifier> ids);
|
||||
|
||||
/**
|
||||
* "message-removed" is fired when a message has been removed (deleted or moved) from the
|
||||
* "email-locally-appended" is fired when previously unknown messages have been appended to the
|
||||
* list of messages in the folder. This is similar to "email-appended", but that signal
|
||||
* lists all messages appended to the folder. "email-locally-appended" only reports emails that
|
||||
* have not been seen prior. Hence, an email that is removed from the folder and returned
|
||||
* later will not be listed here (unless it was removed from the local store in the meantime).
|
||||
*
|
||||
* Note that these messages were appended as well, hence their positional addressing may have
|
||||
* changed since last seen in this folder. However, it's important to realize that this list
|
||||
* does *not* represent all newly appended messages.
|
||||
*/
|
||||
public signal void email_locally_appended(Gee.Collection<Geary.EmailIdentifier> ids);
|
||||
|
||||
/**
|
||||
* "email-removed" is fired when a message has been removed (deleted or moved) from the
|
||||
* folder (and therefore old message position numbers may no longer be valid, i.e. those after
|
||||
* the removed message).
|
||||
*
|
||||
|
|
@ -80,14 +93,14 @@ public interface Geary.Folder : Object {
|
|||
* known locally (and therefore the caller could not have record of). If this happens, this
|
||||
* signal will *not* fire, although "email-count-changed" will.
|
||||
*/
|
||||
public signal void message_removed(Geary.EmailIdentifier id);
|
||||
public signal void email_removed(Gee.Collection<Geary.EmailIdentifier> ids);
|
||||
|
||||
/**
|
||||
* "email-count-changed" is fired when the total count of email in a folder has changed in any way.
|
||||
*
|
||||
* Note that this signal will be fired alongside "messages-appended" or "message-removed".
|
||||
* That is, do not use both signals to process email count changes; one will suffice.
|
||||
* This signal will fire after those (although see the note at "message-removed").
|
||||
* This signal will fire after those (although see the note at "messages-removed").
|
||||
*/
|
||||
public signal void email_count_changed(int new_count, CountChangeReason reason);
|
||||
|
||||
|
|
@ -97,8 +110,7 @@ public interface Geary.Folder : Object {
|
|||
* This signal will be fired both when changes occur on the client side via the
|
||||
* mark_email_async() method as well as changes occur remotely.
|
||||
*/
|
||||
public signal void email_flags_changed(Gee.Map<Geary.EmailIdentifier,
|
||||
Geary.EmailFlags> flag_map);
|
||||
public signal void email_flags_changed(Gee.Map<Geary.EmailIdentifier, Geary.EmailFlags> map);
|
||||
|
||||
/**
|
||||
* This helper method should be called by implementors of Folder rather than firing the signal
|
||||
|
|
@ -119,14 +131,21 @@ public interface Geary.Folder : Object {
|
|||
* directly. This allows subclasses and superclasses the opportunity to inspect the email
|
||||
* and update state before and/or after the signal has been fired.
|
||||
*/
|
||||
protected abstract void notify_messages_appended(int total);
|
||||
protected abstract void notify_email_appended(Gee.Collection<Geary.EmailIdentifier> ids);
|
||||
|
||||
/**
|
||||
* This helper method should be called by implementors of Folder rather than firing the signal
|
||||
* directly. This allows subclasses and superclasses the opportunity to inspect the email
|
||||
* and update state before and/or after the signal has been fired.
|
||||
*/
|
||||
protected abstract void notify_message_removed(Geary.EmailIdentifier id);
|
||||
protected abstract void notify_email_locally_appended(Gee.Collection<Geary.EmailIdentifier> ids);
|
||||
|
||||
/**
|
||||
* This helper method should be called by implementors of Folder rather than firing the signal
|
||||
* directly. This allows subclasses and superclasses the opportunity to inspect the email
|
||||
* and update state before and/or after the signal has been fired.
|
||||
*/
|
||||
protected abstract void notify_email_removed(Gee.Collection<Geary.EmailIdentifier> ids);
|
||||
|
||||
/**
|
||||
* This helper method should be called by implementors of Folder rather than firing the signal
|
||||
|
|
@ -271,35 +290,6 @@ public interface Geary.Folder : Object {
|
|||
public abstract void lazy_list_email(int low, int count, Geary.Email.Field required_fields,
|
||||
ListFlags flags, EmailCallback cb, Cancellable? cancellable = null);
|
||||
|
||||
/**
|
||||
* Like list_email_async(), but the caller passes a sparse list of email by it's ordered
|
||||
* position in the folder. If any of the positions in the sparse list are out of range,
|
||||
* only the emails within range are reported. The list is not guaranteed to be in any
|
||||
* particular order.
|
||||
*
|
||||
* See the notes in list_email_async() regarding issues about local versus remote stores.
|
||||
*
|
||||
* The Folder must be opened prior to attempting this operation.
|
||||
*
|
||||
* All positions are one-based.
|
||||
*/
|
||||
public abstract async Gee.List<Geary.Email>? list_email_sparse_async(int[] by_position,
|
||||
Geary.Email.Field required_fields, ListFlags flags, Cancellable? cancellable = null)
|
||||
throws Error;
|
||||
|
||||
/**
|
||||
* Similar in contract to list_email_sparse_async(), but like lazy_list_email(), the
|
||||
* messages are passed back to the caller in chunks as they're retrieved. When null is passed
|
||||
* as the first parameter, all the messages have been fetched. If an Error occurs during
|
||||
* processing, it's passed as the second parameter. There's no guarantee of the returned
|
||||
* messages' order.
|
||||
*
|
||||
* The Folder must be opened prior to attempting this operation.
|
||||
*/
|
||||
public abstract void lazy_list_email_sparse(int[] by_position,
|
||||
Geary.Email.Field required_fields, ListFlags flags, EmailCallback cb,
|
||||
Cancellable? cancellable = null);
|
||||
|
||||
/**
|
||||
* Similar in contract to list_email_async(), but uses Geary.EmailIdentifier rather than
|
||||
* positional addressing. This allows for a batch of messages to be listed from a starting
|
||||
|
|
|
|||
|
|
@ -5,20 +5,29 @@
|
|||
*/
|
||||
|
||||
public abstract class Geary.AbstractFolder : Object, Geary.Folder {
|
||||
protected virtual void notify_opened(Geary.Folder.OpenState state, int count) {
|
||||
/*
|
||||
* notify_* methods for AbstractFolder are marked internal because the SendReplayOperations
|
||||
* need access to them to report changes as they occur.
|
||||
*/
|
||||
|
||||
internal virtual void notify_opened(Geary.Folder.OpenState state, int count) {
|
||||
opened(state, count);
|
||||
}
|
||||
|
||||
protected virtual void notify_closed(Geary.Folder.CloseReason reason) {
|
||||
internal virtual void notify_closed(Geary.Folder.CloseReason reason) {
|
||||
closed(reason);
|
||||
}
|
||||
|
||||
internal virtual void notify_messages_appended(int total) {
|
||||
messages_appended(total);
|
||||
internal virtual void notify_email_appended(Gee.Collection<Geary.EmailIdentifier> ids) {
|
||||
email_appended(ids);
|
||||
}
|
||||
|
||||
internal virtual void notify_message_removed(Geary.EmailIdentifier id) {
|
||||
message_removed(id);
|
||||
internal virtual void notify_email_locally_appended(Gee.Collection<Geary.EmailIdentifier> ids) {
|
||||
email_locally_appended(ids);
|
||||
}
|
||||
|
||||
internal virtual void notify_email_removed(Gee.Collection<Geary.EmailIdentifier> ids) {
|
||||
email_removed(ids);
|
||||
}
|
||||
|
||||
internal virtual void notify_email_count_changed(int new_count, Folder.CountChangeReason reason) {
|
||||
|
|
@ -50,14 +59,6 @@ public abstract class Geary.AbstractFolder : Object, Geary.Folder {
|
|||
public abstract void lazy_list_email(int low, int count, Geary.Email.Field required_fields,
|
||||
Folder.ListFlags flags, EmailCallback cb, Cancellable? cancellable = null);
|
||||
|
||||
public abstract async Gee.List<Geary.Email>? list_email_sparse_async(int[] by_position,
|
||||
Geary.Email.Field required_fields, Folder.ListFlags flags, Cancellable? cancellable = null)
|
||||
throws Error;
|
||||
|
||||
public abstract void lazy_list_email_sparse(int[] by_position,
|
||||
Geary.Email.Field required_fields, Folder.ListFlags flags, EmailCallback cb,
|
||||
Cancellable? cancellable = null);
|
||||
|
||||
public abstract async Gee.List<Geary.Email>? list_email_by_id_async(Geary.EmailIdentifier initial_id,
|
||||
int count, Geary.Email.Field required_fields, Folder.ListFlags flags, Cancellable? cancellable = null)
|
||||
throws Error;
|
||||
|
|
|
|||
|
|
@ -19,9 +19,6 @@ private class Geary.EngineFolder : Geary.AbstractFolder {
|
|||
private SendReplayQueue? send_replay_queue = null;
|
||||
private NonblockingMutex normalize_email_positions_mutex = new NonblockingMutex();
|
||||
|
||||
public virtual signal void local_added(Gee.Collection<Geary.EmailIdentifier> added) {
|
||||
}
|
||||
|
||||
public EngineFolder(Imap.Account remote, Sqlite.Account local, Sqlite.Folder local_folder) {
|
||||
this.remote = remote;
|
||||
this.local = local;
|
||||
|
|
@ -33,10 +30,6 @@ private class Geary.EngineFolder : Geary.AbstractFolder {
|
|||
warning("Folder %s destroyed without closing", to_string());
|
||||
}
|
||||
|
||||
protected virtual void notify_local_added(Gee.Collection<Geary.EmailIdentifier> added) {
|
||||
local_added(added);
|
||||
}
|
||||
|
||||
public override Geary.FolderPath get_path() {
|
||||
return local_folder.get_path();
|
||||
}
|
||||
|
|
@ -245,19 +238,25 @@ private class Geary.EngineFolder : Geary.AbstractFolder {
|
|||
|
||||
Gee.HashSet<Geary.EmailIdentifier> created = new Gee.HashSet<Geary.EmailIdentifier>(
|
||||
Hashable.hash_func, Equalable.equal_func);
|
||||
Gee.HashSet<Geary.EmailIdentifier> appended = new Gee.HashSet<Geary.EmailIdentifier>(
|
||||
Hashable.hash_func, Equalable.equal_func);
|
||||
foreach (Geary.Email email in list) {
|
||||
debug("Creating Email ID %s", email.id.to_string());
|
||||
|
||||
// need to report both if it was created (not known before) and appended (which
|
||||
// could mean created or simply a known email associated with this folder)
|
||||
if (yield local_folder.create_email_async(email, null))
|
||||
created.add(email.id);
|
||||
|
||||
appended.add(email.id);
|
||||
}
|
||||
|
||||
// save new remote count
|
||||
remote_count = new_remote_count;
|
||||
|
||||
notify_messages_appended(new_remote_count);
|
||||
|
||||
notify_email_appended(appended);
|
||||
if (created.size > 0)
|
||||
notify_local_added(created);
|
||||
notify_email_locally_appended(created);
|
||||
} catch (Error err) {
|
||||
debug("Unable to normalize local store of newly appended messages to %s: %s",
|
||||
to_string(), err.message);
|
||||
|
|
@ -295,7 +294,7 @@ private class Geary.EngineFolder : Geary.AbstractFolder {
|
|||
yield local_folder.remove_marked_email_async(owned_id, out marked, null);
|
||||
|
||||
if (!marked)
|
||||
notify_message_removed(owned_id);
|
||||
notify_email_removed(new Geary.Singleton<Geary.EmailIdentifier>(owned_id));
|
||||
} catch (Error err2) {
|
||||
debug("Unable to remove message #%d from %s: %s", remote_position, to_string(),
|
||||
err2.message);
|
||||
|
|
@ -375,48 +374,6 @@ private class Geary.EngineFolder : Geary.AbstractFolder {
|
|||
yield op.wait_for_ready();
|
||||
}
|
||||
|
||||
public override async Gee.List<Geary.Email>? list_email_sparse_async(int[] by_position,
|
||||
Geary.Email.Field required_fields, Folder.ListFlags flags, Cancellable? cancellable = null)
|
||||
throws Error {
|
||||
if (by_position.length == 0)
|
||||
return null;
|
||||
|
||||
Gee.List<Geary.Email> accumulator = new Gee.ArrayList<Geary.Email>();
|
||||
yield do_list_email_sparse_async(by_position, required_fields, accumulator, null,
|
||||
cancellable, flags.is_all_set(Folder.ListFlags.LOCAL_ONLY));
|
||||
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
// TODO: Capture Error and report via EmailCallback.
|
||||
public override void lazy_list_email_sparse(int[] by_position, Geary.Email.Field required_fields,
|
||||
Folder.ListFlags flags, EmailCallback cb, Cancellable? cancellable = null) {
|
||||
// schedule listing in the background, using the callback to drive availability of email
|
||||
do_list_email_sparse_async.begin(by_position, required_fields, null, cb, cancellable,
|
||||
flags.is_all_set(Folder.ListFlags.LOCAL_ONLY));
|
||||
}
|
||||
|
||||
private async void do_list_email_sparse_async(int[] by_position, Geary.Email.Field required_fields,
|
||||
Gee.List<Geary.Email>? accumulator, EmailCallback? cb, Cancellable? cancellable, bool local_only)
|
||||
throws Error {
|
||||
if (!opened)
|
||||
throw new EngineError.OPEN_REQUIRED("%s is not open", to_string());
|
||||
|
||||
if (by_position.length == 0) {
|
||||
// signal finished
|
||||
if (cb != null)
|
||||
cb(null, null);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Schedule list operation and wait for completion.
|
||||
ListEmailSparse op = new ListEmailSparse(this, by_position, required_fields, accumulator,
|
||||
cb, cancellable, local_only);
|
||||
send_replay_queue.schedule(op);
|
||||
yield op.wait_for_ready();
|
||||
}
|
||||
|
||||
public override async Gee.List<Geary.Email>? list_email_by_id_async(Geary.EmailIdentifier initial_id,
|
||||
int count, Geary.Email.Field required_fields, Folder.ListFlags flags,
|
||||
Cancellable? cancellable = null) throws Error {
|
||||
|
|
@ -529,7 +486,7 @@ private class Geary.EngineFolder : Geary.AbstractFolder {
|
|||
}
|
||||
|
||||
if (created_ids.size > 0)
|
||||
notify_local_added(created_ids);
|
||||
notify_email_locally_appended(created_ids);
|
||||
|
||||
if (cb != null)
|
||||
cb(remote_list, null);
|
||||
|
|
@ -579,13 +536,8 @@ private class Geary.EngineFolder : Geary.AbstractFolder {
|
|||
Geary.Email email = yield remote_folder.fetch_email_async(id, fields, cancellable);
|
||||
|
||||
// save to local store
|
||||
if (yield local_folder.create_email_async(email, cancellable)) {
|
||||
// TODO: A Singleton collection would be useful here.
|
||||
Gee.ArrayList<Geary.EmailIdentifier> ids = new Gee.ArrayList<Geary.EmailIdentifier>();
|
||||
ids.add(email.id);
|
||||
|
||||
notify_local_added(ids);
|
||||
}
|
||||
if (yield local_folder.create_email_async(email, cancellable))
|
||||
notify_email_locally_appended(new Geary.Singleton<Geary.EmailIdentifier>(email.id));
|
||||
|
||||
return email;
|
||||
}
|
||||
|
|
@ -681,7 +633,7 @@ private class Geary.EngineFolder : Geary.AbstractFolder {
|
|||
}
|
||||
|
||||
if (created_ids.size > 0)
|
||||
notify_local_added(created_ids);
|
||||
notify_email_locally_appended(created_ids);
|
||||
} catch (Error e) {
|
||||
local_count = 0; // prevent compiler warning
|
||||
error = e;
|
||||
|
|
|
|||
|
|
@ -165,6 +165,7 @@ private class Geary.GenericImapFolder : Geary.EngineFolder {
|
|||
|
||||
int remote_ctr = 0;
|
||||
int local_ctr = 0;
|
||||
Gee.ArrayList<Geary.EmailIdentifier> appended_ids = new Gee.ArrayList<Geary.EmailIdentifier>();
|
||||
Gee.ArrayList<Geary.EmailIdentifier> removed_ids = new Gee.ArrayList<Geary.EmailIdentifier>();
|
||||
Gee.Map<Geary.EmailIdentifier, Geary.EmailFlags> flags_changed = new Gee.HashMap<Geary.EmailIdentifier,
|
||||
Geary.EmailFlags>();
|
||||
|
|
@ -195,6 +196,7 @@ private class Geary.GenericImapFolder : Geary.EngineFolder {
|
|||
} else if (remote_uid.value < local_uid.value) {
|
||||
// one we'd not seen before is present, add and move to next remote
|
||||
batch.add(new CreateLocalEmailOperation(local_folder, remote_email));
|
||||
appended_ids.add(remote_email.id);
|
||||
|
||||
remote_ctr++;
|
||||
} else {
|
||||
|
|
@ -212,10 +214,9 @@ private class Geary.GenericImapFolder : Geary.EngineFolder {
|
|||
// CreateEmailOperations were updates of emails existing previously or additions of emails
|
||||
// that were on the server earlier but not stored locally (i.e. this value represents emails
|
||||
// added to the top of the stack)
|
||||
int appended = 0;
|
||||
for (; remote_ctr < remote_length; remote_ctr++) {
|
||||
batch.add(new CreateLocalEmailOperation(local_folder, old_remote[remote_ctr]));
|
||||
appended++;
|
||||
appended_ids.add(old_remote[remote_ctr].id);
|
||||
}
|
||||
|
||||
// remove anything left over ... use local count rather than remote as we're still in a stage
|
||||
|
|
@ -240,14 +241,13 @@ private class Geary.GenericImapFolder : Geary.EngineFolder {
|
|||
// signalled)
|
||||
if (removed_ids.size > 0) {
|
||||
debug("Notifying of %d removed emails since %s last seen", removed_ids.size, to_string());
|
||||
foreach (Geary.EmailIdentifier removed_id in removed_ids)
|
||||
notify_message_removed(removed_id);
|
||||
notify_email_removed(removed_ids);
|
||||
}
|
||||
|
||||
// notify additions
|
||||
if (appended > 0) {
|
||||
debug("Notifying of %d appended emails since %s last seen", appended, to_string());
|
||||
notify_messages_appended(appended);
|
||||
if (appended_ids.size > 0) {
|
||||
debug("Notifying of %d appended emails since %s last seen", appended_ids.size, to_string());
|
||||
notify_email_appended(appended_ids);
|
||||
}
|
||||
|
||||
// notify flag changes
|
||||
|
|
@ -282,10 +282,10 @@ private class Geary.GenericImapFolder : Geary.EngineFolder {
|
|||
base.notify_closed(reason);
|
||||
}
|
||||
|
||||
protected override void notify_local_added(Gee.Collection<Geary.EmailIdentifier> added) {
|
||||
schedule_prefetch(added);
|
||||
protected override void notify_email_locally_appended(Gee.Collection<Geary.EmailIdentifier> ids) {
|
||||
schedule_prefetch(ids);
|
||||
|
||||
base.notify_local_added(added);
|
||||
base.notify_email_locally_appended(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ private class Geary.MarkEmail : Geary.SendReplayOperation {
|
|||
private Geary.EmailFlags? flags_to_remove;
|
||||
private Gee.Map<Geary.EmailIdentifier, Geary.EmailFlags>? original_flags = null;
|
||||
private Cancellable? cancellable;
|
||||
|
||||
|
||||
public MarkEmail(EngineFolder engine, Gee.List<Geary.EmailIdentifier> to_mark,
|
||||
Geary.EmailFlags? flags_to_add, Geary.EmailFlags? flags_to_remove,
|
||||
Cancellable? cancellable = null) {
|
||||
|
|
@ -70,7 +70,7 @@ private class Geary.RemoveEmail : Geary.SendReplayOperation {
|
|||
public override async bool replay_local() throws Error {
|
||||
foreach (Geary.EmailIdentifier id in to_remove) {
|
||||
yield engine.local_folder.mark_removed_async(id, true, cancellable);
|
||||
engine.notify_message_removed(id);
|
||||
engine.notify_email_removed(new Geary.Singleton<Geary.EmailIdentifier>(id));
|
||||
}
|
||||
|
||||
original_count = engine.remote_count;
|
||||
|
|
@ -93,8 +93,8 @@ private class Geary.RemoveEmail : Geary.SendReplayOperation {
|
|||
foreach (Geary.EmailIdentifier id in to_remove)
|
||||
yield engine.local_folder.mark_removed_async(id, false, cancellable);
|
||||
|
||||
engine.notify_messages_appended(to_remove.size);
|
||||
engine.notify_email_count_changed(original_count, Geary.Folder.CountChangeReason.REMOVED);
|
||||
engine.notify_email_appended(to_remove);
|
||||
engine.notify_email_count_changed(original_count, Geary.Folder.CountChangeReason.ADDED);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
85
src/engine/util/util-singleton.vala
Executable file
85
src/engine/util/util-singleton.vala
Executable file
|
|
@ -0,0 +1,85 @@
|
|||
/* Copyright 2012 Yorba Foundation
|
||||
*
|
||||
* This software is licensed under the GNU Lesser General Public License
|
||||
* (version 2.1 or later). See the COPYING file in this distribution.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Singleton is a simple way of creating a one-item read-only collection.
|
||||
*/
|
||||
private class Geary.Singleton<G> : Gee.AbstractCollection<G> {
|
||||
private class IteratorImpl<G> : Object, Gee.Iterator<G> {
|
||||
private G item;
|
||||
private bool done = false;
|
||||
|
||||
public IteratorImpl(G item) {
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
public bool first() {
|
||||
done = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public new G? get() {
|
||||
return item;
|
||||
}
|
||||
|
||||
public bool has_next() {
|
||||
return !done;
|
||||
}
|
||||
|
||||
public bool next() {
|
||||
if (done)
|
||||
return false;
|
||||
|
||||
done = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
message("Geary.Singleton is read-only");
|
||||
}
|
||||
}
|
||||
|
||||
public G item { get; private set; }
|
||||
public override int size { get { return 1; } }
|
||||
|
||||
private EqualFunc equal_func;
|
||||
|
||||
public Singleton(G item, EqualFunc? equal_func = null) {
|
||||
this.item = item;
|
||||
|
||||
if (equal_func != null)
|
||||
this.equal_func = equal_func;
|
||||
else if (typeof(G).is_a(typeof(Geary.Equalable)))
|
||||
this.equal_func = Geary.Equalable.equal_func;
|
||||
else
|
||||
this.equal_func = Gee.Functions.get_equal_func_for(typeof(G));
|
||||
}
|
||||
|
||||
public override bool add(G element) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void clear() {
|
||||
message("Geary.Singleton is read-only");
|
||||
}
|
||||
|
||||
public override bool contains(G element) {
|
||||
return equal_func(item, element);
|
||||
}
|
||||
|
||||
public override Gee.Iterator<G> iterator() {
|
||||
return new IteratorImpl<G>(item);
|
||||
}
|
||||
|
||||
public override bool remove(G element) {
|
||||
message("Geary.Singleton is read-only");
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -155,6 +155,7 @@ def build(bld):
|
|||
'../engine/util/util-numeric.vala',
|
||||
'../engine/util/util-reference-semantics.vala',
|
||||
'../engine/util/util-scheduler.vala',
|
||||
'../engine/util/util-singleton.vala',
|
||||
'../engine/util/util-stream.vala',
|
||||
'../engine/util/util-string.vala',
|
||||
'../engine/util/util-trillian.vala'
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue