[geary/wip/730682-refine-convo-list] Move Controller's ConversationMonitor to MainWindow.
- From: Michael Gratton <mjog src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/wip/730682-refine-convo-list] Move Controller's ConversationMonitor to MainWindow.
- Date: Wed, 3 Jan 2018 09:03:21 +0000 (UTC)
commit fa62f4e1475ed01ff7d11389c40ff024ceb70325
Author: Michael James Gratton <mike vee net>
Date: Thu Dec 28 11:44:53 2017 +1100
Move Controller's ConversationMonitor to MainWindow.
It's per-window specific, and managing it there means we can make the
folder/monitor loading process more obvious.
* src/client/components/main-window.vala (MainWindow): Add a
ConversationMonitor, merge folder and monitor management code so we are
now updating the folder and closing the monitor as needed. When
closing the window, ensure the conversation monitor is stopped.
* src/client/application/geary-controller.vala (GearyController): Remove
ConversationMonitor instance and related code. When quitting, close the
main window if not already closing.
src/client/application/geary-controller.vala | 68 ++-------
src/client/components/main-window.vala | 154 +++++++++++---------
.../conversation-list/conversation-list-view.vala | 80 +++++-----
3 files changed, 140 insertions(+), 162 deletions(-)
---
diff --git a/src/client/application/geary-controller.vala b/src/client/application/geary-controller.vala
index 4317efa..578eb7d 100644
--- a/src/client/application/geary-controller.vala
+++ b/src/client/application/geary-controller.vala
@@ -47,11 +47,6 @@ public class GearyController : Geary.BaseObject {
public const string ACTION_TOGGLE_SEARCH = "toggle-search";
public const string ACTION_TOGGLE_FIND = "toggle-find";
- // Properties
- public const string PROP_CURRENT_CONVERSATION ="current-conversations";
-
- internal const int CONVERSATION_PAGE_SIZE = 50;
-
private const int SELECT_FOLDER_TIMEOUT_USEC = 100 * 1000;
private const string PROP_ATTEMPT_OPEN_ACCOUNT = "attempt-open-account";
@@ -59,11 +54,9 @@ public class GearyController : Geary.BaseObject {
public weak GearyApplication application { get; private set; } // circular ref
public MainWindow main_window { get; private set; }
-
- public Geary.App.ConversationMonitor? current_conversations { get; private set; default = null; }
-
+
public AutostartManager? autostart_manager { get; private set; default = null; }
-
+
public LoginDialog? login_dialog { get; private set; default = null; }
public Soup.Session? avatar_session { get; private set; default = null; }
@@ -301,31 +294,17 @@ public class GearyController : Geary.BaseObject {
on_conversation_view_added
);
- // hide window while shutting down, as this can take a few seconds under certain conditions
- main_window.hide();
-
+ // Ensure the main window is closed if not already doing so
+ // that its conversation monitor stops accessing the network.
+ if (!this.main_window.is_closing) {
+ main_window.close();
+ }
+
// drop the Revokable, which will commit it if necessary
save_revokable(null, null);
this.autostart_manager = null;
- // Close the ConversationMonitor
- if (current_conversations != null) {
- debug("Stopping conversation monitor for %s...",
- this.current_conversations.base_folder.to_string());
- try {
- yield this.current_conversations.stop_monitoring_async(null);
- } catch (Error err) {
- debug(
- "Error closing conversation monitor %s at shutdown: %s",
- this.current_conversations.base_folder.to_string(),
- err.message
- );
- } finally {
- this.current_conversations = null;
- }
- }
-
// Close all inboxes. Launch these in parallel so we're not
// waiting time waiting for each one to close. The account
// will wait around for them to actually close.
@@ -1375,21 +1354,10 @@ public class GearyController : Geary.BaseObject {
// mutex lock is a bandaid solution to make the function safe to
// reenter.
int mutex_token = yield select_folder_mutex.claim_async(cancellable_folder);
-
- bool current_is_inbox = inboxes.values.contains(current_folder);
-
- Cancellable? conversation_cancellable = (current_is_inbox ?
- inbox_cancellables.get(folder.account) : cancellable_folder);
-
+
// clear Revokable, as Undo is only available while a folder is selected
save_revokable(null, null);
- // stop monitoring for conversations and close the folder
- if (current_conversations != null) {
- yield current_conversations.stop_monitoring_async(null);
- current_conversations = null;
- }
-
// re-enable copy/move to the last selected folder
if (current_folder != null) {
main_window.main_toolbar.copy_folder_menu.enable_disable_folder(current_folder, true);
@@ -1434,21 +1402,11 @@ public class GearyController : Geary.BaseObject {
!(current_folder is Geary.FolderSupport.Remove)
);
- current_conversations = new Geary.App.ConversationMonitor(
- current_folder,
- Geary.Folder.OpenFlags.NO_DELAY,
- ConversationListModel.REQUIRED_FIELDS,
- CONVERSATION_PAGE_SIZE * 2 // load double up front when not scrolling
- );
-
if (inboxes.values.contains(current_folder)) {
// Inbox selected, clear new messages if visible
clear_new_messages("do_select_folder (inbox)", null);
}
- if (!current_conversations.is_monitoring)
- yield current_conversations.start_monitoring_async(conversation_cancellable);
-
select_folder_mutex.release(ref mutex_token);
debug("Switched to %s", folder.to_string());
@@ -1459,11 +1417,11 @@ public class GearyController : Geary.BaseObject {
if (folder == null || email == null || !can_switch_conversation_view())
return;
-
- main_window.folder_list.select_folder(folder);
- Geary.App.Conversation? conversation = current_conversations.get_conversation_for_email(email.id);
+
+ this.main_window.folder_list.select_folder(folder);
+ Geary.App.Conversation? conversation =
this.main_window.current_conversations.get_conversation_for_email(email.id);
if (conversation != null)
- main_window.conversation_list.select_conversation(conversation);
+ this.main_window.conversation_list.select_conversation(conversation);
}
private void on_indicator_activated_application(uint32 timestamp) {
diff --git a/src/client/components/main-window.vala b/src/client/components/main-window.vala
index 97f0e09..afc9d7a 100644
--- a/src/client/components/main-window.vala
+++ b/src/client/components/main-window.vala
@@ -23,6 +23,8 @@ public class MainWindow : Gtk.ApplicationWindow {
public const string ACTION_SELECTION_MODE_DISABLE = "selection-mode-disable";
public const string ACTION_SELECTION_MODE_ENABLE = "selection-mode-enable";
+ internal const int CONVERSATION_PAGE_SIZE = 50;
+
private const int STATUS_BAR_HEIGHT = 18;
private const ActionEntry[] action_entries = {
@@ -51,6 +53,9 @@ public class MainWindow : Gtk.ApplicationWindow {
public int window_height { get; set; }
public bool window_maximized { get; set; }
+ /** Determines if the window is shutting down. */
+ public bool is_closing { get; private set; default = false; }
+
// Widget descendants
public FolderList.Tree folder_list { get; private set; default = new FolderList.Tree(); }
public MainToolbar main_toolbar { get; private set; }
@@ -60,12 +65,13 @@ public class MainWindow : Gtk.ApplicationWindow {
public StatusBar status_bar { get; private set; default = new StatusBar(); }
public Geary.Folder? current_folder { get; private set; default = null; }
+ public Geary.App.ConversationMonitor? current_conversations { get; private set; default = null; }
+ private Cancellable load_cancellable = new Cancellable();
private ConversationActionBar conversation_list_actions =
new ConversationActionBar();
private Geary.AggregateProgressMonitor progress_monitor =
new Geary.AggregateProgressMonitor();
- private Geary.ProgressMonitor? folder_progress = null;
private MonitoredSpinner spinner = new MonitoredSpinner();
@@ -117,8 +123,6 @@ public class MainWindow : Gtk.ApplicationWindow {
load_config(application.config);
restore_saved_window_state();
- application.controller.notify[GearyController.PROP_CURRENT_CONVERSATION]
- .connect(on_conversation_monitor_changed);
application.controller.folder_selected.connect(on_folder_selected);
this.application.engine.account_available.connect(on_account_available);
this.application.engine.account_unavailable.connect(on_account_unavailable);
@@ -424,8 +428,74 @@ public class MainWindow : Gtk.ApplicationWindow {
}
}
- private inline SimpleAction get_action(string name) {
- return (SimpleAction) lookup_action(name);
+ private void update_folder(Geary.Folder folder) {
+ debug("Loading new folder: %s...", folder.to_string());
+ this.conversation_list.freeze_selection();
+
+ if (this.current_folder != null) {
+ this.progress_monitor.remove(this.current_folder.opening_monitor);
+ this.progress_monitor.remove(this.current_conversations.progress_monitor);
+ this.progress_monitor.remove(this.conversation_list.model.previews.progress);
+
+ this.current_folder.properties.notify.disconnect(update_headerbar);
+ this.stop_conversation_monitor.begin();
+ }
+
+ folder.properties.notify.connect(update_headerbar);
+ this.current_folder = folder;
+
+ // Set up a new conversation monitor for the folder
+ Geary.App.ConversationMonitor monitor = new Geary.App.ConversationMonitor(
+ folder,
+ Geary.Folder.OpenFlags.NO_DELAY,
+ ConversationListModel.REQUIRED_FIELDS,
+ CONVERSATION_PAGE_SIZE * 2 // load double up front when not scrolling
+ );
+ monitor.scan_error.connect(on_scan_error);
+ monitor.seed_completed.connect(on_seed_completed);
+ monitor.seed_completed.connect(on_initial_conversation_load);
+ monitor.seed_completed.connect(on_conversation_count_changed);
+ monitor.scan_completed.connect(on_conversation_count_changed);
+ monitor.conversations_added.connect(on_conversation_count_changed);
+ monitor.conversations_removed.connect(on_conversation_count_changed);
+ monitor.email_flags_changed.connect(on_conversation_flags_changed);
+
+ this.current_conversations = monitor;
+ this.conversation_list.bind_model(monitor);
+
+ // Update the UI
+ this.conversation_list_actions.set_account(folder.account);
+ this.conversation_list_actions.update_location(this.current_folder);
+ update_headerbar();
+ set_selection_mode_enabled(false);
+
+ this.progress_monitor.add(folder.opening_monitor);
+ this.progress_monitor.add(monitor.progress_monitor);
+ this.progress_monitor.add(this.conversation_list.model.previews.progress);
+
+ // Finally, start the folder loading
+ this.load_cancellable = new Cancellable();
+ monitor.start_monitoring_async.begin(this.load_cancellable);
+ this.conversation_list.thaw_selection();
+ }
+
+ private async void stop_conversation_monitor() {
+ Geary.App.ConversationMonitor old_monitor = this.current_conversations;
+ if (old_monitor != null) {
+ this.current_conversations = null;
+
+ // Cancel any pending operations, then shut it down
+ this.load_cancellable.cancel();
+ try {
+ yield old_monitor.stop_monitoring_async(null);
+ } catch (Error err) {
+ debug(
+ "Error closing conversation monitor %s on close: %s",
+ old_monitor.base_folder.to_string(),
+ err.message
+ );
+ }
+ }
}
private void show_conversation(Geary.App.Conversation? target) {
@@ -478,72 +548,14 @@ public class MainWindow : Gtk.ApplicationWindow {
err.message);
}
- private void on_conversation_monitor_changed() {
- this.conversation_list.freeze_selection();
- ConversationListModel? old_model = this.conversation_list.model;
- if (old_model != null) {
- this.progress_monitor.remove(old_model.monitor.progress_monitor);
- this.progress_monitor.remove(old_model.previews.progress);
-
- Geary.App.ConversationMonitor? old_monitor = old_model.monitor;
- old_monitor.scan_error.disconnect(on_scan_error);
- old_monitor.seed_completed.disconnect(on_seed_completed);
- old_monitor.seed_completed.disconnect(on_conversation_count_changed);
- old_monitor.seed_completed.disconnect(on_initial_conversation_load);
- old_monitor.scan_completed.disconnect(on_conversation_count_changed);
- old_monitor.conversations_added.disconnect(on_conversation_count_changed);
- old_monitor.conversations_removed.disconnect(on_conversation_count_changed);
- old_monitor.email_flags_changed.disconnect(on_conversation_flags_changed);
- }
-
- Geary.App.ConversationMonitor? new_monitor =
- this.application.controller.current_conversations;
- if (new_monitor != null) {
- this.conversation_list.bind_model(new_monitor);
- ConversationListModel new_model = this.conversation_list.model;
-
- this.progress_monitor.add(new_model.monitor.progress_monitor);
- this.progress_monitor.add(new_model.previews.progress);
-
- new_monitor.scan_error.connect(on_scan_error);
- new_monitor.seed_completed.connect(on_seed_completed);
- new_monitor.seed_completed.connect(on_conversation_count_changed);
- new_monitor.seed_completed.connect(on_initial_conversation_load);
- new_monitor.scan_completed.connect(on_conversation_count_changed);
- new_monitor.conversations_added.connect(on_conversation_count_changed);
- new_monitor.conversations_removed.connect(on_conversation_count_changed);
- new_monitor.email_flags_changed.connect(on_conversation_flags_changed);
- }
- this.conversation_list.thaw_selection();
+ private inline SimpleAction get_action(string name) {
+ return (SimpleAction) lookup_action(name);
}
private void on_folder_selected(Geary.Folder? folder) {
- if (this.folder_progress != null) {
- this.progress_monitor.remove(this.folder_progress);
- this.folder_progress = null;
- }
-
- if (folder != null) {
- this.folder_progress = folder.opening_monitor;
- this.progress_monitor.add(this.folder_progress);
- }
-
- // disconnect from old folder
- if (this.current_folder != null)
- this.current_folder.properties.notify.disconnect(update_headerbar);
-
- // connect to new folder
if (folder != null) {
- folder.properties.notify.connect(update_headerbar);
- this.conversation_list_actions.set_account(folder.account);
- this.conversation_list_actions.update_location(this.current_folder);
+ update_folder(folder);
}
-
- // swap it in
- this.current_folder = folder;
-
- update_headerbar();
- set_selection_mode_enabled(false);
}
private void on_account_available(Geary.AccountInformation account) {
@@ -639,7 +651,9 @@ public class MainWindow : Gtk.ApplicationWindow {
private void on_load_more() {
debug("on_load_more");
- this.application.controller.current_conversations.min_window_count +=
GearyController.CONVERSATION_PAGE_SIZE;
+ if (this.current_conversations != null) {
+ this.current_conversations.min_window_count += CONVERSATION_PAGE_SIZE;
+ }
}
private void on_scan_error(Error err) {
@@ -683,6 +697,12 @@ public class MainWindow : Gtk.ApplicationWindow {
hide();
}
} else {
+ set_sensitive(false);
+ this.is_closing = true;
+ this.stop_conversation_monitor.begin((obj, res) => {
+ this.stop_conversation_monitor.end(res);
+ hide();
+ });
this.application.exit();
}
return Gdk.EVENT_STOP;
diff --git a/src/client/conversation-list/conversation-list-view.vala
b/src/client/conversation-list/conversation-list-view.vala
index c636be1..ec4f72f 100644
--- a/src/client/conversation-list/conversation-list-view.vala
+++ b/src/client/conversation-list/conversation-list-view.vala
@@ -16,7 +16,7 @@ public class ConversationListView : Gtk.TreeView {
// scroll adjustment seen at the call to load_more().
private double last_upper = -1.0;
private bool reset_adjustment = false;
- private Geary.App.ConversationMonitor? conversation_monitor;
+ //private Geary.App.ConversationMonitor? conversation_monitor;
private Gee.Set<Geary.App.Conversation>? current_visible_conversations = null;
private Geary.Scheduler.Scheduled? scheduled_update_visible_conversations = null;
private Gee.Set<Geary.App.Conversation> selected = new Gee.HashSet<Geary.App.Conversation>();
@@ -61,8 +61,8 @@ public class ConversationListView : Gtk.TreeView {
GearyApplication.instance.config.settings.changed[Configuration.DISPLAY_PREVIEW_KEY].connect(
on_display_preview_changed);
- GearyApplication.instance.controller.notify[GearyController.PROP_CURRENT_CONVERSATION].
- connect(on_conversation_monitor_changed);
+ // GearyApplication.instance.controller.notify[GearyController.PROP_CURRENT_CONVERSATION].
+ // connect(on_conversation_monitor_changed);
// Watch for mouse events.
motion_notify_event.connect(on_motion_notify_event);
@@ -134,47 +134,47 @@ public class ConversationListView : Gtk.TreeView {
}
}
- private void on_conversation_monitor_changed() {
- if (conversation_monitor != null) {
- conversation_monitor.scan_started.disconnect(on_scan_started);
- conversation_monitor.scan_completed.disconnect(on_scan_completed);
- conversation_monitor.seed_completed.disconnect(on_seed_completed);
- }
+ // private void on_conversation_monitor_changed() {
+ // if (conversation_monitor != null) {
+ // conversation_monitor.scan_started.disconnect(on_scan_started);
+ // conversation_monitor.scan_completed.disconnect(on_scan_completed);
+ // conversation_monitor.seed_completed.disconnect(on_seed_completed);
+ // }
- conversation_monitor = GearyApplication.instance.controller.current_conversations;
+ // conversation_monitor = GearyApplication.instance.controller.current_conversations;
- if (conversation_monitor != null) {
- conversation_monitor.scan_started.connect(on_scan_started);
- conversation_monitor.scan_completed.connect(on_scan_completed);
- conversation_monitor.seed_completed.connect(on_seed_completed);
- }
- }
+ // if (conversation_monitor != null) {
+ // conversation_monitor.scan_started.connect(on_scan_started);
+ // conversation_monitor.scan_completed.connect(on_scan_completed);
+ // conversation_monitor.seed_completed.connect(on_seed_completed);
+ // }
+ // }
- private void on_scan_started() {
- enable_load_more = false;
- }
+ // private void on_scan_started() {
+ // enable_load_more = false;
+ // }
- private void on_scan_completed() {
- enable_load_more = true;
-
- // Select the first conversation, if autoselect is enabled,
- // nothing has been selected yet and we're not composing. Do
- // this here instead of in on_seed_completed since we want to
- // to select the first row on folder change as soon as
- // possible.
- if (GearyApplication.instance.config.autoselect &&
- get_selection().count_selected_rows() == 0 &&
- !GearyApplication.instance.controller.any_inline_composers()) {
- set_cursor(new Gtk.TreePath.from_indices(0, -1), null, false);
- }
- }
-
- private void on_seed_completed() {
- if (!GearyApplication.instance.config.autoselect) {
- // Notify that no conversations will be selected
- conversations_selected(this.selected.read_only_view);
- }
- }
+ // private void on_scan_completed() {
+ // enable_load_more = true;
+
+ // // Select the first conversation, if autoselect is enabled,
+ // // nothing has been selected yet and we're not composing. Do
+ // // this here instead of in on_seed_completed since we want to
+ // // to select the first row on folder change as soon as
+ // // possible.
+ // if (GearyApplication.instance.config.autoselect &&
+ // get_selection().count_selected_rows() == 0 &&
+ // !GearyApplication.instance.controller.any_inline_composers()) {
+ // set_cursor(new Gtk.TreePath.from_indices(0, -1), null, false);
+ // }
+ // }
+
+ // private void on_seed_completed() {
+ // if (!GearyApplication.instance.config.autoselect) {
+ // // Notify that no conversations will be selected
+ // conversations_selected(this.selected.read_only_view);
+ // }
+ // }
private void on_conversations_added(bool start) {
Gtk.Adjustment? adjustment = get_adjustment();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]