[almanah] Bug 622193 — Use single instance



commit 0d2374f0bd55461b8bb6ca3a234b60fb395c6f32
Author: Philip Withnall <philip tecnocode co uk>
Date:   Thu Apr 14 23:48:54 2011 +0100

    Bug 622193 â?? Use single instance
    
    A long exercise in yak shaving to remove the global struct, port to
    GtkApplication and consequently get single instance support.
    
    Closes: bgo#622193

 po/POTFILES.in                    |    9 +-
 src/Makefile.am                   |    2 +
 src/application.c                 |  372 +++++++++++++++++++++++++++++++++++++
 src/application.h                 |   62 ++++++
 src/date-entry-dialog.c           |    1 -
 src/event-manager.c               |    8 +-
 src/event.c                       |    4 +-
 src/event.h                       |    4 +-
 src/events/calendar-appointment.c |   11 +-
 src/events/calendar-task.c        |   11 +-
 src/export-operation.c            |   59 ++++++-
 src/export-operation.h            |    5 +-
 src/import-export-dialog.c        |   87 ++++++++--
 src/import-export-dialog.h        |    3 +-
 src/import-operation.c            |   65 ++++++-
 src/import-operation.h            |    5 +-
 src/main-window.c                 |  236 +++++++++++++++++-------
 src/main-window.h                 |    4 +-
 src/main.c                        |  148 +--------------
 src/main.h                        |   24 ---
 src/preferences-dialog.c          |   68 ++++++-
 src/preferences-dialog.h          |    2 +-
 src/printing.c                    |   44 ++---
 src/printing.h                    |    7 +-
 src/search-dialog.c               |   29 ++-
 src/storage-manager.c             |   40 ++++-
 src/storage-manager.h             |    2 +-
 src/widgets/calendar.c            |  109 ++++++++++-
 src/widgets/calendar.h            |    7 +-
 29 files changed, 1081 insertions(+), 347 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index b00c4d8..e8d72b5 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -3,7 +3,7 @@
 data/almanah.desktop.in
 data/org.gnome.almanah.gschema.xml.in.in
 [type: gettext/glade]data/almanah.ui
-src/add-definition-dialog.c
+src/application.c
 src/date-entry-dialog.c
 src/entry.c
 src/events/calendar-appointment.c
@@ -12,12 +12,6 @@ src/export-operation.c
 src/import-export-dialog.c
 src/import-operation.c
 src/interface.c
-src/definition-manager-window.c
-src/definition.c
-src/definitions/contact.c
-src/definitions/file.c
-src/definitions/note.c
-src/definitions/uri.c
 src/main-window.c
 src/main.c
 src/preferences-dialog.c
@@ -25,3 +19,4 @@ src/printing.c
 src/search-dialog.c
 src/storage-manager.c
 src/widgets/calendar.c
+src/uri-entry-dialog.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 778da31..cf85ddd 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -5,6 +5,8 @@ almanah_SOURCES = \
 	$(ALMANAH_ENUM_FILES)		\
 	main.c				\
 	main.h				\
+	application.c			\
+	application.h			\
 	interface.c			\
 	interface.h			\
 	main-window.c			\
diff --git a/src/application.c b/src/application.c
new file mode 100644
index 0000000..519f9a6
--- /dev/null
+++ b/src/application.c
@@ -0,0 +1,372 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * Almanah
+ * Copyright (C) Philip Withnall 2011 <philip tecnocode co uk>
+ *
+ * Almanah is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Almanah 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Almanah.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+
+#include "application.h"
+#include "storage-manager.h"
+#include "event-manager.h"
+#include "main-window.h"
+
+static void constructed (GObject *object);
+static void dispose (GObject *object);
+static void get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
+static void set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec);
+
+static void startup (GApplication *application);
+static void activate (GApplication *application);
+static gint handle_command_line (GApplication *application, GApplicationCommandLine *command_line);
+static void quit_main_loop (GApplication *application);
+
+struct _AlmanahApplicationPrivate {
+	gboolean debug;
+
+	GSettings *settings;
+	AlmanahStorageManager *storage_manager;
+	AlmanahEventManager *event_manager;
+
+	AlmanahMainWindow *main_window;
+
+	GtkWidget *search_dialog;
+	GtkWidget *date_entry_dialog;
+#ifdef ENABLE_ENCRYPTION
+	GtkWidget *preferences_dialog;
+#endif /* ENABLE_ENCRYPTION */
+};
+
+enum {
+	PROP_DEBUG = 1
+};
+
+G_DEFINE_TYPE (AlmanahApplication, almanah_application, GTK_TYPE_APPLICATION)
+
+static void
+almanah_application_class_init (AlmanahApplicationClass *klass)
+{
+	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+	GApplicationClass *gapplication_class = G_APPLICATION_CLASS (klass);
+
+	g_type_class_add_private (klass, sizeof (AlmanahApplicationPrivate));
+
+	gobject_class->constructed = constructed;
+	gobject_class->dispose = dispose;
+	gobject_class->get_property = get_property;
+	gobject_class->set_property = set_property;
+
+	gapplication_class->startup = startup;
+	gapplication_class->activate = activate;
+	gapplication_class->command_line = handle_command_line;
+	gapplication_class->quit_mainloop = quit_main_loop;
+
+	g_object_class_install_property (gobject_class, PROP_DEBUG,
+	                                 g_param_spec_boolean ("debug",
+	                                                       "Debugging Mode", "Whether debugging mode is active.",
+	                                                       FALSE,
+	                                                       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+}
+
+static void
+almanah_application_init (AlmanahApplication *self)
+{
+	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, ALMANAH_TYPE_APPLICATION, AlmanahApplicationPrivate);
+	self->priv->debug = FALSE;
+}
+
+static void
+constructed (GObject *object)
+{
+	/* Set various properties up */
+	g_application_set_application_id (G_APPLICATION (object), "org.gnome.Almanah");
+	g_application_set_flags (G_APPLICATION (object), G_APPLICATION_HANDLES_COMMAND_LINE);
+
+	/* Localisation */
+#ifdef ENABLE_NLS
+	bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
+	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+	textdomain (GETTEXT_PACKAGE);
+#endif
+
+	g_set_application_name (_("Almanah Diary"));
+	gtk_window_set_default_icon_name ("almanah");
+
+	/* Chain up to the parent class */
+	G_OBJECT_CLASS (almanah_application_parent_class)->constructed (object);
+}
+
+static void
+dispose (GObject *object)
+{
+	AlmanahApplicationPrivate *priv = ALMANAH_APPLICATION (object)->priv;
+
+	/* TODO */
+	if (priv->search_dialog != NULL)
+		gtk_widget_destroy (priv->search_dialog);
+	priv->search_dialog = NULL;
+
+	if (priv->date_entry_dialog != NULL)
+		gtk_widget_destroy (priv->date_entry_dialog);
+	priv->date_entry_dialog = NULL;
+
+#ifdef ENABLE_ENCRYPTION
+	if (priv->preferences_dialog != NULL)
+		gtk_widget_destroy (priv->preferences_dialog);
+	priv->preferences_dialog = NULL;
+#endif /* ENABLE_ENCRYPTION */
+
+	if (priv->main_window != NULL)
+		gtk_widget_destroy (GTK_WIDGET (priv->main_window));
+	priv->main_window = NULL;
+
+	if (priv->event_manager != NULL)
+		g_object_unref (priv->event_manager);
+	priv->event_manager = NULL;
+
+	if (priv->storage_manager != NULL)
+		g_object_unref (priv->storage_manager);
+	priv->storage_manager = NULL;
+
+	if (priv->settings != NULL)
+		g_object_unref (priv->settings);
+	priv->settings = NULL;
+
+	/* Chain up to the parent class */
+	G_OBJECT_CLASS (almanah_application_parent_class)->dispose (object);
+}
+
+static void
+get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
+{
+	AlmanahApplicationPrivate *priv = ALMANAH_APPLICATION (object)->priv;
+
+	switch (property_id) {
+		case PROP_DEBUG:
+			g_value_set_boolean (value, priv->debug);
+			break;
+		default:
+			/* We don't have any other property... */
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+			break;
+	}
+}
+
+static void
+set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
+{
+	AlmanahApplicationPrivate *priv = ALMANAH_APPLICATION (object)->priv;
+
+	switch (property_id) {
+		case PROP_DEBUG:
+			priv->debug = g_value_get_boolean (value);
+			break;
+		default:
+			/* We don't have any other property... */
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+			break;
+	}
+}
+
+static void
+debug_handler (const char *log_domain, GLogLevelFlags log_level, const char *message, AlmanahApplication *self)
+{
+	/* Only display debug messages if we've been run with --debug */
+	if (self->priv->debug == TRUE) {
+		g_log_default_handler (log_domain, log_level, message, NULL);
+	}
+}
+
+static void
+startup (GApplication *application)
+{
+	AlmanahApplicationPrivate *priv = ALMANAH_APPLICATION (application)->priv;
+	gchar *db_filename, *encryption_key;
+	GError *error = NULL;
+g_message ("startup");
+	/* Debug log handling */
+	g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, (GLogFunc) debug_handler, application);
+
+	/* Open GSettings */
+	priv->settings = g_settings_new ("org.gnome.almanah");
+
+	/* Ensure the DB directory exists */
+	if (g_file_test (g_get_user_data_dir (), G_FILE_TEST_IS_DIR) == FALSE) {
+		g_mkdir_with_parents (g_get_user_data_dir (), 0700);
+	}
+
+	/* Open the DB */
+	db_filename = g_build_filename (g_get_user_data_dir (), "diary.db", NULL);
+	encryption_key = g_settings_get_string (priv->settings, "encryption-key");
+	priv->storage_manager = almanah_storage_manager_new (db_filename, encryption_key);
+	g_free (encryption_key);
+	g_free (db_filename);
+
+	if (almanah_storage_manager_connect (priv->storage_manager, &error) == FALSE) {
+		GtkWidget *dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
+		                                            _("Error opening database"));
+		gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", error->message);
+		gtk_dialog_run (GTK_DIALOG (dialog));
+		gtk_widget_destroy (dialog);
+
+		/* TODO */
+		exit (1);
+	}
+
+	/* Create the event manager */
+	priv->event_manager = almanah_event_manager_new ();
+}
+
+static void
+activate (GApplication *application)
+{
+	AlmanahApplication *self = ALMANAH_APPLICATION (application);
+	AlmanahApplicationPrivate *priv = self->priv;
+g_message ("activate");
+	/* Create the interface */
+	if (priv->main_window == NULL) {
+		priv->main_window = almanah_main_window_new (self);
+		gtk_widget_show_all (GTK_WIDGET (priv->main_window));
+	}
+
+	/* Bring it to the foreground */
+	gtk_window_present (GTK_WINDOW (priv->main_window));
+}
+
+static gint
+handle_command_line (GApplication *application, GApplicationCommandLine *command_line)
+{
+	AlmanahApplicationPrivate *priv = ALMANAH_APPLICATION (application)->priv;
+	GOptionContext *context;
+	GError *error = NULL;
+	gchar **args, **argv;
+	gint argc, i, status = 0;
+
+	const GOptionEntry options[] = {
+		{ "debug", 0, 0, G_OPTION_ARG_NONE, &(priv->debug), N_("Enable debug mode"), NULL },
+		{ NULL }
+	};
+g_message ("handle_command_line");
+	args = g_application_command_line_get_arguments (command_line, &argc);
+
+	/* We have to make an extra copy of the array, since g_option_context_parse() assumes that it can remove strings from the array without
+	 * freeing them. */
+	argv = g_new (gchar*, argc + 1);
+	for (i = 0; i <= argc; i++) {
+		argv[i] = args[i];
+	}
+
+	/* Options */
+	context = g_option_context_new (NULL);
+	g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
+
+	g_option_context_set_summary (context, _("Manage your diary. Only one instance of the program may be open at any time."));
+
+	g_option_context_add_main_entries (context, options, GETTEXT_PACKAGE);
+	g_option_context_add_group (context, gtk_get_option_group (TRUE));
+
+	if (g_option_context_parse (context, &argc, &argv, &error) == TRUE) {
+		/* Activate the remote instance */
+		g_application_activate (application);
+		status = 0;
+	} else {
+		/* Print an error */
+		g_application_command_line_printerr (command_line, _("Command line options could not be parsed: %s\n"), error->message);
+		g_error_free (error);
+
+		status = 1;
+	}
+
+	g_option_context_free (context);
+
+	g_free (argv);
+	g_strfreev (args);
+
+	return status;
+}
+
+static void
+storage_manager_disconnected_cb (AlmanahStorageManager *self, const gchar *gpgme_error_message, const gchar *warning_message, GApplication *application)
+{
+	if (gpgme_error_message != NULL || warning_message != NULL) {
+		GtkWidget *dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
+		                                            _("Error encrypting database"));
+
+		if (gpgme_error_message != NULL && warning_message != NULL)
+			gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s %s", warning_message, gpgme_error_message);
+		else if (gpgme_error_message != NULL)
+			gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", gpgme_error_message);
+		else
+			gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", warning_message);
+
+		gtk_dialog_run (GTK_DIALOG (dialog));
+		gtk_widget_destroy (dialog);
+	}
+
+	/* Chain up to the parent class */
+	G_APPLICATION_CLASS (almanah_application_parent_class)->quit_mainloop (application);
+}
+
+static void
+quit_main_loop (GApplication *application)
+{
+	AlmanahApplicationPrivate *priv = ALMANAH_APPLICATION (application)->priv;
+
+	/* This would normally result in gtk_main_quit() being called, but we need to close the database connection first. */
+	g_signal_connect (priv->storage_manager, "disconnected", (GCallback) storage_manager_disconnected_cb, application);
+	almanah_storage_manager_disconnect (priv->storage_manager, NULL);
+
+	/* Quitting is actually done in storage_manager_disconnected_cb, which is called once
+	 * the storage manager has encrypted the DB and disconnected from it. */
+}
+
+AlmanahApplication *
+almanah_application_new (void)
+{
+	return ALMANAH_APPLICATION (g_object_new (ALMANAH_TYPE_APPLICATION, NULL));
+}
+
+gboolean
+almanah_application_get_debug (AlmanahApplication *self)
+{
+	g_return_val_if_fail (ALMANAH_IS_APPLICATION (self), FALSE);
+	return self->priv->debug;
+}
+
+AlmanahEventManager *
+almanah_application_dup_event_manager (AlmanahApplication *self)
+{
+	g_return_val_if_fail (ALMANAH_IS_APPLICATION (self), NULL);
+	return g_object_ref (self->priv->event_manager);
+}
+
+AlmanahStorageManager *
+almanah_application_dup_storage_manager (AlmanahApplication *self)
+{
+	g_return_val_if_fail (ALMANAH_IS_APPLICATION (self), NULL);
+	return g_object_ref (self->priv->storage_manager);
+}
+
+GSettings *
+almanah_application_dup_settings (AlmanahApplication *self)
+{
+	g_return_val_if_fail (ALMANAH_IS_APPLICATION (self), NULL);
+	return g_object_ref (self->priv->settings);
+}
diff --git a/src/application.h b/src/application.h
new file mode 100644
index 0000000..cec5d09
--- /dev/null
+++ b/src/application.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * Almanah
+ * Copyright (C) Philip Withnall 2011 <philip tecnocode co uk>
+ *
+ * Almanah is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Almanah 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Almanah.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef ALMANAH_APPLICATION_H
+#define ALMANAH_APPLICATION_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include "event-manager.h"
+#include "storage-manager.h"
+
+G_BEGIN_DECLS
+
+#define ALMANAH_TYPE_APPLICATION		(almanah_application_get_type ())
+#define ALMANAH_APPLICATION(o)			(G_TYPE_CHECK_INSTANCE_CAST ((o), ALMANAH_TYPE_APPLICATION, AlmanahApplication))
+#define ALMANAH_APPLICATION_CLASS(k)		(G_TYPE_CHECK_CLASS_CAST((k), ALMANAH_TYPE_APPLICATION, AlmanahApplicationClass))
+#define ALMANAH_IS_APPLICATION(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), ALMANAH_TYPE_APPLICATION))
+#define ALMANAH_IS_APPLICATION_CLASS(k)		(G_TYPE_CHECK_CLASS_TYPE ((k), ALMANAH_TYPE_APPLICATION))
+#define ALMANAH_APPLICATION_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ALMANAH_TYPE_APPLICATION, AlmanahApplicationClass))
+
+typedef struct _AlmanahApplicationPrivate	AlmanahApplicationPrivate;
+
+typedef struct {
+	GtkApplication parent;
+	AlmanahApplicationPrivate *priv;
+} AlmanahApplication;
+
+typedef struct {
+	GtkApplicationClass parent;
+} AlmanahApplicationClass;
+
+GType almanah_application_get_type (void) G_GNUC_CONST;
+
+AlmanahApplication *almanah_application_new (void) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
+
+gboolean almanah_application_get_debug (AlmanahApplication *self) G_GNUC_PURE;
+
+AlmanahEventManager *almanah_application_dup_event_manager (AlmanahApplication *self) G_GNUC_WARN_UNUSED_RESULT;
+AlmanahStorageManager *almanah_application_dup_storage_manager (AlmanahApplication *self) G_GNUC_WARN_UNUSED_RESULT;
+GSettings *almanah_application_dup_settings (AlmanahApplication *self) G_GNUC_WARN_UNUSED_RESULT;
+
+G_END_DECLS
+
+#endif /* !ALMANAH_APPLICATION_H */
diff --git a/src/date-entry-dialog.c b/src/date-entry-dialog.c
index aa2c539..e2a756d 100644
--- a/src/date-entry-dialog.c
+++ b/src/date-entry-dialog.c
@@ -71,7 +71,6 @@ almanah_date_entry_dialog_init (AlmanahDateEntryDialog *self)
 	g_signal_connect (self, "response", G_CALLBACK (gtk_widget_hide), self);
 	gtk_window_set_resizable (GTK_WINDOW (self), FALSE);
 	gtk_window_set_title (GTK_WINDOW (self), _("Select Date"));
-	gtk_window_set_transient_for (GTK_WINDOW (self), GTK_WINDOW (almanah->main_window));
 }
 
 static void
diff --git a/src/event-manager.c b/src/event-manager.c
index 55706dd..e64b3bf 100644
--- a/src/event-manager.c
+++ b/src/event-manager.c
@@ -127,8 +127,8 @@ almanah_event_manager_query_events (AlmanahEventManager *self, AlmanahEventFacto
 	AlmanahEventManagerPrivate *priv = ALMANAH_EVENT_MANAGER_GET_PRIVATE (self);
 	guint i;
 
-	if (almanah->debug == TRUE)
-		g_debug ("almanah_event_manager_query_events called for factory %u and date %u-%u-%u.", type_id, g_date_get_year (date), g_date_get_month (date), g_date_get_day (date));
+	g_debug ("almanah_event_manager_query_events called for factory %u and date %u-%u-%u.", type_id,
+	         g_date_get_year (date), g_date_get_month (date), g_date_get_day (date));
 
 	if (type_id != ALMANAH_EVENT_FACTORY_UNKNOWN) {
 		/* Just query that factory */
@@ -152,8 +152,8 @@ almanah_event_manager_get_events (AlmanahEventManager *self, AlmanahEventFactory
 	GSList *list = NULL, *end = NULL;
 	guint i;
 
-	if (almanah->debug == TRUE)
-		g_debug ("almanah_event_manager_get_events called for factory %u and date %u-%u-%u.", type_id, g_date_get_year (date), g_date_get_month (date), g_date_get_day (date));
+	g_debug ("almanah_event_manager_get_events called for factory %u and date %u-%u-%u.", type_id,
+	         g_date_get_year (date), g_date_get_month (date), g_date_get_day (date));
 
 	if (type_id != ALMANAH_EVENT_FACTORY_UNKNOWN) {
 		/* Just return the events for the specified event factory */
diff --git a/src/event.c b/src/event.c
index 42f4797..7c03f54 100644
--- a/src/event.c
+++ b/src/event.c
@@ -96,11 +96,11 @@ almanah_event_format_value (AlmanahEvent *self)
 }
 
 gboolean
-almanah_event_view (AlmanahEvent *self)
+almanah_event_view (AlmanahEvent *self, GtkWindow *parent_window)
 {
 	AlmanahEventClass *klass = ALMANAH_EVENT_GET_CLASS (self);
 	g_assert (klass->view != NULL);
-	return klass->view (self);
+	return klass->view (self, parent_window);
 }
 
 const gchar *
diff --git a/src/event.h b/src/event.h
index 0de9a44..53a1c2c 100644
--- a/src/event.h
+++ b/src/event.h
@@ -47,13 +47,13 @@ typedef struct {
 	const gchar *icon_name;
 
 	const gchar *(*format_value) (AlmanahEvent *event);
-	gboolean (*view) (AlmanahEvent *event);
+	gboolean (*view) (AlmanahEvent *event, GtkWindow *parent_window);
 } AlmanahEventClass;
 
 GType almanah_event_get_type (void);
 
 const gchar *almanah_event_format_value (AlmanahEvent *self);
-gboolean almanah_event_view (AlmanahEvent *self);
+gboolean almanah_event_view (AlmanahEvent *self, GtkWindow *parent_window);
 const gchar *almanah_event_get_name (AlmanahEvent *self);
 const gchar *almanah_event_get_description (AlmanahEvent *self);
 const gchar *almanah_event_get_icon_name (AlmanahEvent *self);
diff --git a/src/events/calendar-appointment.c b/src/events/calendar-appointment.c
index a5e7e70..029182d 100644
--- a/src/events/calendar-appointment.c
+++ b/src/events/calendar-appointment.c
@@ -26,7 +26,7 @@
 
 static void almanah_calendar_appointment_event_finalize (GObject *object);
 static const gchar *almanah_calendar_appointment_event_format_value (AlmanahEvent *event);
-static gboolean almanah_calendar_appointment_event_view (AlmanahEvent *event);
+static gboolean almanah_calendar_appointment_event_view (AlmanahEvent *event, GtkWindow *parent_window);
 
 struct _AlmanahCalendarAppointmentEventPrivate {
 	gchar *summary;
@@ -88,7 +88,7 @@ almanah_calendar_appointment_event_format_value (AlmanahEvent *event)
 }
 
 static gboolean
-almanah_calendar_appointment_event_view (AlmanahEvent *event)
+almanah_calendar_appointment_event_view (AlmanahEvent *event, GtkWindow *parent_window)
 {
 	AlmanahCalendarAppointmentEventPrivate *priv = ALMANAH_CALENDAR_APPOINTMENT_EVENT (event)->priv;
 	struct tm utc_date_tm;
@@ -108,14 +108,13 @@ almanah_calendar_appointment_event_view (AlmanahEvent *event)
 					utc_date_tm.tm_min,
 					0);
 
-	if (almanah->debug == TRUE)
-		g_debug ("Executing \"%s\".", command_line);
+	g_debug ("Executing \"%s\".", command_line);
 
-	retval = almanah_run_on_screen (gtk_widget_get_screen (almanah->main_window), command_line, &error);
+	retval = almanah_run_on_screen (gtk_widget_get_screen (GTK_WIDGET (parent_window)), command_line, &error);
 	g_free (command_line);
 
 	if (retval == FALSE) {
-		GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW (almanah->main_window),
+		GtkWidget *dialog = gtk_message_dialog_new (parent_window,
 							    GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
 							    _("Error launching Evolution"));
 		gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", error->message);
diff --git a/src/events/calendar-task.c b/src/events/calendar-task.c
index 39c17e3..d315967 100644
--- a/src/events/calendar-task.c
+++ b/src/events/calendar-task.c
@@ -26,7 +26,7 @@
 
 static void almanah_calendar_task_event_finalize (GObject *object);
 static const gchar *almanah_calendar_task_event_format_value (AlmanahEvent *event);
-static gboolean almanah_calendar_task_event_view (AlmanahEvent *event);
+static gboolean almanah_calendar_task_event_view (AlmanahEvent *event, GtkWindow *parent_window);
 
 struct _AlmanahCalendarTaskEventPrivate {
 	gchar *uid;
@@ -88,7 +88,7 @@ almanah_calendar_task_event_format_value (AlmanahEvent *event)
 }
 
 static gboolean
-almanah_calendar_task_event_view (AlmanahEvent *event)
+almanah_calendar_task_event_view (AlmanahEvent *event, GtkWindow *parent_window)
 {
 	AlmanahCalendarTaskEventPrivate *priv = ALMANAH_CALENDAR_TASK_EVENT (event)->priv;
 	gchar *command_line;
@@ -97,14 +97,13 @@ almanah_calendar_task_event_view (AlmanahEvent *event)
 
 	command_line = g_strdup_printf ("evolution task:%s", priv->uid);
 
-	if (almanah->debug == TRUE)
-		g_debug ("Executing \"%s\".", command_line);
+	g_debug ("Executing \"%s\".", command_line);
 
-	retval = almanah_run_on_screen (gtk_widget_get_screen (almanah->main_window), command_line, &error);
+	retval = almanah_run_on_screen (gtk_widget_get_screen (GTK_WIDGET (parent_window)), command_line, &error);
 	g_free (command_line);
 
 	if (retval == FALSE) {
-		GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW (almanah->main_window),
+		GtkWidget *dialog = gtk_message_dialog_new (parent_window,
 							    GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
 							    _("Error launching Evolution"));
 		gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", error->message);
diff --git a/src/export-operation.c b/src/export-operation.c
index 47ab893..2f30a0b 100644
--- a/src/export-operation.c
+++ b/src/export-operation.c
@@ -54,13 +54,20 @@ static const ExportModeDetails export_modes[] = {
 	  export_database }
 };
 
+static void get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
+static void set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec);
 static void almanah_export_operation_dispose (GObject *object);
 
 struct _AlmanahExportOperationPrivate {
 	gint current_mode; /* index into export_modes */
+	AlmanahStorageManager *storage_manager;
 	GFile *destination;
 };
 
+enum {
+	PROP_STORAGE_MANAGER = 1,
+};
+
 G_DEFINE_TYPE (AlmanahExportOperation, almanah_export_operation, G_TYPE_OBJECT)
 #define ALMANAH_EXPORT_OPERATION_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ALMANAH_TYPE_EXPORT_OPERATION, AlmanahExportOperationPrivate))
 
@@ -71,7 +78,15 @@ almanah_export_operation_class_init (AlmanahExportOperationClass *klass)
 
 	g_type_class_add_private (klass, sizeof (AlmanahExportOperationPrivate));
 
+	gobject_class->get_property = get_property;
+	gobject_class->set_property = set_property;
 	gobject_class->dispose = almanah_export_operation_dispose;
+
+	g_object_class_install_property (gobject_class, PROP_STORAGE_MANAGER,
+	                                 g_param_spec_object ("storage-manager",
+	                                                      "Storage manager", "The source storage manager for the export operation.",
+	                                                      ALMANAH_TYPE_STORAGE_MANAGER,
+	                                                      G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 }
 
 static void
@@ -86,6 +101,10 @@ almanah_export_operation_dispose (GObject *object)
 {
 	AlmanahExportOperationPrivate *priv = ALMANAH_EXPORT_OPERATION (object)->priv;
 
+	if (priv->storage_manager != NULL)
+		g_object_unref (priv->storage_manager);
+	priv->storage_manager = NULL;
+
 	if (priv->destination != NULL)
 		g_object_unref (priv->destination);
 	priv->destination = NULL;
@@ -94,10 +113,42 @@ almanah_export_operation_dispose (GObject *object)
 	G_OBJECT_CLASS (almanah_export_operation_parent_class)->dispose (object);
 }
 
+static void
+get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
+{
+	AlmanahExportOperationPrivate *priv = ALMANAH_EXPORT_OPERATION (object)->priv;
+
+	switch (property_id) {
+		case PROP_STORAGE_MANAGER:
+			g_value_set_object (value, priv->storage_manager);
+			break;
+		default:
+			/* We don't have any other property... */
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+			break;
+	}
+}
+
+static void
+set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
+{
+	AlmanahExportOperation *self = ALMANAH_EXPORT_OPERATION (object);
+
+	switch (property_id) {
+		case PROP_STORAGE_MANAGER:
+			self->priv->storage_manager = g_value_dup_object (value);
+			break;
+		default:
+			/* We don't have any other property... */
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+			break;
+	}
+}
+
 AlmanahExportOperation *
-almanah_export_operation_new (AlmanahExportOperationType type_id, GFile *destination)
+almanah_export_operation_new (AlmanahExportOperationType type_id, AlmanahStorageManager *source_storage_manager, GFile *destination)
 {
-	AlmanahExportOperation *export_operation = g_object_new (ALMANAH_TYPE_EXPORT_OPERATION, NULL);
+	AlmanahExportOperation *export_operation = g_object_new (ALMANAH_TYPE_EXPORT_OPERATION, "storage-manager", source_storage_manager, NULL);
 	export_operation->priv->current_mode = type_id;
 	export_operation->priv->destination = g_object_ref (destination);
 
@@ -161,7 +212,7 @@ export_text_files (AlmanahExportOperation *self, GFile *destination, AlmanahExpo
 
 	/* Iterate through the entries */
 	almanah_storage_manager_iter_init (&iter);
-	while ((entry = almanah_storage_manager_get_entries (almanah->storage_manager, &iter)) != NULL) {
+	while ((entry = almanah_storage_manager_get_entries (self->priv->storage_manager, &iter)) != NULL) {
 		GDate date;
 		gchar *filename, *content;
 		GFile *file;
@@ -230,7 +281,7 @@ export_database (AlmanahExportOperation *self, GFile *destination, AlmanahExport
 	/* We ignore the progress callbacks, since this is a fairly fast operation, and it exports all the entries at once. */
 
 	/* Get the input file (current unencrypted database) */
-	source = g_file_new_for_path (almanah_storage_manager_get_filename (almanah->storage_manager, TRUE));
+	source = g_file_new_for_path (almanah_storage_manager_get_filename (self->priv->storage_manager, TRUE));
 
 	/* Copy the current database to that location */
 	success = g_file_copy (source, destination, G_FILE_COPY_OVERWRITE, cancellable, NULL, NULL, error);
diff --git a/src/export-operation.h b/src/export-operation.h
index 7292519..07cfd74 100644
--- a/src/export-operation.h
+++ b/src/export-operation.h
@@ -23,6 +23,8 @@
 #include <glib.h>
 #include <glib-object.h>
 
+#include "storage-manager.h"
+
 G_BEGIN_DECLS
 
 typedef guint AlmanahExportOperationType;
@@ -49,7 +51,8 @@ typedef struct {
 
 GType almanah_export_operation_get_type (void) G_GNUC_CONST;
 
-AlmanahExportOperation *almanah_export_operation_new (AlmanahExportOperationType type_id, GFile *destination) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
+AlmanahExportOperation *almanah_export_operation_new (AlmanahExportOperationType type_id, AlmanahStorageManager *source_storage_manager,
+                                                      GFile *destination) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
 
 void almanah_export_operation_run (AlmanahExportOperation *self, GCancellable *cancellable,
                                    AlmanahExportProgressCallback progress_callback, gpointer progress_user_data,
diff --git a/src/import-export-dialog.c b/src/import-export-dialog.c
index 3b8aeda..cf6de22 100644
--- a/src/import-export-dialog.c
+++ b/src/import-export-dialog.c
@@ -37,6 +37,7 @@ void ied_file_chooser_selection_changed_cb (GtkFileChooser *file_chooser, Almana
 void ied_file_chooser_file_activated_cb (GtkFileChooser *file_chooser, AlmanahImportExportDialog *self);
 
 struct _AlmanahImportExportDialogPrivate {
+	AlmanahStorageManager *storage_manager;
 	gboolean import; /* TRUE if we're in import mode, FALSE otherwise */
 	GtkComboBox *mode_combo_box;
 	GtkListStore *mode_store;
@@ -48,18 +49,35 @@ struct _AlmanahImportExportDialogPrivate {
 	GCancellable *cancellable; /* non-NULL iff an operation is underway */
 };
 
+enum {
+	PROP_STORAGE_MANAGER = 1,
+};
+
 G_DEFINE_TYPE (AlmanahImportExportDialog, almanah_import_export_dialog, GTK_TYPE_DIALOG)
 #define ALMANAH_IMPORT_EXPORT_DIALOG_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ALMANAH_TYPE_IMPORT_EXPORT_DIALOG,\
                                                        AlmanahImportExportDialogPrivate))
 
+static void get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
+static void set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec);
 static void almanah_import_export_dialog_dispose (GObject *object);
 
 static void
 almanah_import_export_dialog_class_init (AlmanahImportExportDialogClass *klass)
 {
 	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-	gobject_class->dispose = almanah_import_export_dialog_dispose;
+
 	g_type_class_add_private (klass, sizeof (AlmanahImportExportDialogPrivate));
+
+	gobject_class->get_property = get_property;
+	gobject_class->set_property = set_property;
+	gobject_class->dispose = almanah_import_export_dialog_dispose;
+
+	g_object_class_install_property (gobject_class, PROP_STORAGE_MANAGER,
+	                                 g_param_spec_object ("storage-manager",
+	                                                      "Storage manager", "The local storage manager: source for export operations and "
+	                                                      "destination for import operations.",
+	                                                      ALMANAH_TYPE_STORAGE_MANAGER,
+	                                                      G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 }
 
 static void
@@ -75,20 +93,59 @@ almanah_import_export_dialog_init (AlmanahImportExportDialog *self)
 static void
 almanah_import_export_dialog_dispose (GObject *object)
 {
+	AlmanahImportExportDialogPrivate *priv = ALMANAH_IMPORT_EXPORT_DIALOG (object)->priv;
+
+	if (priv->storage_manager != NULL)
+		g_object_unref (priv->storage_manager);
+	priv->storage_manager = NULL;
+
 	/* Chain up to the parent class */
 	G_OBJECT_CLASS (almanah_import_export_dialog_parent_class)->dispose (object);
 }
 
+static void
+get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
+{
+	AlmanahImportExportDialogPrivate *priv = ALMANAH_IMPORT_EXPORT_DIALOG (object)->priv;
+
+	switch (property_id) {
+		case PROP_STORAGE_MANAGER:
+			g_value_set_object (value, priv->storage_manager);
+			break;
+		default:
+			/* We don't have any other property... */
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+			break;
+	}
+}
+
+static void
+set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
+{
+	AlmanahImportExportDialog *self = ALMANAH_IMPORT_EXPORT_DIALOG (object);
+
+	switch (property_id) {
+		case PROP_STORAGE_MANAGER:
+			self->priv->storage_manager = g_value_dup_object (value);
+			break;
+		default:
+			/* We don't have any other property... */
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+			break;
+	}
+}
+
 /**
  * almanah_import_export_dialog_new:
  * @import: %TRUE to set the dialog up for importing, %FALSE to set it up for exporting
+ * @storage_manager: the storage manager which will be the source for export operations and the destination for import operations
  *
  * Returns a new #AlmanahImportExportDialog, configured for importing if @import is %TRUE, and exporting otherwise.
  *
  * Return value: a new #AlmanahImportExportDialog; destroy with gtk_widget_destroy()
  **/
 AlmanahImportExportDialog *
-almanah_import_export_dialog_new (gboolean import)
+almanah_import_export_dialog_new (AlmanahStorageManager *storage_manager, gboolean import)
 {
 	GtkBuilder *builder;
 	AlmanahImportExportDialog *import_export_dialog;
@@ -101,6 +158,8 @@ almanah_import_export_dialog_new (gboolean import)
 		NULL
 	};
 
+	g_return_val_if_fail (ALMANAH_IS_STORAGE_MANAGER (storage_manager), NULL);
+
 	builder = gtk_builder_new ();
 
 	if (gtk_builder_add_objects_from_file (builder, interface_filename, (gchar**) object_names, &error) == FALSE) {
@@ -127,6 +186,7 @@ almanah_import_export_dialog_new (gboolean import)
 	}
 
 	priv = import_export_dialog->priv;
+	priv->storage_manager = g_object_ref (storage_manager);
 	priv->import = import;
 
 	/* Grab our child widgets */
@@ -279,7 +339,7 @@ response_cb (GtkDialog *dialog, gint response_id, AlmanahImportExportDialog *sel
 		AlmanahImportResultsDialog *results_dialog = almanah_import_results_dialog_new (); /* destroyed in import_cb() */
 		gtk_window_set_transient_for (GTK_WINDOW (results_dialog), GTK_WINDOW (self)); /* this is required in import_cb() */
 
-		operation = almanah_import_operation_new (priv->current_mode, file);
+		operation = almanah_import_operation_new (priv->current_mode, file, priv->storage_manager);
 		almanah_import_operation_run (operation, priv->cancellable, (AlmanahImportProgressCallback) import_progress_cb, results_dialog,
 		                              (GAsyncReadyCallback) import_cb, results_dialog);
 		g_object_unref (operation);
@@ -287,7 +347,7 @@ response_cb (GtkDialog *dialog, gint response_id, AlmanahImportExportDialog *sel
 		/* Export the entries according to the selected method. */
 		AlmanahExportOperation *operation;
 
-		operation = almanah_export_operation_new (priv->current_mode, file);
+		operation = almanah_export_operation_new (priv->current_mode, priv->storage_manager, file);
 		almanah_export_operation_run (operation, priv->cancellable, (AlmanahExportProgressCallback) export_progress_cb, self,
 		                              (GAsyncReadyCallback) export_cb, self);
 		g_object_unref (operation);
@@ -352,7 +412,7 @@ static gboolean filter_results_cb (GtkTreeModel *model, GtkTreeIter *iter, Alman
 static void results_selection_changed_cb (GtkTreeSelection *tree_selection, GtkWidget *button);
 
 /* GtkBuilder callbacks */
-void ird_results_tree_view_row_activated_cb (GtkTreeView *self, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data);
+void ird_results_tree_view_row_activated_cb (GtkTreeView *tree_view, GtkTreePath *path, GtkTreeViewColumn *column, AlmanahImportResultsDialog *self);
 void ird_view_button_clicked_cb (GtkButton *button, AlmanahImportResultsDialog *self);
 void ird_view_combo_box_changed_cb (GtkComboBox *combo_box, AlmanahImportResultsDialog *self);
 
@@ -489,8 +549,9 @@ almanah_import_results_dialog_add_result (AlmanahImportResultsDialog *self, cons
 }
 
 static void
-select_date (GtkTreeModel *model, GtkTreeIter *iter)
+select_date (AlmanahImportResultsDialog *self, GtkTreeModel *model, GtkTreeIter *iter)
 {
+	AlmanahMainWindow *main_window;
 	guint day, month, year;
 	GDate date;
 
@@ -500,19 +561,20 @@ select_date (GtkTreeModel *model, GtkTreeIter *iter)
 	                    2, &year,
 	                    -1);
 
+	main_window = ALMANAH_MAIN_WINDOW (gtk_window_get_transient_for (GTK_WINDOW (self)));
 	g_date_set_dmy (&date, day, month, year);
-	almanah_main_window_select_date (ALMANAH_MAIN_WINDOW (almanah->main_window), &date);
+	almanah_main_window_select_date (main_window, &date);
 }
 
 void
-ird_results_tree_view_row_activated_cb (GtkTreeView *self, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data)
+ird_results_tree_view_row_activated_cb (GtkTreeView *tree_view, GtkTreePath *path, GtkTreeViewColumn *column, AlmanahImportResultsDialog *self)
 {
 	GtkTreeIter iter;
 	GtkTreeModel *model;
 
-	model = gtk_tree_view_get_model (self);
+	model = gtk_tree_view_get_model (tree_view);
 	gtk_tree_model_get_iter (model, &iter, path);
-	select_date (model, &iter);
+	select_date (self, model, &iter);
 }
 
 void
@@ -521,8 +583,9 @@ ird_view_button_clicked_cb (GtkButton *button, AlmanahImportResultsDialog *self)
 	GtkTreeIter iter;
 	GtkTreeModel *model;
 
-	if (gtk_tree_selection_get_selected (self->priv->results_selection, &model, &iter) == TRUE)
-		select_date (model, &iter);
+	if (gtk_tree_selection_get_selected (self->priv->results_selection, &model, &iter) == TRUE) {
+		select_date (self, model, &iter);
+	}
 }
 
 void
diff --git a/src/import-export-dialog.h b/src/import-export-dialog.h
index 7cf4203..8601cc3 100644
--- a/src/import-export-dialog.h
+++ b/src/import-export-dialog.h
@@ -25,6 +25,7 @@
 #include <gtk/gtk.h>
 
 #include "import-operation.h"
+#include "storage-manager.h"
 
 G_BEGIN_DECLS
 
@@ -48,7 +49,7 @@ typedef struct {
 
 GType almanah_import_export_dialog_get_type (void) G_GNUC_CONST;
 
-AlmanahImportExportDialog *almanah_import_export_dialog_new (gboolean import) G_GNUC_WARN_UNUSED_RESULT;
+AlmanahImportExportDialog *almanah_import_export_dialog_new (AlmanahStorageManager *storage_manager, gboolean import) G_GNUC_WARN_UNUSED_RESULT;
 
 #define ALMANAH_TYPE_IMPORT_RESULTS_DIALOG		(almanah_import_results_dialog_get_type ())
 #define ALMANAH_IMPORT_RESULTS_DIALOG(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), ALMANAH_TYPE_IMPORT_RESULTS_DIALOG, AlmanahImportResultsDialog))
diff --git a/src/import-operation.c b/src/import-operation.c
index 5e941f8..3a76568 100644
--- a/src/import-operation.c
+++ b/src/import-operation.c
@@ -54,11 +54,18 @@ static const ImportModeDetails import_modes[] = {
 	  import_database }
 };
 
+static void get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
+static void set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec);
 static void almanah_import_operation_dispose (GObject *object);
 
 struct _AlmanahImportOperationPrivate {
 	gint current_mode; /* index into import_modes */
 	GFile *source;
+	AlmanahStorageManager *storage_manager;
+};
+
+enum {
+	PROP_STORAGE_MANAGER = 1,
 };
 
 G_DEFINE_TYPE (AlmanahImportOperation, almanah_import_operation, G_TYPE_OBJECT)
@@ -71,7 +78,15 @@ almanah_import_operation_class_init (AlmanahImportOperationClass *klass)
 
 	g_type_class_add_private (klass, sizeof (AlmanahImportOperationPrivate));
 
+	gobject_class->get_property = get_property;
+	gobject_class->set_property = set_property;
 	gobject_class->dispose = almanah_import_operation_dispose;
+
+	g_object_class_install_property (gobject_class, PROP_STORAGE_MANAGER,
+	                                 g_param_spec_object ("storage-manager",
+	                                                      "Storage manager", "The destination storage manager for the import operation.",
+	                                                      ALMANAH_TYPE_STORAGE_MANAGER,
+	                                                      G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 }
 
 static void
@@ -90,14 +105,50 @@ almanah_import_operation_dispose (GObject *object)
 		g_object_unref (priv->source);
 	priv->source = NULL;
 
+	if (priv->storage_manager != NULL)
+		g_object_unref (priv->storage_manager);
+	priv->storage_manager = NULL;
+
 	/* Chain up to the parent class */
 	G_OBJECT_CLASS (almanah_import_operation_parent_class)->dispose (object);
 }
 
+static void
+get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
+{
+	AlmanahImportOperationPrivate *priv = ALMANAH_IMPORT_OPERATION (object)->priv;
+
+	switch (property_id) {
+		case PROP_STORAGE_MANAGER:
+			g_value_set_object (value, priv->storage_manager);
+			break;
+		default:
+			/* We don't have any other property... */
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+			break;
+	}
+}
+
+static void
+set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
+{
+	AlmanahImportOperation *self = ALMANAH_IMPORT_OPERATION (object);
+
+	switch (property_id) {
+		case PROP_STORAGE_MANAGER:
+			self->priv->storage_manager = g_value_dup_object (value);
+			break;
+		default:
+			/* We don't have any other property... */
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+			break;
+	}
+}
+
 AlmanahImportOperation *
-almanah_import_operation_new (AlmanahImportOperationType type_id, GFile *source)
+almanah_import_operation_new (AlmanahImportOperationType type_id, GFile *source, AlmanahStorageManager *dest_storage_manager)
 {
-	AlmanahImportOperation *import_operation = g_object_new (ALMANAH_TYPE_IMPORT_OPERATION, NULL);
+	AlmanahImportOperation *import_operation = g_object_new (ALMANAH_TYPE_IMPORT_OPERATION, "storage-manager", dest_storage_manager, NULL);
 	import_operation->priv->current_mode = type_id;
 	import_operation->priv->source = g_object_ref (source);
 
@@ -182,11 +233,11 @@ set_entry (AlmanahImportOperation *self, AlmanahEntry *imported_entry, const gch
 
 	/* Check to see if there's a conflict first */
 	almanah_entry_get_date (imported_entry, &entry_date);
-	existing_entry = almanah_storage_manager_get_entry (almanah->storage_manager, &entry_date);
+	existing_entry = almanah_storage_manager_get_entry (self->priv->storage_manager, &entry_date);
 
 	if (existing_entry == NULL) {
 		/* Add the entry to the proper database and return, ignoring failure */
-		almanah_storage_manager_set_entry (almanah->storage_manager, imported_entry);
+		almanah_storage_manager_set_entry (self->priv->storage_manager, imported_entry);
 
 		return ALMANAH_IMPORT_STATUS_IMPORTED;
 	}
@@ -208,7 +259,7 @@ set_entry (AlmanahImportOperation *self, AlmanahEntry *imported_entry, const gch
 	existing_buffer = gtk_text_buffer_new (gtk_text_buffer_get_tag_table (imported_buffer));
 	if (almanah_entry_get_content (existing_entry, existing_buffer, FALSE, &error) == FALSE) {
 		/* Deserialising the existing entry failed; use the imported entry instead */
-		almanah_storage_manager_set_entry (almanah->storage_manager, imported_entry);
+		almanah_storage_manager_set_entry (self->priv->storage_manager, imported_entry);
 
 		if (message != NULL) {
 			*message = g_strdup_printf (_("Error deserializing existing entry into buffer; overwriting with imported entry: %s"),
@@ -271,7 +322,7 @@ set_entry (AlmanahImportOperation *self, AlmanahEntry *imported_entry, const gch
 	if (g_date_valid (&existing_last_edited) == FALSE || g_date_compare (&existing_last_edited, &imported_last_edited) < 0)
 		almanah_entry_set_last_edited (existing_entry, &imported_last_edited);
 
-	almanah_storage_manager_set_entry (almanah->storage_manager, existing_entry);
+	almanah_storage_manager_set_entry (self->priv->storage_manager, existing_entry);
 	g_object_unref (existing_entry);
 
 	return ALMANAH_IMPORT_STATUS_MERGED;
@@ -396,7 +447,7 @@ import_database (AlmanahImportOperation *self, GFile *source, AlmanahImportProgr
 
 	/* Open the database */
 	path = g_file_get_path (source);
-	database = almanah_storage_manager_new (path);
+	database = almanah_storage_manager_new (path, NULL);
 	g_free (path);
 
 	/* Connect to the database */
diff --git a/src/import-operation.h b/src/import-operation.h
index 921f5fd..6b49207 100644
--- a/src/import-operation.h
+++ b/src/import-operation.h
@@ -24,6 +24,8 @@
 #include <glib-object.h>
 #include <gtk/gtk.h>
 
+#include "storage-manager.h"
+
 G_BEGIN_DECLS
 
 /* TODO: These must be kept in synchrony with the rows in almanah_ird_view_store in almanah.ui */
@@ -57,7 +59,8 @@ typedef struct {
 
 GType almanah_import_operation_get_type (void) G_GNUC_CONST;
 
-AlmanahImportOperation *almanah_import_operation_new (AlmanahImportOperationType type_id, GFile *source) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
+AlmanahImportOperation *almanah_import_operation_new (AlmanahImportOperationType type_id, GFile *source,
+                                                      AlmanahStorageManager *dest_storage_manager) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
 
 void almanah_import_operation_run (AlmanahImportOperation *self, GCancellable *cancellable,
                                    AlmanahImportProgressCallback progress_callback, gpointer progress_user_data,
diff --git a/src/main-window.c b/src/main-window.c
index 5c0c4d8..2006d92 100644
--- a/src/main-window.c
+++ b/src/main-window.c
@@ -36,6 +36,7 @@
 #include "printing.h"
 #include "entry.h"
 #include "storage-manager.h"
+#include "event-manager.h"
 #include "event.h"
 #include "import-export-dialog.h"
 #include "uri-entry-dialog.h"
@@ -111,8 +112,11 @@ struct _AlmanahMainWindowPrivate {
 	AlmanahEntry *current_entry; /* whether it's been modified is stored as gtk_text_buffer_get_modified (priv->entry_buffer) */
 	gulong current_entry_notify_id; /* signal handler for current_entry::notify */
 
+	GtkPrintSettings *print_settings;
+	GtkPageSetup *page_setup;
+
 #ifdef ENABLE_SPELL_CHECKING
-	gulong spell_checking_enabled_changed_id; /* signal handler for almanah->settings::changed::spell-checking-enabled */
+	gulong spell_checking_enabled_changed_id; /* signal handler for application->settings::changed::spell-checking-enabled */
 #endif /* ENABLE_SPELL_CHECKING */
 };
 
@@ -137,19 +141,23 @@ almanah_main_window_init (AlmanahMainWindow *self)
 
 	gtk_window_set_title (GTK_WINDOW (self), _("Almanah Diary"));
 	g_signal_connect (self, "delete-event", G_CALLBACK (mw_delete_event_cb), NULL);
-
-#ifdef ENABLE_SPELL_CHECKING
-	/* We don't use g_settings_bind() because enabling spell checking could fail, and we need to show an error dialogue */
-	self->priv->spell_checking_enabled_changed_id = g_signal_connect (almanah->settings, "changed::spell-checking-enabled",
-	                                                                  (GCallback) spell_checking_enabled_changed_cb, self);
-#endif /* ENABLE_SPELL_CHECKING */
 }
 
 static void
 almanah_main_window_dispose (GObject *object)
 {
+	AlmanahMainWindowPrivate *priv = ALMANAH_MAIN_WINDOW (object)->priv;
+
 	set_current_entry (ALMANAH_MAIN_WINDOW (object), NULL);
 
+	if (priv->page_setup != NULL)
+		g_object_unref (priv->page_setup);
+	priv->page_setup = NULL;
+
+	if (priv->print_settings != NULL)
+		g_object_unref (priv->print_settings);
+	priv->print_settings = NULL;
+
 	/* Chain up to the parent class */
 	G_OBJECT_CLASS (almanah_main_window_parent_class)->dispose (object);
 }
@@ -168,9 +176,11 @@ almanah_main_window_finalize (GObject *object)
 #endif /* ENABLE_SPELL_CHECKING */
 
 AlmanahMainWindow *
-almanah_main_window_new (void)
+almanah_main_window_new (AlmanahApplication *application)
 {
 	GtkBuilder *builder;
+	AlmanahStorageManager *storage_manager;
+	AlmanahEventManager *event_manager;
 	AlmanahMainWindow *main_window;
 	AlmanahMainWindowPrivate *priv;
 	GError *error = NULL;
@@ -183,6 +193,8 @@ almanah_main_window_new (void)
 		NULL
 	};
 
+	g_return_val_if_fail (ALMANAH_IS_APPLICATION (application), NULL);
+
 	builder = gtk_builder_new ();
 
 	if (gtk_builder_add_objects_from_file (builder, interface_filename, (gchar**) object_names, &error) == FALSE) {
@@ -211,6 +223,9 @@ almanah_main_window_new (void)
 		return NULL;
 	}
 
+	/* Set up the application */
+	gtk_window_set_application (GTK_WINDOW (main_window), GTK_APPLICATION (application));
+
 	priv = ALMANAH_MAIN_WINDOW (main_window)->priv;
 
 	/* Grab our child widgets */
@@ -234,8 +249,17 @@ almanah_main_window_new (void)
 
 #ifdef ENABLE_SPELL_CHECKING
 	/* Set up spell checking, if it's enabled */
-	if (g_settings_get_boolean (almanah->settings, "spell-checking-enabled") == TRUE)
+	settings = almanah_application_dup_settings (application);
+
+	if (g_settings_get_boolean (settings, "spell-checking-enabled") == TRUE) {
 		enable_spell_checking (main_window, NULL);
+	}
+
+	/* We don't use g_settings_bind() because enabling spell checking could fail, and we need to show an error dialogue */
+	priv->spell_checking_enabled_changed_id = g_signal_connect (settings, "changed::spell-checking-enabled",
+	                                                            (GCallback) spell_checking_enabled_changed_cb, main_window);
+
+	g_object_unref (settings);
 #endif /* ENABLE_SPELL_CHECKING */
 
 	/* Set up text formatting. It's important this is done after setting up GtkSpell, so that we know whether to
@@ -259,8 +283,19 @@ almanah_main_window_new (void)
 	g_signal_connect (priv->underline_action, "toggled", G_CALLBACK (mw_underline_toggled_cb), main_window);
 	g_signal_connect (priv->hyperlink_action, "toggled", (GCallback) mw_hyperlink_toggled_cb, main_window);
 
+	/* Notification for calendar changes */
+	storage_manager = almanah_application_dup_storage_manager (application);
+	almanah_calendar_set_storage_manager (priv->calendar, storage_manager);
+	g_object_unref (storage_manager);
+
 	/* Notification for event changes */
-	g_signal_connect (almanah->event_manager, "events-updated", G_CALLBACK (mw_events_updated_cb), main_window);
+	event_manager = almanah_application_dup_event_manager (application);
+	g_signal_connect (event_manager, "events-updated", G_CALLBACK (mw_events_updated_cb), main_window);
+	g_object_unref (event_manager);
+
+	/* Set up printing objects */
+	priv->print_settings = gtk_print_settings_new ();
+	priv->page_setup = gtk_page_setup_new ();
 
 	/* Select the current day and month */
 	mw_jump_to_today_activate_cb (NULL, main_window);
@@ -514,6 +549,7 @@ save_current_entry (AlmanahMainWindow *self)
 {
 	gboolean entry_exists, existing_entry_is_empty, entry_is_empty;
 	GDate date, last_edited;
+	AlmanahStorageManager *storage_manager;
 	AlmanahMainWindowPrivate *priv = self->priv;
 	AlmanahEntryEditability editability;
 
@@ -525,9 +561,11 @@ save_current_entry (AlmanahMainWindow *self)
 	    gtk_text_buffer_get_modified (priv->entry_buffer) == FALSE)
 		return;
 
+	storage_manager = almanah_application_dup_storage_manager (ALMANAH_APPLICATION (gtk_window_get_application (GTK_WINDOW (self))));
+
 	almanah_entry_get_date (priv->current_entry, &date);
 	editability = almanah_entry_get_editability (priv->current_entry);
-	entry_exists = almanah_storage_manager_entry_exists (almanah->storage_manager, &date);
+	entry_exists = almanah_storage_manager_entry_exists (storage_manager, &date);
 	existing_entry_is_empty = almanah_entry_is_empty (priv->current_entry);
 	entry_is_empty = (gtk_text_buffer_get_char_count (priv->entry_buffer) == 0) ? TRUE : FALSE;
 
@@ -536,7 +574,7 @@ save_current_entry (AlmanahMainWindow *self)
 	 * If an entry is being deleted, permission must be given for that as a priority. */
 	if (editability == ALMANAH_ENTRY_FUTURE) {
 		/* Can't edit entries for dates in the future */
-		return;
+		goto done;
 	} else if (editability == ALMANAH_ENTRY_PAST && (existing_entry_is_empty == FALSE || entry_is_empty == FALSE)) {
 		/* Attempting to edit an existing entry in the past */
 		gchar date_string[100];
@@ -558,7 +596,7 @@ save_current_entry (AlmanahMainWindow *self)
 		if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_ACCEPT) {
 			/* Cancelled the edit */
 			gtk_widget_destroy (dialog);
-			return;
+			goto done;
 		}
 
 		gtk_widget_destroy (dialog);
@@ -583,7 +621,7 @@ save_current_entry (AlmanahMainWindow *self)
 		if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_ACCEPT) {
 			/* Cancelled deletion */
 			gtk_widget_destroy (dialog);
-			return;
+			goto done;
 		}
 
 		gtk_widget_destroy (dialog);
@@ -597,12 +635,15 @@ save_current_entry (AlmanahMainWindow *self)
 	almanah_entry_set_last_edited (priv->current_entry, &last_edited);
 
 	/* Store the entry! */
-	almanah_storage_manager_set_entry (almanah->storage_manager, priv->current_entry);
+	almanah_storage_manager_set_entry (storage_manager, priv->current_entry);
 
 	if (entry_is_empty == TRUE) {
 		/* Since the entry is empty, remove all the events from the treeview */
 		gtk_list_store_clear (priv->event_store);
 	}
+
+done:
+	g_object_unref (storage_manager);
 }
 
 void
@@ -745,7 +786,7 @@ mw_delete_event_cb (GtkWindow *window, gpointer user_data)
 	save_current_entry (ALMANAH_MAIN_WINDOW (window));
 	save_window_state (ALMANAH_MAIN_WINDOW (window));
 
-	almanah_quit ();
+	gtk_widget_destroy (GTK_WIDGET (window));
 
 	return TRUE;
 }
@@ -753,7 +794,15 @@ mw_delete_event_cb (GtkWindow *window, gpointer user_data)
 void
 mw_import_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
 {
-	GtkWidget *dialog = GTK_WIDGET (almanah_import_export_dialog_new (TRUE));
+	AlmanahApplication *application;
+	AlmanahStorageManager *storage_manager;
+	GtkWidget *dialog;
+
+	application = ALMANAH_APPLICATION (gtk_window_get_application (GTK_WINDOW (main_window)));
+	storage_manager = almanah_application_dup_storage_manager (application);
+	dialog = GTK_WIDGET (almanah_import_export_dialog_new (storage_manager, TRUE));
+	g_object_unref (storage_manager);
+
 	gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (main_window));
 	gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
 
@@ -764,7 +813,15 @@ mw_import_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
 void
 mw_export_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
 {
-	GtkWidget *dialog = GTK_WIDGET (almanah_import_export_dialog_new (FALSE));
+	AlmanahApplication *application;
+	AlmanahStorageManager *storage_manager;
+	GtkWidget *dialog;
+
+	application = ALMANAH_APPLICATION (gtk_window_get_application (GTK_WINDOW (main_window)));
+	storage_manager = almanah_application_dup_storage_manager (application);
+	dialog = GTK_WIDGET (almanah_import_export_dialog_new (storage_manager, FALSE));
+	g_object_unref (storage_manager);
+
 	gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (main_window));
 	gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
 
@@ -775,26 +832,46 @@ mw_export_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
 void
 mw_page_setup_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
 {
-	almanah_print_page_setup ();
+	AlmanahMainWindowPrivate *priv = main_window->priv;
+	GtkPageSetup *page_setup;
+
+	page_setup = gtk_print_run_page_setup_dialog (GTK_WINDOW (main_window), priv->page_setup, priv->print_settings);
+	if (priv->page_setup != NULL)
+		g_object_unref (priv->page_setup);
+	priv->page_setup = page_setup;
 }
 
 void
 mw_print_preview_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
 {
-	almanah_print_entries (TRUE);
+	AlmanahMainWindowPrivate *priv = main_window->priv;
+	AlmanahApplication *application;
+	AlmanahStorageManager *storage_manager;
+
+	application = ALMANAH_APPLICATION (gtk_window_get_application (GTK_WINDOW (main_window)));
+	storage_manager = almanah_application_dup_storage_manager (application);
+	almanah_print_entries (TRUE, GTK_WINDOW (main_window), &(priv->page_setup), &(priv->print_settings), storage_manager);
+	g_object_unref (storage_manager);
 }
 
 void
 mw_print_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
 {
-	almanah_print_entries (FALSE);
+	AlmanahMainWindowPrivate *priv = main_window->priv;
+	AlmanahApplication *application;
+	AlmanahStorageManager *storage_manager;
+
+	application = ALMANAH_APPLICATION (gtk_window_get_application (GTK_WINDOW (main_window)));
+	storage_manager = almanah_application_dup_storage_manager (application);
+	almanah_print_entries (FALSE, GTK_WINDOW (main_window), &(priv->page_setup), &(priv->print_settings), storage_manager);
+	g_object_unref (storage_manager);
 }
 
 void
 mw_quit_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
 {
 	save_current_entry (main_window);
-	almanah_quit ();
+	gtk_widget_destroy (GTK_WIDGET (main_window));
 }
 
 void
@@ -844,38 +921,51 @@ mw_important_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
 void
 mw_select_date_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
 {
-	if (almanah->date_entry_dialog == NULL)
-		almanah->date_entry_dialog = GTK_WIDGET (almanah_date_entry_dialog_new ());
+	AlmanahDateEntryDialog *dialog = almanah_date_entry_dialog_new ();
 
-	gtk_widget_show_all (almanah->date_entry_dialog);
-	if (almanah_date_entry_dialog_run (ALMANAH_DATE_ENTRY_DIALOG (almanah->date_entry_dialog)) == TRUE) {
+	gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (main_window));
+	gtk_widget_show_all (GTK_WIDGET (dialog));
+	if (almanah_date_entry_dialog_run (dialog) == TRUE) {
 		GDate new_date;
 
 		/* Switch to the specified date */
-		almanah_date_entry_dialog_get_date (ALMANAH_DATE_ENTRY_DIALOG (almanah->date_entry_dialog), &new_date);
+		almanah_date_entry_dialog_get_date (dialog, &new_date);
 		almanah_main_window_select_date (main_window, &new_date);
 	}
+
+	gtk_widget_destroy (GTK_WIDGET (dialog));
 }
 
 void
 mw_search_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
 {
-	if (almanah->search_dialog == NULL)
-		almanah->search_dialog = GTK_WIDGET (almanah_search_dialog_new ());
+	AlmanahSearchDialog *dialog = almanah_search_dialog_new ();
+
+	gtk_window_set_application (GTK_WINDOW (dialog), gtk_window_get_application (GTK_WINDOW (main_window)));
+	gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (main_window));
+	gtk_widget_show_all (GTK_WIDGET (dialog));
+	gtk_dialog_run (GTK_DIALOG (dialog));
 
-	gtk_widget_show_all (almanah->search_dialog);
-	gtk_dialog_run (GTK_DIALOG (almanah->search_dialog));
+	gtk_widget_destroy (GTK_WIDGET (dialog));
 }
 
 void
 mw_preferences_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
 {
 #ifdef ENABLE_ENCRYPTION
-	if (almanah->preferences_dialog == NULL)
-		almanah->preferences_dialog = GTK_WIDGET (almanah_preferences_dialog_new ());
+	AlmanahApplication *application;
+	GSettings *settings;
+	AlmanahPreferencesDialog *dialog;
 
-	gtk_widget_show_all (almanah->preferences_dialog);
-	gtk_dialog_run (GTK_DIALOG (almanah->preferences_dialog));
+	application = ALMANAH_APPLICATION (gtk_window_get_application (GTK_WINDOW (main_window)));
+	settings = almanah_application_dup_settings (application);
+	dialog = almanah_preferences_dialog_new (settings);
+	g_object_unref (settings);
+
+	gtk_widget_show_all (GTK_WIDGET (dialog));
+	gtk_dialog_run (GTK_DIALOG (dialog));
+
+	gtk_widget_destroy (GTK_WIDGET (dialog));
 #endif /* ENABLE_ENCRYPTION */
 }
 
@@ -917,25 +1007,23 @@ mw_underline_toggled_cb (GtkToggleAction *action, AlmanahMainWindow *main_window
 }
 
 static gboolean
-hyperlink_tag_event_cb (GtkTextTag *tag, GObject *object, GdkEvent *event, GtkTextIter *iter, gpointer user_data)
+hyperlink_tag_event_cb (GtkTextTag *tag, GObject *object, GdkEvent *event, GtkTextIter *iter, AlmanahMainWindow *self)
 {
-	AlmanahHyperlinkTag *self = ALMANAH_HYPERLINK_TAG (tag);
+	AlmanahHyperlinkTag *hyperlink_tag = ALMANAH_HYPERLINK_TAG (tag);
 
 	/* Open the hyperlink if it's control-clicked */
 	if (event->type == GDK_BUTTON_RELEASE && event->button.state & GDK_CONTROL_MASK) {
-		GtkWindow *main_window;
 		const gchar *uri;
 		GError *error = NULL;
 
-		main_window = GTK_WINDOW (almanah->main_window);
-		uri = almanah_hyperlink_tag_get_uri (self);
+		uri = almanah_hyperlink_tag_get_uri (hyperlink_tag);
 
 		/* Attempt to open the URI */
-		gtk_show_uri (gtk_widget_get_screen (GTK_WIDGET (main_window)), uri, gdk_event_get_time (event), &error);
+		gtk_show_uri (gtk_widget_get_screen (GTK_WIDGET (self)), uri, gdk_event_get_time (event), &error);
 
 		if (error != NULL) {
 			/* Error */
-			GtkWidget *dialog = gtk_message_dialog_new (main_window,
+			GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW (self),
 			                                            GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
 			                                            _("Error opening URI"));
 			gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", error->message);
@@ -986,7 +1074,7 @@ mw_hyperlink_toggled_cb (GtkToggleAction *action, AlmanahMainWindow *self)
 			gtk_text_buffer_apply_tag (priv->entry_buffer, tag, &start, &end);
 
 			/* Connect up events */
-			g_signal_connect (tag, "event", (GCallback) hyperlink_tag_event_cb, NULL);
+			g_signal_connect (tag, "event", (GCallback) hyperlink_tag_event_cb, self);
 
 			/* The text tag table keeps a reference */
 			g_object_unref (tag);
@@ -1042,6 +1130,8 @@ mw_hyperlink_toggled_cb (GtkToggleAction *action, AlmanahMainWindow *self)
 void
 mw_about_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
 {
+	AlmanahApplication *application;
+	AlmanahStorageManager *storage_manager;
 	gchar *license, *description;
 	guint entry_count;
 
@@ -1069,7 +1159,11 @@ mw_about_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
 			  _(license_parts[2]),
 			  NULL);
 
-	almanah_storage_manager_get_statistics (almanah->storage_manager, &entry_count);
+	application = ALMANAH_APPLICATION (gtk_window_get_application (GTK_WINDOW (main_window)));
+	storage_manager = almanah_application_dup_storage_manager (application);
+	almanah_storage_manager_get_statistics (storage_manager, &entry_count);
+	g_object_unref (storage_manager);
+
 	description = g_strdup_printf (_("A helpful diary keeper, storing %u entries."), entry_count);
 
 	gtk_show_about_dialog (GTK_WINDOW (main_window),
@@ -1108,8 +1202,7 @@ clear_factory_events (AlmanahMainWindow *self, AlmanahEventFactoryType type_id)
 	GtkTreeIter iter;
 	GtkTreeModel *model = GTK_TREE_MODEL (self->priv->event_store);
 
-	if (almanah->debug == TRUE)
-		g_debug ("Removing events belonging to factory %u from the list store...", type_id);
+	g_debug ("Removing events belonging to factory %u from the list store...", type_id);
 
 	if (gtk_tree_model_get_iter_first (model, &iter) == FALSE)
 		return;
@@ -1120,11 +1213,9 @@ clear_factory_events (AlmanahMainWindow *self, AlmanahEventFactoryType type_id)
 		gtk_tree_model_get (model, &iter, 2, &row_type_id, -1);
 
 		if (row_type_id == type_id) {
-			if (almanah->debug == TRUE) {
-				AlmanahEvent *event;
-				gtk_tree_model_get (model, &iter, 0, &event, -1);
-				g_debug ("\t%s", almanah_event_format_value (event));
-			}
+			AlmanahEvent *event;
+			gtk_tree_model_get (model, &iter, 0, &event, -1);
+			g_debug ("\t%s", almanah_event_format_value (event));
 
 			if (gtk_list_store_remove (GTK_LIST_STORE (model), &iter) == FALSE)
 				break;
@@ -1134,8 +1225,7 @@ clear_factory_events (AlmanahMainWindow *self, AlmanahEventFactoryType type_id)
 		}
 	}
 
-	if (almanah->debug == TRUE)
-		g_debug ("Finished removing events.");
+	g_debug ("Finished removing events.");
 }
 
 static void
@@ -1151,15 +1241,13 @@ mw_events_updated_cb (AlmanahEventManager *event_manager, AlmanahEventFactoryTyp
 	/* Clear all the events generated by this factory out of the list store first */
 	clear_factory_events (main_window, type_id);
 
-	if (almanah->debug == TRUE)
-		g_debug ("Adding events from factory %u to the list store...", type_id);
+	g_debug ("Adding events from factory %u to the list store...", type_id);
 
 	for (events = _events; events != NULL; events = g_slist_next (events)) {
 		GtkTreeIter iter;
 		AlmanahEvent *event = events->data;
 
-		if (almanah->debug == TRUE)
-			g_debug ("\t%s", almanah_event_format_value (event));
+		g_debug ("\t%s", almanah_event_format_value (event));
 
 		gtk_list_store_append (priv->event_store, &iter);
 		gtk_list_store_set (priv->event_store, &iter,
@@ -1171,8 +1259,7 @@ mw_events_updated_cb (AlmanahEventManager *event_manager, AlmanahEventFactoryTyp
 		g_object_unref (event);
 	}
 
-	if (almanah->debug == TRUE)
-		g_debug ("Finished adding events.");
+	g_debug ("Finished adding events.");
 
 	g_slist_free (_events);
 }
@@ -1180,6 +1267,9 @@ mw_events_updated_cb (AlmanahEventManager *event_manager, AlmanahEventFactoryTyp
 void
 mw_calendar_day_selected_cb (GtkCalendar *calendar, AlmanahMainWindow *main_window)
 {
+	AlmanahApplication *application;
+	AlmanahStorageManager *storage_manager;
+	AlmanahEventManager *event_manager;
 	GDate calendar_date;
 	gchar calendar_string[100];
 #ifdef ENABLE_SPELL_CHECKING
@@ -1188,6 +1278,9 @@ mw_calendar_day_selected_cb (GtkCalendar *calendar, AlmanahMainWindow *main_wind
 	AlmanahMainWindowPrivate *priv = main_window->priv;
 	AlmanahEntry *entry;
 
+	/* Set up */
+	application = ALMANAH_APPLICATION (gtk_window_get_application (GTK_WINDOW (main_window)));
+
 	/* Save the previous entry */
 	save_current_entry (main_window);
 
@@ -1199,7 +1292,10 @@ mw_calendar_day_selected_cb (GtkCalendar *calendar, AlmanahMainWindow *main_wind
 	gtk_label_set_markup (priv->date_label, calendar_string);
 
 	/* Update the entry */
-	entry = almanah_storage_manager_get_entry (almanah->storage_manager, &calendar_date);
+	storage_manager = almanah_application_dup_storage_manager (application);
+	entry = almanah_storage_manager_get_entry (storage_manager, &calendar_date);
+	g_object_unref (storage_manager);
+
 	if (entry == NULL)
 		entry = almanah_entry_new (&calendar_date);
 	set_current_entry (main_window, entry);
@@ -1218,7 +1314,7 @@ mw_calendar_day_selected_cb (GtkCalendar *calendar, AlmanahMainWindow *main_wind
 
 		gtk_text_buffer_set_text (priv->entry_buffer, "", 0);
 		if (almanah_entry_get_content (priv->current_entry, priv->entry_buffer, FALSE, &error) == FALSE) {
-			GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW (almanah->main_window),
+			GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW (main_window),
 								    GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
 								    _("Entry content could not be loaded"));
 			gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", error->message);
@@ -1250,7 +1346,9 @@ mw_calendar_day_selected_cb (GtkCalendar *calendar, AlmanahMainWindow *main_wind
 	gtk_text_buffer_set_modified (priv->entry_buffer, FALSE);
 
 	/* List the entry's events */
-	almanah_event_manager_query_events (almanah->event_manager, ALMANAH_EVENT_FACTORY_UNKNOWN, &calendar_date);
+	event_manager = almanah_application_dup_event_manager (application);
+	almanah_event_manager_query_events (event_manager, ALMANAH_EVENT_FACTORY_UNKNOWN, &calendar_date);
+	g_object_unref (event_manager);
 }
 
 static void
@@ -1288,7 +1386,7 @@ mw_events_tree_view_row_activated_cb (GtkTreeView *tree_view, GtkTreePath *path,
 			    -1);
 
 	/* NOTE: event types should display their own errors, so one won't be displayed here. */
-	almanah_event_view (event);
+	almanah_event_view (event, GTK_WINDOW (main_window));
 }
 
 void
@@ -1309,7 +1407,7 @@ mw_view_button_clicked_cb (GtkButton *button, AlmanahMainWindow *main_window)
 				    -1);
 
 		/* NOTE: event types should display their own errors, so one won't be displayed here. */
-		almanah_event_view (event);
+		almanah_event_view (event, GTK_WINDOW (main_window));
 
 		gtk_tree_path_free (events->data);
 	}
@@ -1323,8 +1421,7 @@ spell_checking_enabled_changed_cb (GSettings *settings, gchar *key, AlmanahMainW
 {
 	gboolean enabled = g_settings_get_boolean (settings, "spell-checking-enabled");
 
-	if (almanah->debug)
-		g_debug ("spell_checking_enabled_changed_cb called with %u.", enabled);
+	g_debug ("spell_checking_enabled_changed_cb called with %u.", enabled);
 
 	if (enabled == TRUE) {
 		GError *error = NULL;
@@ -1349,6 +1446,8 @@ spell_checking_enabled_changed_cb (GSettings *settings, gchar *key, AlmanahMainW
 static gboolean
 enable_spell_checking (AlmanahMainWindow *self, GError **error)
 {
+	AlmanahApplication *application;
+	GSettings *settings;
 	GtkSpell *gtkspell;
 	gchar *spelling_language;
 	GtkTextTagTable *table;
@@ -1365,7 +1464,10 @@ enable_spell_checking (AlmanahMainWindow *self, GError **error)
 		gtk_text_tag_table_remove (table, tag);
 
 	/* Get the spell checking language */
-	spelling_language = g_settings_get_string (almanah->settings, "spelling-language");
+	application = ALMANAH_APPLICATION (gtk_window_get_application (GTK_WINDOW (self)));
+	settings = almanah_application_dup_settings (application);
+	spelling_language = g_settings_get_string (settings, "spelling-language");
+	g_object_unref (settings);
 
 	/* Make sure it's either NULL or a proper locale specifier */
 	if (spelling_language != NULL && spelling_language[0] == '\0') {
diff --git a/src/main-window.h b/src/main-window.h
index 71feafd..58cf8e0 100644
--- a/src/main-window.h
+++ b/src/main-window.h
@@ -24,6 +24,8 @@
 #include <glib.h>
 #include <glib-object.h>
 
+#include "application.h"
+
 G_BEGIN_DECLS
 
 #define ALMANAH_TYPE_MAIN_WINDOW		(almanah_main_window_get_type ())
@@ -45,7 +47,7 @@ typedef struct {
 } AlmanahMainWindowClass;
 
 GType almanah_main_window_get_type (void);
-AlmanahMainWindow *almanah_main_window_new (void);
+AlmanahMainWindow *almanah_main_window_new (AlmanahApplication *application) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
 
 void almanah_main_window_select_date (AlmanahMainWindow *self, GDate *date);
 
diff --git a/src/main.c b/src/main.c
index 75d6e28..fc2080f 100644
--- a/src/main.c
+++ b/src/main.c
@@ -18,48 +18,10 @@
  */
 
 #include <config.h>
-#include <stdlib.h>
 #include <gtk/gtk.h>
-#include <glib/gi18n.h>
-#include <gio/gio.h>
 
 #include "main.h"
-#include "storage-manager.h"
-#include "event-manager.h"
-#include "main-window.h"
-
-Almanah *almanah;
-
-static G_GNUC_NORETURN void
-storage_manager_disconnected_cb (AlmanahStorageManager *self, const gchar *gpgme_error_message, const gchar *warning_message, gpointer user_data)
-{
-	if (gpgme_error_message != NULL || warning_message != NULL) {
-		GtkWidget *dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
-							    _("Error encrypting database"));
-
-		if (gpgme_error_message != NULL && warning_message != NULL)
-			gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s %s", warning_message, gpgme_error_message);
-		else if (gpgme_error_message != NULL)
-			gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", gpgme_error_message);
-		else
-			gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", warning_message);
-
-		gtk_dialog_run (GTK_DIALOG (dialog));
-		gtk_widget_destroy (dialog);
-	}
-
-	g_object_unref (almanah->storage_manager);
-	g_object_unref (almanah->settings);
-	g_object_unref (almanah->page_setup);
-	g_object_unref (almanah->print_settings);
-
-	g_free (almanah);
-
-	if (gtk_main_level () > 0)
-		gtk_main_quit ();
-
-	exit (0);
-}
+#include "application.h"
 
 gboolean
 almanah_run_on_screen (GdkScreen *screen, const gchar *commandline, GError **error)
@@ -87,112 +49,18 @@ almanah_run_on_screen (GdkScreen *screen, const gchar *commandline, GError **err
 	return retval;
 }
 
-void
-almanah_quit (void)
-{
-	g_signal_connect (almanah->storage_manager, "disconnected", G_CALLBACK (storage_manager_disconnected_cb), NULL);
-	almanah_storage_manager_disconnect (almanah->storage_manager, NULL);
-
-	if (almanah->search_dialog != NULL)
-		gtk_widget_destroy (almanah->search_dialog);
-	if (almanah->date_entry_dialog != NULL)
-		gtk_widget_destroy (almanah->date_entry_dialog);
-#ifdef ENABLE_ENCRYPTION
-	if (almanah->preferences_dialog != NULL)
-		gtk_widget_destroy (almanah->preferences_dialog);
-#endif /* ENABLE_ENCRYPTION */
-	gtk_widget_destroy (almanah->main_window);
-
-	g_object_unref (almanah->event_manager);
-
-	/* Quitting is actually done in storage_manager_disconnected_cb, which is called once
-	 * the storage manager has encrypted the DB and disconnected from it. */
-}
-
 int
 main (int argc, char *argv[])
 {
-	GOptionContext *context;
-	GError *error = NULL;
-	gboolean debug = FALSE;
-	gchar *db_filename;
-
-	const GOptionEntry options[] = {
-		{ "debug", 0, 0, G_OPTION_ARG_NONE, &debug, N_("Enable debug mode"), NULL },
-		{ NULL }
-	};
-
-#ifdef ENABLE_NLS
-	bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
-	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
-	textdomain (GETTEXT_PACKAGE);
-#endif
+	AlmanahApplication *application;
+	int status;
 
 	g_thread_init (NULL);
-	gtk_init (&argc, &argv);
-	g_set_application_name (_("Almanah Diary"));
-	gtk_window_set_default_icon_name ("almanah");
-
-	/* Options */
-	context = g_option_context_new (_("- Manage your diary"));
-	g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
-	g_option_context_add_main_entries (context, options, GETTEXT_PACKAGE);
-
-	if (g_option_context_parse (context, &argc, &argv, &error) == FALSE) {
-		/* Show an error */
-		GtkWidget *dialog = gtk_message_dialog_new (NULL,
-				GTK_DIALOG_MODAL,
-				GTK_MESSAGE_ERROR,
-				GTK_BUTTONS_OK,
-				_("Command-line options could not be parsed"));
-		gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", error->message);
-		gtk_dialog_run (GTK_DIALOG (dialog));
-		gtk_widget_destroy (dialog);
-
-		g_error_free (error);
-		exit (1);
-	}
-
-	g_option_context_free (context);
-
-	/* Setup */
-	almanah = g_new0 (Almanah, 1);
-	almanah->debug = debug;
-
-	/* Open GSettings */
-	almanah->settings = g_settings_new ("org.gnome.almanah");
-
-	/* Ensure the DB directory exists */
-	if (g_file_test (g_get_user_data_dir (), G_FILE_TEST_IS_DIR) == FALSE)
-		g_mkdir_with_parents (g_get_user_data_dir (), 0700);
-
-	/* Open the DB */
-	db_filename = g_build_filename (g_get_user_data_dir (), "diary.db", NULL);
-	almanah->storage_manager = almanah_storage_manager_new (db_filename);
-	g_free (db_filename);
-
-	if (almanah_storage_manager_connect (almanah->storage_manager, &error) == FALSE) {
-		GtkWidget *dialog = gtk_message_dialog_new (NULL,
-							    GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
-							    _("Error opening database"));
-		gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", error->message);
-		gtk_dialog_run (GTK_DIALOG (dialog));
-		gtk_widget_destroy (dialog);
-
-		almanah_quit ();
-	}
-
-	/* Create the event manager */
-	almanah->event_manager = almanah_event_manager_new ();
-
-	/* Set up printing objects */
-	almanah->print_settings = gtk_print_settings_new ();
-	almanah->page_setup = gtk_page_setup_new ();
+	g_type_init ();
 
-	/* Create and show the interface */
-	almanah->main_window = GTK_WIDGET (almanah_main_window_new ());
-	gtk_widget_show_all (almanah->main_window);
+	application = almanah_application_new ();
+	status = g_application_run (G_APPLICATION (application), argc, argv);
+	g_object_unref (application);
 
-	gtk_main ();
-	return 0;
+	return status;
 }
diff --git a/src/main.h b/src/main.h
index bb91a8f..9e68f7a 100644
--- a/src/main.h
+++ b/src/main.h
@@ -20,37 +20,13 @@
 #include <config.h>
 #include <gtk/gtk.h>
 #include <glib.h>
-#include <gio/gio.h>
-
-#include "storage-manager.h"
-#include "event-manager.h"
 
 #ifndef ALMANAH_MAIN_H
 #define ALMANAH_MAIN_H
 
 G_BEGIN_DECLS
 
-typedef struct {
-	AlmanahStorageManager *storage_manager;
-	AlmanahEventManager *event_manager;
-	GSettings *settings;
-	GtkPrintSettings *print_settings;
-	GtkPageSetup *page_setup;
-
-	GtkWidget *main_window;
-	GtkWidget *search_dialog;
-	GtkWidget *date_entry_dialog;
-#ifdef ENABLE_ENCRYPTION
-	GtkWidget *preferences_dialog;
-#endif /* ENABLE_ENCRYPTION */
-
-	gboolean debug;
-} Almanah;
-
-extern Almanah *almanah;
-
 gboolean almanah_run_on_screen (GdkScreen *screen, const gchar *commandline, GError **error);
-void almanah_quit (void);
 
 G_END_DECLS
 
diff --git a/src/preferences-dialog.c b/src/preferences-dialog.c
index 3e415a0..85f2023 100644
--- a/src/preferences-dialog.c
+++ b/src/preferences-dialog.c
@@ -35,6 +35,8 @@
 #include "main.h"
 #include "main-window.h"
 
+static void get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
+static void set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec);
 static void almanah_preferences_dialog_dispose (GObject *object);
 #ifdef ENABLE_ENCRYPTION
 static void pd_key_combo_changed_cb (GtkComboBox *combo_box, AlmanahPreferencesDialog *preferences_dialog);
@@ -43,6 +45,7 @@ static void pd_new_key_button_clicked_cb (GtkButton *button, AlmanahPreferencesD
 static void pd_response_cb (GtkDialog *dialog, gint response_id, AlmanahPreferencesDialog *preferences_dialog);
 
 struct _AlmanahPreferencesDialogPrivate {
+	GSettings *settings;
 #ifdef ENABLE_ENCRYPTION
 	CryptUIKeyset *keyset;
 	CryptUIKeyStore *key_store;
@@ -54,6 +57,10 @@ struct _AlmanahPreferencesDialogPrivate {
 #endif /* ENABLE_SPELL_CHECKING */
 };
 
+enum {
+	PROP_SETTINGS = 1,
+};
+
 G_DEFINE_TYPE (AlmanahPreferencesDialog, almanah_preferences_dialog, GTK_TYPE_DIALOG)
 #define ALMANAH_PREFERENCES_DIALOG_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ALMANAH_TYPE_PREFERENCES_DIALOG, AlmanahPreferencesDialogPrivate))
 
@@ -61,8 +68,18 @@ static void
 almanah_preferences_dialog_class_init (AlmanahPreferencesDialogClass *klass)
 {
 	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
 	g_type_class_add_private (klass, sizeof (AlmanahPreferencesDialogPrivate));
+
+	gobject_class->get_property = get_property;
+	gobject_class->set_property = set_property;
 	gobject_class->dispose = almanah_preferences_dialog_dispose;
+
+	g_object_class_install_property (gobject_class, PROP_SETTINGS,
+	                                 g_param_spec_object ("settings",
+	                                                      "Settings", "Settings instance to modify.",
+	                                                      G_TYPE_SETTINGS,
+	                                                      G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 }
 
 static void
@@ -94,10 +111,46 @@ almanah_preferences_dialog_dispose (GObject *object)
 	}
 #endif /* ENABLE_ENCRYPTION */
 
+	if (priv->settings != NULL)
+		g_object_unref (priv->settings);
+	priv->settings = NULL;
+
 	/* Chain up to the parent class */
 	G_OBJECT_CLASS (almanah_preferences_dialog_parent_class)->dispose (object);
 }
 
+static void
+get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
+{
+	AlmanahPreferencesDialogPrivate *priv = ALMANAH_PREFERENCES_DIALOG (object)->priv;
+
+	switch (property_id) {
+		case PROP_SETTINGS:
+			g_value_set_object (value, priv->settings);
+			break;
+		default:
+			/* We don't have any other property... */
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+			break;
+	}
+}
+
+static void
+set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
+{
+	AlmanahPreferencesDialog *self = ALMANAH_PREFERENCES_DIALOG (object);
+
+	switch (property_id) {
+		case PROP_SETTINGS:
+			self->priv->settings = g_value_dup_object (value);
+			break;
+		default:
+			/* We don't have any other property... */
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+			break;
+	}
+}
+
 /* Filter the key list so it's not pages and pages long */
 static gboolean
 key_store_filter_cb (CryptUIKeyset *keyset, const gchar *key, gpointer user_data)
@@ -107,7 +160,7 @@ key_store_filter_cb (CryptUIKeyset *keyset, const gchar *key, gpointer user_data
 }
 
 AlmanahPreferencesDialog *
-almanah_preferences_dialog_new (void)
+almanah_preferences_dialog_new (GSettings *settings)
 {
 	GtkBuilder *builder;
 	GtkTable *table;
@@ -125,6 +178,8 @@ almanah_preferences_dialog_new (void)
 		NULL
 	};
 
+	g_return_val_if_fail (G_IS_SETTINGS (settings), NULL);
+
 	builder = gtk_builder_new ();
 
 	if (gtk_builder_add_objects_from_file (builder, interface_filename, (gchar**) object_names, &error) == FALSE) {
@@ -154,6 +209,7 @@ almanah_preferences_dialog_new (void)
 	}
 
 	priv = ALMANAH_PREFERENCES_DIALOG (preferences_dialog)->priv;
+	priv->settings = g_object_ref (settings);
 	table = GTK_TABLE (gtk_builder_get_object (builder, "almanah_pd_table"));
 
 #ifdef ENABLE_ENCRYPTION
@@ -176,7 +232,7 @@ almanah_preferences_dialog_new (void)
 	atk_object_add_relationship (a11y_key_combo, ATK_RELATION_LABELLED_BY, a11y_label);
 
 	/* Set the selected key combo value */
-	key = g_settings_get_string (almanah->settings, "encryption-key");
+	key = g_settings_get_string (priv->settings, "encryption-key");
 	if (key != NULL && *key == '\0') {
 		g_free (key);
 		key = NULL;
@@ -197,7 +253,7 @@ almanah_preferences_dialog_new (void)
 	priv->spell_checking_enabled_check_button = GTK_CHECK_BUTTON (gtk_check_button_new_with_mnemonic (_("Enable _spell checking")));
 	gtk_table_attach_defaults (table, GTK_WIDGET (priv->spell_checking_enabled_check_button), 1, 4, 2, 3);
 
-	g_settings_bind (almanah->settings, "spell-checking-enabled", priv->spell_checking_enabled_check_button, "active", G_SETTINGS_BIND_DEFAULT);
+	g_settings_bind (priv->settings, "spell-checking-enabled", priv->spell_checking_enabled_check_button, "active", G_SETTINGS_BIND_DEFAULT);
 #endif /* ENABLE_SPELL_CHECKING */
 
 	g_object_unref (builder);
@@ -217,8 +273,8 @@ pd_key_combo_changed_cb (GtkComboBox *combo_box, AlmanahPreferencesDialog *prefe
 	if (key == NULL)
 		key = "";
 
-	if (g_settings_set_string (almanah->settings, "encryption-key", key) == FALSE) {
-		GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW (almanah->preferences_dialog),
+	if (g_settings_set_string (preferences_dialog->priv->settings, "encryption-key", key) == FALSE) {
+		GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW (preferences_dialog),
 							    GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
 							    _("Error saving the encryption key"));
 		gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", error->message);
@@ -237,7 +293,7 @@ pd_new_key_button_clicked_cb (GtkButton *button, AlmanahPreferencesDialog *prefe
 	GError *error = NULL;
 
 	if (g_spawn_async (NULL, (gchar**) argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &error) == FALSE) {
-		GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW (almanah->preferences_dialog),
+		GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW (preferences_dialog),
 							    GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
 							    _("Error opening Seahorse"));
 		gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", error->message);
diff --git a/src/preferences-dialog.h b/src/preferences-dialog.h
index 1344590..865cf54 100644
--- a/src/preferences-dialog.h
+++ b/src/preferences-dialog.h
@@ -44,7 +44,7 @@ typedef struct {
 } AlmanahPreferencesDialogClass;
 
 GType almanah_preferences_dialog_get_type (void);
-AlmanahPreferencesDialog *almanah_preferences_dialog_new (void);
+AlmanahPreferencesDialog *almanah_preferences_dialog_new (GSettings *settings) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
 
 G_END_DECLS
 
diff --git a/src/printing.c b/src/printing.c
index 5c38e4b..8d738fe 100644
--- a/src/printing.c
+++ b/src/printing.c
@@ -34,6 +34,7 @@
 #define PAGE_MARGIN 20 /* left- and right-hand page margin size, in pixels */
 
 typedef struct {
+	AlmanahStorageManager *storage_manager;
 	GtkTextBuffer *buffer;
 	GDate *start_date;
 	GDate *end_date;
@@ -252,7 +253,7 @@ print_entry (GtkPrintOperation *operation, GtkPrintContext *context, AlmanahPrin
 	gdouble title_y = 0, important_y = 0, entry_y;
 	cairo_t *cr = NULL;
 
-	entry = almanah_storage_manager_get_entry (almanah->storage_manager, almanah_operation->current_date);
+	entry = almanah_storage_manager_get_entry (almanah_operation->storage_manager, almanah_operation->current_date);
 
 	if (almanah_operation->current_line == 0) {
 		/* Set up the title layout */
@@ -444,8 +445,8 @@ create_custom_widget_cb (GtkPrintOperation *operation, AlmanahPrintOperation *al
 	GtkBox *vbox, *hbox;
 
 	/* Start and end calendars */
-	start_calendar = almanah_calendar_new ();
-	end_calendar = almanah_calendar_new ();
+	start_calendar = almanah_calendar_new (almanah_operation->storage_manager);
+	end_calendar = almanah_calendar_new (almanah_operation->storage_manager);
 
 	g_object_set (G_OBJECT (start_calendar), "show-details", FALSE, NULL);
 	g_object_set (G_OBJECT (end_calendar), "show-details", FALSE, NULL);
@@ -513,7 +514,8 @@ custom_widget_apply_cb (GtkPrintOperation *operation, GtkWidget *widget, Almanah
 }
 
 void
-almanah_print_entries (gboolean print_preview)
+almanah_print_entries (gboolean print_preview, GtkWindow *parent_window, GtkPageSetup **page_setup, GtkPrintSettings **print_settings,
+                       AlmanahStorageManager *storage_manager)
 {
 	GtkPrintOperation *operation;
 	GtkPrintOperationResult res;
@@ -524,6 +526,7 @@ almanah_print_entries (gboolean print_preview)
 	almanah_operation.paginated = FALSE;
 	almanah_operation.y = 0;
 	almanah_operation.current_line = 0;
+	almanah_operation.storage_manager = storage_manager;
 
 	almanah_operation.buffer = gtk_text_buffer_new (NULL);
 	almanah_interface_create_text_tags (almanah_operation.buffer, FALSE);
@@ -538,10 +541,10 @@ almanah_print_entries (gboolean print_preview)
 
 	almanah_operation.current_date = g_memdup (almanah_operation.start_date, sizeof (*(almanah_operation.start_date)));
 
-	if (almanah->print_settings != NULL) 
-		gtk_print_operation_set_print_settings (operation, almanah->print_settings);
-	if (almanah->page_setup != NULL)
-		gtk_print_operation_set_default_page_setup (operation, almanah->page_setup);
+	if (*print_settings != NULL)
+		gtk_print_operation_set_print_settings (operation, *print_settings);
+	if (*page_setup != NULL)
+		gtk_print_operation_set_default_page_setup (operation, *page_setup);
 
 	gtk_print_operation_set_n_pages (operation, 1);
 
@@ -552,16 +555,16 @@ almanah_print_entries (gboolean print_preview)
 
 	res = gtk_print_operation_run (operation,
 				       (print_preview == TRUE) ? GTK_PRINT_OPERATION_ACTION_PREVIEW : GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
-				       GTK_WINDOW (almanah->main_window), NULL);
+				       parent_window, NULL);
 
 	if (res == GTK_PRINT_OPERATION_RESULT_APPLY) {
-		if (almanah->print_settings != NULL)
-			g_object_unref (almanah->print_settings);
-		almanah->print_settings = g_object_ref (gtk_print_operation_get_print_settings (operation));
+		if (*print_settings != NULL)
+			g_object_unref (*print_settings);
+		*print_settings = g_object_ref (gtk_print_operation_get_print_settings (operation));
 
-		if (almanah->page_setup != NULL)
-			g_object_unref (almanah->page_setup);
-		almanah->page_setup = g_object_ref (gtk_print_operation_get_default_page_setup (operation));
+		if (*page_setup != NULL)
+			g_object_unref (*page_setup);
+		*page_setup = g_object_ref (gtk_print_operation_get_default_page_setup (operation));
 	}
 
 	if (almanah_operation.current_date != NULL) {
@@ -572,14 +575,3 @@ almanah_print_entries (gboolean print_preview)
 	}
 	g_object_unref (operation);
 }
-
-void
-almanah_print_page_setup (void)
-{
-	GtkPageSetup *page_setup;
-
-	page_setup = gtk_print_run_page_setup_dialog (GTK_WINDOW (almanah->main_window), almanah->page_setup, almanah->print_settings);
-	if (almanah->page_setup != NULL)
-		g_object_unref (almanah->page_setup);
-	almanah->page_setup = page_setup;
-}
diff --git a/src/printing.h b/src/printing.h
index c3f1047..2d10dbd 100644
--- a/src/printing.h
+++ b/src/printing.h
@@ -18,14 +18,17 @@
  */
 
 #include <glib.h>
+#include <gtk/gtk.h>
+
+#include "storage-manager.h"
 
 #ifndef ALMANAH_PRINTING_H
 #define ALMANAH_PRINTING_H
 
 G_BEGIN_DECLS
 
-void almanah_print_entries (gboolean print_preview);
-void almanah_print_page_setup (void);
+void almanah_print_entries (gboolean print_preview, GtkWindow *parent_window, GtkPageSetup **page_setup, GtkPrintSettings **print_settings,
+                            AlmanahStorageManager *storage_manager);
 
 G_END_DECLS
 
diff --git a/src/search-dialog.c b/src/search-dialog.c
index 702cb96..7946851 100644
--- a/src/search-dialog.c
+++ b/src/search-dialog.c
@@ -32,7 +32,7 @@ static void sd_results_selection_changed_cb (GtkTreeSelection *tree_selection, G
 
 /* GtkBuilder callbacks */
 void sd_search_button_clicked_cb (GtkButton *self, AlmanahSearchDialog *search_dialog);
-void sd_results_tree_view_row_activated_cb (GtkTreeView *self, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data);
+void sd_results_tree_view_row_activated_cb (GtkTreeView *tree_view, GtkTreePath *path, GtkTreeViewColumn *column, AlmanahSearchDialog *self);
 void sd_view_button_clicked_cb (GtkButton *self, AlmanahSearchDialog *search_dialog);
 
 struct _AlmanahSearchDialogPrivate {
@@ -139,6 +139,8 @@ sd_response_cb (GtkDialog *dialog, gint response_id, AlmanahSearchDialog *search
 void
 sd_search_button_clicked_cb (GtkButton *self, AlmanahSearchDialog *search_dialog)
 {
+	AlmanahApplication *application;
+	AlmanahStorageManager *storage_manager;
 	AlmanahEntry *entry;
 	AlmanahStorageManagerIter iter;
 	AlmanahSearchDialogPrivate *priv = search_dialog->priv;
@@ -147,9 +149,13 @@ sd_search_button_clicked_cb (GtkButton *self, AlmanahSearchDialog *search_dialog
 	/* Clear the results store of previous search results first */
 	gtk_list_store_clear (search_dialog->priv->sd_results_store);
 
+	/* Grab the storage manager */
+	application = ALMANAH_APPLICATION (gtk_window_get_application (GTK_WINDOW (search_dialog)));
+	storage_manager = almanah_application_dup_storage_manager (application);
+
 	/* Search over all entries */
 	almanah_storage_manager_iter_init (&iter);
-	while ((entry = almanah_storage_manager_search_entries (almanah->storage_manager, search_string, &iter)) != NULL) {
+	while ((entry = almanah_storage_manager_search_entries (storage_manager, search_string, &iter)) != NULL) {
 		GDate date;
 		gchar formatted_date[100];
 		GtkTreeIter tree_iter;
@@ -170,11 +176,14 @@ sd_search_button_clicked_cb (GtkButton *self, AlmanahSearchDialog *search_dialog
 
 		g_object_unref (entry);
 	}
+
+	g_object_unref (storage_manager);
 }
 
 static void
-select_date (GtkTreeModel *model, GtkTreeIter *iter)
+select_date (AlmanahSearchDialog *self, GtkTreeModel *model, GtkTreeIter *iter)
 {
+	AlmanahMainWindow *main_window;
 	guint day, month, year;
 	GDate date;
 
@@ -184,19 +193,20 @@ select_date (GtkTreeModel *model, GtkTreeIter *iter)
 			    2, &year,
 			    -1);
 
+	main_window = ALMANAH_MAIN_WINDOW (gtk_window_get_transient_for (GTK_WINDOW (self)));
 	g_date_set_dmy (&date, day, month, year);
-	almanah_main_window_select_date (ALMANAH_MAIN_WINDOW (almanah->main_window), &date);
+	almanah_main_window_select_date (main_window, &date);
 }
 
 void
-sd_results_tree_view_row_activated_cb (GtkTreeView *self, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data)
+sd_results_tree_view_row_activated_cb (GtkTreeView *tree_view, GtkTreePath *path, GtkTreeViewColumn *column, AlmanahSearchDialog *self)
 {
 	GtkTreeIter iter;
 	GtkTreeModel *model;
 
-	model = gtk_tree_view_get_model (self);
+	model = gtk_tree_view_get_model (tree_view);
 	gtk_tree_model_get_iter (model, &iter, path);
-	select_date (model, &iter);
+	select_date (self, model, &iter);
 }
 
 void
@@ -205,6 +215,7 @@ sd_view_button_clicked_cb (GtkButton *self, AlmanahSearchDialog *search_dialog)
 	GtkTreeIter iter;
 	GtkTreeModel *model;
 
-	if (gtk_tree_selection_get_selected (search_dialog->priv->sd_results_selection, &model, &iter) == TRUE)
-		select_date (model, &iter);
+	if (gtk_tree_selection_get_selected (search_dialog->priv->sd_results_selection, &model, &iter) == TRUE) {
+		select_date (search_dialog, model, &iter);
+	}
 }
diff --git a/src/storage-manager.c b/src/storage-manager.c
index 2d14150..1fb648b 100644
--- a/src/storage-manager.c
+++ b/src/storage-manager.c
@@ -44,12 +44,14 @@ static gboolean simple_query (AlmanahStorageManager *self, const gchar *query, G
 
 struct _AlmanahStorageManagerPrivate {
 	gchar *filename, *plain_filename;
+	gchar *encryption_key;
 	sqlite3 *connection;
 	gboolean decrypted;
 };
 
 enum {
-	PROP_FILENAME = 1
+	PROP_FILENAME = 1,
+	PROP_ENCRYPTION_KEY,
 };
 
 enum {
@@ -88,6 +90,12 @@ almanah_storage_manager_class_init (AlmanahStorageManagerClass *klass)
 	                                                      NULL,
 	                                                      G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+	g_object_class_install_property (gobject_class, PROP_ENCRYPTION_KEY,
+	                                 g_param_spec_string ("encryption-key",
+	                                                      "Encryption key", "The identifier for the encryption key in the user's keyring.",
+	                                                      NULL,
+	                                                      G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
 	storage_manager_signals[SIGNAL_DISCONNECTED] = g_signal_new ("disconnected",
 	                                                             G_TYPE_FROM_CLASS (klass),
 	                                                             G_SIGNAL_RUN_LAST,
@@ -120,22 +128,26 @@ almanah_storage_manager_init (AlmanahStorageManager *self)
 	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, ALMANAH_TYPE_STORAGE_MANAGER, AlmanahStorageManagerPrivate);
 	self->priv->filename = NULL;
 	self->priv->plain_filename = NULL;
+	self->priv->encryption_key = NULL;
 	self->priv->decrypted = FALSE;
 }
 
 /**
  * almanah_storage_manager_new:
  * @filename: database filename to open
+ * @encryption_key: identifier for the encryption key to use in the user's keyring, or %NULL
  *
  * Creates a new #AlmanahStorageManager, connected to the given database @filename.
  *
  * If @filename is for an encrypted database, it will automatically be changed to the canonical filename for the unencrypted database, even if that
  * file doesn't exist, and even if Almanah was compiled without encryption support. Database filenames are always passed as the unencrypted filename.
  *
+ * If @encryption_key is %NULL, encryption will be disabled.
+ *
  * Return value: the new #AlmanahStorageManager
  **/
 AlmanahStorageManager *
-almanah_storage_manager_new (const gchar *filename)
+almanah_storage_manager_new (const gchar *filename, const gchar *encryption_key)
 {
 	gchar *new_filename = NULL;
 	AlmanahStorageManager *sm;
@@ -143,7 +155,10 @@ almanah_storage_manager_new (const gchar *filename)
 	if (g_str_has_suffix (filename, ENCRYPTED_SUFFIX) == TRUE)
 		filename = new_filename = g_strndup (filename, strlen (filename) - strlen (ENCRYPTED_SUFFIX));
 
-	sm = g_object_new (ALMANAH_TYPE_STORAGE_MANAGER, "filename", filename, NULL);
+	sm = g_object_new (ALMANAH_TYPE_STORAGE_MANAGER,
+	                   "filename", filename,
+	                   "encryption-key", encryption_key,
+	                   NULL);
 	g_free (new_filename);
 
 	return sm;
@@ -156,6 +171,7 @@ almanah_storage_manager_finalize (GObject *object)
 
 	g_free (priv->filename);
 	g_free (priv->plain_filename);
+	g_free (priv->encryption_key);
 
 	/* Chain up to the parent class */
 	G_OBJECT_CLASS (almanah_storage_manager_parent_class)->finalize (object);
@@ -170,6 +186,9 @@ almanah_storage_manager_get_property (GObject *object, guint property_id, GValue
 		case PROP_FILENAME:
 			g_value_set_string (value, g_strdup (priv->filename));
 			break;
+		case PROP_ENCRYPTION_KEY:
+			g_value_set_string (value, priv->encryption_key);
+			break;
 		default:
 			/* We don't have any other property... */
 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -187,6 +206,11 @@ almanah_storage_manager_set_property (GObject *object, guint property_id, const
 			priv->plain_filename = g_strdup (g_value_get_string (value));
 			priv->filename = g_strjoin (NULL, priv->plain_filename, ENCRYPTED_SUFFIX, NULL);
 			break;
+		case PROP_ENCRYPTION_KEY:
+			g_free (priv->encryption_key);
+			priv->encryption_key = g_value_dup_string (value);
+			g_object_notify (object, "encryption-key");
+			break;
 		default:
 			/* We don't have any other property... */
 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -457,13 +481,13 @@ encrypt_database (AlmanahStorageManager *self, const gchar *encryption_key, GErr
 }
 
 static gchar *
-get_encryption_key (void)
+get_encryption_key (AlmanahStorageManager *self)
 {
 	gchar **key_parts;
 	guint i;
 	gchar *encryption_key;
 
-	encryption_key = g_settings_get_string (almanah->settings, "encryption-key");
+	encryption_key = g_strdup (self->priv->encryption_key);
 	if (encryption_key == NULL || encryption_key[0] == '\0') {
 		g_free (encryption_key);
 		return NULL;
@@ -576,7 +600,7 @@ almanah_storage_manager_disconnect (AlmanahStorageManager *self, GError **error)
 		goto delete_encrypted_db;
 
 	/* Get the encryption key */
-	encryption_key = get_encryption_key ();
+	encryption_key = get_encryption_key (self);
 	if (encryption_key == NULL)
 		goto delete_encrypted_db;
 
@@ -620,8 +644,8 @@ simple_query (AlmanahStorageManager *self, const gchar *query, GError **error, .
 	new_query = sqlite3_vmprintf (query, params);
 	va_end (params);
 
-	if (almanah->debug)
-		g_debug ("Database query: %s", new_query);
+	g_debug ("Database query: %s", new_query);
+
 	if (sqlite3_exec (priv->connection, new_query, NULL, NULL, NULL) != SQLITE_OK) {
 		g_set_error (error, ALMANAH_STORAGE_MANAGER_ERROR, ALMANAH_STORAGE_MANAGER_ERROR_RUNNING_QUERY,
 		             _("Could not run query \"%s\". SQLite provided the following error message: %s"),
diff --git a/src/storage-manager.h b/src/storage-manager.h
index b47dc93..7032e9d 100644
--- a/src/storage-manager.h
+++ b/src/storage-manager.h
@@ -66,7 +66,7 @@ typedef struct {
 
 GType almanah_storage_manager_get_type (void);
 GQuark almanah_storage_manager_error_quark (void);
-AlmanahStorageManager *almanah_storage_manager_new (const gchar *filename);
+AlmanahStorageManager *almanah_storage_manager_new (const gchar *filename, const gchar *encryption_key) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
 
 gboolean almanah_storage_manager_connect (AlmanahStorageManager *self, GError **error);
 gboolean almanah_storage_manager_disconnect (AlmanahStorageManager *self, GError **error);
diff --git a/src/widgets/calendar.c b/src/widgets/calendar.c
index d3d5636..986242f 100644
--- a/src/widgets/calendar.c
+++ b/src/widgets/calendar.c
@@ -24,6 +24,9 @@
 #include "storage-manager.h"
 #include "main.h"
 
+static void get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
+static void set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec);
+static void dispose (GObject *object);
 static void almanah_calendar_finalize (GObject *object);
 static void almanah_calendar_month_changed (GtkCalendar *calendar);
 static gchar *almanah_calendar_detail_func (GtkCalendar *calendar, guint year, guint month, guint day, gpointer user_data);
@@ -31,9 +34,17 @@ static void entry_added_cb (AlmanahStorageManager *storage_manager, AlmanahEntry
 static void entry_removed_cb (AlmanahStorageManager *storage_manager, GDate *date, AlmanahCalendar *calendar);
 
 struct _AlmanahCalendarPrivate {
+	AlmanahStorageManager *storage_manager;
+	gulong entry_added_signal;
+	gulong entry_removed_signal;
+
 	gboolean *important_days;
 };
 
+enum {
+	PROP_STORAGE_MANAGER = 1,
+};
+
 G_DEFINE_TYPE (AlmanahCalendar, almanah_calendar, GTK_TYPE_CALENDAR)
 
 static void
@@ -44,9 +55,18 @@ almanah_calendar_class_init (AlmanahCalendarClass *klass)
 
 	g_type_class_add_private (klass, sizeof (AlmanahCalendarPrivate));
 
+	gobject_class->get_property = get_property;
+	gobject_class->set_property = set_property;
+	gobject_class->dispose = dispose;
 	gobject_class->finalize = almanah_calendar_finalize;
 
 	calendar_class->month_changed = almanah_calendar_month_changed;
+
+	g_object_class_install_property (gobject_class, PROP_STORAGE_MANAGER,
+	                                 g_param_spec_object ("storage-manager",
+	                                                      "Storage manager", "The storage manager whose entries should be listed.",
+	                                                      ALMANAH_TYPE_STORAGE_MANAGER,
+	                                                      G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 }
 
 static void
@@ -54,10 +74,19 @@ almanah_calendar_init (AlmanahCalendar *self)
 {
 	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, ALMANAH_TYPE_CALENDAR, AlmanahCalendarPrivate);
 	gtk_calendar_set_detail_func (GTK_CALENDAR (self), almanah_calendar_detail_func, NULL, NULL);
+}
+
+static void
+dispose (GObject *object)
+{
+	AlmanahCalendarPrivate *priv = ALMANAH_CALENDAR (object)->priv;
+
+	if (priv->storage_manager != NULL)
+		g_object_unref (priv->storage_manager);
+	priv->storage_manager = NULL;
 
-	/* Connect to signals from the storage manager so we can mark/unmark days as appropriate */
-	g_signal_connect (almanah->storage_manager, "entry-added", G_CALLBACK (entry_added_cb), self);
-	g_signal_connect (almanah->storage_manager, "entry-removed", G_CALLBACK (entry_removed_cb), self);
+	/* Chain up to the parent class */
+	G_OBJECT_CLASS (almanah_calendar_parent_class)->dispose (object);
 }
 
 static void
@@ -72,6 +101,38 @@ almanah_calendar_finalize (GObject *object)
 }
 
 static void
+get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
+{
+	AlmanahCalendarPrivate *priv = ALMANAH_CALENDAR (object)->priv;
+
+	switch (property_id) {
+		case PROP_STORAGE_MANAGER:
+			g_value_set_object (value, priv->storage_manager);
+			break;
+		default:
+			/* We don't have any other property... */
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+			break;
+	}
+}
+
+static void
+set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
+{
+	AlmanahCalendar *self = ALMANAH_CALENDAR (object);
+
+	switch (property_id) {
+		case PROP_STORAGE_MANAGER:
+			almanah_calendar_set_storage_manager (self, g_value_get_object (value));
+			break;
+		default:
+			/* We don't have any other property... */
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+			break;
+	}
+}
+
+static void
 almanah_calendar_month_changed (GtkCalendar *calendar)
 {
 	AlmanahCalendarPrivate *priv = ALMANAH_CALENDAR (calendar)->priv;
@@ -81,7 +142,7 @@ almanah_calendar_month_changed (GtkCalendar *calendar)
 	/* Mark the days on the calendar which have diary entries */
 	gtk_calendar_get_date (calendar, &year, &month, NULL);
 	month++;
-	days = almanah_storage_manager_get_month_marked_days (almanah->storage_manager, year, month, &num_days);
+	days = almanah_storage_manager_get_month_marked_days (priv->storage_manager, year, month, &num_days);
 
 	gtk_calendar_clear_marks (calendar);
 	for (i = 0; i < num_days; i++) {
@@ -95,7 +156,7 @@ almanah_calendar_month_changed (GtkCalendar *calendar)
 
 	/* Cache the days which are important, so that the detail function isn't hideously slow */
 	g_free (priv->important_days);
-	priv->important_days = almanah_storage_manager_get_month_important_days (almanah->storage_manager, year, month, &num_days);
+	priv->important_days = almanah_storage_manager_get_month_important_days (priv->storage_manager, year, month, &num_days);
 }
 
 static gchar *
@@ -147,9 +208,43 @@ entry_removed_cb (AlmanahStorageManager *storage_manager, GDate *date, AlmanahCa
 }
 
 GtkWidget *
-almanah_calendar_new (void)
+almanah_calendar_new (AlmanahStorageManager *storage_manager)
+{
+	g_return_val_if_fail (ALMANAH_IS_STORAGE_MANAGER (storage_manager), NULL);
+	return g_object_new (ALMANAH_TYPE_CALENDAR, "storage-manager", storage_manager, NULL);
+}
+
+AlmanahStorageManager *
+almanah_calendar_get_storage_manager (AlmanahCalendar *self)
+{
+	g_return_val_if_fail (ALMANAH_IS_CALENDAR (self), NULL);
+	return self->priv->storage_manager;
+}
+
+void
+almanah_calendar_set_storage_manager (AlmanahCalendar *self, AlmanahStorageManager *storage_manager)
 {
-	return g_object_new (ALMANAH_TYPE_CALENDAR, NULL);
+	AlmanahCalendarPrivate *priv = self->priv;
+
+	g_return_if_fail (ALMANAH_IS_CALENDAR (self));
+	g_return_if_fail (storage_manager == NULL || ALMANAH_IS_STORAGE_MANAGER (storage_manager));
+
+	if (priv->storage_manager != NULL) {
+		g_signal_handler_disconnect (priv->storage_manager, priv->entry_added_signal);
+		g_signal_handler_disconnect (priv->storage_manager, priv->entry_removed_signal);
+
+		g_object_unref (priv->storage_manager);
+	}
+
+	priv->storage_manager = storage_manager;
+
+	if (priv->storage_manager != NULL) {
+		g_object_ref (priv->storage_manager);
+
+		/* Connect to signals from the storage manager so we can mark/unmark days as appropriate */
+		priv->entry_added_signal = g_signal_connect (priv->storage_manager, "entry-added", (GCallback) entry_added_cb, self);
+		priv->entry_removed_signal = g_signal_connect (priv->storage_manager, "entry-removed", (GCallback) entry_removed_cb, self);
+	}
 }
 
 void
diff --git a/src/widgets/calendar.h b/src/widgets/calendar.h
index 492f440..a281b84 100644
--- a/src/widgets/calendar.h
+++ b/src/widgets/calendar.h
@@ -24,6 +24,8 @@
 #include <glib-object.h>
 #include <gtk/gtk.h>
 
+#include "storage-manager.h"
+
 G_BEGIN_DECLS
 
 #define ALMANAH_TYPE_CALENDAR		(almanah_calendar_get_type ())
@@ -46,7 +48,10 @@ typedef struct {
 
 GType almanah_calendar_get_type (void) G_GNUC_CONST;
 
-GtkWidget *almanah_calendar_new (void) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+GtkWidget *almanah_calendar_new (AlmanahStorageManager *storage_manager) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+
+AlmanahStorageManager *almanah_calendar_get_storage_manager (AlmanahCalendar *self) G_GNUC_PURE;
+void almanah_calendar_set_storage_manager (AlmanahCalendar *self, AlmanahStorageManager *storage_manager);
 
 void almanah_calendar_select_date (AlmanahCalendar *self, GDate *date);
 void almanah_calendar_select_today (AlmanahCalendar *self);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]