gschem

x_log.c

Go to the documentation of this file.
00001 /* gEDA - GPL Electronic Design Automation
00002  * gschem - gEDA Schematic Capture
00003  * Copyright (C) 1998-2010 Ales Hvezda
00004  * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details)
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00019  */
00020 
00021 /*
00022  * \file x_log.c
00023  * \brief GType class and functions to support the gschem log window.
00024  */
00025 
00026 #include <config.h>
00027 
00028 #include <stdio.h>
00029 #include <sys/types.h>
00030 #include <sys/stat.h>
00031 #ifdef HAVE_STDLIB_H
00032 #include <stdlib.h>
00033 #endif
00034 #ifdef HAVE_UNISTD_H
00035 #include <unistd.h>
00036 #endif
00037 #ifdef HAVE_FCNTL_H
00038 #include <fcntl.h>
00039 #endif
00040 #ifdef HAVE_STRING_H
00041 #include <string.h>
00042 #endif
00043 
00044 #include "gschem.h"
00045 
00046 #ifdef HAVE_LIBDMALLOC
00047 #include <dmalloc.h>
00048 #endif
00049 
00050 static void x_log_callback_response (GtkDialog *dialog,
00051                                      gint arg1,
00052                                      gpointer user_data);
00053 static void log_message (Log *log, 
00054                          const gchar *message, 
00055                          const gchar *style);
00056 
00057 static void log_class_init (LogClass *class);
00058 static void log_init       (Log *log);
00059 
00060 static GtkWidget *log_dialog = NULL;
00061 
00072 void x_log_open ()
00073 {
00074   if (log_dialog == NULL) {
00075     gchar *contents;
00076     
00077     log_dialog = GTK_WIDGET (g_object_new (TYPE_LOG,
00078                                            /* GtkWindow */
00079                                            "type", GTK_WINDOW_TOPLEVEL,
00080                                            /* GschemDialog */
00081                                            "settings-name", "log",
00082                                            /* "toplevel", TOPEVEL * */
00083                                            NULL));
00084 
00085     g_signal_connect (log_dialog,
00086                       "response",
00087                       G_CALLBACK (x_log_callback_response),
00088                       NULL);
00089 
00090     /* make it read the content of the current log file */
00091     /* and add its contents to the dialog */
00092     contents = s_log_read ();
00093 
00094     /* s_log_read can return NULL if the log file cannot be written to */
00095     if (contents == NULL)
00096     {
00097       return;
00098     }
00099 
00100     log_message (LOG (log_dialog), contents, "old");
00101     g_free (contents);
00102 
00103     x_log_update_func = x_log_message;
00104    
00105     if( auto_place_mode )
00106     gtk_widget_set_uposition( log_dialog, 10, 10); 
00107     gtk_widget_show (log_dialog);
00108   } else {
00109     g_assert (IS_LOG (log_dialog));
00110     gtk_window_present ((GtkWindow*)log_dialog);
00111   }
00112 
00113 }
00114 
00120 void x_log_close ()
00121 {
00122   if (log_dialog) {
00123     g_assert (IS_LOG (log_dialog));
00124     gtk_widget_destroy (log_dialog);
00125     x_log_update_func = NULL;
00126     log_dialog = NULL;
00127   }
00128 
00129 }
00130 
00140 void x_log_message (const gchar *log_domain, GLogLevelFlags log_level,
00141                     const gchar *message)
00142 {
00143   gchar *style;
00144   g_return_if_fail (log_dialog != NULL);
00145 
00146   if (log_level & (G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_ERROR)) {
00147     style = "critical";
00148   } else if (log_level & G_LOG_LEVEL_WARNING) {
00149     style = "warning";
00150   } else {
00151     style = "message";
00152   }
00153 
00154   log_message (LOG(log_dialog), message, style);
00155 }
00156 
00163 static void x_log_callback_response (GtkDialog *dialog,
00164                      gint arg1,
00165                      gpointer user_data)
00166 {
00167   switch (arg1) {
00168     case GTK_RESPONSE_DELETE_EVENT:
00169     case LOG_RESPONSE_CLOSE:
00170     g_assert (GTK_WIDGET (dialog) == log_dialog);
00171     x_log_close ();
00172     break;
00173     default:
00174     g_assert_not_reached ();
00175   }
00176   
00177 }
00178 
00187 static void log_message (Log *log, const gchar *message, 
00188                          const gchar *style)
00189 {
00190   GtkTextBuffer *buffer;
00191   GtkTextIter iter;
00192   GtkTextMark *mark;
00193   
00194   g_return_if_fail (IS_LOG (log));
00195 
00196   buffer = gtk_text_view_get_buffer (log->textview);
00197   gtk_text_buffer_get_end_iter (buffer, &iter);
00198   /* Apply the "plain" tag before the level-specific tag in order to
00199    * reset the formatting */
00200 
00201   if (g_utf8_validate (message, -1, NULL)) {
00202     gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, message, -1,
00203                                               "plain", style, NULL);
00204   } else {
00205     /* If UTF-8 wasn't valid (due to a system locale encoded filename or
00206      * other string being included by mistake), log a warning, and print
00207      * the original message to stderr, where it may be partly intelligible */
00208     gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
00209       _("** Invalid UTF-8 in log message. See stderr or gschem.log.\n"),
00210                                               -1, "plain", style, NULL);
00211     fprintf (stderr, "%s", message);
00212   }
00213 
00214   mark = gtk_text_buffer_create_mark(buffer, NULL, &iter, FALSE);
00215   gtk_text_view_scroll_to_mark (log->textview, mark, 0, TRUE, 0, 1);
00216   gtk_text_buffer_delete_mark (buffer, mark);
00217 }
00218 
00228 GType log_get_type ()
00229 {
00230   static GType log_type = 0;
00231   
00232   if (!log_type) {
00233     static const GTypeInfo log_info = {
00234       sizeof(LogClass),
00235       NULL, /* base_init */
00236       NULL, /* base_finalize */
00237       (GClassInitFunc) log_class_init,
00238       NULL, /* class_finalize */
00239       NULL, /* class_data */
00240       sizeof(Log),
00241       0,    /* n_preallocs */
00242       (GInstanceInitFunc) log_init,
00243     };
00244         
00245     log_type = g_type_register_static (GSCHEM_TYPE_DIALOG,
00246                                        "Log",
00247                                        &log_info, 0);
00248   }
00249   
00250   return log_type;
00251 }
00252 
00261 static void log_class_init (LogClass *klass)
00262 {
00263 /*   GObjectClass *gobject_class = G_OBJECT_CLASS (klass); */
00264     
00265 }
00266 
00277 static void log_init (Log *log)
00278 {
00279   GtkWidget *scrolled_win, *text_view;
00280   GtkTextBuffer *text_buffer;
00281   GtkTextMark *mark;
00282 
00283   /* dialog initialization */
00284   g_object_set (G_OBJECT (log),
00285                 /* GtkContainer */
00286                 "border-width",    0,
00287                 /* GtkWindow */
00288                 "title",           _("Status"),
00289                 "default-width",   600,
00290                 "default-height",  200,
00291                 "modal",           FALSE,
00292                 "window-position", GTK_WIN_POS_NONE,
00293                 "type-hint",       GDK_WINDOW_TYPE_HINT_NORMAL,
00294                 /* GtkDialog */
00295                 "has-separator",   TRUE,
00296                 NULL);
00297 
00298   /* create a scrolled window for the textview */
00299   scrolled_win = GTK_WIDGET (
00300     g_object_new (GTK_TYPE_SCROLLED_WINDOW,
00301                   /* GtkContainer */
00302                   "border-width",      5,
00303                   /* GtkScrolledWindow */
00304                   "hscrollbar-policy", GTK_POLICY_AUTOMATIC,
00305                   "vscrollbar-policy", GTK_POLICY_AUTOMATIC,
00306                   "shadow-type",       GTK_SHADOW_ETCHED_IN,
00307                   NULL));
00308   /* create the text buffer */
00309   text_buffer = GTK_TEXT_BUFFER (g_object_new (GTK_TYPE_TEXT_BUFFER,
00310                                                NULL));
00311 
00312   /* Add some tags for highlighting log messages to the buffer */
00313   gtk_text_buffer_create_tag (text_buffer, "plain",
00314                               "foreground", "black",
00315                               "foreground-set", TRUE,
00316                               "weight", PANGO_WEIGHT_NORMAL,
00317                               "weight-set", TRUE,
00318                               NULL);
00319   /* The default "message" style is plain */
00320   gtk_text_buffer_create_tag (text_buffer, "message", NULL);
00321   /* "old" messages are in dark grey */
00322   gtk_text_buffer_create_tag (text_buffer, "old",
00323                               "foreground", "#404040",
00324                               "foreground-set", TRUE,
00325                   NULL);
00326   /* "warning" messages are printed in red */
00327   gtk_text_buffer_create_tag (text_buffer, "warning",
00328                               "foreground", "red",
00329                               "foreground-set", TRUE,
00330                               NULL);
00331   /* "critical" messages are bold red */
00332   gtk_text_buffer_create_tag (text_buffer, "critical",
00333                               "foreground", "red",
00334                               "foreground-set", TRUE,
00335                               "weight", PANGO_WEIGHT_BOLD,
00336                               "weight-set", TRUE,
00337                               NULL);
00338 
00339   /* create the text view and attach the buffer to it */
00340   text_view = GTK_WIDGET (g_object_new (GTK_TYPE_TEXT_VIEW,
00341                                         /* GtkTextView */
00342 /* unknown property in GTK 2.2, use gtk_text_view_set_buffer() instead */
00343 /*                                         "buffer",   text_buffer, */
00344                                         "editable", FALSE,
00345                                         NULL));
00346   gtk_text_view_set_buffer (GTK_TEXT_VIEW (text_view), text_buffer);
00347 
00348   /* add the text view to the scrolled window */
00349   gtk_container_add (GTK_CONTAINER (scrolled_win), text_view);
00350   /* set textview of log */
00351   log->textview = GTK_TEXT_VIEW (text_view);
00352 
00353   /* add the scrolled window to the dialog vbox */
00354   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (log)->vbox), scrolled_win,
00355                       TRUE, TRUE, 0);
00356   gtk_widget_show_all (scrolled_win);
00357 
00358   /* now add the close button to the action area */
00359   gtk_dialog_add_button (GTK_DIALOG (log),
00360                          GTK_STOCK_CLOSE, LOG_RESPONSE_CLOSE);
00361 
00362   /* scroll to the end of the buffer */
00363   mark = gtk_text_buffer_get_insert (text_buffer);
00364   gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (text_view), mark, 0.0, TRUE, 0.0, 1.0);
00365 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines