~ubuntu-branches/ubuntu/trusty/gnome-utils/trusty

« back to all changes in this revision

Viewing changes to .pc/04_lpi.patch/logview/logview-window.c

  • Committer: Package Import Robot
  • Author(s): Sebastien Bacher
  • Date: 2012-03-21 21:13:36 UTC
  • Revision ID: package-import@ubuntu.com-20120321211336-3joprtdk2evtqf1j
Tags: 3.2.1-0ubuntu6
Dropped other binaries which have their sources, keep the transitional
dummy gnome-utils for the lts though

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
2
 
/* logview-window.c - main window of logview
3
 
 *
4
 
 * Copyright (C) 1998  Cesar Miquel  <miquel@df.uba.ar>
5
 
 * Copyright (C) 2008  Cosimo Cecchi <cosimoc@gnome.org>
6
 
 *
7
 
 * This program is free software; you can redistribute it and/or modify
8
 
 * it under the terms of the GNU General Public License as published by
9
 
 * the Free Software Foundation; either version 2 of the License, or
10
 
 * (at your option) any later version.
11
 
 *
12
 
 * This program is distributed in the hope that it will be useful,
13
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 
 * GNU General Public License for more details.
16
 
 *
17
 
 * You should have received a copy of the GNU General Public License
18
 
 * along with this program; if not, write to the Free Software
19
 
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
 
 */
21
 
 
22
 
#include <config.h>
23
 
#include <stdlib.h>
24
 
#include <string.h>
25
 
#include <gtk/gtk.h>
26
 
#include <gdk/gdkkeysyms.h>
27
 
#include <glib/gi18n.h>
28
 
 
29
 
#include "logview-window.h"
30
 
 
31
 
#include "logview-loglist.h"
32
 
#include "logview-findbar.h"
33
 
#include "logview-about.h"
34
 
#include "logview-prefs.h"
35
 
#include "logview-manager.h"
36
 
#include "logview-filter-manager.h"
37
 
 
38
 
#define APP_NAME _("System Log Viewer")
39
 
#define SEARCH_START_MARK "lw-search-start-mark"
40
 
#define SEARCH_END_MARK "lw-search-end-mark"
41
 
 
42
 
struct _LogviewWindowPrivate {
43
 
  GtkUIManager *ui_manager;
44
 
  GtkActionGroup *action_group;
45
 
  GtkActionGroup *filter_action_group;
46
 
 
47
 
  GtkWidget *find_bar;
48
 
  GtkWidget *loglist;
49
 
  GtkWidget *sidebar; 
50
 
  GtkWidget *version_bar;
51
 
  GtkWidget *version_selector;
52
 
  GtkWidget *hpaned;
53
 
  GtkWidget *text_view;
54
 
  GtkWidget *statusbar;
55
 
 
56
 
  GtkWidget *message_area;
57
 
  GtkWidget *message_primary;
58
 
  GtkWidget *message_secondary;
59
 
 
60
 
  GtkTextTagTable *tag_table;
61
 
 
62
 
  int original_fontsize, fontsize;
63
 
 
64
 
  LogviewPrefs *prefs;
65
 
  LogviewManager *manager;
66
 
 
67
 
  gulong monitor_id;
68
 
  guint search_timeout_id;
69
 
 
70
 
  guint filter_merge_id;
71
 
  GList *active_filters;
72
 
  gboolean matches_only;
73
 
  gboolean auto_scroll;
74
 
};
75
 
 
76
 
#define GET_PRIVATE(o) \
77
 
  (G_TYPE_INSTANCE_GET_PRIVATE ((o), LOGVIEW_TYPE_WINDOW, LogviewWindowPrivate))
78
 
 
79
 
G_DEFINE_TYPE (LogviewWindow, logview_window, GTK_TYPE_WINDOW);
80
 
 
81
 
static void findbar_close_cb  (LogviewFindbar *findbar,
82
 
                               gpointer user_data);
83
 
static void read_new_lines_cb (LogviewLog *log,
84
 
                               const char **lines,
85
 
                               GSList *new_days,
86
 
                               GError *error,
87
 
                               gpointer user_data);
88
 
 
89
 
/* private functions */
90
 
 
91
 
static void
92
 
logview_version_selector_changed (GtkComboBox *version_selector, gpointer user_data)
93
 
{
94
 
 
95
 
}
96
 
#if 0
97
 
        LogviewWindow *logview = user_data;
98
 
        Log *log = logview->curlog;
99
 
        int selected;
100
 
 
101
 
    g_assert (LOGVIEW_IS_WINDOW (logview));
102
 
 
103
 
        selected = gtk_combo_box_get_active (version_selector);
104
 
 
105
 
        if (selected == log->current_version)
106
 
                return;
107
 
 
108
 
        /* select a new version */
109
 
        if (selected == 0) {
110
 
                logview_select_log (logview, log->parent_log);
111
 
        } else {
112
 
                Log *new;
113
 
                if (log->parent_log) {
114
 
                        new = log->parent_log->older_logs[selected];
115
 
                } else {
116
 
                        new = log->older_logs[selected];
117
 
                }
118
 
 
119
 
                logview_select_log (logview, new);
120
 
        }
121
 
}
122
 
 
123
 
#endif
124
 
 
125
 
/* private helpers */
126
 
 
127
 
static void
128
 
populate_tag_table (GtkTextTagTable *tag_table)
129
 
{
130
 
  GtkTextTag *tag;
131
 
  
132
 
  tag = gtk_text_tag_new ("bold");
133
 
  g_object_set (tag, "weight", PANGO_WEIGHT_BOLD,
134
 
                "weight-set", TRUE, NULL);
135
 
 
136
 
  gtk_text_tag_table_add (tag_table, tag);
137
 
 
138
 
  tag = gtk_text_tag_new ("invisible");
139
 
  g_object_set (tag, "invisible", TRUE, "invisible-set", TRUE, NULL);
140
 
  gtk_text_tag_table_add (tag_table, tag);
141
 
 
142
 
  tag = gtk_text_tag_new ("invisible-filter");
143
 
  g_object_set (tag, "invisible", TRUE, "invisible-set", TRUE, NULL);
144
 
  gtk_text_tag_table_add (tag_table, tag); 
145
 
}
146
 
 
147
 
 
148
 
static void
149
 
populate_style_tag_table (GtkStyle *style,
150
 
                          GtkTextTagTable *tag_table)
151
 
{
152
 
  GtkTextTag *tag;
153
 
  GdkColor color;
154
 
 
155
 
  tag = gtk_text_tag_table_lookup (tag_table, "gray");
156
 
 
157
 
  if (tag) {
158
 
    /* FIXME: do we need a way to update the buffer/view? */
159
 
    gtk_text_tag_table_remove (tag_table, tag);
160
 
  }
161
 
 
162
 
  tag = gtk_text_tag_new ("gray");
163
 
  color = style->text[GTK_STATE_INSENSITIVE];
164
 
  g_object_set (tag, "foreground-gdk", &color, "foreground-set", TRUE, NULL);
165
 
 
166
 
  gtk_text_tag_table_add (tag_table, tag);
167
 
}
168
 
 
169
 
static void
170
 
_gtk_text_buffer_apply_tag_to_rectangle (GtkTextBuffer *buffer, int line_start, int line_end,
171
 
                                        int offset_start, int offset_end, char *tag_name)
172
 
{
173
 
  GtkTextIter start, end;
174
 
  int line_cur;
175
 
 
176
 
  gtk_text_buffer_get_iter_at_line (buffer, &start, line_start);
177
 
  gtk_text_buffer_get_iter_at_line (buffer, &end, line_start);
178
 
 
179
 
  for (line_cur = line_start; line_cur < line_end + 1; line_cur++) {
180
 
 
181
 
    if (offset_start > 0) {
182
 
      gtk_text_iter_forward_chars (&start, offset_start);
183
 
    }
184
 
 
185
 
    gtk_text_iter_forward_chars (&end, offset_end);
186
 
 
187
 
    gtk_text_buffer_apply_tag_by_name (buffer, tag_name, &start, &end);
188
 
 
189
 
    gtk_text_iter_forward_line (&start);
190
 
    gtk_text_iter_forward_line (&end);
191
 
  }
192
 
}
193
 
 
194
 
static void
195
 
logview_update_statusbar (LogviewWindow *logview, LogviewLog *active)
196
 
{
197
 
  char *statusbar_text;
198
 
  char *size, *modified, *timestring_utf8;
199
 
  time_t timestamp;
200
 
  char timestring[255];
201
 
 
202
 
  if (active == NULL) {
203
 
    gtk_statusbar_pop (GTK_STATUSBAR (logview->priv->statusbar), 0);
204
 
    return;
205
 
  }
206
 
 
207
 
  timestamp = logview_log_get_timestamp (active);
208
 
  strftime (timestring, sizeof (timestring), "%a %b %e %T %Y", localtime (&timestamp));
209
 
  timestring_utf8 = g_locale_to_utf8 (timestring, -1, NULL, NULL, NULL);
210
 
 
211
 
  modified = g_strdup_printf (_("last update: %s"), timestring_utf8);
212
 
 
213
 
  size = g_format_size_for_display (logview_log_get_file_size (active));
214
 
  statusbar_text = g_strdup_printf (_("%d lines (%s) - %s"), 
215
 
                                    logview_log_get_cached_lines_number (active),
216
 
                                    size, modified);
217
 
 
218
 
  gtk_statusbar_pop (GTK_STATUSBAR (logview->priv->statusbar), 0);
219
 
  gtk_statusbar_push (GTK_STATUSBAR (logview->priv->statusbar), 0, statusbar_text);
220
 
  
221
 
  g_free (size);
222
 
  g_free (timestring_utf8);
223
 
  g_free (modified);
224
 
  g_free (statusbar_text);
225
 
}
226
 
 
227
 
#define DEFAULT_LOGVIEW_FONT "Monospace 10"
228
 
 
229
 
static void
230
 
logview_set_font (LogviewWindow *logview,
231
 
                  const char    *fontname)
232
 
{
233
 
  PangoFontDescription *font_desc;
234
 
 
235
 
  if (fontname == NULL)
236
 
    fontname = DEFAULT_LOGVIEW_FONT;
237
 
 
238
 
  font_desc = pango_font_description_from_string (fontname);
239
 
  if (font_desc) {
240
 
    gtk_widget_modify_font (logview->priv->text_view, font_desc);
241
 
    pango_font_description_free (font_desc);
242
 
  }
243
 
}
244
 
 
245
 
static void
246
 
logview_set_fontsize (LogviewWindow *logview, gboolean store)
247
 
{
248
 
  PangoFontDescription *fontdesc;
249
 
  PangoContext *context;
250
 
  LogviewWindowPrivate *priv = logview->priv;
251
 
 
252
 
  context = gtk_widget_get_pango_context (priv->text_view);
253
 
  fontdesc = pango_context_get_font_description (context);
254
 
  pango_font_description_set_size (fontdesc, (priv->fontsize) * PANGO_SCALE);
255
 
  gtk_widget_modify_font (priv->text_view, fontdesc);
256
 
 
257
 
  if (store) {
258
 
    logview_prefs_store_fontsize (logview->priv->prefs, priv->fontsize);
259
 
  }
260
 
}
261
 
 
262
 
static void
263
 
logview_set_window_title (LogviewWindow *logview, const char * log_name)
264
 
{
265
 
  char *window_title;
266
 
 
267
 
  if (log_name) {
268
 
    window_title = g_strdup_printf ("%s - %s", log_name, APP_NAME);
269
 
  } else {
270
 
    window_title = g_strdup_printf (APP_NAME);
271
 
  }
272
 
 
273
 
  gtk_window_set_title (GTK_WINDOW (logview), window_title);
274
 
 
275
 
  g_free (window_title);
276
 
}
277
 
 
278
 
/* actions callbacks */
279
 
 
280
 
static void
281
 
open_file_selected_cb (GtkWidget *chooser, gint response, LogviewWindow *logview)
282
 
{
283
 
  GFile *f;
284
 
  char *file_uri;
285
 
  LogviewLog *log;
286
 
 
287
 
  gtk_widget_hide (GTK_WIDGET (chooser));
288
 
  if (response != GTK_RESPONSE_OK) {
289
 
          return;
290
 
  }
291
 
 
292
 
  f = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (chooser));
293
 
  file_uri = g_file_get_uri (f);
294
 
 
295
 
  log = logview_manager_get_if_loaded (logview->priv->manager, file_uri);
296
 
 
297
 
  g_free (file_uri);
298
 
 
299
 
  if (log) {
300
 
    logview_manager_set_active_log (logview->priv->manager, log);
301
 
    g_object_unref (log);
302
 
    goto out;
303
 
  }
304
 
 
305
 
  logview_manager_add_log_from_gfile (logview->priv->manager, f, TRUE);
306
 
 
307
 
out:
308
 
  g_object_unref (f);
309
 
}
310
 
 
311
 
static void
312
 
logview_open_log (GtkAction *action, LogviewWindow *logview)
313
 
{
314
 
  static GtkWidget *chooser = NULL;
315
 
  char *active;
316
 
 
317
 
  if (chooser == NULL) {
318
 
    chooser = gtk_file_chooser_dialog_new (_("Open Log"),
319
 
                                           GTK_WINDOW (logview),
320
 
                                           GTK_FILE_CHOOSER_ACTION_OPEN,
321
 
                                           GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
322
 
                                           GTK_STOCK_OPEN, GTK_RESPONSE_OK,
323
 
                                           NULL);
324
 
    gtk_dialog_set_default_response (GTK_DIALOG (chooser), GTK_RESPONSE_OK);
325
 
    gtk_window_set_modal (GTK_WINDOW (chooser), TRUE);
326
 
    g_signal_connect (chooser, "response",
327
 
                      G_CALLBACK (open_file_selected_cb), logview);
328
 
    g_signal_connect (chooser, "destroy",
329
 
                      G_CALLBACK (gtk_widget_destroyed), &chooser);
330
 
    active = logview_prefs_get_active_logfile (logview->priv->prefs);
331
 
    if (active != NULL) {
332
 
      gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (chooser), active);
333
 
      g_free (active);
334
 
    }
335
 
  }
336
 
 
337
 
  gtk_window_present (GTK_WINDOW (chooser));
338
 
}
339
 
 
340
 
static void
341
 
logview_close_log (GtkAction *action, LogviewWindow *logview)
342
 
{
343
 
  findbar_close_cb (LOGVIEW_FINDBAR (logview->priv->find_bar), logview);
344
 
  logview_manager_close_active_log (logview->priv->manager);
345
 
}
346
 
 
347
 
static void
348
 
logview_help (GtkAction *action, GtkWidget *parent_window)
349
 
{
350
 
  GError *error = NULL;
351
 
 
352
 
  gtk_show_uri (gtk_widget_get_screen (parent_window),
353
 
                "ghelp:gnome-system-log", gtk_get_current_event_time (),
354
 
                &error);
355
 
 
356
 
  if (error) {
357
 
    g_warning (_("There was an error displaying help: %s"), error->message);
358
 
    g_error_free (error);
359
 
  }
360
 
}
361
 
 
362
 
static void
363
 
logview_bigger_text (GtkAction *action, LogviewWindow *logview)
364
 
{
365
 
  logview->priv->fontsize = MIN (logview->priv->fontsize + 1, 24);
366
 
  logview_set_fontsize (logview, TRUE);
367
 
}       
368
 
 
369
 
static void
370
 
logview_smaller_text (GtkAction *action, LogviewWindow *logview)
371
 
{
372
 
  logview->priv->fontsize = MAX (logview->priv->fontsize-1, 6);
373
 
  logview_set_fontsize (logview, TRUE);
374
 
}       
375
 
 
376
 
static void
377
 
logview_normal_text (GtkAction *action, LogviewWindow *logview)
378
 
{
379
 
  logview->priv->fontsize = logview->priv->original_fontsize;
380
 
  logview_set_fontsize (logview, TRUE);
381
 
}
382
 
 
383
 
static void
384
 
logview_select_all (GtkAction *action, LogviewWindow *logview)
385
 
{
386
 
  GtkTextIter start, end;
387
 
  GtkTextBuffer *buffer;
388
 
 
389
 
  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (logview->priv->text_view));
390
 
 
391
 
  gtk_text_buffer_get_bounds (buffer, &start, &end);
392
 
  gtk_text_buffer_select_range (buffer, &start, &end);
393
 
 
394
 
  gtk_widget_grab_focus (GTK_WIDGET (logview->priv->text_view));
395
 
}
396
 
 
397
 
static void
398
 
logview_copy (GtkAction *action, LogviewWindow *logview)
399
 
{
400
 
  GtkTextBuffer *buffer;
401
 
  GtkClipboard *clipboard;
402
 
 
403
 
  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (logview->priv->text_view));
404
 
  clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
405
 
 
406
 
  gtk_text_buffer_copy_clipboard (buffer, clipboard);
407
 
 
408
 
  gtk_widget_grab_focus (GTK_WIDGET (logview->priv->text_view));
409
 
}
410
 
 
411
 
static void
412
 
findbar_close_cb (LogviewFindbar *findbar,
413
 
                  gpointer user_data)
414
 
{
415
 
  gtk_widget_hide (GTK_WIDGET (findbar));
416
 
  logview_findbar_set_message (findbar, NULL);
417
 
}
418
 
 
419
 
static void
420
 
logview_search_text (LogviewWindow *logview, gboolean forward)
421
 
{
422
 
  GtkTextBuffer *buffer;
423
 
  GtkTextMark *search_start, *search_end;
424
 
  GtkTextIter search, start_m, end_m;
425
 
  const char *text;
426
 
  gboolean res, wrapped;
427
 
 
428
 
  wrapped = FALSE;
429
 
 
430
 
  text = logview_findbar_get_text (LOGVIEW_FINDBAR (logview->priv->find_bar));
431
 
 
432
 
  if (!text || g_strcmp0 (text, "") == 0) {
433
 
    return;
434
 
  }
435
 
 
436
 
  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (logview->priv->text_view));
437
 
  search_start = gtk_text_buffer_get_mark (buffer, SEARCH_START_MARK);
438
 
  search_end = gtk_text_buffer_get_mark (buffer, SEARCH_END_MARK);
439
 
 
440
 
  if (!search_start) {
441
 
    /* this is our first search on the buffer, create a new search mark */
442
 
    gtk_text_buffer_get_start_iter (buffer, &search);
443
 
    search_start = gtk_text_buffer_create_mark (buffer, SEARCH_START_MARK,
444
 
                                                &search, TRUE);
445
 
    search_end = gtk_text_buffer_create_mark (buffer, SEARCH_END_MARK,
446
 
                                              &search, TRUE);
447
 
  } else {
448
 
    if (forward) {
449
 
      gtk_text_buffer_get_iter_at_mark (buffer, &search, search_end);
450
 
    } else {
451
 
      gtk_text_buffer_get_iter_at_mark (buffer, &search, search_start);
452
 
    }
453
 
  }
454
 
 
455
 
wrap:
456
 
 
457
 
  if (forward) {
458
 
    res = gtk_text_iter_forward_search (&search, text, GTK_TEXT_SEARCH_VISIBLE_ONLY, &start_m, &end_m, NULL);
459
 
  } else {
460
 
    res = gtk_text_iter_backward_search (&search, text, GTK_TEXT_SEARCH_VISIBLE_ONLY, &start_m, &end_m, NULL);
461
 
  }
462
 
 
463
 
  if (res) {
464
 
    gtk_text_buffer_select_range (buffer, &start_m, &end_m);
465
 
    gtk_text_buffer_move_mark (buffer, search_start, &start_m);
466
 
    gtk_text_buffer_move_mark (buffer, search_end, &end_m);
467
 
 
468
 
    gtk_text_view_scroll_mark_onscreen (GTK_TEXT_VIEW (logview->priv->text_view), search_end);
469
 
 
470
 
    if (wrapped) {
471
 
      logview_findbar_set_message (LOGVIEW_FINDBAR (logview->priv->find_bar), _("Wrapped"));
472
 
    }
473
 
  } else {
474
 
    if (wrapped) {
475
 
      
476
 
      GtkTextMark *mark;
477
 
      GtkTextIter iter;
478
 
 
479
 
      if (gtk_text_buffer_get_has_selection (buffer)) {
480
 
        /* unselect */
481
 
        mark = gtk_text_buffer_get_mark (buffer, "insert");
482
 
        gtk_text_buffer_get_iter_at_mark (buffer, &iter, mark);
483
 
        gtk_text_buffer_move_mark_by_name (buffer, "selection_bound", &iter);
484
 
      }
485
 
 
486
 
      logview_findbar_set_message (LOGVIEW_FINDBAR (logview->priv->find_bar), _("Not found"));
487
 
    } else {
488
 
      if (forward) {
489
 
        gtk_text_buffer_get_start_iter (buffer, &search);
490
 
      } else {
491
 
        gtk_text_buffer_get_end_iter (buffer, &search);
492
 
      }
493
 
 
494
 
      wrapped = TRUE;
495
 
      goto wrap;
496
 
    }
497
 
  }
498
 
}
499
 
 
500
 
static void
501
 
findbar_previous_cb (LogviewFindbar *findbar,
502
 
                     gpointer user_data)
503
 
{
504
 
  LogviewWindow *logview = user_data;
505
 
 
506
 
  logview_search_text (logview, FALSE);
507
 
}
508
 
 
509
 
static void
510
 
findbar_next_cb (LogviewFindbar *findbar,
511
 
                 gpointer user_data)
512
 
{
513
 
  LogviewWindow *logview = user_data;
514
 
 
515
 
  logview_search_text (logview, TRUE);
516
 
}
517
 
 
518
 
static gboolean
519
 
text_changed_timeout_cb (gpointer user_data)
520
 
{
521
 
  LogviewWindow *logview = user_data;
522
 
  GtkTextMark *search_start, *search_end;
523
 
  GtkTextIter start;
524
 
  GtkTextBuffer *buffer;
525
 
 
526
 
  logview->priv->search_timeout_id = 0;
527
 
 
528
 
  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (logview->priv->text_view));
529
 
  search_start = gtk_text_buffer_get_mark (buffer, SEARCH_START_MARK);
530
 
  search_end = gtk_text_buffer_get_mark (buffer, SEARCH_END_MARK);
531
 
  
532
 
  if (search_start) {
533
 
    /* reset the search mark to the start */
534
 
    gtk_text_buffer_get_start_iter (buffer, &start);
535
 
    gtk_text_buffer_move_mark (buffer, search_start, &start);
536
 
    gtk_text_buffer_move_mark (buffer, search_end, &start);
537
 
  }
538
 
 
539
 
  logview_findbar_set_message (LOGVIEW_FINDBAR (logview->priv->find_bar), NULL);
540
 
 
541
 
  logview_search_text (logview, TRUE);
542
 
 
543
 
  return FALSE;
544
 
}
545
 
 
546
 
static void
547
 
findbar_text_changed_cb (LogviewFindbar *findbar,
548
 
                         gpointer user_data)
549
 
{
550
 
  LogviewWindow *logview = user_data;
551
 
 
552
 
  if (logview->priv->search_timeout_id != 0) {
553
 
    g_source_remove (logview->priv->search_timeout_id);
554
 
  }
555
 
 
556
 
  logview->priv->search_timeout_id = g_timeout_add (300, text_changed_timeout_cb, logview);
557
 
}
558
 
 
559
 
static void
560
 
logview_search (GtkAction *action, LogviewWindow *logview)
561
 
{
562
 
  logview_findbar_open (LOGVIEW_FINDBAR (logview->priv->find_bar));
563
 
}
564
 
 
565
 
static void
566
 
filter_buffer (LogviewWindow *logview, gint start_line)
567
 
{
568
 
  GtkTextBuffer *buffer;
569
 
  GtkTextIter start, *end;
570
 
  gchar* text;
571
 
  GList* cur_filter;
572
 
  gboolean matched;
573
 
  int lines, i;
574
 
 
575
 
  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (logview->priv->text_view));
576
 
  lines = gtk_text_buffer_get_line_count (buffer);
577
 
 
578
 
  for (i = start_line; i < lines; i++) {
579
 
    matched = FALSE;
580
 
 
581
 
    gtk_text_buffer_get_iter_at_line (buffer, &start, i);
582
 
    end = gtk_text_iter_copy (&start);
583
 
    gtk_text_iter_forward_line (end);
584
 
 
585
 
    text = gtk_text_buffer_get_text (buffer, &start, end, TRUE);
586
 
 
587
 
    for (cur_filter = logview->priv->active_filters; cur_filter != NULL;
588
 
         cur_filter = g_list_next (cur_filter))
589
 
    {
590
 
      if (logview_filter_filter (LOGVIEW_FILTER (cur_filter->data), text)) {
591
 
        gtk_text_buffer_apply_tag (buffer, 
592
 
                                   logview_filter_get_tag (LOGVIEW_FILTER (cur_filter->data)),
593
 
                                   &start, end);
594
 
        matched = TRUE;
595
 
      }
596
 
    }
597
 
 
598
 
    g_free (text);
599
 
 
600
 
    if (!matched && logview->priv->matches_only) {
601
 
      gtk_text_buffer_apply_tag_by_name (buffer, 
602
 
                                         "invisible-filter",
603
 
                                         &start, end);
604
 
    } else {
605
 
      gtk_text_buffer_remove_tag_by_name (buffer,
606
 
                                          "invisible-filter",
607
 
                                          &start, end);
608
 
    }
609
 
 
610
 
    gtk_text_iter_free (end);
611
 
  }
612
 
}
613
 
 
614
 
static void
615
 
filter_remove (LogviewWindow *logview, LogviewFilter *filter)
616
 
{
617
 
  GtkTextIter start, end;  
618
 
  GtkTextBuffer *buffer;
619
 
 
620
 
  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (logview->priv->text_view));
621
 
  gtk_text_buffer_get_bounds (buffer, &start, &end);
622
 
 
623
 
  gtk_text_buffer_remove_tag (buffer, logview_filter_get_tag (filter),
624
 
                              &start, &end);
625
 
}
626
 
 
627
 
static void
628
 
on_filter_toggled (GtkToggleAction *action, LogviewWindow *logview)
629
 
{
630
 
  LogviewWindowPrivate *priv = GET_PRIVATE (logview);
631
 
  const gchar* name;
632
 
  LogviewFilter *filter;
633
 
 
634
 
  name = gtk_action_get_name (GTK_ACTION (action));
635
 
  
636
 
  if (gtk_toggle_action_get_active (action)) {
637
 
    priv->active_filters = g_list_append (priv->active_filters,
638
 
                                          logview_prefs_get_filter (priv->prefs,
639
 
                                                                    name));
640
 
    filter_buffer(logview, 0);
641
 
  } else {
642
 
    filter = logview_prefs_get_filter (priv->prefs, name);
643
 
    priv->active_filters = g_list_remove (priv->active_filters,
644
 
                                          filter);
645
 
 
646
 
    filter_remove (logview, filter);
647
 
  }
648
 
}
649
 
 
650
 
#define FILTER_PLACEHOLDER "/LogviewMenu/FilterMenu/PlaceholderFilters"
651
 
static void
652
 
update_filter_menu (LogviewWindow *window)
653
 
{
654
 
  LogviewWindowPrivate *priv;
655
 
  GtkUIManager* ui;
656
 
  GList *actions, *l;
657
 
  guint id;
658
 
  GList *filters;
659
 
  GtkTextBuffer *buffer;
660
 
  GtkTextTagTable *table;
661
 
  GtkTextTag *tag;
662
 
  GtkToggleAction *action;
663
 
  gchar* name;
664
 
 
665
 
  priv = GET_PRIVATE (window);
666
 
  ui = priv->ui_manager;
667
 
 
668
 
  g_return_if_fail (priv->filter_action_group != NULL);
669
 
 
670
 
  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->text_view));
671
 
  table = priv->tag_table;
672
 
 
673
 
  if (priv->filter_merge_id != 0) {
674
 
    gtk_ui_manager_remove_ui (ui,
675
 
                              priv->filter_merge_id);
676
 
  }
677
 
 
678
 
  actions = gtk_action_group_list_actions (priv->filter_action_group);
679
 
 
680
 
  for (l = actions; l != NULL; l = g_list_next (l)) {
681
 
    tag = gtk_text_tag_table_lookup (table, gtk_action_get_name (GTK_ACTION (l->data)));
682
 
    gtk_text_tag_table_remove (table, tag);
683
 
 
684
 
    g_signal_handlers_disconnect_by_func (GTK_ACTION (l->data),
685
 
                                          G_CALLBACK (on_filter_toggled),
686
 
                                          window);
687
 
    gtk_action_group_remove_action (priv->filter_action_group,
688
 
                                    GTK_ACTION (l->data));
689
 
  }
690
 
 
691
 
  g_list_free (actions);
692
 
  
693
 
  filters = logview_prefs_get_filters (logview_prefs_get ());
694
 
 
695
 
  id = (g_list_length (filters) > 0) ? gtk_ui_manager_new_merge_id (ui) : 0;
696
 
 
697
 
  for (l = filters; l != NULL; l = g_list_next (l)) {
698
 
    g_object_get (l->data, "name", &name, NULL);
699
 
 
700
 
    action = gtk_toggle_action_new (name, name, NULL, NULL);
701
 
    gtk_action_group_add_action (priv->filter_action_group,
702
 
                                 GTK_ACTION (action));
703
 
 
704
 
    g_signal_connect (action,
705
 
                      "toggled",
706
 
                      G_CALLBACK (on_filter_toggled),
707
 
                      window);
708
 
 
709
 
    gtk_ui_manager_add_ui (ui, id, FILTER_PLACEHOLDER,
710
 
                           name, name, GTK_UI_MANAGER_MENUITEM, FALSE);
711
 
    gtk_text_tag_table_add (table, 
712
 
                            logview_filter_get_tag (LOGVIEW_FILTER (l->data)));
713
 
 
714
 
    g_object_unref (action);
715
 
    g_free(name);
716
 
  }
717
 
 
718
 
  g_list_free (filters);
719
 
 
720
 
  priv->filter_merge_id = id;
721
 
}
722
 
 
723
 
static void
724
 
on_logview_filter_manager_response (GtkDialog *dialog, 
725
 
                                    gint response,
726
 
                                    LogviewWindow *logview)
727
 
{
728
 
  update_filter_menu (logview);
729
 
 
730
 
  g_list_free (logview->priv->active_filters);
731
 
  logview->priv->active_filters = NULL;
732
 
}
733
 
 
734
 
static void
735
 
logview_manage_filters (GtkAction *action, LogviewWindow *logview)
736
 
{
737
 
  GtkWidget *manager;
738
 
 
739
 
  manager = logview_filter_manager_new ();
740
 
 
741
 
  g_signal_connect (manager, "response", 
742
 
                    G_CALLBACK (on_logview_filter_manager_response),
743
 
                    logview);
744
 
  
745
 
  gtk_window_set_transient_for (GTK_WINDOW (manager),
746
 
                                GTK_WINDOW (logview));
747
 
  gtk_widget_show (GTK_WIDGET (manager));
748
 
}
749
 
 
750
 
static void
751
 
logview_about (GtkWidget *widget, GtkWidget *window)
752
 
{
753
 
  g_return_if_fail (GTK_IS_WINDOW (window));
754
 
 
755
 
  char *license_trans = g_strjoin ("\n\n", _(logview_about_license[0]),
756
 
                                   _(logview_about_license[1]),
757
 
                                   _(logview_about_license[2]), NULL);
758
 
 
759
 
  gtk_show_about_dialog (GTK_WINDOW (window),
760
 
                         "name",  _("System Log Viewer"),
761
 
                         "version", VERSION,
762
 
                         "copyright", "Copyright \xc2\xa9 1998-2008 Free Software Foundation, Inc.",
763
 
                         "license", license_trans,
764
 
                         "wrap-license", TRUE,
765
 
                         "comments", _("A system log viewer for GNOME."),
766
 
                         "authors", logview_about_authors,
767
 
                         "documenters", logview_about_documenters,
768
 
                         "translator_credits", strcmp (logview_about_translator_credits,
769
 
                                                       "translator-credits") != 0 ?
770
 
                                               logview_about_translator_credits : NULL,
771
 
                         "logo_icon_name", "logview",
772
 
                         NULL);
773
 
  g_free (license_trans);
774
 
 
775
 
  return;
776
 
}
777
 
 
778
 
static void
779
 
logview_toggle_statusbar (GtkAction *action, LogviewWindow *logview)
780
 
{
781
 
  if (gtk_widget_get_visible (logview->priv->statusbar))
782
 
    gtk_widget_hide (logview->priv->statusbar);
783
 
  else
784
 
    gtk_widget_show (logview->priv->statusbar);
785
 
}
786
 
 
787
 
static void
788
 
logview_toggle_sidebar (GtkAction *action, LogviewWindow *logview)
789
 
{
790
 
  if (gtk_widget_get_visible (logview->priv->sidebar))
791
 
    gtk_widget_hide (logview->priv->sidebar);
792
 
  else
793
 
    gtk_widget_show (logview->priv->sidebar);
794
 
}
795
 
 
796
 
static void
797
 
logview_toggle_match_filters (GtkToggleAction *action, LogviewWindow *logview)
798
 
{
799
 
  logview->priv->matches_only = gtk_toggle_action_get_active (action);
800
 
  filter_buffer (logview, 0);
801
 
}
802
 
 
803
 
static void
804
 
logview_toggle_autoscroll (GtkToggleAction *action, LogviewWindow *logview)
805
 
{
806
 
  logview->priv->auto_scroll = gtk_toggle_action_get_active (action);
807
 
}
808
 
 
809
 
/* GObject functions */
810
 
 
811
 
/* Menus */
812
 
 
813
 
static GtkActionEntry entries[] = {
814
 
    { "FileMenu", NULL, N_("_File"), NULL, NULL, NULL },
815
 
    { "EditMenu", NULL, N_("_Edit"), NULL, NULL, NULL },
816
 
    { "ViewMenu", NULL, N_("_View"), NULL, NULL, NULL },
817
 
    { "FilterMenu", NULL, N_("_Filters"), NULL, NULL, NULL },  
818
 
    { "HelpMenu", NULL, N_("_Help"), NULL, NULL, NULL },
819
 
 
820
 
    { "OpenLog", GTK_STOCK_OPEN, N_("_Open..."), "<control>O", N_("Open a log from file"), 
821
 
      G_CALLBACK (logview_open_log) },
822
 
    { "CloseLog", GTK_STOCK_CLOSE, N_("_Close"), "<control>W", N_("Close this log"), 
823
 
      G_CALLBACK (logview_close_log) },
824
 
    { "Quit", GTK_STOCK_QUIT, N_("_Quit"), "<control>Q", N_("Quit the log viewer"), 
825
 
      G_CALLBACK (gtk_main_quit) },
826
 
 
827
 
    { "Copy", GTK_STOCK_COPY, N_("_Copy"), "<control>C", N_("Copy the selection"),
828
 
      G_CALLBACK (logview_copy) },
829
 
    { "SelectAll", NULL, N_("Select _All"), "<Control>A", N_("Select the entire log"),
830
 
      G_CALLBACK (logview_select_all) },
831
 
    { "Search", GTK_STOCK_FIND, N_("_Find..."), "<control>F", N_("Find a word or phrase in the log"),
832
 
      G_CALLBACK (logview_search) },
833
 
 
834
 
    { "ViewZoomIn", GTK_STOCK_ZOOM_IN, NULL, "<control>plus", N_("Bigger text size"),
835
 
      G_CALLBACK (logview_bigger_text)},
836
 
    { "ViewZoomOut", GTK_STOCK_ZOOM_OUT, NULL, "<control>minus", N_("Smaller text size"),
837
 
      G_CALLBACK (logview_smaller_text)},
838
 
    { "ViewZoom100", GTK_STOCK_ZOOM_100, NULL, "<control>0", N_("Normal text size"),
839
 
      G_CALLBACK (logview_normal_text)},
840
 
 
841
 
    { "FilterManage", NULL, N_("Manage Filters"), NULL, N_("Manage filters"),
842
 
      G_CALLBACK (logview_manage_filters)},
843
 
  
844
 
    { "HelpContents", GTK_STOCK_HELP, N_("_Contents"), "F1", N_("Open the help contents for the log viewer"), 
845
 
      G_CALLBACK (logview_help) },
846
 
    { "AboutAction", GTK_STOCK_ABOUT, N_("_About"), NULL, N_("Show the about dialog for the log viewer"), 
847
 
      G_CALLBACK (logview_about) },
848
 
};
849
 
 
850
 
static GtkToggleActionEntry toggle_entries[] = {
851
 
    { "ShowStatusBar", NULL, N_("_Statusbar"), NULL, N_("Show Status Bar"),
852
 
      G_CALLBACK (logview_toggle_statusbar), TRUE },
853
 
    { "ShowSidebar", NULL, N_("Side _Pane"), "F9", N_("Show Side Pane"), 
854
 
      G_CALLBACK (logview_toggle_sidebar), TRUE }, 
855
 
    { "FilterMatchOnly", NULL, N_("Show matches only"), NULL, N_("Only show lines that match one of the given filters"),
856
 
      G_CALLBACK (logview_toggle_match_filters), FALSE },
857
 
    { "AutoScroll", NULL, N_("_Auto Scroll"), "F8", N_("Automatically scroll down when new lines appear"),
858
 
      G_CALLBACK (logview_toggle_autoscroll), TRUE }
859
 
};
860
 
 
861
 
static gboolean 
862
 
window_size_changed_cb (GtkWidget *widget, GdkEventConfigure *event, 
863
 
                        gpointer data)
864
 
{
865
 
  LogviewWindow *window = data;
866
 
 
867
 
  logview_prefs_store_window_size (window->priv->prefs,
868
 
                                   event->width, event->height);
869
 
 
870
 
  return FALSE;
871
 
}
872
 
 
873
 
static void
874
 
real_select_day (LogviewWindow *logview,
875
 
                 GDate *date, int first_line, int last_line)
876
 
{
877
 
  GtkTextBuffer *buffer;
878
 
  GtkTextIter start_iter, end_iter, start_vis, end_vis;
879
 
  GdkRectangle visible_rect;
880
 
 
881
 
  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (logview->priv->text_view));
882
 
 
883
 
  gtk_text_buffer_get_bounds (buffer, &start_iter, &end_iter);
884
 
  gtk_text_buffer_get_iter_at_line (buffer, &start_vis, first_line);
885
 
  gtk_text_buffer_get_iter_at_line (buffer, &end_vis, last_line + 1);
886
 
 
887
 
  /* clear all previous invisible tags */
888
 
  gtk_text_buffer_remove_tag_by_name (buffer, "invisible",
889
 
                                      &start_iter, &end_iter);
890
 
 
891
 
  gtk_text_buffer_apply_tag_by_name (buffer, "invisible",
892
 
                                     &start_iter, &start_vis);
893
 
  gtk_text_buffer_apply_tag_by_name (buffer, "invisible",
894
 
                                     &end_vis, &end_iter);
895
 
 
896
 
  /* FIXME: why is this needed to update the view when selecting a day back? */
897
 
  gtk_text_view_get_visible_rect (GTK_TEXT_VIEW (logview->priv->text_view),
898
 
                                  &visible_rect);
899
 
  gdk_window_invalidate_rect (gtk_widget_get_window (logview->priv->text_view),
900
 
                              &visible_rect, TRUE);
901
 
}
902
 
 
903
 
static void
904
 
loglist_day_selected_cb (LogviewLoglist *loglist,
905
 
                         Day *day,
906
 
                         gpointer user_data)
907
 
{
908
 
  LogviewWindow *logview = user_data;
909
 
 
910
 
  real_select_day (logview, day->date, day->first_line, day->last_line);
911
 
}
912
 
 
913
 
static void
914
 
loglist_day_cleared_cb (LogviewLoglist *loglist,
915
 
                        gpointer user_data)
916
 
{
917
 
  LogviewWindow *logview = user_data;
918
 
  GtkTextBuffer *buffer;
919
 
  GtkTextIter start, end;
920
 
 
921
 
  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (logview->priv->text_view));
922
 
  gtk_text_buffer_get_bounds (buffer, &start, &end);
923
 
 
924
 
  /* clear all previous invisible tags */
925
 
  gtk_text_buffer_remove_tag_by_name (buffer, "invisible",
926
 
                                      &start, &end);
927
 
}
928
 
 
929
 
static void
930
 
log_monitor_changed_cb (LogviewLog *log,
931
 
                        gpointer user_data)
932
 
{
933
 
  /* reschedule a read */
934
 
  logview_log_read_new_lines (log, (LogviewNewLinesCallback) read_new_lines_cb,
935
 
                              user_data);
936
 
}
937
 
 
938
 
static void
939
 
paint_timestamps (GtkTextBuffer *buffer, int old_line_count,
940
 
                  GSList *days)
941
 
{
942
 
  GSList *l;
943
 
 
944
 
  for (l = days; l; l = l->next) {
945
 
    Day *day = l->data;
946
 
 
947
 
    _gtk_text_buffer_apply_tag_to_rectangle (buffer,
948
 
                                             old_line_count + day->first_line - 1,
949
 
                                             old_line_count + day->last_line,
950
 
                                             0, day->timestamp_len, "gray");
951
 
  }
952
 
}
953
 
 
954
 
static void
955
 
read_new_lines_cb (LogviewLog *log,
956
 
                   const char **lines,
957
 
                   GSList *new_days,
958
 
                   GError *error,
959
 
                   gpointer user_data)
960
 
{
961
 
  LogviewWindow *window = user_data;
962
 
  GtkTextBuffer *buffer;
963
 
  gboolean boldify = FALSE;
964
 
  int i, old_line_count, filter_start_line;
965
 
  GtkTextIter iter, start;
966
 
  GtkTextMark *mark;
967
 
  char *converted, *primary;
968
 
  gsize len;
969
 
 
970
 
  if (error != NULL) {
971
 
    primary = g_strdup_printf (_("Can't read from \"%s\""),
972
 
                               logview_log_get_display_name (log));
973
 
    logview_window_add_error (window, primary, error->message);
974
 
    g_free (primary);
975
 
 
976
 
    return;
977
 
  }
978
 
 
979
 
  if (lines == NULL) {
980
 
    /* there's no error, but no lines have been read */
981
 
    return;
982
 
  }
983
 
 
984
 
  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (window->priv->text_view));
985
 
  old_line_count = gtk_text_buffer_get_line_count (buffer);
986
 
  filter_start_line = old_line_count > 0 ? (old_line_count - 1) : 0;
987
 
 
988
 
  if (gtk_text_buffer_get_char_count (buffer) != 0) {
989
 
    boldify = TRUE;
990
 
  }
991
 
 
992
 
  gtk_text_buffer_get_end_iter (buffer, &iter);
993
 
 
994
 
  if (boldify) {
995
 
    mark = gtk_text_buffer_create_mark (buffer, NULL, &iter, TRUE);
996
 
  }
997
 
 
998
 
  for (i = 0; lines[i]; i++) {
999
 
    len = strlen (lines[i]);
1000
 
 
1001
 
    if (!g_utf8_validate (lines[i], len, NULL)) {
1002
 
      converted = g_locale_to_utf8 (lines[i], (gssize) len, NULL, &len, NULL);
1003
 
      gtk_text_buffer_insert (buffer, &iter, lines[i], len);
1004
 
    } else {
1005
 
      gtk_text_buffer_insert (buffer, &iter, lines[i], strlen (lines[i]));
1006
 
    }
1007
 
 
1008
 
    gtk_text_iter_forward_to_end (&iter);
1009
 
    gtk_text_buffer_insert (buffer, &iter, "\n", 1);
1010
 
    gtk_text_iter_forward_char (&iter);
1011
 
  }
1012
 
 
1013
 
  if (boldify) {
1014
 
    gtk_text_buffer_get_iter_at_mark (buffer, &start, mark);
1015
 
    gtk_text_buffer_apply_tag_by_name (buffer, "bold", &start, &iter);
1016
 
    gtk_text_buffer_delete_mark (buffer, mark);
1017
 
  }
1018
 
  filter_buffer (window, filter_start_line);
1019
 
 
1020
 
  if (window->priv->auto_scroll) {
1021
 
    gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (window->priv->text_view),
1022
 
                                  &iter, 0.0, FALSE, 0.0, 0.0);
1023
 
  }
1024
 
 
1025
 
  paint_timestamps (buffer, old_line_count, new_days);
1026
 
 
1027
 
  if (window->priv->monitor_id == 0) {
1028
 
    window->priv->monitor_id = g_signal_connect (log, "log-changed",
1029
 
                                                 G_CALLBACK (log_monitor_changed_cb), window);
1030
 
  }
1031
 
 
1032
 
  logview_update_statusbar (window, log);
1033
 
  logview_loglist_update_lines (LOGVIEW_LOGLIST (window->priv->loglist), log);
1034
 
}
1035
 
 
1036
 
static void
1037
 
active_log_changed_cb (LogviewManager *manager,
1038
 
                       LogviewLog *log,
1039
 
                       LogviewLog *old_log,
1040
 
                       gpointer data)
1041
 
{
1042
 
  LogviewWindow *window = data;
1043
 
  const char **lines;
1044
 
  GtkTextBuffer *buffer;
1045
 
 
1046
 
  findbar_close_cb (LOGVIEW_FINDBAR (window->priv->find_bar),
1047
 
                    window);
1048
 
 
1049
 
  logview_set_window_title (window, logview_log_get_display_name (log));
1050
 
 
1051
 
  if (window->priv->monitor_id) {
1052
 
    g_signal_handler_disconnect (old_log, window->priv->monitor_id);
1053
 
    window->priv->monitor_id = 0;
1054
 
  }
1055
 
 
1056
 
  lines = logview_log_get_cached_lines (log);
1057
 
  buffer = gtk_text_buffer_new (window->priv->tag_table);
1058
 
 
1059
 
  if (lines != NULL) {
1060
 
    int i;
1061
 
    GtkTextIter iter;
1062
 
 
1063
 
    /* update the text view to show the current lines */
1064
 
    gtk_text_buffer_get_end_iter (buffer, &iter);
1065
 
 
1066
 
    for (i = 0; lines[i]; i++) {
1067
 
      gtk_text_buffer_insert (buffer, &iter, lines[i], strlen (lines[i]));
1068
 
      gtk_text_iter_forward_to_end (&iter);
1069
 
      gtk_text_buffer_insert (buffer, &iter, "\n", 1);
1070
 
      gtk_text_iter_forward_char (&iter);
1071
 
    }
1072
 
 
1073
 
    paint_timestamps (buffer, 1, logview_log_get_days_for_cached_lines (log));
1074
 
  }
1075
 
 
1076
 
  if (lines == NULL || logview_log_has_new_lines (log)) {
1077
 
    /* read the new lines */
1078
 
    logview_log_read_new_lines (log, (LogviewNewLinesCallback) read_new_lines_cb, window);
1079
 
  } else {
1080
 
    /* start now monitoring the log for changes */
1081
 
    window->priv->monitor_id = g_signal_connect (log, "log-changed",
1082
 
                                                 G_CALLBACK (log_monitor_changed_cb), window);
1083
 
  }
1084
 
 
1085
 
  /* we set the buffer to the view anyway;
1086
 
   * if there are no lines it will be empty for the duration of the thread
1087
 
   * and will help us to distinguish the two cases of the following if
1088
 
   * cause in the callback.
1089
 
   */
1090
 
  gtk_text_view_set_buffer (GTK_TEXT_VIEW (window->priv->text_view), buffer);
1091
 
  g_object_unref (buffer);
1092
 
}
1093
 
 
1094
 
static void
1095
 
font_changed_cb (LogviewPrefs *prefs,
1096
 
                 const char *font_name,
1097
 
                 gpointer user_data)
1098
 
{
1099
 
  LogviewWindow *window = user_data;
1100
 
 
1101
 
  logview_set_font (window, font_name);
1102
 
}
1103
 
 
1104
 
static void
1105
 
tearoff_changed_cb (LogviewPrefs *prefs,
1106
 
                    gboolean have_tearoffs,
1107
 
                    gpointer user_data)
1108
 
{
1109
 
  LogviewWindow *window = user_data;
1110
 
 
1111
 
  gtk_ui_manager_set_add_tearoffs (window->priv->ui_manager, have_tearoffs);
1112
 
}
1113
 
 
1114
 
static void
1115
 
style_set_cb (GtkWidget *widget,
1116
 
              GtkStyle *prev,
1117
 
              gpointer user_data)
1118
 
{
1119
 
  LogviewWindow *logview = user_data;
1120
 
  GtkStyle *style = gtk_widget_get_style (widget);
1121
 
 
1122
 
  populate_style_tag_table (style, logview->priv->tag_table);
1123
 
}
1124
 
 
1125
 
static const struct {
1126
 
  guint keyval;
1127
 
  GdkModifierType modifier;
1128
 
  const gchar *action;
1129
 
} extra_keybindings [] = {
1130
 
  { GDK_KEY_KP_Add,      GDK_CONTROL_MASK, "ViewZoomIn" },
1131
 
  { GDK_KEY_KP_Subtract, GDK_CONTROL_MASK, "ViewZoomOut" },
1132
 
  { GDK_KEY_KP_0,        GDK_CONTROL_MASK, "ViewZoom100" }
1133
 
};
1134
 
 
1135
 
static gboolean
1136
 
key_press_event_cb (GtkWidget *widget,
1137
 
                    GdkEventKey *event,
1138
 
                    gpointer user_data)
1139
 
{
1140
 
  LogviewWindow *window = user_data;
1141
 
  guint modifier = event->state & gtk_accelerator_get_default_mod_mask ();
1142
 
  GtkAction *action;
1143
 
  int i;
1144
 
 
1145
 
  /* handle accelerators that we want bound, but aren't associated with
1146
 
   * an action */
1147
 
  for (i = 0; i < G_N_ELEMENTS (extra_keybindings); i++) {
1148
 
    if (event->keyval == extra_keybindings[i].keyval &&
1149
 
        modifier == extra_keybindings[i].modifier) {
1150
 
 
1151
 
      action = gtk_action_group_get_action (window->priv->action_group,
1152
 
                                            extra_keybindings[i].action);
1153
 
      gtk_action_activate (action);
1154
 
      return TRUE;
1155
 
    }
1156
 
  }
1157
 
 
1158
 
  return FALSE;
1159
 
}
1160
 
 
1161
 
/* adapted from GEdit */
1162
 
 
1163
 
static void
1164
 
message_area_create_error_box (LogviewWindow *window,
1165
 
                               GtkWidget *message_area)
1166
 
{
1167
 
  GtkWidget *hbox_content;
1168
 
  GtkWidget *image;
1169
 
  GtkWidget *vbox;
1170
 
  GtkWidget *primary_label;
1171
 
  GtkWidget *secondary_label;
1172
 
  
1173
 
  hbox_content = gtk_hbox_new (FALSE, 8);
1174
 
  gtk_widget_show (hbox_content);
1175
 
 
1176
 
  image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_ERROR,
1177
 
                                    GTK_ICON_SIZE_DIALOG);
1178
 
  gtk_widget_show (image);
1179
 
  gtk_box_pack_start (GTK_BOX (hbox_content), image, FALSE, FALSE, 0);
1180
 
  gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0);
1181
 
 
1182
 
  vbox = gtk_vbox_new (FALSE, 6);
1183
 
  gtk_widget_show (vbox);
1184
 
  gtk_box_pack_start (GTK_BOX (hbox_content), vbox, TRUE, TRUE, 0);
1185
 
 
1186
 
  primary_label = gtk_label_new (NULL);
1187
 
  gtk_widget_show (primary_label);
1188
 
  gtk_box_pack_start (GTK_BOX (vbox), primary_label, TRUE, TRUE, 0);
1189
 
  gtk_label_set_use_markup (GTK_LABEL (primary_label), TRUE);
1190
 
  gtk_label_set_line_wrap (GTK_LABEL (primary_label), TRUE);
1191
 
  gtk_misc_set_alignment (GTK_MISC (primary_label), 0, 0.5);
1192
 
  gtk_widget_set_can_focus (primary_label, TRUE);
1193
 
  gtk_label_set_selectable (GTK_LABEL (primary_label), TRUE);
1194
 
 
1195
 
  window->priv->message_primary = primary_label;
1196
 
 
1197
 
  secondary_label = gtk_label_new (NULL);
1198
 
  gtk_widget_show (secondary_label);
1199
 
  gtk_box_pack_start (GTK_BOX (vbox), secondary_label, TRUE, TRUE, 0);
1200
 
  gtk_widget_set_can_focus (secondary_label, TRUE);
1201
 
  gtk_label_set_use_markup (GTK_LABEL (secondary_label), TRUE);
1202
 
  gtk_label_set_line_wrap (GTK_LABEL (secondary_label), TRUE);
1203
 
  gtk_label_set_selectable (GTK_LABEL (secondary_label), TRUE);
1204
 
  gtk_misc_set_alignment (GTK_MISC (secondary_label), 0, 0.5);
1205
 
 
1206
 
  window->priv->message_secondary = secondary_label;
1207
 
 
1208
 
  gtk_container_add
1209
 
      (GTK_CONTAINER (gtk_info_bar_get_content_area
1210
 
                      (GTK_INFO_BAR (message_area))),
1211
 
       hbox_content);
1212
 
}
1213
 
 
1214
 
static void
1215
 
message_area_set_labels (LogviewWindow *window,
1216
 
                         const char *primary,
1217
 
                         const char *secondary)
1218
 
{
1219
 
  char *primary_markup, *secondary_markup;
1220
 
 
1221
 
  primary_markup = g_markup_printf_escaped ("<b>%s</b>", primary);
1222
 
  secondary_markup = g_markup_printf_escaped ("<small>%s</small>",
1223
 
                                              secondary);
1224
 
 
1225
 
  gtk_label_set_markup (GTK_LABEL (window->priv->message_primary),
1226
 
                        primary_markup);
1227
 
  gtk_label_set_markup (GTK_LABEL (window->priv->message_secondary),
1228
 
                        secondary_markup);
1229
 
 
1230
 
  g_free (primary_markup);
1231
 
  g_free (secondary_markup);
1232
 
}
1233
 
 
1234
 
static void
1235
 
message_area_response_cb (GtkInfoBar *message_area,
1236
 
                          int response_id, gpointer user_data)
1237
 
{
1238
 
  gtk_widget_hide (GTK_WIDGET (message_area));
1239
 
 
1240
 
  g_signal_handlers_disconnect_by_func (message_area,
1241
 
                                        message_area_response_cb,
1242
 
                                        user_data);
1243
 
}
1244
 
 
1245
 
static void
1246
 
logview_window_finalize (GObject *object)
1247
 
{
1248
 
  LogviewWindow *logview = LOGVIEW_WINDOW (object);
1249
 
 
1250
 
  g_object_unref (logview->priv->ui_manager);
1251
 
  G_OBJECT_CLASS (logview_window_parent_class)->finalize (object);
1252
 
}
1253
 
 
1254
 
static void
1255
 
logview_window_init (LogviewWindow *logview)
1256
 
{
1257
 
  GtkActionGroup *action_group;
1258
 
  GtkAccelGroup *accel_group;
1259
 
  GError *error = NULL;
1260
 
  GtkWidget *hpaned, *main_view, *vbox, *w;
1261
 
  PangoContext *context;
1262
 
  PangoFontDescription *fontdesc;
1263
 
  gchar *monospace_font_name;
1264
 
  LogviewWindowPrivate *priv;
1265
 
  int width, height;
1266
 
  gboolean res;
1267
 
 
1268
 
  priv = logview->priv = GET_PRIVATE (logview);
1269
 
  priv->prefs = logview_prefs_get ();
1270
 
  priv->manager = logview_manager_get ();
1271
 
  priv->monitor_id = 0;
1272
 
 
1273
 
  logview_prefs_get_stored_window_size (priv->prefs, &width, &height);
1274
 
  gtk_window_set_default_size (GTK_WINDOW (logview), width, height);
1275
 
 
1276
 
  vbox = gtk_vbox_new (FALSE, 0);
1277
 
  gtk_container_add (GTK_CONTAINER (logview), vbox);
1278
 
 
1279
 
  /* create menus */
1280
 
  action_group = gtk_action_group_new ("LogviewMenuActions");
1281
 
  gtk_action_group_set_translation_domain (action_group, NULL);
1282
 
  gtk_action_group_add_actions (action_group, entries, G_N_ELEMENTS (entries), logview);
1283
 
  gtk_action_group_add_toggle_actions (action_group, toggle_entries, G_N_ELEMENTS (toggle_entries), logview);
1284
 
  priv->action_group = action_group;
1285
 
  priv->auto_scroll = TRUE;
1286
 
 
1287
 
  priv->ui_manager = gtk_ui_manager_new ();
1288
 
 
1289
 
  gtk_ui_manager_insert_action_group (priv->ui_manager, action_group, 0);
1290
 
  accel_group = gtk_ui_manager_get_accel_group (priv->ui_manager);
1291
 
  gtk_window_add_accel_group (GTK_WINDOW (logview), accel_group);
1292
 
 
1293
 
  res = gtk_ui_manager_add_ui_from_file (priv->ui_manager,
1294
 
                                         LOGVIEW_DATADIR "/logview-toolbar.xml",
1295
 
                                         &error);
1296
 
 
1297
 
  if (res == FALSE) {
1298
 
    priv->ui_manager = NULL;
1299
 
    g_critical ("Can't load the UI description: %s", error->message);
1300
 
    g_error_free (error);
1301
 
    return;
1302
 
  }
1303
 
 
1304
 
  gtk_ui_manager_set_add_tearoffs (priv->ui_manager,
1305
 
                                   logview_prefs_get_have_tearoff (priv->prefs));
1306
 
 
1307
 
  w = gtk_ui_manager_get_widget (priv->ui_manager, "/LogviewMenu");
1308
 
  gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 0);
1309
 
  gtk_widget_show (w);
1310
 
  
1311
 
  /* panes */
1312
 
  hpaned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
1313
 
  gtk_box_pack_start (GTK_BOX (vbox), hpaned, TRUE, TRUE, 0);
1314
 
  priv->hpaned = hpaned;
1315
 
  gtk_widget_show (hpaned);
1316
 
 
1317
 
  /* first pane : sidebar (list of logs) */
1318
 
  priv->sidebar = gtk_vbox_new (FALSE, 0);
1319
 
  gtk_widget_show (priv->sidebar);
1320
 
 
1321
 
  /* first pane: log list */
1322
 
  w = gtk_scrolled_window_new (NULL, NULL);
1323
 
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (w),
1324
 
                                  GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1325
 
  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (w),
1326
 
                                       GTK_SHADOW_ETCHED_IN);
1327
 
 
1328
 
  priv->loglist = logview_loglist_new ();
1329
 
  gtk_container_add (GTK_CONTAINER (w), priv->loglist);
1330
 
  gtk_box_pack_start (GTK_BOX (priv->sidebar), w, TRUE, TRUE, 0);
1331
 
  gtk_paned_pack1 (GTK_PANED (hpaned), priv->sidebar, FALSE, FALSE);
1332
 
  gtk_widget_show (w);
1333
 
  gtk_widget_show (priv->loglist);
1334
 
 
1335
 
  g_signal_connect (priv->loglist, "day_selected",
1336
 
                    G_CALLBACK (loglist_day_selected_cb), logview);
1337
 
  g_signal_connect (priv->loglist, "day_cleared",
1338
 
                    G_CALLBACK (loglist_day_cleared_cb), logview);
1339
 
 
1340
 
  /* second pane: log */
1341
 
  main_view = gtk_vbox_new (FALSE, 0);
1342
 
  gtk_paned_pack2 (GTK_PANED (hpaned), main_view, TRUE, TRUE);
1343
 
 
1344
 
  /* second pane: error message area */
1345
 
  priv->message_area = gtk_info_bar_new ();
1346
 
  message_area_create_error_box (logview, priv->message_area);
1347
 
  gtk_info_bar_add_button (GTK_INFO_BAR (priv->message_area),
1348
 
                           GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE);
1349
 
  gtk_box_pack_start (GTK_BOX (main_view), priv->message_area, FALSE, FALSE, 0);
1350
 
 
1351
 
  /* second pane: text view */
1352
 
  w = gtk_scrolled_window_new (NULL, NULL);
1353
 
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (w),
1354
 
                                  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1355
 
  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (w), GTK_SHADOW_IN);
1356
 
  gtk_box_pack_start (GTK_BOX (main_view), w, TRUE, TRUE, 0);
1357
 
  gtk_widget_show (w);
1358
 
 
1359
 
  priv->tag_table = gtk_text_tag_table_new ();
1360
 
  populate_tag_table (priv->tag_table);
1361
 
  priv->text_view = gtk_text_view_new ();
1362
 
  g_object_set (priv->text_view, "editable", FALSE, NULL);
1363
 
 
1364
 
  gtk_container_add (GTK_CONTAINER (w), priv->text_view);
1365
 
  gtk_widget_show (priv->text_view);
1366
 
 
1367
 
  /* use the desktop monospace font */
1368
 
  monospace_font_name = logview_prefs_get_monospace_font_name (priv->prefs);
1369
 
  logview_set_font (logview, monospace_font_name);
1370
 
  g_free (monospace_font_name);
1371
 
 
1372
 
  /* remember the original font size */
1373
 
  context = gtk_widget_get_pango_context (priv->text_view);
1374
 
  fontdesc = pango_context_get_font_description (context);
1375
 
  priv->original_fontsize = pango_font_description_get_size (fontdesc) / PANGO_SCALE;
1376
 
 
1377
 
  /* restore saved zoom */
1378
 
  priv->fontsize = logview_prefs_get_stored_fontsize (priv->prefs);
1379
 
 
1380
 
  if (priv->fontsize <= 0) {
1381
 
    /* restore the default */
1382
 
    logview_normal_text (NULL, logview);
1383
 
  } else {
1384
 
    logview_set_fontsize (logview, FALSE);
1385
 
  }
1386
 
 
1387
 
  /* version selector */
1388
 
  priv->version_bar = gtk_hbox_new (FALSE, 0);
1389
 
  gtk_container_set_border_width (GTK_CONTAINER (priv->version_bar), 3);
1390
 
  priv->version_selector = gtk_combo_box_text_new ();
1391
 
  g_signal_connect (priv->version_selector, "changed",
1392
 
                    G_CALLBACK (logview_version_selector_changed), logview);
1393
 
  w = gtk_label_new (_("Version: "));
1394
 
 
1395
 
  gtk_box_pack_end (GTK_BOX (priv->version_bar), priv->version_selector, FALSE, FALSE, 0);
1396
 
  gtk_box_pack_end (GTK_BOX (priv->version_bar), w, FALSE, FALSE, 0);
1397
 
  gtk_box_pack_end (GTK_BOX (main_view), priv->version_bar, FALSE, FALSE, 0);
1398
 
 
1399
 
  priv->find_bar = logview_findbar_new ();
1400
 
  gtk_box_pack_end (GTK_BOX (main_view), priv->find_bar, FALSE, FALSE, 0);
1401
 
 
1402
 
  g_signal_connect (priv->find_bar, "previous",
1403
 
                    G_CALLBACK (findbar_previous_cb), logview);
1404
 
  g_signal_connect (priv->find_bar, "next",
1405
 
                    G_CALLBACK (findbar_next_cb), logview);
1406
 
  g_signal_connect (priv->find_bar, "text_changed",
1407
 
                    G_CALLBACK (findbar_text_changed_cb), logview);
1408
 
  g_signal_connect (priv->find_bar, "close",
1409
 
                    G_CALLBACK (findbar_close_cb), logview);
1410
 
 
1411
 
  /* signal handlers
1412
 
   * - first is used to remember/restore the window size on quit.
1413
 
   */
1414
 
  g_signal_connect (logview, "configure_event",
1415
 
                    G_CALLBACK (window_size_changed_cb), logview);
1416
 
  g_signal_connect (priv->prefs, "system-font-changed",
1417
 
                    G_CALLBACK (font_changed_cb), logview);
1418
 
  g_signal_connect (priv->prefs, "have-tearoff-changed",
1419
 
                    G_CALLBACK (tearoff_changed_cb), logview);
1420
 
  g_signal_connect (priv->manager, "active-changed",
1421
 
                    G_CALLBACK (active_log_changed_cb), logview);
1422
 
  g_signal_connect (logview, "style-set",
1423
 
                    G_CALLBACK (style_set_cb), logview);
1424
 
  g_signal_connect (logview, "key-press-event",
1425
 
                    G_CALLBACK (key_press_event_cb), logview);
1426
 
 
1427
 
  /* status area at bottom */
1428
 
  priv->statusbar = gtk_statusbar_new ();
1429
 
  gtk_box_pack_start (GTK_BOX (vbox), priv->statusbar, FALSE, FALSE, 0);
1430
 
  gtk_widget_show (priv->statusbar);
1431
 
 
1432
 
  /* Filter menu */
1433
 
  priv->filter_action_group = gtk_action_group_new ("ActionGroupFilter");
1434
 
  gtk_ui_manager_insert_action_group (priv->ui_manager, priv->filter_action_group,
1435
 
                                      1);
1436
 
  priv->active_filters = NULL;
1437
 
  update_filter_menu (logview);
1438
 
  
1439
 
  gtk_widget_show (vbox);
1440
 
  gtk_widget_show (main_view);
1441
 
}
1442
 
 
1443
 
static void
1444
 
logview_window_class_init (LogviewWindowClass *klass)
1445
 
{
1446
 
  GObjectClass *object_class = (GObjectClass *) klass;
1447
 
 
1448
 
  object_class->finalize = logview_window_finalize;
1449
 
 
1450
 
  g_type_class_add_private (klass, sizeof (LogviewWindowPrivate));
1451
 
}
1452
 
 
1453
 
/* public methods */
1454
 
 
1455
 
GtkWidget *
1456
 
logview_window_new ()
1457
 
{
1458
 
  LogviewWindow *logview;
1459
 
 
1460
 
  logview = g_object_new (LOGVIEW_TYPE_WINDOW, NULL);
1461
 
 
1462
 
  if (logview->priv->ui_manager == NULL) {
1463
 
    return NULL;
1464
 
  }
1465
 
 
1466
 
  return GTK_WIDGET (logview);
1467
 
}
1468
 
 
1469
 
void
1470
 
logview_window_add_error (LogviewWindow *window,
1471
 
                          const char *primary,
1472
 
                          const char *secondary)
1473
 
{
1474
 
  LogviewWindowPrivate *priv;
1475
 
 
1476
 
  g_assert (LOGVIEW_IS_WINDOW (window));
1477
 
  priv = window->priv;
1478
 
 
1479
 
  message_area_set_labels (window,
1480
 
                           primary, secondary); 
1481
 
 
1482
 
  gtk_widget_show (priv->message_area);
1483
 
 
1484
 
  g_signal_connect (priv->message_area, "response",
1485
 
                    G_CALLBACK (message_area_response_cb), window);
1486
 
}
1487
 
 
1488
 
void
1489
 
logview_window_add_errors (LogviewWindow *window,
1490
 
                           GPtrArray *errors)
1491
 
{
1492
 
  char *primary, *secondary;
1493
 
  GString *str;
1494
 
  char **err;
1495
 
  int i;
1496
 
 
1497
 
  g_assert (LOGVIEW_IS_WINDOW (window));
1498
 
  g_assert (errors->len > 1);
1499
 
 
1500
 
  primary = g_strdup (_("Could not open the following files:"));
1501
 
  str = g_string_new (NULL);
1502
 
 
1503
 
  for (i = 0; i < errors->len; i++) {
1504
 
    err = (char **) g_ptr_array_index (errors, i);
1505
 
    g_string_append (str, err[0]);
1506
 
    g_string_append (str, ": ");
1507
 
    g_string_append (str, err[1]);
1508
 
    g_string_append (str, "\n");
1509
 
  }
1510
 
 
1511
 
  secondary = g_string_free (str, FALSE);
1512
 
 
1513
 
  message_area_set_labels (window, primary, secondary);
1514
 
 
1515
 
  gtk_widget_show (window->priv->message_area);
1516
 
 
1517
 
  g_signal_connect (window->priv->message_area, "response",
1518
 
                    G_CALLBACK (message_area_response_cb), window);
1519
 
 
1520
 
  g_free (primary);
1521
 
  g_free (secondary);
1522
 
}
1523
 
 
1524