1
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
4
* Copyright (C) Philip Withnall 2011 <philip@tecnocode.co.uk>
6
* Almanah is free software: you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation, either version 3 of the License, or
9
* (at your option) any later version.
11
* Almanah is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with Almanah. If not, see <http://www.gnu.org/licenses/>.
22
#include <glib/gi18n.h>
26
#include "application.h"
27
#include "storage-manager.h"
28
#include "event-manager.h"
29
#include "main-window.h"
31
static void constructed (GObject *object);
32
static void dispose (GObject *object);
33
static void get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
34
static void set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec);
36
static void startup (GApplication *application);
37
static void activate (GApplication *application);
38
static gint handle_command_line (GApplication *application, GApplicationCommandLine *command_line);
39
static void quit_main_loop (GApplication *application);
41
struct _AlmanahApplicationPrivate {
45
AlmanahStorageManager *storage_manager;
46
AlmanahEventManager *event_manager;
48
AlmanahMainWindow *main_window;
55
G_DEFINE_TYPE (AlmanahApplication, almanah_application, GTK_TYPE_APPLICATION)
58
almanah_application_class_init (AlmanahApplicationClass *klass)
60
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
61
GApplicationClass *gapplication_class = G_APPLICATION_CLASS (klass);
63
g_type_class_add_private (klass, sizeof (AlmanahApplicationPrivate));
65
gobject_class->constructed = constructed;
66
gobject_class->dispose = dispose;
67
gobject_class->get_property = get_property;
68
gobject_class->set_property = set_property;
70
gapplication_class->startup = startup;
71
gapplication_class->activate = activate;
72
gapplication_class->command_line = handle_command_line;
73
gapplication_class->quit_mainloop = quit_main_loop;
75
g_object_class_install_property (gobject_class, PROP_DEBUG,
76
g_param_spec_boolean ("debug",
77
"Debugging Mode", "Whether debugging mode is active.",
79
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
83
almanah_application_init (AlmanahApplication *self)
85
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, ALMANAH_TYPE_APPLICATION, AlmanahApplicationPrivate);
86
self->priv->debug = FALSE;
90
constructed (GObject *object)
92
/* Set various properties up */
93
g_application_set_application_id (G_APPLICATION (object), "org.gnome.Almanah");
94
g_application_set_flags (G_APPLICATION (object), G_APPLICATION_HANDLES_COMMAND_LINE);
97
bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
98
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
99
textdomain (GETTEXT_PACKAGE);
101
g_set_application_name (_("Almanah Diary"));
102
gtk_window_set_default_icon_name ("almanah");
104
/* Chain up to the parent class */
105
G_OBJECT_CLASS (almanah_application_parent_class)->constructed (object);
109
dispose (GObject *object)
111
AlmanahApplicationPrivate *priv = ALMANAH_APPLICATION (object)->priv;
113
if (priv->main_window != NULL)
114
gtk_widget_destroy (GTK_WIDGET (priv->main_window));
115
priv->main_window = NULL;
117
if (priv->event_manager != NULL)
118
g_object_unref (priv->event_manager);
119
priv->event_manager = NULL;
121
if (priv->storage_manager != NULL)
122
g_object_unref (priv->storage_manager);
123
priv->storage_manager = NULL;
125
if (priv->settings != NULL)
126
g_object_unref (priv->settings);
127
priv->settings = NULL;
129
/* Chain up to the parent class */
130
G_OBJECT_CLASS (almanah_application_parent_class)->dispose (object);
134
get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
136
AlmanahApplicationPrivate *priv = ALMANAH_APPLICATION (object)->priv;
138
switch (property_id) {
140
g_value_set_boolean (value, priv->debug);
143
/* We don't have any other property... */
144
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
150
set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
152
AlmanahApplicationPrivate *priv = ALMANAH_APPLICATION (object)->priv;
154
switch (property_id) {
156
priv->debug = g_value_get_boolean (value);
159
/* We don't have any other property... */
160
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
166
debug_handler (const char *log_domain, GLogLevelFlags log_level, const char *message, AlmanahApplication *self)
168
/* Only display debug messages if we've been run with --debug */
169
if (self->priv->debug == TRUE) {
170
g_log_default_handler (log_domain, log_level, message, NULL);
175
startup (GApplication *application)
177
AlmanahApplicationPrivate *priv = ALMANAH_APPLICATION (application)->priv;
179
GError *error = NULL;
182
G_APPLICATION_CLASS (almanah_application_parent_class)->startup (application);
184
/* Debug log handling */
185
g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, (GLogFunc) debug_handler, application);
188
priv->settings = g_settings_new ("org.gnome.almanah");
190
/* Ensure the DB directory exists */
191
if (g_file_test (g_get_user_data_dir (), G_FILE_TEST_IS_DIR) == FALSE) {
192
g_mkdir_with_parents (g_get_user_data_dir (), 0700);
196
db_filename = g_build_filename (g_get_user_data_dir (), "diary.db", NULL);
197
priv->storage_manager = almanah_storage_manager_new (db_filename, NULL);
198
g_free (db_filename);
200
g_settings_bind (priv->settings, "encryption-key", priv->storage_manager, "encryption-key",
201
G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_NO_SENSITIVITY);
203
if (almanah_storage_manager_connect (priv->storage_manager, &error) == FALSE) {
204
GtkWidget *dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
205
_("Error opening database"));
206
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", error->message);
207
gtk_dialog_run (GTK_DIALOG (dialog));
208
gtk_widget_destroy (dialog);
214
/* Create the event manager */
215
priv->event_manager = almanah_event_manager_new ();
218
/* Nullify our pointer to the main window when it gets destroyed (e.g. when we quit) so that we don't then try
219
* to destroy it again in dispose(). */
221
main_window_destroy_cb (AlmanahMainWindow *main_window, AlmanahApplication *self)
223
self->priv->main_window = NULL;
227
activate (GApplication *application)
229
AlmanahApplication *self = ALMANAH_APPLICATION (application);
230
AlmanahApplicationPrivate *priv = self->priv;
232
/* Create the interface */
233
if (priv->main_window == NULL) {
234
priv->main_window = almanah_main_window_new (self);
235
gtk_widget_show_all (GTK_WIDGET (priv->main_window));
236
g_signal_connect (priv->main_window, "destroy", (GCallback) main_window_destroy_cb, application);
239
/* Bring it to the foreground */
240
gtk_window_present (GTK_WINDOW (priv->main_window));
244
handle_command_line (GApplication *application, GApplicationCommandLine *command_line)
246
AlmanahApplicationPrivate *priv = ALMANAH_APPLICATION (application)->priv;
247
GOptionContext *context;
248
GError *error = NULL;
249
gchar **args, **argv;
250
gint argc, i, status = 0;
252
const GOptionEntry options[] = {
253
{ "debug", 0, 0, G_OPTION_ARG_NONE, &(priv->debug), N_("Enable debug mode"), NULL },
257
args = g_application_command_line_get_arguments (command_line, &argc);
259
/* 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
261
argv = g_new (gchar*, argc + 1);
262
for (i = 0; i <= argc; i++) {
267
context = g_option_context_new (NULL);
268
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
270
g_option_context_set_summary (context, _("Manage your diary. Only one instance of the program may be open at any time."));
272
g_option_context_add_main_entries (context, options, GETTEXT_PACKAGE);
273
g_option_context_add_group (context, gtk_get_option_group (TRUE));
275
if (g_option_context_parse (context, &argc, &argv, &error) == TRUE) {
276
/* Activate the remote instance */
277
g_application_activate (application);
281
g_application_command_line_printerr (command_line, _("Command line options could not be parsed: %s\n"), error->message);
282
g_error_free (error);
287
g_option_context_free (context);
296
storage_manager_disconnected_cb (AlmanahStorageManager *self, const gchar *gpgme_error_message, const gchar *warning_message, GApplication *application)
298
if (gpgme_error_message != NULL || warning_message != NULL) {
299
GtkWidget *dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
300
_("Error encrypting database"));
302
if (gpgme_error_message != NULL && warning_message != NULL)
303
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s %s", warning_message, gpgme_error_message);
304
else if (gpgme_error_message != NULL)
305
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", gpgme_error_message);
307
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", warning_message);
309
gtk_dialog_run (GTK_DIALOG (dialog));
310
gtk_widget_destroy (dialog);
313
/* Chain up to the parent class */
314
G_APPLICATION_CLASS (almanah_application_parent_class)->quit_mainloop (application);
318
quit_main_loop (GApplication *application)
320
AlmanahApplicationPrivate *priv = ALMANAH_APPLICATION (application)->priv;
322
/* This would normally result in gtk_main_quit() being called, but we need to close the database connection first. */
323
g_signal_connect (priv->storage_manager, "disconnected", (GCallback) storage_manager_disconnected_cb, application);
324
almanah_storage_manager_disconnect (priv->storage_manager, NULL);
326
/* Quitting is actually done in storage_manager_disconnected_cb, which is called once
327
* the storage manager has encrypted the DB and disconnected from it. */
331
almanah_application_new (void)
333
return ALMANAH_APPLICATION (g_object_new (ALMANAH_TYPE_APPLICATION, NULL));
337
almanah_application_get_debug (AlmanahApplication *self)
339
g_return_val_if_fail (ALMANAH_IS_APPLICATION (self), FALSE);
340
return self->priv->debug;
343
AlmanahEventManager *
344
almanah_application_dup_event_manager (AlmanahApplication *self)
346
g_return_val_if_fail (ALMANAH_IS_APPLICATION (self), NULL);
347
return g_object_ref (self->priv->event_manager);
350
AlmanahStorageManager *
351
almanah_application_dup_storage_manager (AlmanahApplication *self)
353
g_return_val_if_fail (ALMANAH_IS_APPLICATION (self), NULL);
354
return g_object_ref (self->priv->storage_manager);
358
almanah_application_dup_settings (AlmanahApplication *self)
360
g_return_val_if_fail (ALMANAH_IS_APPLICATION (self), NULL);
361
return g_object_ref (self->priv->settings);