[geary] Use GtkApplication
- From: Charles Lindsay <clindsay src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary] Use GtkApplication
- Date: Sat, 7 Dec 2013 00:48:05 +0000 (UTC)
commit 3eaa1dcb8f78aae7c9b49bdf13a917285667e9f4
Author: Charles Lindsay <chaz yorba org>
Date: Fri Dec 6 16:43:11 2013 -0800
Use GtkApplication
This ports the Geary application to use GtkApplication, and removes the
dependency on libunique.
Closes: bgo#714145
debian/control | 2 -
src/CMakeLists.txt | 4 +-
src/client/application/geary-application.vala | 180 ++++++++++++++++++------
src/client/application/geary-config.vala | 4 +-
src/client/application/geary-controller.vala | 6 +-
src/client/components/main-window.vala | 6 +-
src/client/notification/libnotify.vala | 2 +-
src/client/util/util-yorba-application.vala | 189 -------------------------
8 files changed, 149 insertions(+), 244 deletions(-)
---
diff --git a/debian/control b/debian/control
index 441a048..0a01182 100644
--- a/debian/control
+++ b/debian/control
@@ -6,7 +6,6 @@ Build-Depends: debhelper (>= 8),
libgee-0.8-dev (>= 0.8.5),
libglib2.0-dev (>= 2.32.0),
libgtk-3-dev (>= 3.6.0),
- libunique-3.0-dev (>= 3.0.0),
libnotify-dev (>=0.7.5),
libcanberra-dev (>= 0.28),
libwebkitgtk-3.0-dev (<< 2.1.0),
@@ -30,7 +29,6 @@ Depends: ${shlibs:Depends}, ${misc:Depends},
libgee-0.8-2 (>= 0.8.5),
libglib2.0-0 (>= 2.32.0),
libgtk-3-0 (>= 3.6.0),
- libunique-3.0-0 (>= 3.0.0),
libnotify4 (>= 0.7.5),
libcanberra0 (>= 0.28),
libwebkitgtk-3.0-0 (<< 2.1.0),
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 204836f..9f8278a 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -370,7 +370,6 @@ client/util/util-gravatar.vala
client/util/util-gtk.vala
client/util/util-international.vala
client/util/util-webkit.vala
-client/util/util-yorba-application.vala
)
set(CONSOLE_SRC
@@ -479,7 +478,6 @@ pkg_check_modules(DEPS REQUIRED
gio-2.0>=2.28.0
gtk+-3.0>=3.6.0
gee-0.8>=0.8.5
- unique-3.0>=3.0.0
libnotify>=0.7.5
libcanberra>=0.28
sqlite3>=3.7.4
@@ -490,7 +488,7 @@ pkg_check_modules(DEPS REQUIRED
)
set(ENGINE_PACKAGES
- glib-2.0 gee-0.8 gio-2.0 gmime-2.6 unique-3.0 posix sqlite3 libxml-2.0
+ glib-2.0 gee-0.8 gio-2.0 gmime-2.6 posix sqlite3 libxml-2.0
)
set(CLIENT_PACKAGES
diff --git a/src/client/application/geary-application.vala b/src/client/application/geary-application.vala
index 54f2e51..a43e3e0 100644
--- a/src/client/application/geary-application.vala
+++ b/src/client/application/geary-application.vala
@@ -9,10 +9,12 @@ extern const string _VERSION;
extern const string _INSTALL_PREFIX;
extern const string _GSETTINGS_DIR;
extern const string _SOURCE_ROOT_DIR;
+extern const string GETTEXT_PACKAGE;
-public class GearyApplication : YorbaApplication {
+public class GearyApplication : Gtk.Application {
public const string NAME = "Geary";
public const string PRGNAME = "geary";
+ public const string APP_ID = "org.yorba.geary";
public const string DESCRIPTION = DESKTOP_GENERIC_NAME;
public const string COPYRIGHT = _("Copyright 2011-2013 Yorba Foundation");
public const string WEBSITE = "http://www.yorba.org";
@@ -44,30 +46,49 @@ public class GearyApplication : YorbaApplication {
};
public const string LICENSE = """
-Geary is free software; you can redistribute it and/or modify it under the
-terms of the GNU Lesser General Public License as published by the Free
-Software Foundation; either version 2.1 of the License, or (at your option)
+Geary is free software; you can redistribute it and/or modify it under the
+terms of the GNU Lesser General Public License as published by the Free
+Software Foundation; either version 2.1 of the License, or (at your option)
any later version.
-Geary is distributed in the hope that it will be useful, but WITHOUT
+Geary is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
more details.
-You should have received a copy of the GNU Lesser General Public License
-along with Geary; if not, write to the Free Software Foundation, Inc.,
+You should have received a copy of the GNU Lesser General Public License
+along with Geary; if not, write to the Free Software Foundation, Inc.,
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""";
- public static GearyApplication instance {
+ private static const string ACTION_ENTRY_COMPOSE = "compose";
+
+ public static const ActionEntry[] action_entries = {
+ {ACTION_ENTRY_COMPOSE, activate_compose, "s"},
+ };
+
+ public static GearyApplication instance {
get { return _instance; }
- private set {
+ private set {
// Ensure singleton behavior.
assert (_instance == null);
_instance = value;
}
}
+ /**
+ * Signal that is activated when 'exit' is called, but before the application actually exits.
+ *
+ * To cancel an exit, a callback should return GearyApplication.cancel_exit(). To procede with
+ * an exit, a callback should return true.
+ */
+ public virtual signal bool exiting(bool panicked) {
+ controller.close();
+ Date.terminate();
+
+ return true;
+ }
+
public GearyController controller { get; private set; default = new GearyController(); }
public Gtk.ActionGroup actions {
@@ -82,50 +103,84 @@ along with Geary; if not, write to the Free Software Foundation, Inc.,
private static GearyApplication _instance = null;
+ private string bin;
private File exec_dir;
+ private bool exiting_fired = false;
+ private int exitcode = 0;
+
public GearyApplication() {
- base (NAME, PRGNAME, "org.yorba.geary");
+ Object(application_id: APP_ID);
_instance = this;
}
- public override int startup() {
- exec_dir =
(File.new_for_path(Posix.realpath(Environment.find_program_in_path(args[0])))).get_parent();
+ // Application.run() calls this as an entry point.
+ public override bool local_command_line(ref unowned string[] args, out int exit_status) {
+ bin = args[0];
+ exec_dir = (File.new_for_path(Posix.realpath(Environment.find_program_in_path(bin)))).get_parent();
- Geary.Logging.init();
+ try {
+ register();
+ } catch (Error e) {
+ error("Error registering GearyApplication: %s", e.message);
+ }
+
+ Args.parse(args);
+
+ activate();
+ foreach (unowned string arg in args) {
+ if (arg != null && arg.has_prefix(Geary.ComposedEmail.MAILTO_SCHEME))
+ activate_action(ACTION_ENTRY_COMPOSE, new Variant.string(arg));
+ }
+
+ exit_status = 0;
+ return true;
+ }
+
+ public override void startup() {
Configuration.init(is_installed(), GSETTINGS_DIR);
+
+ Environment.set_application_name(NAME);
+ Environment.set_prgname(PRGNAME);
+ International.init(GETTEXT_PACKAGE, bin);
+
+ Geary.Logging.init();
Date.init();
WebKit.set_cache_model(WebKit.CacheModel.DOCUMENT_BROWSER);
- int ec = base.startup();
- if (ec != 0)
- return ec;
+ base.startup();
- return Args.parse(args);
+ add_action_entries(action_entries, this);
}
- public override bool exiting(bool panicked) {
- controller.close();
- Date.terminate();
+ public override void activate() {
+ base.activate();
- return true;
+ if (!present())
+ create_async.begin();
}
- public override void activate(string[] args) {
- do_activate_async.begin(args);
- }
-
- // Without owned on the args parameter, vala won't bother to keep the array
- // around until the open_async() call completes, leading to crashes. This
- // way, this method gets its own long-lived copy.
- private async void do_activate_async(owned string[] args) {
- // If Geary is already running, show the main window and return.
- if (controller != null && controller.main_window != null) {
- controller.main_window.present();
- handle_args(args);
+ public void activate_compose(SimpleAction action, Variant? param) {
+ if (param == null)
return;
- }
+
+ compose(param.get_string());
+ }
+
+ public bool present() {
+ if (controller == null || controller.main_window == null)
+ return false;
+
+ controller.main_window.present();
+ return true;
+ }
+
+ private async void create_async() {
+ // Manually keep the main loop around for the duration of this call.
+ // Without this, the main loop will exit as soon as we hit the yield
+ // below, before we create the main window.
+ hold();
// do *after* parsing args, as they dicate where logging is sent to, if anywhere, and only
// after activate (which means this is only logged for the one user-visible instance, not
@@ -133,10 +188,18 @@ along with Geary; if not, write to the Free Software Foundation, Inc.,
message("%s %s prefix=%s exec_dir=%s is_installed=%s", NAME, VERSION, INSTALL_PREFIX,
exec_dir.get_path(), is_installed().to_string());
- config = new Configuration();
+ config = new Configuration(APP_ID);
yield controller.open_async();
- handle_args(args);
+ release();
+ }
+
+ public bool compose(string mailto) {
+ if (controller == null)
+ return false;
+
+ controller.compose_mailto(mailto);
+ return true;
}
// NOTE: This assert()'s if the Gtk.Action is not present in the default action group
@@ -241,12 +304,45 @@ along with Geary; if not, write to the Free Software Foundation, Inc.,
load_ui_file_for_manager(ui_manager, ui_filename);
}
- private void handle_args(string[] args) {
- foreach(string arg in args) {
- if (arg.has_prefix(Geary.ComposedEmail.MAILTO_SCHEME)) {
- controller.compose_mailto(arg);
- }
+ // This call will fire "exiting" only if it's not already been fired.
+ public void exit(int exitcode = 0) {
+ if (exiting_fired)
+ return;
+
+ this.exitcode = exitcode;
+
+ exiting_fired = true;
+ if (!exiting(false)) {
+ exiting_fired = false;
+ this.exitcode = 0;
+
+ return;
+ }
+
+ if (Gtk.main_level() > 0)
+ Gtk.main_quit();
+ else
+ Posix.exit(exitcode);
+ }
+
+ /**
+ * A callback for GearyApplication.exiting should return cancel_exit() to prevent the
+ * application from exiting.
+ */
+ public bool cancel_exit() {
+ Signal.stop_emission_by_name(this, "exiting");
+ return false;
+ }
+
+ // This call will fire "exiting" only if it's not already been fired and halt the application
+ // in its tracks.
+ public void panic() {
+ if (!exiting_fired) {
+ exiting_fired = true;
+ exiting(true);
}
+
+ Posix.exit(1);
}
}
diff --git a/src/client/application/geary-config.vala b/src/client/application/geary-config.vala
index 5351fa8..b7dc253 100644
--- a/src/client/application/geary-config.vala
+++ b/src/client/application/geary-config.vala
@@ -115,9 +115,9 @@ public class Configuration {
}
// Creates a configuration object.
- public Configuration() {
+ public Configuration(string schema_id) {
// Start GSettings.
- settings = new Settings("org.yorba.geary");
+ settings = new Settings(schema_id);
gnome_interface = new Settings("org.gnome.desktop.interface");
foreach(string schema in GLib.Settings.list_schemas()) {
if (schema == "com.canonical.indicator.datetime") {
diff --git a/src/client/application/geary-controller.vala b/src/client/application/geary-controller.vala
index b15b488..af171d6 100644
--- a/src/client/application/geary-controller.vala
+++ b/src/client/application/geary-controller.vala
@@ -161,7 +161,7 @@ public class GearyController : Geary.BaseObject {
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 = new MainWindow(GearyApplication.instance);
main_window.notify["has-toplevel-focus"].connect(on_has_toplevel_focus);
enable_message_buttons(false);
@@ -1184,8 +1184,8 @@ public class GearyController : Geary.BaseObject {
}
// We need to include the second parameter, or valac doesn't recognize the function as matching
- // YorbaApplication.exiting's signature.
- private bool on_application_exiting(YorbaApplication sender, bool panicked) {
+ // GearyApplication.exiting's signature.
+ private bool on_application_exiting(GearyApplication sender, bool panicked) {
if (close_composition_windows())
return true;
diff --git a/src/client/components/main-window.vala b/src/client/components/main-window.vala
index 4f29e9f..3880c22 100644
--- a/src/client/components/main-window.vala
+++ b/src/client/components/main-window.vala
@@ -4,7 +4,7 @@
* (version 2.1 or later). See the COPYING file in this distribution.
*/
-public class MainWindow : Gtk.Window {
+public class MainWindow : Gtk.ApplicationWindow {
private const int MESSAGE_LIST_WIDTH = 250;
private const int FOLDER_LIST_WIDTH = 100;
private const int STATUS_BAR_HEIGHT = 18;
@@ -28,7 +28,9 @@ public class MainWindow : Gtk.Window {
private Geary.AggregateProgressMonitor progress_monitor = new Geary.AggregateProgressMonitor();
private Geary.ProgressMonitor? conversation_monitor_progress = null;
- public MainWindow() {
+ public MainWindow(GearyApplication application) {
+ Object(application: application);
+
title = GearyApplication.NAME;
conversation_list_view = new ConversationListView(conversation_list_store);
diff --git a/src/client/notification/libnotify.vala b/src/client/notification/libnotify.vala
index 4da8a5a..421b8e9 100644
--- a/src/client/notification/libnotify.vala
+++ b/src/client/notification/libnotify.vala
@@ -57,7 +57,7 @@ public class Libnotify : Geary.BaseObject {
private void on_default_action(Notify.Notification notification, string action) {
invoked(folder, email);
- GearyApplication.instance.activate(new string[0]);
+ GearyApplication.instance.activate();
}
private void notify_new_mail(Geary.Folder folder, int added) {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]