1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
2 /* logview-window.c - main window of logview
4 * Copyright (C) 1998 Cesar Miquel <miquel@df.uba.ar>
5 * Copyright (C) 2008 Cosimo Cecchi <cosimoc@gnome.org>
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.
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.
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.
26 #include <gdk/gdkkeysyms.h>
27 #include <glib/gi18n.h>
29 #include "logview-window.h"
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"
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"
42 struct _LogviewWindowPrivate
{
43 GtkUIManager
*ui_manager
;
44 GtkActionGroup
*action_group
;
45 GtkActionGroup
*filter_action_group
;
50 GtkWidget
*version_bar
;
51 GtkWidget
*version_selector
;
56 GtkWidget
*message_area
;
57 GtkWidget
*message_primary
;
58 GtkWidget
*message_secondary
;
60 GtkTextTagTable
*tag_table
;
62 int original_fontsize
, fontsize
;
65 LogviewManager
*manager
;
68 guint search_timeout_id
;
70 guint filter_merge_id
;
71 GList
*active_filters
;
72 gboolean matches_only
;
76 #define GET_PRIVATE(o) \
77 (G_TYPE_INSTANCE_GET_PRIVATE ((o), LOGVIEW_TYPE_WINDOW, LogviewWindowPrivate))
79 G_DEFINE_TYPE (LogviewWindow
, logview_window
, GTK_TYPE_WINDOW
);
81 static void findbar_close_cb (LogviewFindbar
*findbar
,
83 static void read_new_lines_cb (LogviewLog
*log
,
89 /* private functions */
92 logview_version_selector_changed (GtkComboBox
*version_selector
, gpointer user_data
)
97 LogviewWindow
*logview
= user_data
;
98 Log
*log
= logview
->curlog
;
101 g_assert (LOGVIEW_IS_WINDOW (logview
));
103 selected
= gtk_combo_box_get_active (version_selector
);
105 if (selected
== log
->current_version
)
108 /* select a new version */
110 logview_select_log (logview
, log
->parent_log
);
113 if (log
->parent_log
) {
114 new = log
->parent_log
->older_logs
[selected
];
116 new = log
->older_logs
[selected
];
119 logview_select_log (logview
, new);
125 /* private helpers */
128 populate_tag_table (GtkTextTagTable
*tag_table
)
132 tag
= gtk_text_tag_new ("bold");
133 g_object_set (tag
, "weight", PANGO_WEIGHT_BOLD
,
134 "weight-set", TRUE
, NULL
);
136 gtk_text_tag_table_add (tag_table
, tag
);
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
);
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
);
149 populate_style_tag_table (GtkStyle
*style
,
150 GtkTextTagTable
*tag_table
)
155 tag
= gtk_text_tag_table_lookup (tag_table
, "gray");
158 /* FIXME: do we need a way to update the buffer/view? */
159 gtk_text_tag_table_remove (tag_table
, tag
);
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
);
166 gtk_text_tag_table_add (tag_table
, tag
);
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
)
173 GtkTextIter start
, end
;
176 gtk_text_buffer_get_iter_at_line (buffer
, &start
, line_start
);
177 gtk_text_buffer_get_iter_at_line (buffer
, &end
, line_start
);
179 for (line_cur
= line_start
; line_cur
< line_end
+ 1; line_cur
++) {
181 if (offset_start
> 0) {
182 gtk_text_iter_forward_chars (&start
, offset_start
);
185 gtk_text_iter_forward_chars (&end
, offset_end
);
187 gtk_text_buffer_apply_tag_by_name (buffer
, tag_name
, &start
, &end
);
189 gtk_text_iter_forward_line (&start
);
190 gtk_text_iter_forward_line (&end
);
195 logview_update_statusbar (LogviewWindow
*logview
, LogviewLog
*active
)
197 char *statusbar_text
;
198 char *size
, *modified
, *timestring_utf8
;
200 char timestring
[255];
202 if (active
== NULL
) {
203 gtk_statusbar_pop (GTK_STATUSBAR (logview
->priv
->statusbar
), 0);
207 timestamp
= logview_log_get_timestamp (active
);
208 strftime (timestring
, sizeof (timestring
), "%a %b %e %T %Y", localtime (×tamp
));
209 timestring_utf8
= g_locale_to_utf8 (timestring
, -1, NULL
, NULL
, NULL
);
211 modified
= g_strdup_printf (_("last update: %s"), timestring_utf8
);
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
),
218 gtk_statusbar_pop (GTK_STATUSBAR (logview
->priv
->statusbar
), 0);
219 gtk_statusbar_push (GTK_STATUSBAR (logview
->priv
->statusbar
), 0, statusbar_text
);
222 g_free (timestring_utf8
);
224 g_free (statusbar_text
);
227 #define DEFAULT_LOGVIEW_FONT "Monospace 10"
230 logview_set_font (LogviewWindow
*logview
,
231 const char *fontname
)
233 PangoFontDescription
*font_desc
;
235 if (fontname
== NULL
)
236 fontname
= DEFAULT_LOGVIEW_FONT
;
238 font_desc
= pango_font_description_from_string (fontname
);
240 gtk_widget_modify_font (logview
->priv
->text_view
, font_desc
);
241 pango_font_description_free (font_desc
);
246 logview_set_fontsize (LogviewWindow
*logview
, gboolean store
)
248 PangoFontDescription
*fontdesc
;
249 PangoContext
*context
;
250 LogviewWindowPrivate
*priv
= logview
->priv
;
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
);
258 logview_prefs_store_fontsize (logview
->priv
->prefs
, priv
->fontsize
);
263 logview_set_window_title (LogviewWindow
*logview
, const char * log_name
)
268 window_title
= g_strdup_printf ("%s - %s", log_name
, APP_NAME
);
270 window_title
= g_strdup_printf (APP_NAME
);
273 gtk_window_set_title (GTK_WINDOW (logview
), window_title
);
275 g_free (window_title
);
278 /* actions callbacks */
281 open_file_selected_cb (GtkWidget
*chooser
, gint response
, LogviewWindow
*logview
)
287 gtk_widget_hide (GTK_WIDGET (chooser
));
288 if (response
!= GTK_RESPONSE_OK
) {
292 f
= gtk_file_chooser_get_file (GTK_FILE_CHOOSER (chooser
));
293 file_uri
= g_file_get_uri (f
);
295 log
= logview_manager_get_if_loaded (logview
->priv
->manager
, file_uri
);
300 logview_manager_set_active_log (logview
->priv
->manager
, log
);
301 g_object_unref (log
);
305 logview_manager_add_log_from_gfile (logview
->priv
->manager
, f
, TRUE
);
312 logview_open_log (GtkAction
*action
, LogviewWindow
*logview
)
314 static GtkWidget
*chooser
= NULL
;
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
,
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
);
337 gtk_window_present (GTK_WINDOW (chooser
));
341 logview_close_log (GtkAction
*action
, LogviewWindow
*logview
)
343 findbar_close_cb (LOGVIEW_FINDBAR (logview
->priv
->find_bar
), logview
);
344 logview_manager_close_active_log (logview
->priv
->manager
);
348 logview_help (GtkAction
*action
, GtkWidget
*parent_window
)
350 GError
*error
= NULL
;
352 gtk_show_uri (gtk_widget_get_screen (parent_window
),
353 "ghelp:gnome-system-log", gtk_get_current_event_time (),
357 g_warning (_("There was an error displaying help: %s"), error
->message
);
358 g_error_free (error
);
363 logview_bigger_text (GtkAction
*action
, LogviewWindow
*logview
)
365 logview
->priv
->fontsize
= MIN (logview
->priv
->fontsize
+ 1, 24);
366 logview_set_fontsize (logview
, TRUE
);
370 logview_smaller_text (GtkAction
*action
, LogviewWindow
*logview
)
372 logview
->priv
->fontsize
= MAX (logview
->priv
->fontsize
-1, 6);
373 logview_set_fontsize (logview
, TRUE
);
377 logview_normal_text (GtkAction
*action
, LogviewWindow
*logview
)
379 logview
->priv
->fontsize
= logview
->priv
->original_fontsize
;
380 logview_set_fontsize (logview
, TRUE
);
384 logview_select_all (GtkAction
*action
, LogviewWindow
*logview
)
386 GtkTextIter start
, end
;
387 GtkTextBuffer
*buffer
;
389 buffer
= gtk_text_view_get_buffer (GTK_TEXT_VIEW (logview
->priv
->text_view
));
391 gtk_text_buffer_get_bounds (buffer
, &start
, &end
);
392 gtk_text_buffer_select_range (buffer
, &start
, &end
);
394 gtk_widget_grab_focus (GTK_WIDGET (logview
->priv
->text_view
));
398 logview_copy (GtkAction
*action
, LogviewWindow
*logview
)
400 GtkTextBuffer
*buffer
;
401 GtkClipboard
*clipboard
;
403 buffer
= gtk_text_view_get_buffer (GTK_TEXT_VIEW (logview
->priv
->text_view
));
404 clipboard
= gtk_clipboard_get (GDK_SELECTION_CLIPBOARD
);
406 gtk_text_buffer_copy_clipboard (buffer
, clipboard
);
408 gtk_widget_grab_focus (GTK_WIDGET (logview
->priv
->text_view
));
412 findbar_close_cb (LogviewFindbar
*findbar
,
415 gtk_widget_hide (GTK_WIDGET (findbar
));
416 logview_findbar_set_message (findbar
, NULL
);
420 logview_search_text (LogviewWindow
*logview
, gboolean forward
)
422 GtkTextBuffer
*buffer
;
423 GtkTextMark
*search_start
, *search_end
;
424 GtkTextIter search
, start_m
, end_m
;
426 gboolean res
, wrapped
;
430 text
= logview_findbar_get_text (LOGVIEW_FINDBAR (logview
->priv
->find_bar
));
432 if (!text
|| g_strcmp0 (text
, "") == 0) {
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
);
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
,
445 search_end
= gtk_text_buffer_create_mark (buffer
, SEARCH_END_MARK
,
449 gtk_text_buffer_get_iter_at_mark (buffer
, &search
, search_end
);
451 gtk_text_buffer_get_iter_at_mark (buffer
, &search
, search_start
);
458 res
= gtk_text_iter_forward_search (&search
, text
, GTK_TEXT_SEARCH_VISIBLE_ONLY
, &start_m
, &end_m
, NULL
);
460 res
= gtk_text_iter_backward_search (&search
, text
, GTK_TEXT_SEARCH_VISIBLE_ONLY
, &start_m
, &end_m
, NULL
);
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
);
468 gtk_text_view_scroll_mark_onscreen (GTK_TEXT_VIEW (logview
->priv
->text_view
), search_end
);
471 logview_findbar_set_message (LOGVIEW_FINDBAR (logview
->priv
->find_bar
), _("Wrapped"));
479 if (gtk_text_buffer_get_has_selection (buffer
)) {
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
);
486 logview_findbar_set_message (LOGVIEW_FINDBAR (logview
->priv
->find_bar
), _("Not found"));
489 gtk_text_buffer_get_start_iter (buffer
, &search
);
491 gtk_text_buffer_get_end_iter (buffer
, &search
);
501 findbar_previous_cb (LogviewFindbar
*findbar
,
504 LogviewWindow
*logview
= user_data
;
506 logview_search_text (logview
, FALSE
);
510 findbar_next_cb (LogviewFindbar
*findbar
,
513 LogviewWindow
*logview
= user_data
;
515 logview_search_text (logview
, TRUE
);
519 text_changed_timeout_cb (gpointer user_data
)
521 LogviewWindow
*logview
= user_data
;
522 GtkTextMark
*search_start
, *search_end
;
524 GtkTextBuffer
*buffer
;
526 logview
->priv
->search_timeout_id
= 0;
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
);
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
);
539 logview_findbar_set_message (LOGVIEW_FINDBAR (logview
->priv
->find_bar
), NULL
);
541 logview_search_text (logview
, TRUE
);
547 findbar_text_changed_cb (LogviewFindbar
*findbar
,
550 LogviewWindow
*logview
= user_data
;
552 if (logview
->priv
->search_timeout_id
!= 0) {
553 g_source_remove (logview
->priv
->search_timeout_id
);
556 logview
->priv
->search_timeout_id
= g_timeout_add (300, text_changed_timeout_cb
, logview
);
560 logview_search (GtkAction
*action
, LogviewWindow
*logview
)
562 logview_findbar_open (LOGVIEW_FINDBAR (logview
->priv
->find_bar
));
566 filter_buffer (LogviewWindow
*logview
, gint start_line
)
568 GtkTextBuffer
*buffer
;
569 GtkTextIter start
, *end
;
575 buffer
= gtk_text_view_get_buffer (GTK_TEXT_VIEW (logview
->priv
->text_view
));
576 lines
= gtk_text_buffer_get_line_count (buffer
);
578 for (i
= start_line
; i
< lines
; i
++) {
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
);
585 text
= gtk_text_buffer_get_text (buffer
, &start
, end
, TRUE
);
587 for (cur_filter
= logview
->priv
->active_filters
; cur_filter
!= NULL
;
588 cur_filter
= g_list_next (cur_filter
))
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
)),
600 if (!matched
&& logview
->priv
->matches_only
) {
601 gtk_text_buffer_apply_tag_by_name (buffer
,
605 gtk_text_buffer_remove_tag_by_name (buffer
,
610 gtk_text_iter_free (end
);
615 filter_remove (LogviewWindow
*logview
, LogviewFilter
*filter
)
617 GtkTextIter start
, end
;
618 GtkTextBuffer
*buffer
;
620 buffer
= gtk_text_view_get_buffer (GTK_TEXT_VIEW (logview
->priv
->text_view
));
621 gtk_text_buffer_get_bounds (buffer
, &start
, &end
);
623 gtk_text_buffer_remove_tag (buffer
, logview_filter_get_tag (filter
),
628 on_filter_toggled (GtkToggleAction
*action
, LogviewWindow
*logview
)
630 LogviewWindowPrivate
*priv
= GET_PRIVATE (logview
);
632 LogviewFilter
*filter
;
634 name
= gtk_action_get_name (GTK_ACTION (action
));
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
,
640 filter_buffer(logview
, 0);
642 filter
= logview_prefs_get_filter (priv
->prefs
, name
);
643 priv
->active_filters
= g_list_remove (priv
->active_filters
,
646 filter_remove (logview
, filter
);
650 #define FILTER_PLACEHOLDER "/LogviewMenu/FilterMenu/PlaceholderFilters"
652 update_filter_menu (LogviewWindow
*window
)
654 LogviewWindowPrivate
*priv
;
659 GtkTextBuffer
*buffer
;
660 GtkTextTagTable
*table
;
662 GtkToggleAction
*action
;
665 priv
= GET_PRIVATE (window
);
666 ui
= priv
->ui_manager
;
668 g_return_if_fail (priv
->filter_action_group
!= NULL
);
670 buffer
= gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv
->text_view
));
671 table
= priv
->tag_table
;
673 if (priv
->filter_merge_id
!= 0) {
674 gtk_ui_manager_remove_ui (ui
,
675 priv
->filter_merge_id
);
678 actions
= gtk_action_group_list_actions (priv
->filter_action_group
);
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
);
684 g_signal_handlers_disconnect_by_func (GTK_ACTION (l
->data
),
685 G_CALLBACK (on_filter_toggled
),
687 gtk_action_group_remove_action (priv
->filter_action_group
,
688 GTK_ACTION (l
->data
));
691 g_list_free (actions
);
693 filters
= logview_prefs_get_filters (logview_prefs_get ());
695 id
= (g_list_length (filters
) > 0) ? gtk_ui_manager_new_merge_id (ui
) : 0;
697 for (l
= filters
; l
!= NULL
; l
= g_list_next (l
)) {
698 g_object_get (l
->data
, "name", &name
, NULL
);
700 action
= gtk_toggle_action_new (name
, name
, NULL
, NULL
);
701 gtk_action_group_add_action (priv
->filter_action_group
,
702 GTK_ACTION (action
));
704 g_signal_connect (action
,
706 G_CALLBACK (on_filter_toggled
),
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
)));
714 g_object_unref (action
);
718 g_list_free (filters
);
720 priv
->filter_merge_id
= id
;
724 on_logview_filter_manager_response (GtkDialog
*dialog
,
726 LogviewWindow
*logview
)
728 update_filter_menu (logview
);
730 g_list_free (logview
->priv
->active_filters
);
731 logview
->priv
->active_filters
= NULL
;
735 logview_manage_filters (GtkAction
*action
, LogviewWindow
*logview
)
739 manager
= logview_filter_manager_new ();
741 g_signal_connect (manager
, "response",
742 G_CALLBACK (on_logview_filter_manager_response
),
745 gtk_window_set_transient_for (GTK_WINDOW (manager
),
746 GTK_WINDOW (logview
));
747 gtk_widget_show (GTK_WIDGET (manager
));
751 logview_about (GtkWidget
*widget
, GtkWidget
*window
)
753 g_return_if_fail (GTK_IS_WINDOW (window
));
755 char *license_trans
= g_strjoin ("\n\n", _(logview_about_license
[0]),
756 _(logview_about_license
[1]),
757 _(logview_about_license
[2]), NULL
);
759 gtk_show_about_dialog (GTK_WINDOW (window
),
760 "name", _("System Log Viewer"),
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",
773 g_free (license_trans
);
779 logview_toggle_statusbar (GtkAction
*action
, LogviewWindow
*logview
)
781 if (gtk_widget_get_visible (logview
->priv
->statusbar
))
782 gtk_widget_hide (logview
->priv
->statusbar
);
784 gtk_widget_show (logview
->priv
->statusbar
);
788 logview_toggle_sidebar (GtkAction
*action
, LogviewWindow
*logview
)
790 if (gtk_widget_get_visible (logview
->priv
->sidebar
))
791 gtk_widget_hide (logview
->priv
->sidebar
);
793 gtk_widget_show (logview
->priv
->sidebar
);
797 logview_toggle_match_filters (GtkToggleAction
*action
, LogviewWindow
*logview
)
799 logview
->priv
->matches_only
= gtk_toggle_action_get_active (action
);
800 filter_buffer (logview
, 0);
804 logview_toggle_autoscroll (GtkToggleAction
*action
, LogviewWindow
*logview
)
806 logview
->priv
->auto_scroll
= gtk_toggle_action_get_active (action
);
809 /* GObject functions */
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
},
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
) },
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
) },
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
)},
841 { "FilterManage", NULL
, N_("Manage Filters"), NULL
, N_("Manage filters"),
842 G_CALLBACK (logview_manage_filters
)},
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
) },
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
}
862 window_size_changed_cb (GtkWidget
*widget
, GdkEventConfigure
*event
,
865 LogviewWindow
*window
= data
;
867 logview_prefs_store_window_size (window
->priv
->prefs
,
868 event
->width
, event
->height
);
874 real_select_day (LogviewWindow
*logview
,
875 GDate
*date
, int first_line
, int last_line
)
877 GtkTextBuffer
*buffer
;
878 GtkTextIter start_iter
, end_iter
, start_vis
, end_vis
;
879 GdkRectangle visible_rect
;
881 buffer
= gtk_text_view_get_buffer (GTK_TEXT_VIEW (logview
->priv
->text_view
));
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);
887 /* clear all previous invisible tags */
888 gtk_text_buffer_remove_tag_by_name (buffer
, "invisible",
889 &start_iter
, &end_iter
);
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
);
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
),
899 gdk_window_invalidate_rect (gtk_widget_get_window (logview
->priv
->text_view
),
900 &visible_rect
, TRUE
);
904 loglist_day_selected_cb (LogviewLoglist
*loglist
,
908 LogviewWindow
*logview
= user_data
;
910 real_select_day (logview
, day
->date
, day
->first_line
, day
->last_line
);
914 loglist_day_cleared_cb (LogviewLoglist
*loglist
,
917 LogviewWindow
*logview
= user_data
;
918 GtkTextBuffer
*buffer
;
919 GtkTextIter start
, end
;
921 buffer
= gtk_text_view_get_buffer (GTK_TEXT_VIEW (logview
->priv
->text_view
));
922 gtk_text_buffer_get_bounds (buffer
, &start
, &end
);
924 /* clear all previous invisible tags */
925 gtk_text_buffer_remove_tag_by_name (buffer
, "invisible",
930 log_monitor_changed_cb (LogviewLog
*log
,
933 /* reschedule a read */
934 logview_log_read_new_lines (log
, (LogviewNewLinesCallback
) read_new_lines_cb
,
939 paint_timestamps (GtkTextBuffer
*buffer
, int old_line_count
,
944 for (l
= days
; l
; l
= l
->next
) {
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");
955 read_new_lines_cb (LogviewLog
*log
,
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
;
967 char *converted
, *primary
;
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
);
980 /* there's no error, but no lines have been read */
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;
988 if (gtk_text_buffer_get_char_count (buffer
) != 0) {
992 gtk_text_buffer_get_end_iter (buffer
, &iter
);
995 mark
= gtk_text_buffer_create_mark (buffer
, NULL
, &iter
, TRUE
);
998 for (i
= 0; lines
[i
]; i
++) {
999 len
= strlen (lines
[i
]);
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
);
1005 gtk_text_buffer_insert (buffer
, &iter
, lines
[i
], strlen (lines
[i
]));
1008 gtk_text_iter_forward_to_end (&iter
);
1009 gtk_text_buffer_insert (buffer
, &iter
, "\n", 1);
1010 gtk_text_iter_forward_char (&iter
);
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
);
1018 filter_buffer (window
, filter_start_line
);
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);
1025 paint_timestamps (buffer
, old_line_count
, new_days
);
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
);
1032 logview_update_statusbar (window
, log
);
1033 logview_loglist_update_lines (LOGVIEW_LOGLIST (window
->priv
->loglist
), log
);
1037 active_log_changed_cb (LogviewManager
*manager
,
1039 LogviewLog
*old_log
,
1042 LogviewWindow
*window
= data
;
1044 GtkTextBuffer
*buffer
;
1046 findbar_close_cb (LOGVIEW_FINDBAR (window
->priv
->find_bar
),
1049 logview_set_window_title (window
, logview_log_get_display_name (log
));
1051 if (window
->priv
->monitor_id
) {
1052 g_signal_handler_disconnect (old_log
, window
->priv
->monitor_id
);
1053 window
->priv
->monitor_id
= 0;
1056 lines
= logview_log_get_cached_lines (log
);
1057 buffer
= gtk_text_buffer_new (window
->priv
->tag_table
);
1059 if (lines
!= NULL
) {
1063 /* update the text view to show the current lines */
1064 gtk_text_buffer_get_end_iter (buffer
, &iter
);
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
);
1073 paint_timestamps (buffer
, 1, logview_log_get_days_for_cached_lines (log
));
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
);
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
);
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.
1090 gtk_text_view_set_buffer (GTK_TEXT_VIEW (window
->priv
->text_view
), buffer
);
1091 g_object_unref (buffer
);
1095 font_changed_cb (LogviewPrefs
*prefs
,
1096 const char *font_name
,
1099 LogviewWindow
*window
= user_data
;
1101 logview_set_font (window
, font_name
);
1105 tearoff_changed_cb (LogviewPrefs
*prefs
,
1106 gboolean have_tearoffs
,
1109 LogviewWindow
*window
= user_data
;
1111 gtk_ui_manager_set_add_tearoffs (window
->priv
->ui_manager
, have_tearoffs
);
1115 style_set_cb (GtkWidget
*widget
,
1119 LogviewWindow
*logview
= user_data
;
1120 GtkStyle
*style
= gtk_widget_get_style (widget
);
1122 populate_style_tag_table (style
, logview
->priv
->tag_table
);
1125 static const struct {
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" }
1136 key_press_event_cb (GtkWidget
*widget
,
1140 LogviewWindow
*window
= user_data
;
1141 guint modifier
= event
->state
& gtk_accelerator_get_default_mod_mask ();
1145 /* handle accelerators that we want bound, but aren't associated with
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
) {
1151 action
= gtk_action_group_get_action (window
->priv
->action_group
,
1152 extra_keybindings
[i
].action
);
1153 gtk_action_activate (action
);
1161 /* adapted from GEdit */
1164 message_area_create_error_box (LogviewWindow
*window
,
1165 GtkWidget
*message_area
)
1167 GtkWidget
*hbox_content
;
1170 GtkWidget
*primary_label
;
1171 GtkWidget
*secondary_label
;
1173 hbox_content
= gtk_hbox_new (FALSE
, 8);
1174 gtk_widget_show (hbox_content
);
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);
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);
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
);
1195 window
->priv
->message_primary
= primary_label
;
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);
1206 window
->priv
->message_secondary
= secondary_label
;
1209 (GTK_CONTAINER (gtk_info_bar_get_content_area
1210 (GTK_INFO_BAR (message_area
))),
1215 message_area_set_labels (LogviewWindow
*window
,
1216 const char *primary
,
1217 const char *secondary
)
1219 char *primary_markup
, *secondary_markup
;
1221 primary_markup
= g_markup_printf_escaped ("<b>%s</b>", primary
);
1222 secondary_markup
= g_markup_printf_escaped ("<small>%s</small>",
1225 gtk_label_set_markup (GTK_LABEL (window
->priv
->message_primary
),
1227 gtk_label_set_markup (GTK_LABEL (window
->priv
->message_secondary
),
1230 g_free (primary_markup
);
1231 g_free (secondary_markup
);
1235 message_area_response_cb (GtkInfoBar
*message_area
,
1236 int response_id
, gpointer user_data
)
1238 gtk_widget_hide (GTK_WIDGET (message_area
));
1240 g_signal_handlers_disconnect_by_func (message_area
,
1241 message_area_response_cb
,
1246 logview_window_finalize (GObject
*object
)
1248 LogviewWindow
*logview
= LOGVIEW_WINDOW (object
);
1250 g_object_unref (logview
->priv
->ui_manager
);
1251 G_OBJECT_CLASS (logview_window_parent_class
)->finalize (object
);
1255 logview_window_init (LogviewWindow
*logview
)
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
;
1268 priv
= logview
->priv
= GET_PRIVATE (logview
);
1269 priv
->prefs
= logview_prefs_get ();
1270 priv
->manager
= logview_manager_get ();
1271 priv
->monitor_id
= 0;
1273 logview_prefs_get_stored_window_size (priv
->prefs
, &width
, &height
);
1274 gtk_window_set_default_size (GTK_WINDOW (logview
), width
, height
);
1276 vbox
= gtk_vbox_new (FALSE
, 0);
1277 gtk_container_add (GTK_CONTAINER (logview
), vbox
);
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
;
1287 priv
->ui_manager
= gtk_ui_manager_new ();
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
);
1293 res
= gtk_ui_manager_add_ui_from_file (priv
->ui_manager
,
1294 LOGVIEW_DATADIR
"/logview-toolbar.xml",
1298 priv
->ui_manager
= NULL
;
1299 g_critical ("Can't load the UI description: %s", error
->message
);
1300 g_error_free (error
);
1304 gtk_ui_manager_set_add_tearoffs (priv
->ui_manager
,
1305 logview_prefs_get_have_tearoff (priv
->prefs
));
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
);
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
);
1317 /* first pane : sidebar (list of logs) */
1318 priv
->sidebar
= gtk_vbox_new (FALSE
, 0);
1319 gtk_widget_show (priv
->sidebar
);
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
);
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
);
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
);
1340 /* second pane: log */
1341 main_view
= gtk_vbox_new (FALSE
, 0);
1342 gtk_paned_pack2 (GTK_PANED (hpaned
), main_view
, TRUE
, TRUE
);
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);
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
);
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
);
1364 gtk_container_add (GTK_CONTAINER (w
), priv
->text_view
);
1365 gtk_widget_show (priv
->text_view
);
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
);
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
;
1377 /* restore saved zoom */
1378 priv
->fontsize
= logview_prefs_get_stored_fontsize (priv
->prefs
);
1380 if (priv
->fontsize
<= 0) {
1381 /* restore the default */
1382 logview_normal_text (NULL
, logview
);
1384 logview_set_fontsize (logview
, FALSE
);
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: "));
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);
1399 priv
->find_bar
= logview_findbar_new ();
1400 gtk_box_pack_end (GTK_BOX (main_view
), priv
->find_bar
, FALSE
, FALSE
, 0);
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
);
1412 * - first is used to remember/restore the window size on quit.
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
);
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
);
1433 priv
->filter_action_group
= gtk_action_group_new ("ActionGroupFilter");
1434 gtk_ui_manager_insert_action_group (priv
->ui_manager
, priv
->filter_action_group
,
1436 priv
->active_filters
= NULL
;
1437 update_filter_menu (logview
);
1439 gtk_widget_show (vbox
);
1440 gtk_widget_show (main_view
);
1444 logview_window_class_init (LogviewWindowClass
*klass
)
1446 GObjectClass
*object_class
= (GObjectClass
*) klass
;
1448 object_class
->finalize
= logview_window_finalize
;
1450 g_type_class_add_private (klass
, sizeof (LogviewWindowPrivate
));
1453 /* public methods */
1456 logview_window_new ()
1458 LogviewWindow
*logview
;
1460 logview
= g_object_new (LOGVIEW_TYPE_WINDOW
, NULL
);
1462 if (logview
->priv
->ui_manager
== NULL
) {
1466 return GTK_WIDGET (logview
);
1470 logview_window_add_error (LogviewWindow
*window
,
1471 const char *primary
,
1472 const char *secondary
)
1474 LogviewWindowPrivate
*priv
;
1476 g_assert (LOGVIEW_IS_WINDOW (window
));
1477 priv
= window
->priv
;
1479 message_area_set_labels (window
,
1480 primary
, secondary
);
1482 gtk_widget_show (priv
->message_area
);
1484 g_signal_connect (priv
->message_area
, "response",
1485 G_CALLBACK (message_area_response_cb
), window
);
1489 logview_window_add_errors (LogviewWindow
*window
,
1492 char *primary
, *secondary
;
1497 g_assert (LOGVIEW_IS_WINDOW (window
));
1498 g_assert (errors
->len
> 1);
1500 primary
= g_strdup (_("Could not open the following files:"));
1501 str
= g_string_new (NULL
);
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");
1511 secondary
= g_string_free (str
, FALSE
);
1513 message_area_set_labels (window
, primary
, secondary
);
1515 gtk_widget_show (window
->priv
->message_area
);
1517 g_signal_connect (window
->priv
->message_area
, "response",
1518 G_CALLBACK (message_area_response_cb
), window
);