~ubuntu-branches/ubuntu/utopic/almanah/utopic

« back to all changes in this revision

Viewing changes to src/application.c

  • Committer: Package Import Robot
  • Author(s): Angel Abad
  • Date: 2012-10-29 10:14:18 UTC
  • mfrom: (1.4.1) (10.1.7 sid)
  • Revision ID: package-import@ubuntu.com-20121029101418-k2c27xb0aku22zeg
Tags: 0.10.0-1~exp1
* Imported Upstream version 0.10.0
* debian/control:
  - Bump evolution Build-Depends ( >=3.6.0)
  - debian/control: Depends on evolution-common (>= 3.6.0)
* Bump Standards-Version to 3.9.4 (no changes)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 
2
/*
 
3
 * Almanah
 
4
 * Copyright (C) Philip Withnall 2011 <philip@tecnocode.co.uk>
 
5
 *
 
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.
 
10
 *
 
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.
 
15
 *
 
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/>.
 
18
 */
 
19
 
 
20
#include <stdlib.h>
 
21
#include <glib.h>
 
22
#include <glib/gi18n.h>
 
23
#include <gio/gio.h>
 
24
#include <gtk/gtk.h>
 
25
 
 
26
#include "application.h"
 
27
#include "storage-manager.h"
 
28
#include "event-manager.h"
 
29
#include "main-window.h"
 
30
 
 
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);
 
35
 
 
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);
 
40
 
 
41
struct _AlmanahApplicationPrivate {
 
42
        gboolean debug;
 
43
 
 
44
        GSettings *settings;
 
45
        AlmanahStorageManager *storage_manager;
 
46
        AlmanahEventManager *event_manager;
 
47
 
 
48
        AlmanahMainWindow *main_window;
 
49
};
 
50
 
 
51
enum {
 
52
        PROP_DEBUG = 1
 
53
};
 
54
 
 
55
G_DEFINE_TYPE (AlmanahApplication, almanah_application, GTK_TYPE_APPLICATION)
 
56
 
 
57
static void
 
58
almanah_application_class_init (AlmanahApplicationClass *klass)
 
59
{
 
60
        GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
61
        GApplicationClass *gapplication_class = G_APPLICATION_CLASS (klass);
 
62
 
 
63
        g_type_class_add_private (klass, sizeof (AlmanahApplicationPrivate));
 
64
 
 
65
        gobject_class->constructed = constructed;
 
66
        gobject_class->dispose = dispose;
 
67
        gobject_class->get_property = get_property;
 
68
        gobject_class->set_property = set_property;
 
69
 
 
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;
 
74
 
 
75
        g_object_class_install_property (gobject_class, PROP_DEBUG,
 
76
                                         g_param_spec_boolean ("debug",
 
77
                                                               "Debugging Mode", "Whether debugging mode is active.",
 
78
                                                               FALSE,
 
79
                                                               G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
80
}
 
81
 
 
82
static void
 
83
almanah_application_init (AlmanahApplication *self)
 
84
{
 
85
        self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, ALMANAH_TYPE_APPLICATION, AlmanahApplicationPrivate);
 
86
        self->priv->debug = FALSE;
 
87
}
 
88
 
 
89
static void
 
90
constructed (GObject *object)
 
91
{
 
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);
 
95
 
 
96
        /* Localisation */
 
97
        bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
 
98
        bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
 
99
        textdomain (GETTEXT_PACKAGE);
 
100
 
 
101
        g_set_application_name (_("Almanah Diary"));
 
102
        gtk_window_set_default_icon_name ("almanah");
 
103
 
 
104
        /* Chain up to the parent class */
 
105
        G_OBJECT_CLASS (almanah_application_parent_class)->constructed (object);
 
106
}
 
107
 
 
108
static void
 
109
dispose (GObject *object)
 
110
{
 
111
        AlmanahApplicationPrivate *priv = ALMANAH_APPLICATION (object)->priv;
 
112
 
 
113
        if (priv->main_window != NULL)
 
114
                gtk_widget_destroy (GTK_WIDGET (priv->main_window));
 
115
        priv->main_window = NULL;
 
116
 
 
117
        if (priv->event_manager != NULL)
 
118
                g_object_unref (priv->event_manager);
 
119
        priv->event_manager = NULL;
 
120
 
 
121
        if (priv->storage_manager != NULL)
 
122
                g_object_unref (priv->storage_manager);
 
123
        priv->storage_manager = NULL;
 
124
 
 
125
        if (priv->settings != NULL)
 
126
                g_object_unref (priv->settings);
 
127
        priv->settings = NULL;
 
128
 
 
129
        /* Chain up to the parent class */
 
130
        G_OBJECT_CLASS (almanah_application_parent_class)->dispose (object);
 
131
}
 
132
 
 
133
static void
 
134
get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
 
135
{
 
136
        AlmanahApplicationPrivate *priv = ALMANAH_APPLICATION (object)->priv;
 
137
 
 
138
        switch (property_id) {
 
139
                case PROP_DEBUG:
 
140
                        g_value_set_boolean (value, priv->debug);
 
141
                        break;
 
142
                default:
 
143
                        /* We don't have any other property... */
 
144
                        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
145
                        break;
 
146
        }
 
147
}
 
148
 
 
149
static void
 
150
set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
 
151
{
 
152
        AlmanahApplicationPrivate *priv = ALMANAH_APPLICATION (object)->priv;
 
153
 
 
154
        switch (property_id) {
 
155
                case PROP_DEBUG:
 
156
                        priv->debug = g_value_get_boolean (value);
 
157
                        break;
 
158
                default:
 
159
                        /* We don't have any other property... */
 
160
                        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
161
                        break;
 
162
        }
 
163
}
 
164
 
 
165
static void
 
166
debug_handler (const char *log_domain, GLogLevelFlags log_level, const char *message, AlmanahApplication *self)
 
167
{
 
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);
 
171
        }
 
172
}
 
173
 
 
174
static void
 
175
startup (GApplication *application)
 
176
{
 
177
        AlmanahApplicationPrivate *priv = ALMANAH_APPLICATION (application)->priv;
 
178
        gchar *db_filename;
 
179
        GError *error = NULL;
 
180
 
 
181
        /* Chain up. */
 
182
        G_APPLICATION_CLASS (almanah_application_parent_class)->startup (application);
 
183
 
 
184
        /* Debug log handling */
 
185
        g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, (GLogFunc) debug_handler, application);
 
186
 
 
187
        /* Open GSettings */
 
188
        priv->settings = g_settings_new ("org.gnome.almanah");
 
189
 
 
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);
 
193
        }
 
194
 
 
195
        /* Open the DB */
 
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);
 
199
 
 
200
        g_settings_bind (priv->settings, "encryption-key", priv->storage_manager, "encryption-key",
 
201
                         G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_NO_SENSITIVITY);
 
202
 
 
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);
 
209
 
 
210
                /* TODO */
 
211
                exit (1);
 
212
        }
 
213
 
 
214
        /* Create the event manager */
 
215
        priv->event_manager = almanah_event_manager_new ();
 
216
}
 
217
 
 
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(). */
 
220
static void
 
221
main_window_destroy_cb (AlmanahMainWindow *main_window, AlmanahApplication *self)
 
222
{
 
223
        self->priv->main_window = NULL;
 
224
}
 
225
 
 
226
static void
 
227
activate (GApplication *application)
 
228
{
 
229
        AlmanahApplication *self = ALMANAH_APPLICATION (application);
 
230
        AlmanahApplicationPrivate *priv = self->priv;
 
231
 
 
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);
 
237
        }
 
238
 
 
239
        /* Bring it to the foreground */
 
240
        gtk_window_present (GTK_WINDOW (priv->main_window));
 
241
}
 
242
 
 
243
static gint
 
244
handle_command_line (GApplication *application, GApplicationCommandLine *command_line)
 
245
{
 
246
        AlmanahApplicationPrivate *priv = ALMANAH_APPLICATION (application)->priv;
 
247
        GOptionContext *context;
 
248
        GError *error = NULL;
 
249
        gchar **args, **argv;
 
250
        gint argc, i, status = 0;
 
251
 
 
252
        const GOptionEntry options[] = {
 
253
                { "debug", 0, 0, G_OPTION_ARG_NONE, &(priv->debug), N_("Enable debug mode"), NULL },
 
254
                { NULL }
 
255
        };
 
256
 
 
257
        args = g_application_command_line_get_arguments (command_line, &argc);
 
258
 
 
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
 
260
         * freeing them. */
 
261
        argv = g_new (gchar*, argc + 1);
 
262
        for (i = 0; i <= argc; i++) {
 
263
                argv[i] = args[i];
 
264
        }
 
265
 
 
266
        /* Options */
 
267
        context = g_option_context_new (NULL);
 
268
        g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
 
269
 
 
270
        g_option_context_set_summary (context, _("Manage your diary. Only one instance of the program may be open at any time."));
 
271
 
 
272
        g_option_context_add_main_entries (context, options, GETTEXT_PACKAGE);
 
273
        g_option_context_add_group (context, gtk_get_option_group (TRUE));
 
274
 
 
275
        if (g_option_context_parse (context, &argc, &argv, &error) == TRUE) {
 
276
                /* Activate the remote instance */
 
277
                g_application_activate (application);
 
278
                status = 0;
 
279
        } else {
 
280
                /* Print an error */
 
281
                g_application_command_line_printerr (command_line, _("Command line options could not be parsed: %s\n"), error->message);
 
282
                g_error_free (error);
 
283
 
 
284
                status = 1;
 
285
        }
 
286
 
 
287
        g_option_context_free (context);
 
288
 
 
289
        g_free (argv);
 
290
        g_strfreev (args);
 
291
 
 
292
        return status;
 
293
}
 
294
 
 
295
static void
 
296
storage_manager_disconnected_cb (AlmanahStorageManager *self, const gchar *gpgme_error_message, const gchar *warning_message, GApplication *application)
 
297
{
 
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"));
 
301
 
 
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);
 
306
                else
 
307
                        gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", warning_message);
 
308
 
 
309
                gtk_dialog_run (GTK_DIALOG (dialog));
 
310
                gtk_widget_destroy (dialog);
 
311
        }
 
312
 
 
313
        /* Chain up to the parent class */
 
314
        G_APPLICATION_CLASS (almanah_application_parent_class)->quit_mainloop (application);
 
315
}
 
316
 
 
317
static void
 
318
quit_main_loop (GApplication *application)
 
319
{
 
320
        AlmanahApplicationPrivate *priv = ALMANAH_APPLICATION (application)->priv;
 
321
 
 
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);
 
325
 
 
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. */
 
328
}
 
329
 
 
330
AlmanahApplication *
 
331
almanah_application_new (void)
 
332
{
 
333
        return ALMANAH_APPLICATION (g_object_new (ALMANAH_TYPE_APPLICATION, NULL));
 
334
}
 
335
 
 
336
gboolean
 
337
almanah_application_get_debug (AlmanahApplication *self)
 
338
{
 
339
        g_return_val_if_fail (ALMANAH_IS_APPLICATION (self), FALSE);
 
340
        return self->priv->debug;
 
341
}
 
342
 
 
343
AlmanahEventManager *
 
344
almanah_application_dup_event_manager (AlmanahApplication *self)
 
345
{
 
346
        g_return_val_if_fail (ALMANAH_IS_APPLICATION (self), NULL);
 
347
        return g_object_ref (self->priv->event_manager);
 
348
}
 
349
 
 
350
AlmanahStorageManager *
 
351
almanah_application_dup_storage_manager (AlmanahApplication *self)
 
352
{
 
353
        g_return_val_if_fail (ALMANAH_IS_APPLICATION (self), NULL);
 
354
        return g_object_ref (self->priv->storage_manager);
 
355
}
 
356
 
 
357
GSettings *
 
358
almanah_application_dup_settings (AlmanahApplication *self)
 
359
{
 
360
        g_return_val_if_fail (ALMANAH_IS_APPLICATION (self), NULL);
 
361
        return g_object_ref (self->priv->settings);
 
362
}