1 /* gEDA - GPL Electronic Design Automation
2 * gschem - gEDA Schematic Capture
3 * Copyright (C) 1998-2010 Ales Hvezda
4 * Copyright (C) 1998-2020 gEDA Contributors (see ChangeLog for details)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 * \file gschem_log_dockable.c
23 * \brief GType class and functions to support the gschem log window.
29 #include <sys/types.h>
46 #include "../include/gschem_log_dockable.h"
49 static gpointer parent_class
= NULL
;
52 apply_tag_cb (GtkTextBuffer
*buffer
, GtkTextTag
*tag
,
53 GtkTextIter
*start
, GtkTextIter
*end
,
54 GschemLogDockable
*dockable
);
57 class_init (GschemLogDockableClass
*class);
63 create_widget (GschemDockable
*parent
);
66 dispose (GObject
*object
);
69 x_log_message (const gchar
*log_domain
, GLogLevelFlags log_level
, const gchar
*message
);
72 log_message (GschemLogDockableClass
*klass
, const gchar
*message
, const gchar
*style
);
76 * \brief Get the Log class type
78 * \par Function Description
80 * On first call, registers the Log class with the GType dynamic type system.
81 * On subsequent calls, returns the saved value from first execution.
82 * \returns the type identifier for the Log class
85 gschem_log_dockable_get_type ()
87 static GType type
= 0;
90 static const GTypeInfo info
= {
91 sizeof(GschemLogDockableClass
),
93 NULL
, /* base_finalize */
94 (GClassInitFunc
) class_init
,
95 NULL
, /* class_finalize */
96 NULL
, /* class_data */
97 sizeof(GschemLogDockable
),
99 NULL
, /* instance_init */
102 type
= g_type_register_static (GSCHEM_TYPE_DOCKABLE
,
112 /*! \brief Add a message to the status log
114 * \param [in] log_domain
115 * \param [in] log_level The severity of the message
116 * \param [in] message The message to be displayed
119 x_log_message (const gchar
*log_domain
, GLogLevelFlags log_level
, const gchar
*message
)
121 GschemLogDockableClass
*klass
= GSCHEM_LOG_DOCKABLE_CLASS (g_type_class_peek_static (GSCHEM_TYPE_LOG_DOCKABLE
));
124 if (log_level
& (G_LOG_LEVEL_CRITICAL
| G_LOG_LEVEL_ERROR
)) {
126 } else if (log_level
& G_LOG_LEVEL_WARNING
) {
132 log_message (klass
, message
, style
);
137 * \brief Add a message to the log window
139 * \par Function Description
140 * \param [in] log The log instance
141 * \param [in] message The message to be logged
142 * \param [in] style The style to use in the text rendering
145 log_message (GschemLogDockableClass
*klass
, const gchar
*message
, const gchar
*style
)
149 g_return_if_fail (klass
!= NULL
);
150 g_return_if_fail (klass
->buffer
!= NULL
);
152 gtk_text_buffer_get_end_iter (klass
->buffer
, &iter
);
153 /* Apply the "plain" tag before the level-specific tag in order to
154 * reset the formatting */
156 if (g_utf8_validate (message
, -1, NULL
)) {
157 gtk_text_buffer_insert_with_tags_by_name (klass
->buffer
, &iter
, message
, -1,
158 "plain", style
, NULL
);
160 /* If UTF-8 wasn't valid (due to a system locale encoded filename or
161 * other string being included by mistake), log a warning, and print
162 * the original message to stderr, where it may be partly intelligible */
163 gtk_text_buffer_insert_with_tags_by_name (klass
->buffer
, &iter
,
164 _("** Invalid UTF-8 in log message. See stderr or gschem.log.\n"),
165 -1, "plain", style
, NULL
);
166 fprintf (stderr
, "%s", message
);
171 /*! \brief callback for tags being applied to the text buffer
173 * Applying tags to the buffer causes all text view widgets to scroll
174 * to the bottom. Additionally, for high priority tags, the log
175 * dockable is presented to the user.
177 * \param [in] buffer the text buffer triggering the event
178 * \param [in] tag the applied tag
179 * \param [in] start the start of the range the tag is applied to
180 * \param [in] end the end of the range the tag is applied to
181 * \param [in] dockable the dockable to scroll to the bottom
184 apply_tag_cb (GtkTextBuffer
*buffer
, GtkTextTag
*tag
,
185 GtkTextIter
*start
, GtkTextIter
*end
,
186 GschemLogDockable
*dockable
)
190 g_return_if_fail (buffer
!= NULL
);
191 g_return_if_fail (dockable
!= NULL
);
192 g_return_if_fail (dockable
->viewer
!= NULL
);
194 g_object_get (tag
, "name", &tag_name
, NULL
);
195 if ((strcmp (tag_name
, "critical") == 0 ||
196 strcmp (tag_name
, "warning") == 0))
197 gschem_dockable_present (GSCHEM_DOCKABLE (dockable
));
200 if (gtk_widget_get_realized (GTK_WIDGET (dockable
->viewer
)))
201 gtk_text_view_scroll_to_iter (dockable
->viewer
, end
, 0.0, TRUE
, 0.0, 1.0);
205 /*! \brief initialize class
208 class_init (GschemLogDockableClass
*klass
)
211 /* GObjectClass *gobject_class = G_OBJECT_CLASS (klass); */
213 klass
->buffer
= create_text_buffer ();
215 /* make it read the content of the current log file */
216 /* and add its contents to the dialog */
217 contents
= s_log_read ();
219 /* s_log_read can return NULL if the log file cannot be written to */
220 if (contents
!= NULL
) {
221 log_message (klass
, contents
, "old");
224 x_log_update_func
= x_log_message
;
227 GSCHEM_DOCKABLE_CLASS (klass
)->create_widget
= create_widget
;
228 G_OBJECT_CLASS (klass
)->dispose
= dispose
;
230 parent_class
= g_type_class_peek_parent (klass
);
234 /*! \brief create the text buffer for storing the status log contents
236 * \return a GtkTextBuffer for storing the status log
238 static GtkTextBuffer
*
241 GtkTextBuffer
*buffer
= gtk_text_buffer_new (NULL
);
243 /* Add some tags for highlighting log messages to the buffer */
244 gtk_text_buffer_create_tag (buffer
,
246 "foreground", "black",
247 "foreground-set", TRUE
,
248 "weight", PANGO_WEIGHT_NORMAL
,
252 /* The default "message" style is plain */
253 gtk_text_buffer_create_tag (buffer
, "message", NULL
);
255 /* "old" messages are in dark grey */
256 gtk_text_buffer_create_tag (buffer
,
258 "foreground", "#404040",
259 "foreground-set", TRUE
,
262 /* "warning" messages are printed in red */
263 gtk_text_buffer_create_tag (buffer
,
266 "foreground-set", TRUE
,
269 /* "critical" messages are bold red */
270 gtk_text_buffer_create_tag (buffer
,
273 "foreground-set", TRUE
,
274 "weight", PANGO_WEIGHT_BOLD
,
282 /*! \brief create widgets
284 * \param [in] parent an instance of the dockable
287 create_widget (GschemDockable
*parent
)
289 GschemLogDockable
*dockable
= GSCHEM_LOG_DOCKABLE (parent
);
291 GschemLogDockableClass
*klass
= GSCHEM_LOG_DOCKABLE_GET_CLASS (dockable
);
294 g_return_val_if_fail (klass
!= NULL
, NULL
);
295 g_return_val_if_fail (klass
->buffer
!= NULL
, NULL
);
296 g_return_val_if_fail (dockable
!= NULL
, NULL
);
298 scrolled
= gtk_scrolled_window_new (NULL
, NULL
);
300 dockable
->viewer
= GTK_TEXT_VIEW (g_object_new (GTK_TYPE_TEXT_VIEW
,
302 "buffer", klass
->buffer
,
306 gtk_container_add (GTK_CONTAINER (scrolled
), GTK_WIDGET (dockable
->viewer
));
308 g_signal_connect (klass
->buffer
,
310 G_CALLBACK (&apply_tag_cb
),
313 gtk_text_buffer_get_end_iter (klass
->buffer
, &iter
);
315 gtk_widget_show_all (scrolled
);
321 dispose (GObject
*object
)
323 g_signal_handlers_disconnect_by_data (
324 GSCHEM_LOG_DOCKABLE_GET_CLASS (object
)->buffer
, object
);
326 G_OBJECT_CLASS (parent_class
)->dispose (object
);