~ubuntu-branches/ubuntu/wily/almanah/wily-proposed

« back to all changes in this revision

Viewing changes to src/main-window.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:
28
28
#endif /* ENABLE_SPELL_CHECKING */
29
29
 
30
30
#include "main-window.h"
31
 
#include "main.h"
32
31
#include "interface.h"
33
 
#include "add-definition-dialog.h"
34
32
#include "preferences-dialog.h"
35
33
#include "search-dialog.h"
36
34
#include "date-entry-dialog.h"
37
35
#include "printing.h"
38
36
#include "entry.h"
39
37
#include "storage-manager.h"
 
38
#include "event-manager.h"
40
39
#include "event.h"
41
 
#include "definition.h"
42
 
#include "definition-manager-window.h"
43
40
#include "import-export-dialog.h"
 
41
#include "uri-entry-dialog.h"
44
42
#include "widgets/calendar.h"
 
43
#include "widgets/calendar-button.h"
 
44
#include "widgets/font-style-menu-action.h"
 
45
#include "widgets/hyperlink-tag.h"
 
46
 
 
47
/* Interval for automatically saving the current entry. Currently an arbitrary 10 minutes. */
 
48
#define SAVE_ENTRY_INTERVAL 10 * 60 /* seconds */
45
49
 
46
50
static void almanah_main_window_dispose (GObject *object);
47
51
#ifdef ENABLE_SPELL_CHECKING
48
 
static void almanah_main_window_finalize (GObject *object);
 
52
static void spell_checking_enabled_changed_cb (GSettings *settings, gchar *key, AlmanahMainWindow *self);
 
53
static gboolean enable_spell_checking (AlmanahMainWindow *self, GError **error);
 
54
static void disable_spell_checking (AlmanahMainWindow *self);
49
55
#endif /* ENABLE_SPELL_CHECKING */
50
56
static void set_current_entry (AlmanahMainWindow *self, AlmanahEntry *entry);
51
57
static void save_window_state (AlmanahMainWindow *self);
55
61
static void mw_entry_buffer_insert_text_cb (GtkTextBuffer *text_buffer, GtkTextIter *start, gchar *text, gint len, AlmanahMainWindow *main_window);
56
62
static void mw_entry_buffer_insert_text_after_cb (GtkTextBuffer *text_buffer, GtkTextIter *start, gchar *text, gint len, AlmanahMainWindow *main_window);
57
63
static void mw_entry_buffer_has_selection_cb (GObject *object, GParamSpec *pspec, AlmanahMainWindow *main_window);
58
 
static void mw_entry_buffer_apply_tag_cb (GtkTextBuffer *buffer, GtkTextTag *tag, GtkTextIter *start_iter, GtkTextIter *end_iter, AlmanahMainWindow *main_window);
59
64
static void mw_bold_toggled_cb (GtkToggleAction *action, AlmanahMainWindow *main_window);
60
65
static void mw_italic_toggled_cb (GtkToggleAction *action, AlmanahMainWindow *main_window);
61
66
static void mw_underline_toggled_cb (GtkToggleAction *action, AlmanahMainWindow *main_window);
 
67
static void mw_hyperlink_toggled_cb (GtkToggleAction *action, AlmanahMainWindow *main_window);
62
68
static void mw_events_updated_cb (AlmanahEventManager *event_manager, AlmanahEventFactoryType type_id, AlmanahMainWindow *main_window);
63
 
static void mw_events_selection_changed_cb (GtkTreeSelection *tree_selection, AlmanahMainWindow *main_window);
64
 
static void mw_events_value_data_cb (GtkTreeViewColumn *column, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data);
65
 
static void mw_definition_removed_cb (AlmanahStorageManager *storage_manager, const gchar *definition_text, AlmanahMainWindow *main_window);
 
69
static void mw_font_style_menu_position_func (GtkMenu *menu, int *x, int *y, gboolean *push_in, GtkMenuToolButton *button);
 
70
static GtkMenuToolButton *mw_get_font_style_tool_button_from_action (GtkAction *action);
 
71
static gboolean save_entry_timeout_cb (AlmanahMainWindow *self);
 
72
static void mw_setup_toolbar (AlmanahMainWindow *main_window, AlmanahApplication *application, GtkToolbar *toolbar, GtkAction *today_action);
66
73
 
67
74
/* GtkBuilder callbacks */
68
 
void mw_calendar_day_selected_cb (GtkCalendar *calendar, AlmanahMainWindow *main_window);
69
75
void mw_import_activate_cb (GtkAction *action, AlmanahMainWindow *main_window);
70
76
void mw_export_activate_cb (GtkAction *action, AlmanahMainWindow *main_window);
71
77
void mw_page_setup_activate_cb (GtkAction *action, AlmanahMainWindow *main_window);
83
89
void mw_preferences_activate_cb (GtkAction *action, AlmanahMainWindow *main_window);
84
90
void mw_about_activate_cb (GtkAction *action, AlmanahMainWindow *main_window);
85
91
void mw_jump_to_today_activate_cb (GtkAction *action, AlmanahMainWindow *main_window);
86
 
void mw_add_definition_activate_cb (GtkAction *action, AlmanahMainWindow *main_window);
87
 
void mw_remove_definition_activate_cb (GtkAction *action, AlmanahMainWindow *main_window);
88
 
void mw_view_definitions_activate_cb (GtkAction *action, AlmanahMainWindow *main_window);
 
92
void mw_old_entries_activate_cb (GtkAction *action, AlmanahMainWindow *main_window);
89
93
void mw_events_tree_view_row_activated_cb (GtkTreeView *tree_view, GtkTreePath *path, GtkTreeViewColumn *column, AlmanahMainWindow *main_window);
90
 
void mw_view_button_clicked_cb (GtkButton *button, AlmanahMainWindow *main_window);
 
94
void mw_font_style_activate_cb (AlmanahFontStyleMenuAction *action, AlmanahMainWindow *main_window);
 
95
 
 
96
/* Other callbacks */
 
97
void mw_calendar_day_selected_cb (AlmanahCalendarButton *calendar, AlmanahMainWindow *main_window);
91
98
 
92
99
struct _AlmanahMainWindowPrivate {
93
100
        GtkTextView *entry_view;
94
101
        GtkTextBuffer *entry_buffer;
95
 
        AlmanahCalendar *calendar;
96
 
        GtkLabel *date_label;
97
 
        GtkButton *view_button;
98
 
        GtkAction *add_action;
99
 
        GtkAction *remove_action;
 
102
        AlmanahCalendarButton *calendar_button;
100
103
        GtkListStore *event_store;
 
104
        GtkWidget *events_expander;
 
105
        GtkLabel *events_count_label;
101
106
        GtkTreeSelection *events_selection;
102
 
        GtkTreeViewColumn *event_value_column;
103
 
        GtkCellRendererText *event_value_renderer;
104
107
        GtkToggleAction *bold_action;
105
108
        GtkToggleAction *italic_action;
106
109
        GtkToggleAction *underline_action;
 
110
        GtkToggleAction *hyperlink_action;
107
111
        GtkAction *cut_action;
108
112
        GtkAction *copy_action;
109
113
        GtkAction *delete_action;
110
114
        GtkAction *important_action;
 
115
        GtkMenuToolButton *font_style_tool_button;
111
116
 
112
117
        gboolean updating_formatting;
113
118
        gboolean pending_bold_active;
116
121
 
117
122
        AlmanahEntry *current_entry; /* whether it's been modified is stored as gtk_text_buffer_get_modified (priv->entry_buffer) */
118
123
        gulong current_entry_notify_id; /* signal handler for current_entry::notify */
 
124
        guint save_entry_timeout_id; /* source ID for timer to save current entry periodically */
 
125
 
 
126
        GtkPrintSettings *print_settings;
 
127
        GtkPageSetup *page_setup;
119
128
 
120
129
#ifdef ENABLE_SPELL_CHECKING
121
 
        gulong spell_checking_enabled_changed_id; /* signal handler for almanah->settings::changed::spell-checking-enabled */
 
130
        GSettings *settings;
 
131
        gulong spell_checking_enabled_changed_id; /* signal handler for application->settings::changed::spell-checking-enabled */
122
132
#endif /* ENABLE_SPELL_CHECKING */
123
133
};
124
134
 
131
141
        GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
132
142
        g_type_class_add_private (klass, sizeof (AlmanahMainWindowPrivate));
133
143
        gobject_class->dispose = almanah_main_window_dispose;
134
 
#ifdef ENABLE_SPELL_CHECKING
135
 
        gobject_class->finalize = almanah_main_window_finalize;
136
 
#endif /* ENABLE_SPELL_CHECKING */
137
144
}
138
145
 
139
146
static void
143
150
 
144
151
        gtk_window_set_title (GTK_WINDOW (self), _("Almanah Diary"));
145
152
        g_signal_connect (self, "delete-event", G_CALLBACK (mw_delete_event_cb), NULL);
146
 
 
147
 
#ifdef ENABLE_SPELL_CHECKING
148
 
        /* We don't use g_settings_bind() because enabling spell checking could fail, and we need to show an error dialogue */
149
 
        self->priv->spell_checking_enabled_changed_id = g_signal_connect (almanah->settings, "changed::spell-checking-enabled",
150
 
                                                                          (GCallback) spell_checking_enabled_changed_cb, self);
151
 
#endif /* ENABLE_SPELL_CHECKING */
152
153
}
153
154
 
154
155
static void
155
156
almanah_main_window_dispose (GObject *object)
156
157
{
 
158
        AlmanahMainWindowPrivate *priv = ALMANAH_MAIN_WINDOW (object)->priv;
 
159
 
 
160
        if (priv->save_entry_timeout_id != 0) {
 
161
                g_source_remove (priv->save_entry_timeout_id);
 
162
                priv->save_entry_timeout_id = 0;
 
163
        }
 
164
 
157
165
        set_current_entry (ALMANAH_MAIN_WINDOW (object), NULL);
158
166
 
 
167
        if (priv->page_setup != NULL)
 
168
                g_object_unref (priv->page_setup);
 
169
        priv->page_setup = NULL;
 
170
 
 
171
        if (priv->print_settings != NULL)
 
172
                g_object_unref (priv->print_settings);
 
173
        priv->print_settings = NULL;
 
174
 
 
175
#ifdef ENABLE_SPELL_CHECKING
 
176
        if (priv->settings != NULL) {
 
177
                if (priv->spell_checking_enabled_changed_id != 0) {
 
178
                        g_signal_handler_disconnect (priv->settings, priv->spell_checking_enabled_changed_id);
 
179
                        priv->spell_checking_enabled_changed_id = 0;
 
180
                }
 
181
 
 
182
                g_object_unref (priv->settings);
 
183
                priv->settings = NULL;
 
184
        }
 
185
#endif /* ENABLE_SPELL_CHECKING */
 
186
 
159
187
        /* Chain up to the parent class */
160
188
        G_OBJECT_CLASS (almanah_main_window_parent_class)->dispose (object);
161
189
}
162
190
 
163
 
#ifdef ENABLE_SPELL_CHECKING
164
 
static void
165
 
almanah_main_window_finalize (GObject *object)
166
 
{
167
 
        AlmanahMainWindowPrivate *priv = ALMANAH_MAIN_WINDOW (object)->priv;
168
 
 
169
 
        g_signal_handler_disconnect (object, priv->spell_checking_enabled_changed_id);
170
 
 
171
 
        /* Chain up to the parent class */
172
 
        G_OBJECT_CLASS (almanah_main_window_parent_class)->finalize (object);
173
 
}
174
 
#endif /* ENABLE_SPELL_CHECKING */
175
 
 
176
191
AlmanahMainWindow *
177
 
almanah_main_window_new (void)
 
192
almanah_main_window_new (AlmanahApplication *application)
178
193
{
179
194
        GtkBuilder *builder;
 
195
        AlmanahEventManager *event_manager;
180
196
        AlmanahMainWindow *main_window;
181
197
        AlmanahMainWindowPrivate *priv;
 
198
        GtkToolbar *toolbar;
 
199
        GtkAction *today_action;
182
200
        GError *error = NULL;
183
201
        const gchar *interface_filename = almanah_get_interface_filename ();
184
202
        const gchar *object_names[] = {
185
203
                "almanah_main_window",
186
204
                "almanah_mw_event_store",
187
 
                "almanah_mw_view_button_image",
188
205
                "almanah_ui_manager",
189
206
                NULL
190
207
        };
191
208
 
 
209
        g_return_val_if_fail (ALMANAH_IS_APPLICATION (application), NULL);
 
210
 
192
211
        builder = gtk_builder_new ();
193
212
 
194
213
        if (gtk_builder_add_objects_from_file (builder, interface_filename, (gchar**) object_names, &error) == FALSE) {
217
236
                return NULL;
218
237
        }
219
238
 
 
239
        /* Set up the application */
 
240
        gtk_window_set_application (GTK_WINDOW (main_window), GTK_APPLICATION (application));
 
241
 
220
242
        priv = ALMANAH_MAIN_WINDOW (main_window)->priv;
221
243
 
222
244
        /* Grab our child widgets */
223
245
        priv->entry_view = GTK_TEXT_VIEW (gtk_builder_get_object (builder, "almanah_mw_entry_view"));
224
246
        priv->entry_buffer = gtk_text_view_get_buffer (priv->entry_view);
225
 
        priv->calendar = ALMANAH_CALENDAR (gtk_builder_get_object (builder, "almanah_mw_calendar"));
226
 
        priv->date_label = GTK_LABEL (gtk_builder_get_object (builder, "almanah_mw_date_label"));
227
 
        priv->view_button = GTK_BUTTON (gtk_builder_get_object (builder, "almanah_mw_view_button"));
228
 
        priv->add_action = GTK_ACTION (gtk_builder_get_object (builder, "almanah_ui_add_definition"));
229
 
        priv->remove_action = GTK_ACTION (gtk_builder_get_object (builder, "almanah_ui_remove_definition"));
230
247
        priv->event_store = GTK_LIST_STORE (gtk_builder_get_object (builder, "almanah_mw_event_store"));
 
248
        priv->events_expander = GTK_WIDGET (gtk_builder_get_object (builder, "almanah_mw_events_expander"));
 
249
        priv->events_count_label = GTK_LABEL (gtk_builder_get_object (builder, "almanah_mw_events_count_label"));
231
250
        priv->events_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (gtk_builder_get_object (builder, "almanah_mw_events_tree_view")));
232
 
        priv->event_value_column = GTK_TREE_VIEW_COLUMN (gtk_builder_get_object (builder, "almanah_mw_event_value_column"));
233
 
        priv->event_value_renderer = GTK_CELL_RENDERER_TEXT (gtk_builder_get_object (builder, "almanah_mw_event_value_renderer"));
234
251
        priv->bold_action = GTK_TOGGLE_ACTION (gtk_builder_get_object (builder, "almanah_ui_bold"));;
235
252
        priv->italic_action = GTK_TOGGLE_ACTION (gtk_builder_get_object (builder, "almanah_ui_italic"));
236
253
        priv->underline_action = GTK_TOGGLE_ACTION (gtk_builder_get_object (builder, "almanah_ui_underline"));
 
254
        priv->hyperlink_action = GTK_TOGGLE_ACTION (gtk_builder_get_object (builder, "almanah_ui_hyperlink"));
237
255
        priv->cut_action = GTK_ACTION (gtk_builder_get_object (builder, "almanah_ui_cut"));
238
256
        priv->copy_action = GTK_ACTION (gtk_builder_get_object (builder, "almanah_ui_copy"));
239
257
        priv->delete_action = GTK_ACTION (gtk_builder_get_object (builder, "almanah_ui_delete"));
240
258
        priv->important_action = GTK_ACTION (gtk_builder_get_object (builder, "almanah_ui_important"));
 
259
        priv->font_style_tool_button = mw_get_font_style_tool_button_from_action (GTK_ACTION (gtk_builder_get_object (builder, "almanah_ui_font_style")));
241
260
 
242
261
#ifdef ENABLE_SPELL_CHECKING
243
262
        /* Set up spell checking, if it's enabled */
244
 
        if (g_settings_get_boolean (almanah->settings, "spell-checking-enabled") == TRUE)
 
263
        priv->settings = almanah_application_dup_settings (application);
 
264
 
 
265
        if (g_settings_get_boolean (priv->settings, "spell-checking-enabled") == TRUE) {
245
266
                enable_spell_checking (main_window, NULL);
 
267
        }
 
268
 
 
269
        /* We don't use g_settings_bind() because enabling spell checking could fail, and we need to show an error dialogue */
 
270
        priv->spell_checking_enabled_changed_id = g_signal_connect (priv->settings, "changed::spell-checking-enabled",
 
271
                                                                    (GCallback) spell_checking_enabled_changed_cb, main_window);
246
272
#endif /* ENABLE_SPELL_CHECKING */
247
273
 
248
274
        /* Set up text formatting. It's important this is done after setting up GtkSpell, so that we know whether to
260
286
        /* Similarly, make sure we're notified when there's a selection so we can change the status of cut/copy/paste actions */
261
287
        g_signal_connect (priv->entry_buffer, "notify::has-selection", G_CALLBACK (mw_entry_buffer_has_selection_cb), main_window);
262
288
 
263
 
        /* Get notified of applied tags so we can check if referenced definitions still exist */
264
 
        g_signal_connect_after (priv->entry_buffer, "apply-tag", G_CALLBACK (mw_entry_buffer_apply_tag_cb), main_window);
265
 
 
266
289
        /* Connect up the formatting actions */
267
290
        g_signal_connect (priv->bold_action, "toggled", G_CALLBACK (mw_bold_toggled_cb), main_window);
268
291
        g_signal_connect (priv->italic_action, "toggled", G_CALLBACK (mw_italic_toggled_cb), main_window);
269
292
        g_signal_connect (priv->underline_action, "toggled", G_CALLBACK (mw_underline_toggled_cb), main_window);
 
293
        g_signal_connect (priv->hyperlink_action, "toggled", (GCallback) mw_hyperlink_toggled_cb, main_window);
270
294
 
271
295
        /* Notification for event changes */
272
 
        g_signal_connect (almanah->event_manager, "events-updated", G_CALLBACK (mw_events_updated_cb), main_window);
273
 
 
274
 
        /* Notification for changes to definitions in the database */
275
 
        g_signal_connect (almanah->storage_manager, "definition-removed", G_CALLBACK (mw_definition_removed_cb), main_window);
 
296
        event_manager = almanah_application_dup_event_manager (application);
 
297
        g_signal_connect (event_manager, "events-updated", G_CALLBACK (mw_events_updated_cb), main_window);
 
298
        g_object_unref (event_manager);
 
299
 
 
300
        /* Set up printing objects */
 
301
        priv->print_settings = gtk_print_settings_new ();
 
302
 
 
303
#ifdef GTK_PRINT_SETTINGS_OUTPUT_BASENAME
 
304
        /* Translators: This is the default name of the PDF/PS/SVG file the diary is printed to if "Print to File" is chosen. */
 
305
        gtk_print_settings_set (priv->print_settings, GTK_PRINT_SETTINGS_OUTPUT_BASENAME, _("Diary"));
 
306
#endif
 
307
 
 
308
        priv->page_setup = gtk_page_setup_new ();
 
309
 
 
310
        /* Set up the toolbar */
 
311
        toolbar = GTK_TOOLBAR (gtk_builder_get_object (builder, "almanah_mw_toolbar"));
 
312
        today_action = GTK_ACTION (gtk_builder_get_object (builder, "almanah_ui_jump_to_today"));
 
313
        mw_setup_toolbar (main_window, application, toolbar, today_action);
276
314
 
277
315
        /* Select the current day and month */
278
316
        mw_jump_to_today_activate_cb (NULL, main_window);
279
317
 
280
 
        /* Set up the treeview */
281
 
        g_signal_connect (priv->events_selection, "changed", G_CALLBACK (mw_events_selection_changed_cb), main_window);
282
 
        gtk_tree_view_column_set_cell_data_func (priv->event_value_column, GTK_CELL_RENDERER (priv->event_value_renderer), mw_events_value_data_cb, NULL, NULL);
 
318
        /* Set up a timeout for saving the current entry every so often. */
 
319
        priv->save_entry_timeout_id = g_timeout_add_seconds (SAVE_ENTRY_INTERVAL, (GSourceFunc) save_entry_timeout_cb, main_window);
283
320
 
284
321
#ifndef ENABLE_ENCRYPTION
285
322
#ifndef ENABLE_SPELL_CHECKING
522
559
}
523
560
 
524
561
static void
525
 
save_current_entry (AlmanahMainWindow *self)
 
562
save_current_entry (AlmanahMainWindow *self, gboolean prompt_user)
526
563
{
527
564
        gboolean entry_exists, existing_entry_is_empty, entry_is_empty;
528
565
        GDate date, last_edited;
 
566
        AlmanahStorageManager *storage_manager;
529
567
        AlmanahMainWindowPrivate *priv = self->priv;
530
568
        AlmanahEntryEditability editability;
531
569
 
537
575
            gtk_text_buffer_get_modified (priv->entry_buffer) == FALSE)
538
576
                return;
539
577
 
 
578
        storage_manager = almanah_application_dup_storage_manager (ALMANAH_APPLICATION (gtk_window_get_application (GTK_WINDOW (self))));
 
579
 
540
580
        almanah_entry_get_date (priv->current_entry, &date);
541
581
        editability = almanah_entry_get_editability (priv->current_entry);
542
 
        entry_exists = almanah_storage_manager_entry_exists (almanah->storage_manager, &date);
 
582
        entry_exists = almanah_storage_manager_entry_exists (storage_manager, &date);
543
583
        existing_entry_is_empty = almanah_entry_is_empty (priv->current_entry);
544
584
        entry_is_empty = (gtk_text_buffer_get_char_count (priv->entry_buffer) == 0) ? TRUE : FALSE;
545
585
 
548
588
         * If an entry is being deleted, permission must be given for that as a priority. */
549
589
        if (editability == ALMANAH_ENTRY_FUTURE) {
550
590
                /* Can't edit entries for dates in the future */
551
 
                return;
 
591
                goto done;
552
592
        } else if (editability == ALMANAH_ENTRY_PAST && (existing_entry_is_empty == FALSE || entry_is_empty == FALSE)) {
553
593
                /* Attempting to edit an existing entry in the past */
554
594
                gchar date_string[100];
555
595
                GtkWidget *dialog;
556
596
 
 
597
                /* No-op if we're not allowed to prompt the user. */
 
598
                if (prompt_user == FALSE) {
 
599
                        goto done;
 
600
                }
 
601
 
557
602
                /* Translators: This is a strftime()-format string for the date to display when asking about editing a diary entry. */
558
603
                g_date_strftime (date_string, sizeof (date_string), _("%A, %e %B %Y"), &date);
559
604
 
570
615
                if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_ACCEPT) {
571
616
                        /* Cancelled the edit */
572
617
                        gtk_widget_destroy (dialog);
573
 
                        return;
 
618
                        goto done;
574
619
                }
575
620
 
576
621
                gtk_widget_destroy (dialog);
579
624
                gchar date_string[100];
580
625
                GtkWidget *dialog;
581
626
 
 
627
                /* No-op if we're not allowed to prompt the user. */
 
628
                if (prompt_user == FALSE) {
 
629
                        goto done;
 
630
                }
 
631
 
582
632
                /* Translators: This is a strftime()-format string for the date to display when asking about deleting a diary entry. */
583
633
                g_date_strftime (date_string, sizeof (date_string), _("%A, %e %B %Y"), &date);
584
634
 
595
645
                if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_ACCEPT) {
596
646
                        /* Cancelled deletion */
597
647
                        gtk_widget_destroy (dialog);
598
 
                        return;
 
648
                        goto done;
599
649
                }
600
650
 
601
651
                gtk_widget_destroy (dialog);
609
659
        almanah_entry_set_last_edited (priv->current_entry, &last_edited);
610
660
 
611
661
        /* Store the entry! */
612
 
        almanah_storage_manager_set_entry (almanah->storage_manager, priv->current_entry);
 
662
        almanah_storage_manager_set_entry (storage_manager, priv->current_entry);
613
663
 
614
664
        if (entry_is_empty == TRUE) {
615
665
                /* Since the entry is empty, remove all the events from the treeview */
616
666
                gtk_list_store_clear (priv->event_store);
617
667
        }
618
 
}
619
 
 
620
 
static void
621
 
add_definition_to_current_entry (AlmanahMainWindow *self)
622
 
{
623
 
        AlmanahMainWindowPrivate *priv = self->priv;
624
 
        GtkTextIter start_iter, end_iter;
625
 
        gchar *text;
626
 
        AlmanahDefinition *definition;
627
 
 
628
 
        g_assert (priv->entry_buffer != NULL);
629
 
        g_assert (gtk_text_buffer_get_char_count (priv->entry_buffer) != 0);
630
 
 
631
 
        if (gtk_text_buffer_get_selection_bounds (priv->entry_buffer, &start_iter, &end_iter) == FALSE)
632
 
                return;
633
 
 
634
 
        text = gtk_text_buffer_get_text (priv->entry_buffer, &start_iter, &end_iter, FALSE);
635
 
 
636
 
        /* If the definition already exists, don't display the dialogue */
637
 
        definition = almanah_storage_manager_get_definition (almanah->storage_manager, text);
638
 
        if (definition != NULL) {
639
 
                g_object_unref (definition);
640
 
 
641
 
                /* Add a GtkTextTag to the GtkTextBuffer to mark the definition */
642
 
                gtk_text_buffer_apply_tag_by_name (priv->entry_buffer, "definition", &start_iter, &end_iter);
643
 
                gtk_text_buffer_set_modified (priv->entry_buffer, TRUE);
644
 
 
645
 
                g_free (text);
646
 
                return;
647
 
        }
648
 
 
649
 
        /* Create the Add Definition dialogue if it doesn't already exist */
650
 
        if (almanah->add_definition_dialog == NULL)
651
 
                almanah->add_definition_dialog = GTK_WIDGET (almanah_add_definition_dialog_new ());
652
 
 
653
 
        /* Ensure that something is selected and its widget's displayed */
654
 
        almanah_add_definition_dialog_set_text (ALMANAH_ADD_DEFINITION_DIALOG (almanah->add_definition_dialog), text);
655
 
        g_free (text);
656
 
        gtk_widget_show_all (almanah->add_definition_dialog);
657
 
 
658
 
        if (gtk_dialog_run (GTK_DIALOG (almanah->add_definition_dialog)) == GTK_RESPONSE_OK) {
659
 
                definition = almanah_add_definition_dialog_get_definition (ALMANAH_ADD_DEFINITION_DIALOG (almanah->add_definition_dialog));
660
 
                if (definition == NULL)
661
 
                        return;
662
 
 
663
 
                /* Add to the DB */
664
 
                almanah_storage_manager_add_definition (almanah->storage_manager, definition);
665
 
 
666
 
                /* Add a GtkTextTag to the GtkTextBuffer to mark the definition */
667
 
                gtk_text_buffer_apply_tag_by_name (priv->entry_buffer, "definition", &start_iter, &end_iter);
668
 
                gtk_text_buffer_set_modified (priv->entry_buffer, TRUE);
669
 
        }
670
 
}
671
 
 
672
 
static void
673
 
remove_definition_from_current_entry (AlmanahMainWindow *self)
674
 
{
675
 
        /* We don't actually remove the definition from the database, since other entries may use it;
676
 
         * we simply remove the formatting. */
677
 
        AlmanahMainWindowPrivate *priv = self->priv;
678
 
        GtkTextIter start_iter, end_iter;
679
 
        GtkTextTag *tag;
680
 
        GtkTextTagTable *tag_table;
681
 
 
682
 
        /* Find the tag in the tag table */
683
 
        tag_table = gtk_text_buffer_get_tag_table (priv->entry_buffer);
684
 
        tag = gtk_text_tag_table_lookup (tag_table, "definition");
685
 
        g_assert (tag != NULL);
686
 
 
687
 
        /* Find the boundaries of the tag (ignoring everything except the position
688
 
         * of the start iter of any selection the user's made). */
689
 
        gtk_text_buffer_get_selection_bounds (priv->entry_buffer, &start_iter, NULL);
690
 
        end_iter = start_iter;
691
 
 
692
 
        if (gtk_text_iter_begins_tag (&start_iter, tag) == TRUE) {
693
 
                /* We're at the start of the tag */
694
 
                gtk_text_iter_forward_to_tag_toggle (&end_iter, tag);
695
 
        } else if (gtk_text_iter_ends_tag (&start_iter, tag) == TRUE) {
696
 
                /* We're at the end of the tag */
697
 
                end_iter = start_iter;
698
 
                gtk_text_iter_backward_to_tag_toggle (&start_iter, tag);
699
 
        } else {
700
 
                /* We're somewhere in the middle of the tag */
701
 
                gtk_text_iter_backward_to_tag_toggle (&start_iter, tag);
702
 
                end_iter = start_iter;
703
 
                gtk_text_iter_forward_to_tag_toggle (&end_iter, tag);
704
 
        }
705
 
 
706
 
        /* Remove the tag */
707
 
        gtk_text_buffer_remove_tag (priv->entry_buffer, tag, &start_iter, &end_iter);
708
 
        gtk_text_buffer_set_modified (priv->entry_buffer, TRUE);
 
668
 
 
669
done:
 
670
        g_object_unref (storage_manager);
 
671
}
 
672
 
 
673
static gboolean
 
674
save_entry_timeout_cb (AlmanahMainWindow *self)
 
675
{
 
676
        save_current_entry (self, FALSE);
 
677
        return TRUE;
709
678
}
710
679
 
711
680
void
712
681
almanah_main_window_select_date (AlmanahMainWindow *self, GDate *date)
713
682
{
714
 
        almanah_calendar_select_date (self->priv->calendar, date);
 
683
        almanah_calendar_button_select_date (self->priv->calendar_button, date);
715
684
}
716
685
 
717
686
static void
721
690
        AlmanahMainWindowPrivate *priv = main_window->priv;
722
691
        GSList *_tag_list = NULL, *tag_list = NULL;
723
692
        gboolean range_selected = FALSE;
724
 
        gboolean bold_toggled = FALSE, italic_toggled = FALSE, underline_toggled = FALSE, remove_definition_toggled = FALSE;
 
693
        gboolean bold_toggled = FALSE, italic_toggled = FALSE, underline_toggled = FALSE, hyperlink_toggled = FALSE;
725
694
 
726
695
        /* Ensure we don't overwrite current formatting options when characters are being typed.
727
696
         * (Execution of this function will be sandwiched between:
736
705
        if (range_selected == FALSE)
737
706
                _tag_list = gtk_text_iter_get_tags (&iter);
738
707
 
739
 
        /* We can only have the "add definition" action sensitive if there's a range selected */
740
 
        gtk_action_set_sensitive (priv->add_action, (range_selected == TRUE) ? TRUE : FALSE);
741
 
 
742
708
        /* Block signal handlers for the formatting actions while we're executing,
743
709
         * so formatting doesn't get unwittingly changed. */
744
710
        priv->updating_formatting = TRUE;
745
711
 
746
712
        tag_list = _tag_list;
747
713
        while (tag_list != NULL) {
 
714
                GtkTextTag *tag;
748
715
                gchar *tag_name;
749
716
                GtkToggleAction *action = NULL;
750
717
 
751
 
                g_object_get (tag_list->data, "name", &tag_name, NULL);
 
718
                tag = GTK_TEXT_TAG (tag_list->data);
 
719
                g_object_get (tag, "name", &tag_name, NULL);
752
720
 
753
721
                /* See if we can do anything with the tag */
754
 
                if (strcmp (tag_name, "bold") == 0) {
755
 
                        action = priv->bold_action;
756
 
                        bold_toggled = TRUE;
757
 
                } else if (strcmp (tag_name, "italic") == 0) {
758
 
                        action = priv->italic_action;
759
 
                        italic_toggled = TRUE;
760
 
                } else if (strcmp (tag_name, "underline") == 0) {
761
 
                        action = priv->underline_action;
762
 
                        underline_toggled = TRUE;
763
 
                }
764
 
 
765
 
                if (strcmp (tag_name, "definition") == 0) {
766
 
                        /* Deal with definition tags slightly differently --- just toggle the sensitivity of the "remove definition" action */
767
 
                        gtk_action_set_sensitive (priv->remove_action, TRUE);
768
 
                        remove_definition_toggled = TRUE;
769
 
                } else if (action != NULL) {
 
722
                if (tag_name != NULL) {
 
723
                        if (strcmp (tag_name, "bold") == 0) {
 
724
                                action = priv->bold_action;
 
725
                                bold_toggled = TRUE;
 
726
                        } else if (strcmp (tag_name, "italic") == 0) {
 
727
                                action = priv->italic_action;
 
728
                                italic_toggled = TRUE;
 
729
                        } else if (strcmp (tag_name, "underline") == 0) {
 
730
                                action = priv->underline_action;
 
731
                                underline_toggled = TRUE;
 
732
                        }
 
733
                }
 
734
 
 
735
                /* Hyperlink? */
 
736
                if (ALMANAH_IS_HYPERLINK_TAG (tag)) {
 
737
                        action = priv->hyperlink_action;
 
738
                        hyperlink_toggled = TRUE;
 
739
                }
 
740
 
 
741
                if (action != NULL) {
770
742
                        /* Force the toggle status on the action */
771
743
                        gtk_toggle_action_set_active (action, TRUE);
772
 
                } else if (strcmp (tag_name, "gtkspell-misspelled") != 0) {
 
744
                } else if (tag_name == NULL || strcmp (tag_name, "gtkspell-misspelled") != 0) {
773
745
                        /* Print a warning about the unknown tag */
774
746
                        g_warning (_("Unknown or duplicate text tag \"%s\" in entry. Ignoring."), tag_name);
775
747
                }
788
760
                        gtk_toggle_action_set_active (priv->italic_action, FALSE);
789
761
                if (underline_toggled == FALSE)
790
762
                        gtk_toggle_action_set_active (priv->underline_action, FALSE);
791
 
                if (remove_definition_toggled == FALSE)
792
 
                        gtk_action_set_sensitive (priv->remove_action, FALSE);
 
763
 
 
764
                if (hyperlink_toggled == FALSE) {
 
765
                        gtk_toggle_action_set_active (priv->hyperlink_action, FALSE);
 
766
                }
793
767
        }
794
768
 
795
769
        /* Unblock signals */
837
811
        gtk_action_set_sensitive (main_window->priv->delete_action, has_selection);
838
812
}
839
813
 
840
 
static void
841
 
mw_entry_buffer_apply_tag_cb (GtkTextBuffer *buffer, GtkTextTag *tag, GtkTextIter *start_iter, GtkTextIter *end_iter, AlmanahMainWindow *main_window)
842
 
{
843
 
        gchar *name;
844
 
 
845
 
        g_object_get (G_OBJECT (tag), "name", &name, NULL);
846
 
        if (strcmp (name, "definition") == 0) {
847
 
                AlmanahDefinition *definition;
848
 
                gchar *definition_text;
849
 
 
850
 
                /* Check to see if the definition still exists in the DB */
851
 
                definition_text = gtk_text_buffer_get_text (buffer, start_iter, end_iter, FALSE);
852
 
                definition = almanah_storage_manager_get_definition (almanah->storage_manager, definition_text);
853
 
                g_free (definition_text);
854
 
 
855
 
                /* If the definition doesn't exist, remove the tag */
856
 
                if (definition == NULL) {
857
 
                        gtk_text_buffer_remove_tag (buffer, tag, start_iter, end_iter);
858
 
                        gtk_text_buffer_set_modified (buffer, TRUE);
859
 
                } else {
860
 
                        g_object_unref (definition);
861
 
                }
862
 
        }
863
 
 
864
 
        g_free (name);
865
 
}
866
 
 
867
814
static gboolean
868
815
mw_delete_event_cb (GtkWindow *window, gpointer user_data)
869
816
{
870
 
        save_current_entry (ALMANAH_MAIN_WINDOW (window));
 
817
        save_current_entry (ALMANAH_MAIN_WINDOW (window), TRUE);
871
818
        save_window_state (ALMANAH_MAIN_WINDOW (window));
872
819
 
873
 
        almanah_quit ();
 
820
        gtk_widget_destroy (GTK_WIDGET (window));
874
821
 
875
822
        return TRUE;
876
823
}
878
825
void
879
826
mw_import_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
880
827
{
881
 
        GtkWidget *dialog = GTK_WIDGET (almanah_import_export_dialog_new (TRUE));
 
828
        AlmanahApplication *application;
 
829
        AlmanahStorageManager *storage_manager;
 
830
        GtkWidget *dialog;
 
831
 
 
832
        application = ALMANAH_APPLICATION (gtk_window_get_application (GTK_WINDOW (main_window)));
 
833
        storage_manager = almanah_application_dup_storage_manager (application);
 
834
        dialog = GTK_WIDGET (almanah_import_export_dialog_new (storage_manager, TRUE));
 
835
        g_object_unref (storage_manager);
 
836
 
882
837
        gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (main_window));
883
838
        gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
884
839
 
889
844
void
890
845
mw_export_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
891
846
{
892
 
        GtkWidget *dialog = GTK_WIDGET (almanah_import_export_dialog_new (FALSE));
 
847
        AlmanahApplication *application;
 
848
        AlmanahStorageManager *storage_manager;
 
849
        GtkWidget *dialog;
 
850
 
 
851
        application = ALMANAH_APPLICATION (gtk_window_get_application (GTK_WINDOW (main_window)));
 
852
        storage_manager = almanah_application_dup_storage_manager (application);
 
853
        dialog = GTK_WIDGET (almanah_import_export_dialog_new (storage_manager, FALSE));
 
854
        g_object_unref (storage_manager);
 
855
 
893
856
        gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (main_window));
894
857
        gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
895
858
 
900
863
void
901
864
mw_page_setup_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
902
865
{
903
 
        almanah_print_page_setup ();
 
866
        AlmanahMainWindowPrivate *priv = main_window->priv;
 
867
        GtkPageSetup *page_setup;
 
868
 
 
869
        page_setup = gtk_print_run_page_setup_dialog (GTK_WINDOW (main_window), priv->page_setup, priv->print_settings);
 
870
        if (priv->page_setup != NULL)
 
871
                g_object_unref (priv->page_setup);
 
872
        priv->page_setup = page_setup;
904
873
}
905
874
 
906
875
void
907
876
mw_print_preview_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
908
877
{
909
 
        almanah_print_entries (TRUE);
 
878
        AlmanahMainWindowPrivate *priv = main_window->priv;
 
879
        AlmanahApplication *application;
 
880
        AlmanahStorageManager *storage_manager;
 
881
 
 
882
        application = ALMANAH_APPLICATION (gtk_window_get_application (GTK_WINDOW (main_window)));
 
883
        storage_manager = almanah_application_dup_storage_manager (application);
 
884
        almanah_print_entries (TRUE, GTK_WINDOW (main_window), &(priv->page_setup), &(priv->print_settings), storage_manager);
 
885
        g_object_unref (storage_manager);
910
886
}
911
887
 
912
888
void
913
889
mw_print_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
914
890
{
915
 
        almanah_print_entries (FALSE);
 
891
        AlmanahMainWindowPrivate *priv = main_window->priv;
 
892
        AlmanahApplication *application;
 
893
        AlmanahStorageManager *storage_manager;
 
894
 
 
895
        application = ALMANAH_APPLICATION (gtk_window_get_application (GTK_WINDOW (main_window)));
 
896
        storage_manager = almanah_application_dup_storage_manager (application);
 
897
        almanah_print_entries (FALSE, GTK_WINDOW (main_window), &(priv->page_setup), &(priv->print_settings), storage_manager);
 
898
        g_object_unref (storage_manager);
916
899
}
917
900
 
918
901
void
919
902
mw_quit_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
920
903
{
921
 
        save_current_entry (main_window);
922
 
        almanah_quit ();
 
904
        /* Hide the window to make things look faster */
 
905
        gtk_widget_hide (GTK_WIDGET (main_window));
 
906
 
 
907
        save_current_entry (main_window, TRUE);
 
908
        gtk_widget_destroy (GTK_WIDGET (main_window));
923
909
}
924
910
 
925
911
void
969
955
void
970
956
mw_select_date_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
971
957
{
972
 
        if (almanah->date_entry_dialog == NULL)
973
 
                almanah->date_entry_dialog = GTK_WIDGET (almanah_date_entry_dialog_new ());
 
958
        AlmanahDateEntryDialog *dialog = almanah_date_entry_dialog_new ();
974
959
 
975
 
        gtk_widget_show_all (almanah->date_entry_dialog);
976
 
        if (almanah_date_entry_dialog_run (ALMANAH_DATE_ENTRY_DIALOG (almanah->date_entry_dialog)) == TRUE) {
 
960
        gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (main_window));
 
961
        gtk_widget_show_all (GTK_WIDGET (dialog));
 
962
        if (almanah_date_entry_dialog_run (dialog) == TRUE) {
977
963
                GDate new_date;
978
964
 
979
965
                /* Switch to the specified date */
980
 
                almanah_date_entry_dialog_get_date (ALMANAH_DATE_ENTRY_DIALOG (almanah->date_entry_dialog), &new_date);
 
966
                almanah_date_entry_dialog_get_date (dialog, &new_date);
981
967
                almanah_main_window_select_date (main_window, &new_date);
982
968
        }
 
969
 
 
970
        gtk_widget_destroy (GTK_WIDGET (dialog));
983
971
}
984
972
 
985
973
void
986
974
mw_search_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
987
975
{
988
 
        if (almanah->search_dialog == NULL)
989
 
                almanah->search_dialog = GTK_WIDGET (almanah_search_dialog_new ());
990
 
 
991
 
        gtk_widget_show_all (almanah->search_dialog);
992
 
        gtk_dialog_run (GTK_DIALOG (almanah->search_dialog));
 
976
        AlmanahSearchDialog *dialog = almanah_search_dialog_new ();
 
977
 
 
978
        gtk_window_set_application (GTK_WINDOW (dialog), gtk_window_get_application (GTK_WINDOW (main_window)));
 
979
        gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (main_window));
 
980
        gtk_widget_show (GTK_WIDGET (dialog));
 
981
        gtk_dialog_run (GTK_DIALOG (dialog));
 
982
 
 
983
        gtk_widget_destroy (GTK_WIDGET (dialog));
993
984
}
994
985
 
995
986
void
996
987
mw_preferences_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
997
988
{
998
 
#ifdef ENABLE_ENCRYPTION
999
 
        if (almanah->preferences_dialog == NULL)
1000
 
                almanah->preferences_dialog = GTK_WIDGET (almanah_preferences_dialog_new ());
1001
 
 
1002
 
        gtk_widget_show_all (almanah->preferences_dialog);
1003
 
        gtk_dialog_run (GTK_DIALOG (almanah->preferences_dialog));
1004
 
#endif /* ENABLE_ENCRYPTION */
 
989
#if defined(ENABLE_ENCRYPTION) || defined(ENABLE_SPELL_CHECKING)
 
990
        AlmanahApplication *application;
 
991
        GSettings *settings;
 
992
        AlmanahPreferencesDialog *dialog;
 
993
 
 
994
        application = ALMANAH_APPLICATION (gtk_window_get_application (GTK_WINDOW (main_window)));
 
995
        settings = almanah_application_dup_settings (application);
 
996
        dialog = almanah_preferences_dialog_new (settings);
 
997
        g_object_unref (settings);
 
998
 
 
999
        gtk_widget_show_all (GTK_WIDGET (dialog));
 
1000
        gtk_dialog_run (GTK_DIALOG (dialog));
 
1001
 
 
1002
        gtk_widget_destroy (GTK_WIDGET (dialog));
 
1003
#endif /* ENABLE_ENCRYPTION || ENABLE_SPELL_CHECKING */
1005
1004
}
1006
1005
 
1007
1006
static void
1041
1040
        apply_formatting (main_window, "underline", gtk_toggle_action_get_active (action));
1042
1041
}
1043
1042
 
 
1043
static gboolean
 
1044
hyperlink_tag_event_cb (GtkTextTag *tag, GObject *object, GdkEvent *event, GtkTextIter *iter, AlmanahMainWindow *self)
 
1045
{
 
1046
        AlmanahHyperlinkTag *hyperlink_tag = ALMANAH_HYPERLINK_TAG (tag);
 
1047
 
 
1048
        /* Open the hyperlink if it's control-clicked */
 
1049
        if (event->type == GDK_BUTTON_RELEASE && event->button.state & GDK_CONTROL_MASK) {
 
1050
                const gchar *uri;
 
1051
                GError *error = NULL;
 
1052
 
 
1053
                uri = almanah_hyperlink_tag_get_uri (hyperlink_tag);
 
1054
 
 
1055
                /* Attempt to open the URI */
 
1056
                gtk_show_uri (gtk_widget_get_screen (GTK_WIDGET (self)), uri, gdk_event_get_time (event), &error);
 
1057
 
 
1058
                if (error != NULL) {
 
1059
                        /* Error */
 
1060
                        GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW (self),
 
1061
                                                                    GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
 
1062
                                                                    _("Error opening URI"));
 
1063
                        gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", error->message);
 
1064
                        gtk_dialog_run (GTK_DIALOG (dialog));
 
1065
                        gtk_widget_destroy (dialog);
 
1066
 
 
1067
                        g_error_free (error);
 
1068
                }
 
1069
 
 
1070
                return TRUE;
 
1071
        }
 
1072
 
 
1073
        return FALSE;
 
1074
}
 
1075
 
 
1076
static void
 
1077
mw_hyperlink_toggled_cb (GtkToggleAction *action, AlmanahMainWindow *self)
 
1078
{
 
1079
        AlmanahMainWindowPrivate *priv = self->priv;
 
1080
        GtkTextIter start, end;
 
1081
 
 
1082
        /* Make sure we don't muck up the formatting when the actions are having
 
1083
         * their sensitivity set by the code. */
 
1084
        if (priv->updating_formatting == TRUE)
 
1085
                return;
 
1086
 
 
1087
        gtk_text_buffer_get_selection_bounds (priv->entry_buffer, &start, &end);
 
1088
 
 
1089
        if (gtk_toggle_action_get_active (action) == TRUE) {
 
1090
                /* Add a new hyperlink on the selected text */
 
1091
                AlmanahUriEntryDialog *uri_entry_dialog;
 
1092
 
 
1093
                /* Get a URI from the user */
 
1094
                uri_entry_dialog = almanah_uri_entry_dialog_new ();
 
1095
                gtk_window_set_transient_for (GTK_WINDOW (uri_entry_dialog), GTK_WINDOW (self));
 
1096
                gtk_widget_show_all (GTK_WIDGET (uri_entry_dialog));
 
1097
 
 
1098
                if (almanah_uri_entry_dialog_run (uri_entry_dialog) == TRUE) {
 
1099
                        GtkTextTag *tag;
 
1100
                        GtkTextTagTable *table;
 
1101
 
 
1102
                        /* Create and apply a new anonymous tag */
 
1103
                        tag = GTK_TEXT_TAG (almanah_hyperlink_tag_new (almanah_uri_entry_dialog_get_uri (uri_entry_dialog)));
 
1104
 
 
1105
                        table = gtk_text_buffer_get_tag_table (priv->entry_buffer);
 
1106
                        gtk_text_tag_table_add (table, tag);
 
1107
 
 
1108
                        gtk_text_buffer_apply_tag (priv->entry_buffer, tag, &start, &end);
 
1109
 
 
1110
                        /* Connect up events */
 
1111
                        g_signal_connect (tag, "event", (GCallback) hyperlink_tag_event_cb, self);
 
1112
 
 
1113
                        /* The text tag table keeps a reference */
 
1114
                        g_object_unref (tag);
 
1115
                }
 
1116
 
 
1117
                gtk_widget_destroy (GTK_WIDGET (uri_entry_dialog));
 
1118
        } else {
 
1119
                GtkTextIter iter = start;
 
1120
                GSList *tags, *i;
 
1121
 
 
1122
                /* Remove all hyperlinks which are active at the start iter. This covers the case of hyperlinks which span more than the
 
1123
                 * selected text (i.e. begin before the start iter and end after the end iter). All other spanning hyperlinks will have an end point
 
1124
                 * inside the selected text, and will be caught below. */
 
1125
                tags  = gtk_text_iter_get_tags (&start);
 
1126
 
 
1127
                for (i = tags; i != NULL; i = i->next) {
 
1128
                        GtkTextTag *tag = GTK_TEXT_TAG (i->data);
 
1129
 
 
1130
                        if (ALMANAH_IS_HYPERLINK_TAG (tag)) {
 
1131
                                GtkTextIter tag_start = start, tag_end = start;
 
1132
 
 
1133
                                if (gtk_text_iter_backward_to_tag_toggle (&tag_start, tag) == TRUE &&
 
1134
                                    gtk_text_iter_forward_to_tag_toggle (&tag_end, tag) == TRUE) {
 
1135
                                        gtk_text_buffer_remove_tag (priv->entry_buffer, tag, &tag_start, &tag_end);
 
1136
                                }
 
1137
                        }
 
1138
                }
 
1139
 
 
1140
                g_slist_free (tags);
 
1141
 
 
1142
                /* Remove all hyperlinks which span the selected text and have an end point inside the selected text */
 
1143
                while (gtk_text_iter_forward_to_tag_toggle (&iter, NULL) == TRUE) {
 
1144
                        /* Break once we've passed the end of the selected text range */
 
1145
                        if (gtk_text_iter_compare (&iter, &end) > 0) {
 
1146
                                break;
 
1147
                        }
 
1148
 
 
1149
                        tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
 
1150
 
 
1151
                        for (i = tags; i != NULL; i = i->next) {
 
1152
                                if (ALMANAH_IS_HYPERLINK_TAG (i->data)) {
 
1153
                                        gtk_text_buffer_remove_tag (priv->entry_buffer, GTK_TEXT_TAG (i->data), &start, &end);
 
1154
                                }
 
1155
                        }
 
1156
 
 
1157
                        g_slist_free (tags);
 
1158
                }
 
1159
        }
 
1160
 
 
1161
        gtk_text_buffer_set_modified (priv->entry_buffer, TRUE);
 
1162
}
 
1163
 
1044
1164
void
1045
1165
mw_about_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
1046
1166
{
 
1167
        AlmanahApplication *application;
 
1168
        AlmanahStorageManager *storage_manager;
1047
1169
        gchar *license, *description;
1048
 
        guint entry_count, definition_count;
 
1170
        guint entry_count;
1049
1171
 
1050
1172
        const gchar *authors[] =
1051
1173
        {
1071
1193
                          _(license_parts[2]),
1072
1194
                          NULL);
1073
1195
 
1074
 
        almanah_storage_manager_get_statistics (almanah->storage_manager, &entry_count, &definition_count);
1075
 
        description = g_strdup_printf (_("A helpful diary keeper, storing %u entries and %u definitions."),
1076
 
                                      entry_count,
1077
 
                                      definition_count);
 
1196
        application = ALMANAH_APPLICATION (gtk_window_get_application (GTK_WINDOW (main_window)));
 
1197
        storage_manager = almanah_application_dup_storage_manager (application);
 
1198
        almanah_storage_manager_get_statistics (storage_manager, &entry_count);
 
1199
        g_object_unref (storage_manager);
 
1200
 
 
1201
        description = g_strdup_printf (_("A helpful diary keeper, storing %u entries."), entry_count);
1078
1202
 
1079
1203
        gtk_show_about_dialog (GTK_WINDOW (main_window),
1080
1204
                                "version", VERSION,
1103
1227
{
1104
1228
        GDate current_date;
1105
1229
        g_date_set_time_t (&current_date, time (NULL));
1106
 
        almanah_main_window_select_date (main_window, &current_date);
1107
 
}
1108
 
 
1109
 
void
1110
 
mw_add_definition_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
1111
 
{
1112
 
        add_definition_to_current_entry (main_window);
1113
 
}
1114
 
 
1115
 
void
1116
 
mw_remove_definition_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
1117
 
{
1118
 
        remove_definition_from_current_entry (main_window);
1119
 
}
1120
 
 
1121
 
void
1122
 
mw_view_definitions_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
1123
 
{
1124
 
        if (almanah->definition_manager_window == NULL)
1125
 
                almanah->definition_manager_window = GTK_WIDGET (almanah_definition_manager_window_new ());
1126
 
 
1127
 
        gtk_widget_show_all (almanah->definition_manager_window);
 
1230
        almanah_calendar_button_select_date (main_window->priv->calendar_button, &current_date);
 
1231
}
 
1232
 
 
1233
void
 
1234
mw_old_entries_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
 
1235
{
 
1236
        // TODO: Show the old entries
 
1237
        g_debug ("Old entries clicked, but nothing implemented yet...");
 
1238
}
 
1239
 
 
1240
/**
 
1241
 * Just copied from GtkMenuToolButton (menu_position_func),
 
1242
 * but using the button widget (not the arrow widget) for
 
1243
 * menu position calc, and removing the code for a vertical
 
1244
 * toolbar situation.
 
1245
 *
 
1246
 * Copyright (C) 2003 Ricardo Fernandez Pascual
 
1247
 * Copyright (C) 2004 Paolo Borelli
 
1248
 * Licensed under the GPL v2
 
1249
 */
 
1250
static void
 
1251
mw_font_style_menu_position_func (GtkMenu *menu, int *x, int *y, gboolean *push_in, GtkMenuToolButton *button)
 
1252
{
 
1253
        GtkAllocation arrow_allocation;
 
1254
        GtkWidget *widget = GTK_WIDGET (button);
 
1255
        GtkRequisition menu_req;
 
1256
        GtkTextDirection direction;
 
1257
        GdkRectangle monitor;
 
1258
        gint monitor_num;
 
1259
        GdkScreen *screen;
 
1260
        GdkWindow *window;
 
1261
        GtkAllocation allocation;
 
1262
 
 
1263
        gtk_widget_get_preferred_size (GTK_WIDGET (menu), &menu_req, NULL);
 
1264
        direction = gtk_widget_get_direction (widget);
 
1265
        window = gtk_widget_get_window (widget);
 
1266
 
 
1267
        screen = gtk_widget_get_screen (GTK_WIDGET (menu));
 
1268
        monitor_num = gdk_screen_get_monitor_at_window (screen, window);
 
1269
        if (monitor_num < 0)
 
1270
                monitor_num = 0;
 
1271
        gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
 
1272
 
 
1273
        gtk_widget_get_allocation (widget, &allocation);
 
1274
 
 
1275
        gdk_window_get_origin (window, x, y);
 
1276
        *x += allocation.x;
 
1277
        *y += allocation.y;
 
1278
 
 
1279
        if (direction == GTK_TEXT_DIR_LTR)
 
1280
                *x += MAX (allocation.width - menu_req.width, 0);
 
1281
        else if (menu_req.width > allocation.width)
 
1282
                *x -= menu_req.width - allocation.width;
 
1283
 
 
1284
        if ((*y + arrow_allocation.height + menu_req.height) <= monitor.y + monitor.height)
 
1285
                *y += allocation.height;
 
1286
        else if ((*y - menu_req.height) >= monitor.y)
 
1287
                *y -= menu_req.height;
 
1288
        else if (monitor.y + monitor.height - (*y + arrow_allocation.height) > *y)
 
1289
                *y += allocation.height;
 
1290
        else
 
1291
                *y -= menu_req.height;
 
1292
 
 
1293
        *push_in = FALSE;
 
1294
}
 
1295
 
 
1296
void
 
1297
mw_font_style_activate_cb (AlmanahFontStyleMenuAction *action, AlmanahMainWindow *main_window)
 
1298
{
 
1299
        AlmanahMainWindowPrivate *priv = ALMANAH_MAIN_WINDOW_GET_PRIVATE(main_window);
 
1300
        GtkMenu *menu = NULL;
 
1301
 
 
1302
        if (GTK_IS_MENU_TOOL_BUTTON (priv->font_style_tool_button)) {
 
1303
                menu = GTK_MENU (gtk_menu_tool_button_get_menu (priv->font_style_tool_button));
 
1304
        }
 
1305
 
 
1306
        if (GTK_IS_MENU (menu)) {
 
1307
                gtk_menu_popup (menu, NULL, NULL,
 
1308
                                (GtkMenuPositionFunc) mw_font_style_menu_position_func,
 
1309
                                priv->font_style_tool_button,
 
1310
                                0,
 
1311
                                gtk_get_current_event_time());
 
1312
        }
 
1313
}
 
1314
 
 
1315
static GtkMenuToolButton *
 
1316
mw_get_font_style_tool_button_from_action (GtkAction *action)
 
1317
{
 
1318
        GSList *proxies;
 
1319
        GtkMenuToolButton *tool_button = NULL;
 
1320
 
 
1321
        proxies = gtk_action_get_proxies (GTK_ACTION (action));
 
1322
        while (proxies != NULL) {
 
1323
                if (GTK_IS_MENU_TOOL_BUTTON (proxies->data)) {
 
1324
                        tool_button = GTK_MENU_TOOL_BUTTON (proxies->data);
 
1325
                }
 
1326
 
 
1327
                proxies = proxies->next;
 
1328
        }
 
1329
 
 
1330
        return tool_button;
1128
1331
}
1129
1332
 
1130
1333
static void
1133
1336
        GtkTreeIter iter;
1134
1337
        GtkTreeModel *model = GTK_TREE_MODEL (self->priv->event_store);
1135
1338
 
1136
 
        if (almanah->debug == TRUE)
1137
 
                g_debug ("Removing events belonging to factory %u from the list store...", type_id);
 
1339
        g_debug ("Removing events belonging to factory %u from the list store...", type_id);
1138
1340
 
1139
1341
        if (gtk_tree_model_get_iter_first (model, &iter) == FALSE)
1140
1342
                return;
1145
1347
                gtk_tree_model_get (model, &iter, 2, &row_type_id, -1);
1146
1348
 
1147
1349
                if (row_type_id == type_id) {
1148
 
                        if (almanah->debug == TRUE) {
1149
 
                                AlmanahEvent *event;
1150
 
                                gtk_tree_model_get (model, &iter, 0, &event, -1);
1151
 
                                g_debug ("\t%s", almanah_event_format_value (event));
1152
 
                        }
 
1350
                        AlmanahEvent *event;
 
1351
                        gtk_tree_model_get (model, &iter, 0, &event, -1);
 
1352
                        g_debug ("\t%s", almanah_event_format_value (event));
1153
1353
 
1154
1354
                        if (gtk_list_store_remove (GTK_LIST_STORE (model), &iter) == FALSE)
1155
1355
                                break;
1159
1359
                }
1160
1360
        }
1161
1361
 
1162
 
        if (almanah->debug == TRUE)
1163
 
                g_debug ("Finished removing events.");
 
1362
        g_debug ("Finished removing events.");
1164
1363
}
1165
1364
 
1166
1365
static void
1169
1368
        AlmanahMainWindowPrivate *priv = main_window->priv;
1170
1369
        GSList *_events, *events;
1171
1370
        GDate date;
 
1371
        guint events_count = 0;
 
1372
        gchar *events_text;
1172
1373
 
1173
 
        almanah_calendar_get_date (main_window->priv->calendar, &date);
 
1374
        almanah_calendar_button_get_date (main_window->priv->calendar_button, &date);
1174
1375
        _events = almanah_event_manager_get_events (event_manager, type_id, &date);
1175
1376
 
1176
1377
        /* Clear all the events generated by this factory out of the list store first */
1177
1378
        clear_factory_events (main_window, type_id);
1178
1379
 
1179
 
        if (almanah->debug == TRUE)
1180
 
                g_debug ("Adding events from factory %u to the list store...", type_id);
 
1380
        g_debug ("Adding events from factory %u to the list store...", type_id);
1181
1381
 
1182
1382
        for (events = _events; events != NULL; events = g_slist_next (events)) {
1183
1383
                GtkTreeIter iter;
1184
1384
                AlmanahEvent *event = events->data;
1185
1385
 
1186
 
                if (almanah->debug == TRUE)
1187
 
                        g_debug ("\t%s", almanah_event_format_value (event));
 
1386
                g_debug ("\t%s", almanah_event_format_value (event));
1188
1387
 
1189
1388
                gtk_list_store_append (priv->event_store, &iter);
1190
1389
                gtk_list_store_set (priv->event_store, &iter,
1191
1390
                                    0, event,
1192
1391
                                    1, almanah_event_get_icon_name (event),
1193
1392
                                    2, type_id,
 
1393
                                    3, almanah_event_format_value (event),
 
1394
                                    4, g_strdup_printf ("<small>%s @ %s</small>", almanah_event_format_time (event), almanah_event_get_name (event)),
1194
1395
                                    -1);
1195
1396
 
 
1397
                events_count++;
 
1398
 
1196
1399
                g_object_unref (event);
1197
1400
        }
1198
1401
 
1199
 
        if (almanah->debug == TRUE)
1200
 
                g_debug ("Finished adding events.");
 
1402
        events_text = g_strdup_printf ("%u", events_count);
 
1403
        gtk_label_set_label (priv->events_count_label, events_text);
 
1404
        g_free (events_text);
 
1405
 
 
1406
        if (events_count > 0) {
 
1407
                gtk_widget_set_sensitive (priv->events_expander, TRUE);
 
1408
        } else {
 
1409
                gtk_expander_set_expanded (GTK_EXPANDER (priv->events_expander), FALSE);
 
1410
                gtk_widget_set_sensitive (priv->events_expander, FALSE);
 
1411
        }
 
1412
 
 
1413
        g_debug ("Finished adding events.");
1201
1414
 
1202
1415
        g_slist_free (_events);
1203
1416
}
1204
1417
 
1205
1418
void
1206
 
mw_calendar_day_selected_cb (GtkCalendar *calendar, AlmanahMainWindow *main_window)
 
1419
mw_calendar_day_selected_cb (AlmanahCalendarButton *calendar_button, AlmanahMainWindow *main_window)
1207
1420
{
 
1421
        AlmanahApplication *application;
 
1422
        AlmanahStorageManager *storage_manager;
 
1423
        AlmanahEventManager *event_manager;
1208
1424
        GDate calendar_date;
1209
 
        gchar calendar_string[100];
1210
1425
#ifdef ENABLE_SPELL_CHECKING
1211
1426
        GtkSpell *gtkspell;
1212
1427
#endif /* ENABLE_SPELL_CHECKING */
1213
1428
        AlmanahMainWindowPrivate *priv = main_window->priv;
1214
1429
        AlmanahEntry *entry;
1215
1430
 
 
1431
        /* Set up */
 
1432
        application = ALMANAH_APPLICATION (gtk_window_get_application (GTK_WINDOW (main_window)));
 
1433
 
1216
1434
        /* Save the previous entry */
1217
 
        save_current_entry (main_window);
 
1435
        save_current_entry (main_window, TRUE);
1218
1436
 
1219
1437
        /* Update the date label */
1220
 
        almanah_calendar_get_date (main_window->priv->calendar, &calendar_date);
1221
 
 
1222
 
        /* Translators: This is a strftime()-format string for the date displayed at the top of the main window. */
1223
 
        g_date_strftime (calendar_string, sizeof (calendar_string), _("%A, %e %B %Y"), &calendar_date);
1224
 
        gtk_label_set_markup (priv->date_label, calendar_string);
 
1438
        almanah_calendar_button_get_date (main_window->priv->calendar_button, &calendar_date);
1225
1439
 
1226
1440
        /* Update the entry */
1227
 
        entry = almanah_storage_manager_get_entry (almanah->storage_manager, &calendar_date);
 
1441
        storage_manager = almanah_application_dup_storage_manager (application);
 
1442
        entry = almanah_storage_manager_get_entry (storage_manager, &calendar_date);
 
1443
        g_object_unref (storage_manager);
 
1444
 
1228
1445
        if (entry == NULL)
1229
1446
                entry = almanah_entry_new (&calendar_date);
1230
1447
        set_current_entry (main_window, entry);
1236
1453
 
1237
1454
        /* Prepare for the possibility of failure --- do as much of the general interface changes as possible first */
1238
1455
        gtk_list_store_clear (priv->event_store);
1239
 
        gtk_action_set_sensitive (priv->add_action, FALSE);
1240
 
        gtk_action_set_sensitive (priv->remove_action, FALSE); /* Only sensitive if something's selected */
1241
 
        gtk_widget_set_sensitive (GTK_WIDGET (priv->view_button), FALSE);
1242
1456
 
1243
1457
        if (almanah_entry_is_empty (priv->current_entry) == FALSE) {
1244
1458
                GError *error = NULL;
1245
1459
 
1246
1460
                gtk_text_buffer_set_text (priv->entry_buffer, "", 0);
1247
1461
                if (almanah_entry_get_content (priv->current_entry, priv->entry_buffer, FALSE, &error) == FALSE) {
1248
 
                        GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW (almanah->main_window),
 
1462
                        GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW (main_window),
1249
1463
                                                                    GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
1250
1464
                                                                    _("Entry content could not be loaded"));
1251
1465
                        gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", error->message);
1277
1491
        gtk_text_buffer_set_modified (priv->entry_buffer, FALSE);
1278
1492
 
1279
1493
        /* List the entry's events */
1280
 
        almanah_event_manager_query_events (almanah->event_manager, ALMANAH_EVENT_FACTORY_UNKNOWN, &calendar_date);
1281
 
}
1282
 
 
1283
 
static void
1284
 
mw_events_selection_changed_cb (GtkTreeSelection *tree_selection, AlmanahMainWindow *main_window)
1285
 
{
1286
 
        AlmanahMainWindowPrivate *priv = main_window->priv;
1287
 
        gtk_widget_set_sensitive (GTK_WIDGET (priv->view_button), (gtk_tree_selection_count_selected_rows (tree_selection) == 0) ? FALSE : TRUE);
1288
 
}
1289
 
 
1290
 
static void
1291
 
mw_events_value_data_cb (GtkTreeViewColumn *column, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
1292
 
{
1293
 
        const gchar *new_value;
1294
 
        AlmanahEvent *event;
1295
 
 
1296
 
        /* TODO: Should really create a new model to render AlmanahEvents */
1297
 
 
1298
 
        gtk_tree_model_get (model, iter,
1299
 
                            0, &event,
1300
 
                            -1);
1301
 
 
1302
 
        new_value = almanah_event_format_value (event);
1303
 
        g_object_set (renderer, "text", new_value, NULL);
 
1494
        event_manager = almanah_application_dup_event_manager (application);
 
1495
        almanah_event_manager_query_events (event_manager, ALMANAH_EVENT_FACTORY_UNKNOWN, &calendar_date);
 
1496
        g_object_unref (event_manager);
1304
1497
}
1305
1498
 
1306
1499
void
1315
1508
                            -1);
1316
1509
 
1317
1510
        /* NOTE: event types should display their own errors, so one won't be displayed here. */
1318
 
        almanah_event_view (event);
1319
 
}
1320
 
 
1321
 
void
1322
 
mw_view_button_clicked_cb (GtkButton *button, AlmanahMainWindow *main_window)
1323
 
{
1324
 
        GList *events;
1325
 
        GtkTreeModel *model;
1326
 
 
1327
 
        events = gtk_tree_selection_get_selected_rows (main_window->priv->events_selection, &model);
1328
 
 
1329
 
        for (; events != NULL; events = events->next) {
1330
 
                AlmanahEvent *event;
1331
 
                GtkTreeIter iter;
1332
 
 
1333
 
                gtk_tree_model_get_iter (model, &iter, (GtkTreePath*) events->data);
1334
 
                gtk_tree_model_get (model, &iter,
1335
 
                                    0, &event,
1336
 
                                    -1);
1337
 
 
1338
 
                /* NOTE: event types should display their own errors, so one won't be displayed here. */
1339
 
                almanah_event_view (event);
1340
 
 
1341
 
                gtk_tree_path_free (events->data);
1342
 
        }
1343
 
 
1344
 
        g_list_free (events);
 
1511
        almanah_event_view (event, GTK_WINDOW (main_window));
1345
1512
}
1346
1513
 
1347
1514
static void
1348
 
mw_definition_removed_cb (AlmanahStorageManager *storage_manager, const gchar *definition_text, AlmanahMainWindow *main_window)
 
1515
mw_setup_toolbar (AlmanahMainWindow *main_window, AlmanahApplication *application, GtkToolbar *toolbar, GtkAction *today_action)
1349
1516
{
1350
 
        /* We need to remove any definition tags in the current entry which match @definition_text. It's
1351
 
         * probably easier to just reload the current entry, though. */
1352
 
        mw_calendar_day_selected_cb (GTK_CALENDAR (main_window->priv->calendar), main_window);
 
1517
        GtkToolItem *calendar_button_item, *separator;
 
1518
        AlmanahStorageManager *storage_manager;
 
1519
 
 
1520
        /* Insert a dynamic space between the text style and calendar & important.
 
1521
         * This can't be done using the <separator/> in the UI file at the moment
 
1522
         */
 
1523
        separator = gtk_separator_tool_item_new ();
 
1524
        gtk_separator_tool_item_set_draw (GTK_SEPARATOR_TOOL_ITEM (separator), FALSE);
 
1525
        gtk_tool_item_set_expand (separator, TRUE);
 
1526
        gtk_toolbar_insert (toolbar, separator, 2);
 
1527
 
 
1528
        /* Setup the calendar button */
 
1529
        storage_manager = almanah_application_dup_storage_manager (application);
 
1530
        main_window->priv->calendar_button = ALMANAH_CALENDAR_BUTTON (almanah_calendar_button_new (storage_manager));
 
1531
        g_object_unref (storage_manager);
 
1532
        g_signal_connect (main_window->priv->calendar_button, "day-selected", G_CALLBACK (mw_calendar_day_selected_cb), main_window);
 
1533
        /* Use the same action for the today button in the dropdown window */
 
1534
        almanah_calendar_button_set_today_action (main_window->priv->calendar_button, today_action);
 
1535
 
 
1536
        /* Insert the calendar button into the toolbar through a GtkToolItem but button style */
 
1537
        calendar_button_item = gtk_tool_item_new ();
 
1538
        gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (calendar_button_item)), GTK_STYLE_CLASS_RAISED);
 
1539
        gtk_container_add (GTK_CONTAINER (calendar_button_item), GTK_WIDGET (main_window->priv->calendar_button));
 
1540
        gtk_toolbar_insert (toolbar, calendar_button_item, 3);
1353
1541
}
1354
1542
 
1355
1543
#ifdef ENABLE_SPELL_CHECKING
1358
1546
{
1359
1547
        gboolean enabled = g_settings_get_boolean (settings, "spell-checking-enabled");
1360
1548
 
1361
 
        if (almanah->debug)
1362
 
                g_debug ("spell_checking_enabled_changed_cb called with %u.", enabled);
 
1549
        g_debug ("spell_checking_enabled_changed_cb called with %u.", enabled);
1363
1550
 
1364
1551
        if (enabled == TRUE) {
1365
1552
                GError *error = NULL;
1384
1571
static gboolean
1385
1572
enable_spell_checking (AlmanahMainWindow *self, GError **error)
1386
1573
{
 
1574
        AlmanahApplication *application;
 
1575
        GSettings *settings;
1387
1576
        GtkSpell *gtkspell;
1388
1577
        gchar *spelling_language;
1389
1578
        GtkTextTagTable *table;
1400
1589
                gtk_text_tag_table_remove (table, tag);
1401
1590
 
1402
1591
        /* Get the spell checking language */
1403
 
        spelling_language = g_settings_get_string (almanah->settings, "spelling-language");
 
1592
        application = ALMANAH_APPLICATION (gtk_window_get_application (GTK_WINDOW (self)));
 
1593
        settings = almanah_application_dup_settings (application);
 
1594
        spelling_language = g_settings_get_string (settings, "spelling-language");
 
1595
        g_object_unref (settings);
1404
1596
 
1405
1597
        /* Make sure it's either NULL or a proper locale specifier */
1406
1598
        if (spelling_language != NULL && spelling_language[0] == '\0') {