~ubuntu-branches/ubuntu/lucid/almanah/lucid

« back to all changes in this revision

Viewing changes to src/main-window.c

  • Committer: Bazaar Package Importer
  • Author(s): Stefan Ebner
  • Date: 2008-07-04 15:07:43 UTC
  • Revision ID: james.westby@ubuntu.com-20080704150743-tgp3cljsjpolgv00
Tags: upstream-0.4.0
ImportĀ upstreamĀ versionĀ 0.4.0

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
 * Diary
 
4
 * Copyright (C) Philip Withnall 2008 <philip@tecnocode.co.uk>
 
5
 * 
 
6
 * Diary 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
 * Diary 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 Diary.  If not, see <http://www.gnu.org/licenses/>.
 
18
 */
 
19
 
 
20
#include <config.h>
 
21
#include <gtk/gtk.h>
 
22
#include <glib/gi18n.h>
 
23
#include <gtkspell/gtkspell.h>
 
24
 
 
25
#include "main.h"
 
26
#include "storage-manager.h"
 
27
#include "link.h"
 
28
#include "add-link-dialog.h"
 
29
#include "interface.h"
 
30
#include "main-window.h"
 
31
#include "printing.h"
 
32
 
 
33
static void save_current_entry ();
 
34
static void add_link_to_current_entry ();
 
35
static void remove_link_from_current_entry ();
 
36
 
 
37
void mw_calendar_day_selected_cb (GtkCalendar *calendar, gpointer user_data);
 
38
void mw_links_selection_changed_cb (GtkTreeSelection *tree_selection, gpointer user_data);
 
39
void mw_links_value_data_cb (GtkTreeViewColumn *column, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data);
 
40
 
 
41
static void
 
42
save_current_entry ()
 
43
{
 
44
        GtkTextIter start_iter, end_iter;
 
45
        gchar *entry_text;
 
46
        guint year, month, day;
 
47
 
 
48
        g_assert (diary->entry_buffer != NULL);
 
49
 
 
50
        /* Don't save if it hasn't been/can't be edited */
 
51
        if (gtk_text_view_get_editable (diary->entry_view) == FALSE ||
 
52
            gtk_text_buffer_get_modified (diary->entry_buffer) == FALSE)
 
53
                return;
 
54
 
 
55
        /* Save the entry */
 
56
        gtk_text_buffer_get_bounds (diary->entry_buffer, &start_iter, &end_iter);
 
57
        entry_text = gtk_text_buffer_get_text (diary->entry_buffer, &start_iter, &end_iter, FALSE);
 
58
 
 
59
        gtk_calendar_get_date (diary->calendar, &year, &month, &day);
 
60
        month++;
 
61
 
 
62
        /* Mark the day on the calendar if the entry was non-empty (and deleted)
 
63
         * and update the state of the add link button. */
 
64
        if (diary_storage_manager_set_entry (diary->storage_manager, year, month, day, entry_text) == FALSE) {
 
65
                gtk_calendar_unmark_day (diary->calendar, day);
 
66
 
 
67
                gtk_widget_set_sensitive (GTK_WIDGET (diary->add_button), FALSE);
 
68
                gtk_action_set_sensitive (diary->add_action, FALSE);
 
69
        } else {
 
70
                gtk_calendar_mark_day (diary->calendar, day);
 
71
 
 
72
                gtk_widget_set_sensitive (GTK_WIDGET (diary->add_button), TRUE);
 
73
                gtk_action_set_sensitive (diary->add_action, TRUE);
 
74
        }
 
75
 
 
76
        gtk_text_buffer_set_modified (diary->entry_buffer, FALSE);
 
77
        g_free (entry_text);
 
78
}
 
79
 
 
80
static void
 
81
add_link_to_current_entry ()
 
82
{
 
83
        guint year, month, day;
 
84
        GtkTreeIter iter;
 
85
        const DiaryLinkType *link_type;
 
86
        gchar *type;
 
87
        DiaryLink link;
 
88
 
 
89
        g_assert (diary->entry_buffer != NULL);
 
90
        g_assert (gtk_text_buffer_get_char_count (diary->entry_buffer) != 0);
 
91
 
 
92
        /* Ensure that something is selected and its widgets displayed */
 
93
        g_signal_emit_by_name (diary->ald_type_combo_box, "changed", NULL, NULL);
 
94
        gtk_widget_show_all (diary->add_link_dialog);
 
95
 
 
96
        if (gtk_dialog_run (GTK_DIALOG (diary->add_link_dialog)) == GTK_RESPONSE_OK) {
 
97
                if (gtk_combo_box_get_active_iter (diary->ald_type_combo_box, &iter) == FALSE)
 
98
                        return;
 
99
 
 
100
                /* Get the link type, then the values entered in the dialogue (specific to the type) */
 
101
                gtk_tree_model_get (GTK_TREE_MODEL (diary->ald_type_store), &iter, 1, &type, -1);
 
102
                link_type = diary_link_get_type (type);
 
103
                g_assert (link_type != NULL);
 
104
                link.type = type;
 
105
                link_type->get_values_func (&link);
 
106
 
 
107
                /* Add to the DB */
 
108
                gtk_calendar_get_date (diary->calendar, &year, &month, &day);
 
109
                month++;
 
110
                diary_storage_manager_add_entry_link (diary->storage_manager,
 
111
                                                      year, month, day,
 
112
                                                      type,
 
113
                                                      link.value,
 
114
                                                      link.value2);
 
115
 
 
116
                /* Add to the treeview */
 
117
                gtk_list_store_append (diary->links_store, &iter);
 
118
                gtk_list_store_set (diary->links_store, &iter,
 
119
                                    0, type,
 
120
                                    1, link.value,
 
121
                                    2, link.value2,
 
122
                                    3, link_type->icon_name,
 
123
                                    -1);
 
124
 
 
125
                g_free (type);
 
126
                g_free (link.value);
 
127
                g_free (link.value2);
 
128
        }
 
129
        diary_hide_ald ();
 
130
}
 
131
 
 
132
static void
 
133
remove_link_from_current_entry ()
 
134
{
 
135
        gchar *link_type;
 
136
        guint year, month, day;
 
137
        GtkTreeIter iter;
 
138
        GtkTreeModel *model;
 
139
        GList *links;
 
140
 
 
141
        g_assert (diary->entry_buffer != NULL);
 
142
        g_assert (gtk_text_buffer_get_char_count (diary->entry_buffer) != 0);
 
143
 
 
144
        links = gtk_tree_selection_get_selected_rows (diary->links_selection, &model);
 
145
        gtk_calendar_get_date (diary->calendar, &year, &month, &day);
 
146
        month++;
 
147
 
 
148
        for (; links != NULL; links = links->next) {
 
149
                gtk_tree_model_get_iter (model, &iter, (GtkTreePath*) links->data);
 
150
                gtk_tree_model_get (model, &iter, 0, &link_type, -1);
 
151
 
 
152
                /* Remove it from the DB */
 
153
                diary_storage_manager_remove_entry_link (diary->storage_manager, year, month, day, link_type);
 
154
 
 
155
                /* Remove it from the treeview */
 
156
                gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
 
157
 
 
158
                gtk_tree_path_free (links->data);
 
159
                g_free (link_type);
 
160
        }
 
161
        g_list_free (links);
 
162
}
 
163
 
 
164
void
 
165
diary_main_window_setup (GtkBuilder *builder)
 
166
{
 
167
        GError *error = NULL;
 
168
 
 
169
        /* Select the current day and month */
 
170
        diary_calendar_month_changed_cb (diary->calendar, NULL);
 
171
        mw_calendar_day_selected_cb (diary->calendar, NULL);
 
172
 
 
173
        /* Set up the treeview */
 
174
        g_signal_connect (diary->links_selection, "changed", (GCallback) mw_links_selection_changed_cb, NULL);
 
175
        gtk_tree_view_column_set_cell_data_func (diary->link_value_column, GTK_CELL_RENDERER (diary->link_value_renderer), mw_links_value_data_cb, NULL, NULL);
 
176
 
 
177
        if (gtkspell_new_attach (diary->entry_view, NULL, &error) == FALSE) {
 
178
                gchar *error_message = g_strdup_printf (_("The spelling checker could not be initialized: %s"), error->message);
 
179
                diary_interface_error (error_message, NULL);
 
180
                g_free (error_message);
 
181
        }
 
182
}
 
183
 
 
184
void
 
185
mw_select_date (GDate *date)
 
186
{
 
187
        gtk_calendar_select_month (diary->calendar, g_date_get_month (date) - 1, g_date_get_year (date));
 
188
        gtk_calendar_select_day (diary->calendar, g_date_get_day (date));
 
189
}
 
190
 
 
191
gboolean
 
192
mw_delete_event_cb (GtkWindow *window, gpointer user_data)
 
193
{
 
194
        save_current_entry ();
 
195
        diary_quit ();
 
196
 
 
197
        return TRUE;
 
198
}
 
199
 
 
200
void
 
201
mw_print_activate_cb (GtkAction *action, gpointer user_data)
 
202
{
 
203
        diary_print_entries ();
 
204
}
 
205
 
 
206
void
 
207
mw_quit_activate_cb (GtkAction *action, gpointer user_data)
 
208
{
 
209
        save_current_entry ();
 
210
        diary_quit ();
 
211
}
 
212
 
 
213
void
 
214
mw_cut_activate_cb (GtkAction *action, gpointer user_data)
 
215
{
 
216
        GtkClipboard *clipboard = gtk_clipboard_get_for_display (gtk_widget_get_display (GTK_WIDGET (diary->main_window)), GDK_SELECTION_CLIPBOARD);
 
217
        gtk_text_buffer_cut_clipboard (diary->entry_buffer, clipboard, TRUE);
 
218
}
 
219
 
 
220
void
 
221
mw_copy_activate_cb (GtkAction *action, gpointer user_data)
 
222
{
 
223
        GtkClipboard *clipboard = gtk_clipboard_get_for_display (gtk_widget_get_display (GTK_WIDGET (diary->main_window)), GDK_SELECTION_CLIPBOARD);
 
224
        gtk_text_buffer_copy_clipboard (diary->entry_buffer, clipboard);
 
225
}
 
226
 
 
227
void
 
228
mw_paste_activate_cb (GtkAction *action, gpointer user_data)
 
229
{
 
230
        GtkClipboard *clipboard = gtk_clipboard_get_for_display (gtk_widget_get_display (GTK_WIDGET (diary->main_window)), GDK_SELECTION_CLIPBOARD);
 
231
        gtk_text_buffer_paste_clipboard (diary->entry_buffer, clipboard, NULL, TRUE);
 
232
}
 
233
 
 
234
void
 
235
mw_delete_activate_cb (GtkAction *action, gpointer user_data)
 
236
{
 
237
        gtk_text_buffer_delete_selection (diary->entry_buffer, TRUE, TRUE);
 
238
}
 
239
 
 
240
void
 
241
mw_search_activate_cb (GtkAction *action, gpointer user_data)
 
242
{
 
243
        /* Ensure everything's tidy first */
 
244
        gtk_list_store_clear (diary->sd_results_store);
 
245
        gtk_entry_set_text (diary->sd_search_entry, "");
 
246
 
 
247
        /* Run the dialogue */
 
248
        gtk_widget_show_all (diary->search_dialog);
 
249
        gtk_dialog_run (GTK_DIALOG (diary->search_dialog));
 
250
        gtk_widget_hide_all (diary->search_dialog);
 
251
}
 
252
 
 
253
void
 
254
mw_about_activate_cb (GtkAction *action, gpointer user_data)
 
255
{
 
256
        gchar *license, *description;
 
257
        guint entry_count, link_count, character_count;
 
258
 
 
259
        const gchar *authors[] =
 
260
        {
 
261
                "Philip Withnall <philip@tecnocode.co.uk>",
 
262
                NULL
 
263
        };
 
264
        const gchar *license_parts[] = {
 
265
                N_("Diary is free software: you can redistribute it and/or modify "
 
266
                   "it under the terms of the GNU General Public License as published by "
 
267
                   "the Free Software Foundation, either version 3 of the License, or "
 
268
                   "(at your option) any later version."),
 
269
                N_("Diary is distributed in the hope that it will be useful, "
 
270
                   "but WITHOUT ANY WARRANTY; without even the implied warranty of "
 
271
                   "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the "
 
272
                   "GNU General Public License for more details."),
 
273
                N_("You should have received a copy of the GNU General Public License "
 
274
                   "along with Diary.  If not, see <http://www.gnu.org/licenses/>."),
 
275
        };
 
276
 
 
277
        license = g_strjoin ("\n\n",
 
278
                          _(license_parts[0]),
 
279
                          _(license_parts[1]),
 
280
                          _(license_parts[2]),
 
281
                          NULL);
 
282
 
 
283
        diary_storage_manager_get_statistics (diary->storage_manager, &entry_count, &link_count, &character_count);
 
284
        description = g_strdup_printf (_("A helpful diary keeper, storing %u entries with %u links and a total of %u characters."),
 
285
                                      entry_count,
 
286
                                      link_count,
 
287
                                      character_count);
 
288
 
 
289
        gtk_show_about_dialog (GTK_WINDOW (diary->main_window),
 
290
                                "version", VERSION,
 
291
                                "copyright", _("Copyright \xc2\xa9 2008 Philip Withnall"),
 
292
                                "comments", description,
 
293
                                "authors", authors,
 
294
                                /* Translators: please include your names here to be credited for your hard work!
 
295
                                 * Format:
 
296
                                 * "Translator name 1 <translator@email.address>\n"
 
297
                                 * "Translator name 2 <translator2@email.address>"
 
298
                                 */
 
299
                                "translator-credits", _("translator-credits"),
 
300
                                "logo-icon-name", "diary",
 
301
                                "license", license,
 
302
                                "wrap-license", TRUE,
 
303
                                "website-label", _("Diary Website"),
 
304
                                "website", "http://tecnocode.co.uk/projects/diary",
 
305
                                NULL);
 
306
 
 
307
        g_free (license);
 
308
        g_free (description);
 
309
}
 
310
 
 
311
void
 
312
mw_jump_to_today_activate_cb (GtkAction *action, gpointer user_data)
 
313
{
 
314
        GDate current_date;
 
315
        g_date_set_time_t (&current_date, time (NULL));
 
316
        mw_select_date (&current_date);
 
317
}
 
318
 
 
319
void
 
320
mw_add_link_activate_cb (GtkAction *action, gpointer user_data)
 
321
{
 
322
        add_link_to_current_entry ();
 
323
}
 
324
 
 
325
void
 
326
mw_remove_link_activate_cb (GtkAction *action, gpointer user_data)
 
327
{
 
328
        remove_link_from_current_entry ();
 
329
}
 
330
 
 
331
void
 
332
mw_calendar_day_selected_cb (GtkCalendar *calendar, gpointer user_data)
 
333
{
 
334
        GDate calendar_date;
 
335
        gchar calendar_string[100], *entry_text;
 
336
        guint year, month, day;
 
337
        DiaryLink **links;
 
338
        guint i;
 
339
        GtkTreeIter iter;
 
340
        const DiaryLinkType *link_type;
 
341
 
 
342
        /* Update the date label */
 
343
        gtk_calendar_get_date (calendar, &year, &month, &day);
 
344
        month++;
 
345
        g_date_set_dmy (&calendar_date, day, month, year);
 
346
 
 
347
        /* Translators: This is a strftime()-format string for the date displayed at the top of the main window. */
 
348
        g_date_strftime (calendar_string, sizeof (calendar_string), _("%A, %e %B %Y"), &calendar_date);
 
349
        gtk_label_set_markup (diary->date_label, calendar_string);
 
350
        diary_interface_embolden_label (diary->date_label);
 
351
 
 
352
        /* Update the entry */
 
353
        entry_text = diary_storage_manager_get_entry (diary->storage_manager, year, month, day);
 
354
        gtk_text_view_set_editable (diary->entry_view, diary_storage_manager_entry_is_editable (diary->storage_manager, year, month, day));
 
355
        gtk_text_buffer_set_modified (diary->entry_buffer, FALSE);
 
356
 
 
357
        if (entry_text != NULL) {
 
358
                gtk_text_buffer_set_text (diary->entry_buffer, entry_text, -1);
 
359
                gtk_widget_set_sensitive (GTK_WIDGET (diary->add_button), TRUE);
 
360
                gtk_action_set_sensitive (diary->add_action, TRUE);
 
361
        } else {
 
362
                gtk_text_buffer_set_text (diary->entry_buffer, "", -1);
 
363
                gtk_widget_set_sensitive (GTK_WIDGET (diary->add_button), FALSE);
 
364
                gtk_action_set_sensitive (diary->add_action, FALSE);
 
365
        }
 
366
        gtk_widget_set_sensitive (GTK_WIDGET (diary->remove_button), FALSE); /* Only sensitive if something's selected */
 
367
        gtk_action_set_sensitive (diary->remove_action, FALSE);
 
368
        gtk_widget_set_sensitive (GTK_WIDGET (diary->view_button), FALSE);
 
369
 
 
370
        g_free (entry_text);
 
371
 
 
372
        /* List the entry's links */
 
373
        gtk_list_store_clear (diary->links_store);
 
374
        links = diary_storage_manager_get_entry_links (diary->storage_manager, year, month, day);
 
375
 
 
376
        i = 0;
 
377
        while (links[i] != NULL) {
 
378
                link_type = diary_link_get_type (links[i]->type);
 
379
 
 
380
                if (link_type != NULL) {
 
381
                        gtk_list_store_append (diary->links_store, &iter);
 
382
                        gtk_list_store_set (diary->links_store, &iter,
 
383
                                            0, links[i]->type,
 
384
                                            1, links[i]->value,
 
385
                                            2, links[i]->value2,
 
386
                                            3, link_type->icon_name,
 
387
                                            -1);
 
388
                }
 
389
 
 
390
                g_free (links[i]->type);
 
391
                g_free (links[i]->value);
 
392
                g_free (links[i]->value2);
 
393
                g_slice_free (DiaryLink, links[i]);
 
394
 
 
395
                i++;
 
396
        }
 
397
 
 
398
        g_free (links);
 
399
}
 
400
 
 
401
void
 
402
mw_links_selection_changed_cb (GtkTreeSelection *tree_selection, gpointer user_data)
 
403
{
 
404
        if (gtk_tree_selection_count_selected_rows (tree_selection) == 0) {
 
405
                gtk_widget_set_sensitive (GTK_WIDGET (diary->remove_button), FALSE);
 
406
                gtk_widget_set_sensitive (GTK_WIDGET (diary->view_button), FALSE);
 
407
                gtk_action_set_sensitive (diary->remove_action, FALSE);
 
408
        } else {
 
409
                gtk_widget_set_sensitive (GTK_WIDGET (diary->remove_button), TRUE);
 
410
                gtk_widget_set_sensitive (GTK_WIDGET (diary->view_button), TRUE);
 
411
                gtk_action_set_sensitive (diary->remove_action, TRUE);
 
412
        }
 
413
}
 
414
 
 
415
void
 
416
mw_links_value_data_cb (GtkTreeViewColumn *column, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
 
417
{
 
418
        gchar *new_value;
 
419
        DiaryLink link;
 
420
 
 
421
        gtk_tree_model_get (model, iter, 0, &(link.type), 1, &(link.value), 2, &(link.value2), -1);
 
422
 
 
423
        new_value = diary_link_format_value (&link);
 
424
        g_object_set (renderer, "text", new_value, NULL);
 
425
        g_free (new_value);
 
426
 
 
427
        g_free (link.type);
 
428
        g_free (link.value);
 
429
        g_free (link.value2);
 
430
}
 
431
 
 
432
void
 
433
mw_links_tree_view_row_activated_cb (GtkTreeView *tree_view, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data)
 
434
{
 
435
        DiaryLink link;
 
436
        GtkTreeIter iter;
 
437
 
 
438
        gtk_tree_model_get_iter (GTK_TREE_MODEL (diary->links_store), &iter, path);
 
439
        gtk_tree_model_get (GTK_TREE_MODEL (diary->links_store), &iter, 0, &(link.type), 1, &(link.value), 2, &(link.value2), -1);
 
440
 
 
441
        /* NOTE: Link types should display their own errors, so one won't be displayed here. */
 
442
        diary_link_view (&link);
 
443
 
 
444
        g_free (link.type);
 
445
        g_free (link.value);
 
446
        g_free (link.value2);
 
447
}
 
448
 
 
449
gboolean
 
450
mw_entry_view_focus_out_event_cb (GtkWidget *entry_view, GdkEventFocus *event, gpointer user_data)
 
451
{
 
452
        save_current_entry ();
 
453
        return FALSE;
 
454
}
 
455
 
 
456
void
 
457
mw_add_button_clicked_cb (GtkButton *button, gpointer user_data)
 
458
{
 
459
        add_link_to_current_entry ();
 
460
}
 
461
 
 
462
void
 
463
mw_remove_button_clicked_cb (GtkButton *button, gpointer user_data)
 
464
{
 
465
        remove_link_from_current_entry ();
 
466
}
 
467
 
 
468
void
 
469
mw_view_button_clicked_cb (GtkButton *button, gpointer user_data)
 
470
{
 
471
        DiaryLink link;
 
472
        GtkTreeIter iter;
 
473
        GList *links;
 
474
        GtkTreeModel *model;
 
475
 
 
476
        links = gtk_tree_selection_get_selected_rows (diary->links_selection, &model);
 
477
 
 
478
        for (; links != NULL; links = links->next) {
 
479
                gtk_tree_model_get_iter (model, &iter, (GtkTreePath*) links->data);
 
480
                gtk_tree_model_get (model, &iter, 0, &(link.type), 1, &(link.value), 2, &(link.value2), -1);
 
481
 
 
482
                /* NOTE: Link types should display their own errors, so one won't be displayed here. */
 
483
                diary_link_view (&link);
 
484
 
 
485
                g_free (link.type);
 
486
                g_free (link.value);
 
487
                g_free (link.value2);
 
488
 
 
489
                gtk_tree_path_free (links->data);
 
490
        }
 
491
        g_list_free (links);
 
492
}