Closes #7154 DB upgrade dialog
This commit is contained in:
parent
a2f6ad8c38
commit
ffa642f458
11 changed files with 267 additions and 17 deletions
|
|
@ -299,6 +299,7 @@ client/dialogs/alert-dialog.vala
|
|||
client/dialogs/attachment-dialog.vala
|
||||
client/dialogs/password-dialog.vala
|
||||
client/dialogs/preferences-dialog.vala
|
||||
client/dialogs/upgrade-dialog.vala
|
||||
|
||||
client/folder-list/folder-list-abstract-folder-entry.vala
|
||||
client/folder-list/folder-list-account-branch.vala
|
||||
|
|
|
|||
67
src/client/dialogs/upgrade-dialog.vala
Normal file
67
src/client/dialogs/upgrade-dialog.vala
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/* Copyright 2013 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.
|
||||
*/
|
||||
|
||||
public class UpgradeDialog : Object {
|
||||
public const string PROP_VISIBLE_NAME = "visible";
|
||||
|
||||
// Progress monitor associated with the upgrade.
|
||||
public Geary.AggregateProgressMonitor monitor { public get; private set;
|
||||
default = new Geary.AggregateProgressMonitor(); }
|
||||
|
||||
// Whether or not this dialog is visible.
|
||||
public bool visible { get; set; }
|
||||
|
||||
private Gtk.Dialog dialog;
|
||||
private Gee.HashSet<Cancellable> cancellables = new Gee.HashSet<Cancellable>();
|
||||
|
||||
/**
|
||||
* Creates and loads the upgrade progress dialog.
|
||||
*/
|
||||
public UpgradeDialog() {
|
||||
// Load UI.
|
||||
Gtk.Builder builder = GearyApplication.instance.create_builder("upgrade_dialog.glade");
|
||||
dialog = (Gtk.Dialog) builder.get_object("dialog");
|
||||
|
||||
// Hook up signals.
|
||||
monitor.start.connect(on_start);
|
||||
monitor.finish.connect(on_close);
|
||||
dialog.delete_event.connect(on_delete_event);
|
||||
|
||||
// Bind visibility flag.
|
||||
dialog.bind_property(PROP_VISIBLE_NAME, this, PROP_VISIBLE_NAME, BindingFlags.BIDIRECTIONAL |
|
||||
BindingFlags.SYNC_CREATE);
|
||||
}
|
||||
|
||||
private void on_start() {
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
private bool on_delete_event() {
|
||||
// Don't allow window to close until we're finished.
|
||||
return !monitor.is_in_progress;
|
||||
}
|
||||
|
||||
private void on_close() {
|
||||
// If the user quit the dialog before the upgrade completed, cancel everything.
|
||||
if (monitor.is_in_progress) {
|
||||
foreach(Cancellable c in cancellables)
|
||||
c.cancel();
|
||||
}
|
||||
|
||||
if (dialog.visible)
|
||||
dialog.destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add accounts before opening them.
|
||||
*/
|
||||
public void add_account(Geary.Account account, Cancellable? cancellable = null) {
|
||||
monitor.add(account.db_upgrade_monitor);
|
||||
if (cancellable != null)
|
||||
cancellables.add(cancellable);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -58,6 +58,8 @@ public class GearyController {
|
|||
private const int SELECT_FOLDER_TIMEOUT_MSEC = 100;
|
||||
private const int SEARCH_TIMEOUT_MSEC = 100;
|
||||
|
||||
private const string PROP_ATTEMPT_OPEN_ACCOUNT = "attempt-open-account";
|
||||
|
||||
public MainWindow main_window { get; private set; }
|
||||
|
||||
private Geary.Account? current_account = null;
|
||||
|
|
@ -68,6 +70,7 @@ public class GearyController {
|
|||
private Cancellable cancellable_folder = new Cancellable();
|
||||
private Cancellable cancellable_message = new Cancellable();
|
||||
private Cancellable cancellable_search = new Cancellable();
|
||||
private Cancellable cancellable_open_account = new Cancellable();
|
||||
private Gee.HashMap<Geary.Account, Cancellable> inbox_cancellables
|
||||
= new Gee.HashMap<Geary.Account, Cancellable>();
|
||||
private int busy_count = 0;
|
||||
|
|
@ -86,6 +89,7 @@ public class GearyController {
|
|||
private Geary.Folder? previous_non_search_folder = null;
|
||||
private uint search_timeout_id = 0;
|
||||
private LoginDialog? login_dialog = null;
|
||||
private UpgradeDialog upgrade_dialog;
|
||||
|
||||
/**
|
||||
* Fired when the currently selected account has changed.
|
||||
|
|
@ -137,6 +141,10 @@ public class GearyController {
|
|||
// Listen for attempts to close the application.
|
||||
GearyApplication.instance.exiting.connect(on_application_exiting);
|
||||
|
||||
// Create DB upgrade dialog.
|
||||
upgrade_dialog = new UpgradeDialog();
|
||||
upgrade_dialog.notify[UpgradeDialog.PROP_VISIBLE_NAME].connect(display_main_window_if_ready);
|
||||
|
||||
// Create the main window (must be done after creating actions.)
|
||||
main_window = new MainWindow();
|
||||
main_window.notify["has-toplevel-focus"].connect(on_has_toplevel_focus);
|
||||
|
|
@ -193,8 +201,6 @@ public class GearyController {
|
|||
GearyApplication.instance.get_resource_directory(), new SecretMediator());
|
||||
if (Geary.Engine.instance.get_accounts().size == 0) {
|
||||
create_account();
|
||||
} else {
|
||||
main_window.show_all();
|
||||
}
|
||||
} catch (Error e) {
|
||||
error("Error opening Geary.Engine instance: %s", e.message);
|
||||
|
|
@ -367,7 +373,7 @@ public class GearyController {
|
|||
|
||||
private void open_account(Geary.Account account) {
|
||||
account.report_problem.connect(on_report_problem);
|
||||
connect_account_async.begin(account);
|
||||
connect_account_async.begin(account, cancellable_open_account);
|
||||
}
|
||||
|
||||
private void close_account(Geary.Account account) {
|
||||
|
|
@ -384,7 +390,10 @@ public class GearyController {
|
|||
}
|
||||
|
||||
private void on_account_available(Geary.AccountInformation account_information) {
|
||||
open_account(get_account_instance(account_information));
|
||||
Geary.Account account = get_account_instance(account_information);
|
||||
|
||||
upgrade_dialog.add_account(account, cancellable_open_account);
|
||||
open_account(account);
|
||||
}
|
||||
|
||||
private void on_account_unavailable(Geary.AccountInformation account_information) {
|
||||
|
|
@ -404,9 +413,6 @@ public class GearyController {
|
|||
result = yield validate_or_retry_async(result, cancellable);
|
||||
} while (result != null);
|
||||
|
||||
if (main_window != null) {
|
||||
main_window.show_all();
|
||||
}
|
||||
if (login_dialog != null)
|
||||
login_dialog.hide();
|
||||
}
|
||||
|
|
@ -571,6 +577,7 @@ public class GearyController {
|
|||
account.folders_available_unavailable.connect(on_folders_available_unavailable);
|
||||
|
||||
try {
|
||||
account.set_data(PROP_ATTEMPT_OPEN_ACCOUNT, true);
|
||||
yield account.open_async(cancellable);
|
||||
} catch (Error open_err) {
|
||||
// TODO: Better error reporting to user
|
||||
|
|
@ -584,6 +591,7 @@ public class GearyController {
|
|||
account.email_sent.connect(on_sent);
|
||||
|
||||
main_window.folder_list.set_user_folders_root_name(account, _("Labels"));
|
||||
display_main_window_if_ready();
|
||||
}
|
||||
|
||||
public async void disconnect_account_async(Geary.Account account, Cancellable? cancellable = null) {
|
||||
|
|
@ -630,6 +638,32 @@ public class GearyController {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if we've attempted to open all accounts at this point.
|
||||
*/
|
||||
private bool did_attempt_open_all_accounts() {
|
||||
try {
|
||||
foreach (Geary.AccountInformation info in Geary.Engine.instance.get_accounts().values) {
|
||||
Geary.Account a = Geary.Engine.instance.get_account_instance(info);
|
||||
if (a.get_data<bool?>(PROP_ATTEMPT_OPEN_ACCOUNT) == null)
|
||||
return false;
|
||||
}
|
||||
} catch(Error e) {
|
||||
error("Could not open accounts: %s", e.message);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the main window if we're ready. Otherwise does nothing.
|
||||
*/
|
||||
private void display_main_window_if_ready() {
|
||||
if (did_attempt_open_all_accounts() && !upgrade_dialog.visible &&
|
||||
!cancellable_open_account.is_cancelled())
|
||||
main_window.show_all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of accounts that exist in Geary. Note that not all accounts may be
|
||||
* open. Zero is returned on an error.
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
public abstract class Geary.AbstractAccount : BaseObject, Geary.Account {
|
||||
public Geary.AccountInformation information { get; protected set; }
|
||||
public Geary.ProgressMonitor search_upgrade_monitor { get; protected set; }
|
||||
public Geary.ProgressMonitor db_upgrade_monitor { get; protected set; }
|
||||
|
||||
private string name;
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ public interface Geary.Account : BaseObject {
|
|||
public abstract Geary.AccountInformation information { get; protected set; }
|
||||
|
||||
public abstract Geary.ProgressMonitor search_upgrade_monitor { get; protected set; }
|
||||
public abstract Geary.ProgressMonitor db_upgrade_monitor { get; protected set; }
|
||||
|
||||
public signal void opened();
|
||||
|
||||
|
|
|
|||
|
|
@ -136,7 +136,9 @@ public class Geary.Engine : BaseObject {
|
|||
FileEnumerator enumerator
|
||||
= yield user_data_dir.enumerate_children_async("standard::*",
|
||||
FileQueryInfoFlags.NONE, Priority.DEFAULT, cancellable);
|
||||
|
||||
|
||||
Gee.List<AccountInformation> account_list = new Gee.ArrayList<AccountInformation>();
|
||||
|
||||
for (;;) {
|
||||
List<FileInfo> info_list;
|
||||
try {
|
||||
|
|
@ -152,9 +154,12 @@ public class Geary.Engine : BaseObject {
|
|||
FileInfo info = info_list.nth_data(0);
|
||||
if (info.get_file_type() == FileType.DIRECTORY) {
|
||||
// TODO: check for geary.ini
|
||||
add_account(new AccountInformation.from_file(user_data_dir.get_child(info.get_name())));
|
||||
account_list.add(new AccountInformation.from_file(user_data_dir.get_child(info.get_name())));
|
||||
}
|
||||
}
|
||||
|
||||
foreach(AccountInformation info in account_list)
|
||||
add_account(info);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -6,11 +6,13 @@
|
|||
|
||||
public class Geary.Db.VersionedDatabase : Geary.Db.Database {
|
||||
public File schema_dir { get; private set; }
|
||||
public ProgressMonitor upgrade_monitor { get; private set; }
|
||||
|
||||
public VersionedDatabase(File db_file, File schema_dir) {
|
||||
public VersionedDatabase(File db_file, File schema_dir, ProgressMonitor upgrade_monitor) {
|
||||
base (db_file);
|
||||
|
||||
this.schema_dir = schema_dir;
|
||||
this.upgrade_monitor = upgrade_monitor;
|
||||
}
|
||||
|
||||
protected virtual void pre_upgrade(int version) {
|
||||
|
|
@ -40,6 +42,11 @@ public class Geary.Db.VersionedDatabase : Geary.Db.Database {
|
|||
if (!upgrade_script.query_exists(cancellable))
|
||||
break;
|
||||
|
||||
if (!upgrade_monitor.is_in_progress)
|
||||
upgrade_monitor.notify_start();
|
||||
|
||||
pump_event_loop();
|
||||
|
||||
pre_upgrade(db_version);
|
||||
|
||||
check_cancelled("VersionedDatabase.open", cancellable);
|
||||
|
|
@ -58,8 +65,18 @@ public class Geary.Db.VersionedDatabase : Geary.Db.Database {
|
|||
throw err;
|
||||
}
|
||||
|
||||
pump_event_loop();
|
||||
|
||||
post_upgrade(db_version);
|
||||
}
|
||||
|
||||
if (upgrade_monitor.is_in_progress)
|
||||
upgrade_monitor.notify_finish();
|
||||
}
|
||||
|
||||
protected void pump_event_loop() {
|
||||
while (Gtk.events_pending())
|
||||
Gtk.main_iteration();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,11 @@ private class Geary.ImapDB.Account : BaseObject {
|
|||
// Only available when the Account is opened
|
||||
public SmtpOutboxFolder? outbox { get; private set; default = null; }
|
||||
public SearchFolder? search_folder { get; private set; default = null; }
|
||||
public ImapEngine.ContactStore contact_store { get; private set; }
|
||||
public IntervalProgressMonitor search_index_monitor { get; private set;
|
||||
default = new IntervalProgressMonitor(ProgressType.SEARCH_INDEX, 0, 0); }
|
||||
public SimpleProgressMonitor upgrade_monitor { get; private set; default = new SimpleProgressMonitor(
|
||||
ProgressType.DB_UPGRADE); }
|
||||
|
||||
private string name;
|
||||
private AccountInformation account_information;
|
||||
|
|
@ -37,9 +42,6 @@ private class Geary.ImapDB.Account : BaseObject {
|
|||
private Gee.HashMap<Geary.FolderPath, FolderReference> folder_refs =
|
||||
new Gee.HashMap<Geary.FolderPath, FolderReference>();
|
||||
private Cancellable? background_cancellable = null;
|
||||
public ImapEngine.ContactStore contact_store { get; private set; }
|
||||
public IntervalProgressMonitor search_index_monitor { get; private set;
|
||||
default = new IntervalProgressMonitor(ProgressType.SEARCH_INDEX, 0, 0); }
|
||||
|
||||
public Account(Geary.AccountInformation account_information) {
|
||||
this.account_information = account_information;
|
||||
|
|
@ -58,7 +60,7 @@ private class Geary.ImapDB.Account : BaseObject {
|
|||
if (db != null)
|
||||
throw new EngineError.ALREADY_OPEN("IMAP database already open");
|
||||
|
||||
db = new ImapDB.Database(user_data_dir, schema_dir, account_information.email);
|
||||
db = new ImapDB.Database(user_data_dir, schema_dir, upgrade_monitor, account_information.email);
|
||||
|
||||
try {
|
||||
db.open(Db.DatabaseFlags.CREATE_DIRECTORY | Db.DatabaseFlags.CREATE_FILE, null,
|
||||
|
|
|
|||
|
|
@ -10,8 +10,9 @@ private class Geary.ImapDB.Database : Geary.Db.VersionedDatabase {
|
|||
private const string DB_FILENAME = "geary.db";
|
||||
private string account_owner_email;
|
||||
|
||||
public Database(File db_dir, File schema_dir, string account_owner_email) {
|
||||
base (db_dir.get_child(DB_FILENAME), schema_dir);
|
||||
public Database(File db_dir, File schema_dir, ProgressMonitor upgrade_monitor,
|
||||
string account_owner_email) {
|
||||
base (db_dir.get_child(DB_FILENAME), schema_dir, upgrade_monitor);
|
||||
this.account_owner_email = account_owner_email;
|
||||
}
|
||||
|
||||
|
|
@ -52,8 +53,11 @@ private class Geary.ImapDB.Database : Geary.Db.VersionedDatabase {
|
|||
while (!result.finished) {
|
||||
MessageAddresses message_addresses =
|
||||
new MessageAddresses.from_result(account_owner_email, result);
|
||||
foreach (Contact contact in message_addresses.contacts)
|
||||
foreach (Contact contact in message_addresses.contacts) {
|
||||
do_update_contact(get_master_connection(), contact, null);
|
||||
pump_event_loop();
|
||||
}
|
||||
|
||||
result.next();
|
||||
}
|
||||
} catch (Error err) {
|
||||
|
|
@ -81,6 +85,8 @@ private class Geary.ImapDB.Database : Geary.Db.VersionedDatabase {
|
|||
}
|
||||
|
||||
select.next();
|
||||
|
||||
pump_event_loop();
|
||||
}
|
||||
} catch (Error e) {
|
||||
debug("Error decoding folder names during upgrade to database schema 6: %s", e.message);
|
||||
|
|
@ -173,6 +179,8 @@ private class Geary.ImapDB.Database : Geary.Db.VersionedDatabase {
|
|||
}
|
||||
|
||||
select.next();
|
||||
|
||||
pump_event_loop();
|
||||
}
|
||||
|
||||
return Db.TransactionOutcome.COMMIT;
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.AbstractAccount {
|
|||
this.remote.email_sent.connect(on_email_sent);
|
||||
|
||||
search_upgrade_monitor = local.search_index_monitor;
|
||||
db_upgrade_monitor = local.upgrade_monitor;
|
||||
|
||||
if (outbox_path == null) {
|
||||
outbox_path = new SmtpOutboxFolderRoot();
|
||||
|
|
|
|||
113
ui/upgrade_dialog.glade
Normal file
113
ui/upgrade_dialog.glade
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<!-- interface-requires gtk+ 3.6 -->
|
||||
<object class="GtkDialog" id="dialog">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="border_width">5</property>
|
||||
<property name="resizable">False</property>
|
||||
<property name="window_position">center</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<property name="deletable">False</property>
|
||||
<child internal-child="vbox">
|
||||
<object class="GtkBox" id="dialog-vbox1">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">2</property>
|
||||
<child internal-child="action_area">
|
||||
<object class="GtkButtonBox" id="dialog-action_area1">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="layout_style">end</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkGrid" id="grid1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">8</property>
|
||||
<property name="margin_right">8</property>
|
||||
<property name="margin_top">8</property>
|
||||
<property name="margin_bottom">8</property>
|
||||
<property name="row_spacing">8</property>
|
||||
<property name="column_spacing">8</property>
|
||||
<child>
|
||||
<object class="GtkSpinner" id="spinner1">
|
||||
<property name="width_request">45</property>
|
||||
<property name="height_request">45</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="active">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Geary upgrade in progress.</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAlignment" id="alignment1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAlignment" id="alignment2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
Loading…
Add table
Add a link
Reference in a new issue