[gnome-latex: 171/205] Log zone: GtkListStore instead of GtkTextBuffer



commit 6461b29a2e657b3509242e4985e0333acc4e8b6c
Author: Sébastien Wilmet <sebastien wilmet gmail com>
Date:   Wed Jan 20 01:33:31 2010 +0100

    Log zone: GtkListStore instead of GtkTextBuffer
    
    It's so beautiful!
    Three columns are showed: filename, line number, and the message.
    All stuff about the log zone is now in log.c. There is two global
    variables: history_view and output_view (the two GtkTreeView's).

 TODO                      |   8 +-
 src/CMakeLists.txt        |   1 +
 src/callbacks.c           |  16 --
 src/callbacks.h           |   2 -
 src/external_commands.c   | 107 +++-----------
 src/latex_output_filter.c |  66 ++-------
 src/latex_output_filter.h |   7 +-
 src/log.c                 | 364 ++++++++++++++++++++++++++++++++++++++++++++++
 src/log.h                 |  72 +++++++++
 src/main.c                |  62 +-------
 src/main.h                |  20 ---
 src/print.c               |  48 ------
 src/print.h               |   4 -
 13 files changed, 485 insertions(+), 292 deletions(-)
---
diff --git a/TODO b/TODO
index d989a9e..cb06795 100644
--- a/TODO
+++ b/TODO
@@ -6,9 +6,10 @@ TODO LaTeXila
        x button to stop the execution
        x show statistics: nb of errors, warnings and badboxes
        x extract informations: file, line, message
-       - jump to lines and files: GtkTextBuffer -> GtkListStore
-       - colors
-       - go to the previous/next error/warning/badbox
+       x GtkTextBuffer -> GtkListStore
+       x colors
+       - jump to lines and files
+       - buttons for going to the previous/next error/warning/badbox
 
 - Auto-completion of LaTeX commands
 
@@ -18,4 +19,5 @@ TODO LaTeXila
        - Autosave files every X minutes
        - Symbols: most recently used
        - File browser: list with all parents directories
+       - File browser: two cell renderers in one column
        - Create personnal templates: choose an icon
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index a364180..60ee278 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -12,6 +12,7 @@ SET(latexila_src
        file_browser.c          file_browser.h
        templates.c             templates.h
        utils.c                 utils.h
+       log.c                   log.h
 )
 
 ADD_EXECUTABLE(latexila ${latexila_src})
diff --git a/src/callbacks.c b/src/callbacks.c
index 667684b..61d01d2 100644
--- a/src/callbacks.c
+++ b/src/callbacks.c
@@ -967,22 +967,6 @@ cb_documents_next (void)
                gtk_notebook_set_current_page (latexila.notebook, current_page + 1);
 }
 
-void
-cb_action_list_changed (GtkTreeSelection *selection, gpointer user_data)
-{
-       GtkTreeIter iter;
-       GtkTreeModel *model;
-       if (gtk_tree_selection_get_selected (selection, &model, &iter))
-       {
-               GtkTextBuffer *text_buffer;
-               gtk_tree_model_get (model, &iter,
-                               COLUMN_ACTION_TEXTBUFFER, &text_buffer,
-                               -1);
-
-               gtk_text_view_set_buffer (latexila.action_log.text_view, text_buffer);
-       }
-}
-
 void
 cb_help_latex_reference (void)
 {
diff --git a/src/callbacks.h b/src/callbacks.h
index e5f4e65..f8fa7cf 100644
--- a/src/callbacks.h
+++ b/src/callbacks.h
@@ -68,8 +68,6 @@ void cb_documents_save_all (void);
 void cb_documents_close_all (void);
 void cb_documents_previous (void);
 void cb_documents_next (void);
-void cb_action_list_changed (GtkTreeSelection *selection,
-               gpointer user_data);
 void cb_help_latex_reference (void);
 void cb_about_dialog (void);
 void cb_text_changed (GtkWidget *widget, gpointer user_data);
diff --git a/src/external_commands.c b/src/external_commands.c
index c855451..a85edb4 100644
--- a/src/external_commands.c
+++ b/src/external_commands.c
@@ -36,8 +36,8 @@
 #include "external_commands.h"
 #include "file_browser.h"
 #include "latex_output_filter.h"
+#include "log.h"
 
-static void add_action (const gchar *title, const gchar *command);
 static void set_action_sensitivity (gboolean sensitive);
 static gchar * get_command_line (gchar **command);
 static void start_command_without_output (gchar **command, gchar *message);
@@ -45,7 +45,6 @@ static void start_command_with_output (gchar **command);
 static void cb_spawn_setup (gpointer data);
 static gboolean cb_watch_output_command (GIOChannel *channel,
                GIOCondition condition, gpointer user_data);
-//static void output_filter_line (const gchar *line);
 static void cb_child_watch (GPid pid, gint status, gpointer user_data);
 static void finish_execute (void);
 static void run_command_on_other_extension (gchar *title, gchar *message,
@@ -113,7 +112,7 @@ view_current_document (gchar *title, gchar *doc_extension)
                gchar *command_output = g_strdup_printf (
                                _("%s does not exist. If this is not already made, compile the document with 
the right command."),
                                g_path_get_basename (doc_path));
-               print_log_add (latexila.action_log.text_view, command_output, TRUE);
+               print_output_exit (1337, command_output);
                g_free (command_output);
                g_free (doc_path);
                return;
@@ -185,66 +184,15 @@ stop_execution (void)
        gtk_action_set_sensitive (latexila.actions.stop_execution, FALSE);
 }
 
-static void
-add_action (const gchar *title, const gchar *command)
-{
-       static gint num = 1;
-       gchar *title2 = g_strdup_printf ("%d. %s", num, title);
-
-       // create a new text buffer
-       GtkTextBuffer *new_text_buffer = gtk_text_buffer_new (
-                       latexila.action_log.tag_table);
-       latexila.action_log.text_buffer = new_text_buffer;
-       gtk_text_view_set_buffer (latexila.action_log.text_view, new_text_buffer);
-
-       // title
-       GtkTextIter end;
-       gtk_text_buffer_get_end_iter (new_text_buffer, &end);
-       gtk_text_buffer_insert_with_tags_by_name (new_text_buffer, &end, title2, -1,
-                       "bold", NULL);
-
-       // command
-    gtk_text_buffer_get_end_iter (new_text_buffer, &end);
-    gchar *command2 = g_strdup_printf ("\n$ %s\n", command);
-    gtk_text_buffer_insert (new_text_buffer, &end, command2, -1);
-    g_free (command2);
-
-       // append a new entry to the action list
-       GtkTreeIter iter;
-       gtk_list_store_append (latexila.action_log.list_store, &iter);
-       gtk_list_store_set (latexila.action_log.list_store, &iter,
-                       COLUMN_ACTION_TITLE, title2,
-                       COLUMN_ACTION_TEXTBUFFER, new_text_buffer,
-                       -1);
-
-       // select the new entry
-       gtk_tree_selection_select_iter (latexila.action_log.list_selection, &iter);
-
-       // scroll to the end
-       GtkTreePath *path = gtk_tree_model_get_path (
-                       GTK_TREE_MODEL (latexila.action_log.list_store), &iter);
-       gtk_tree_view_scroll_to_cell (latexila.action_log.list_view, path, NULL,
-                       FALSE, 0, 0);
-
-       // delete the first entry
-       if (num > 5)
-       {
-               GtkTreeIter first;
-               gtk_tree_model_get_iter_first (
-                               GTK_TREE_MODEL (latexila.action_log.list_store), &first);
-               gtk_list_store_remove (latexila.action_log.list_store, &first);
-       }
-
-       num++;
-       g_free (title2);
-}
-
 static void
 set_action_sensitivity (gboolean sensitive)
 {
-       // Lock the action list when a command is running so the user can not view
-       // an other action.
-       gtk_widget_set_sensitive (GTK_WIDGET (latexila.action_log.list_view), sensitive);
+       // Lock the history action list when a command is running so the user can not view
+       // an other action. We do that because the output lines are added in the
+       // current list store. If the user changed the action in the history list
+       // while a new action is running, the new output lines would be added to the
+       // wrong list store.
+       set_history_sensitivity (sensitive);
 
        gtk_action_set_sensitive (latexila.actions.compile_latex, sensitive);
        gtk_action_set_sensitive (latexila.actions.compile_pdflatex, sensitive);
@@ -289,15 +237,14 @@ start_command_without_output (gchar **command, gchar *message)
        {
                gchar *command_output = g_strdup_printf (_("execution failed: %s"),
                                error->message);
-               print_log_add (latexila.action_log.text_view, command_output, TRUE);
+               print_output_exit (42, command_output);
                g_free (command_output);
                g_error_free (error);
        }
        else if (message == NULL)
-               print_log_add (latexila.action_log.text_view,
-                               _("Viewing in progress. Please wait..."), FALSE);
+               print_output_info (_("Viewing in progress. Please wait..."));
        else
-               print_log_add (latexila.action_log.text_view, message, FALSE);
+               print_output_info (message);
 }
 
 // Attention, before calling this function, set the variable "show_all_output"
@@ -319,7 +266,7 @@ start_command_with_output (gchar **command)
        {
                gchar *command_output = g_strdup_printf (_("execution failed: %s"),
                                error->message);
-               print_log_add (latexila.action_log.text_view, command_output, TRUE);
+               print_output_exit (42, command_output);
                g_free (command_output);
                g_error_free (error);
                g_free (dir);
@@ -341,7 +288,6 @@ start_command_with_output (gchar **command)
 
        // convert the channel
        g_io_channel_set_encoding (out_channel, NULL, NULL);
-       //g_io_channel_set_encoding (out_channel, "ISO-8859-1", NULL);
 
        // lock the action list and all the build actions
        set_action_sensitivity (FALSE);
@@ -401,9 +347,12 @@ cb_watch_output_command (GIOChannel *channel, GIOCondition condition,
                        // the line is not showed if it contains bad characters!
                        if (line_utf8 != NULL)
                        {
+                               // delete the \n
+                               line_utf8[strlen (line_utf8) - 1] = '\0';
+
                                if (show_all_output)
                                {
-                                       print_log_add (latexila.action_log.text_view, line_utf8, FALSE);
+                                       print_output_normal (line_utf8);
 
                                        /* Flush the queue for the 200 first lines and then every 50 lines.
                                         * This is for the fluidity of the output, without that the lines do 
not
@@ -418,11 +367,7 @@ cb_watch_output_command (GIOChannel *channel, GIOCondition condition,
                                }
 
                                else
-                               {
-                                       // delete the \n
-                                       line_utf8[strlen (line_utf8) - 1] = '\0';
                                        latex_output_filter (line_utf8);
-                               }
 
                                g_free (line_utf8);
                        }
@@ -483,21 +428,11 @@ finish_execute (void)
                latex_output_filter_print_stats ();
 
        if (child_pid_exit_code > -1)
-       {
-               gchar *exit_code = g_strdup_printf ("exit code: %d",
-                               child_pid_exit_code);
-
-               if (child_pid_exit_code == 0)
-                       print_log_add (latexila.action_log.text_view, exit_code, FALSE);
-               else
-                       print_log_add (latexila.action_log.text_view, exit_code, TRUE);
-
-               g_free (exit_code);
-       }
+               print_output_exit (child_pid_exit_code, NULL);
        else
-               print_log_add (latexila.action_log.text_view,
-                               _("the child process exited abnormally"), TRUE);
+               print_output_exit (42, _("The child process exited abnormally"));
 
+       output_view_columns_autosize ();
        flush_queue ();
 
        // unlock the action list and all the build actions
@@ -542,7 +477,7 @@ run_command_on_other_extension (gchar *title, gchar *message, gchar *command,
                command_output = g_strdup_printf (
                                _("%s does not exist. If this is not already made, compile the document with 
the right command."),
                                g_path_get_basename (doc_path));
-               print_log_add (latexila.action_log.text_view, command_output, TRUE);
+               print_output_exit (42, command_output);
                g_free (command_output);
                g_free (doc_path);
                return;
@@ -571,7 +506,7 @@ is_current_doc_tex_file (void)
        {
                gchar *command_output = g_strdup_printf (_("failed: %s is not a *.tex file"),
                                g_path_get_basename (latexila.active_doc->path));
-               print_log_add (latexila.action_log.text_view, command_output, TRUE);
+               print_output_exit (0, command_output);
                g_free (command_output);
                return FALSE;
        }
diff --git a/src/latex_output_filter.c b/src/latex_output_filter.c
index 778343f..c3f9696 100644
--- a/src/latex_output_filter.c
+++ b/src/latex_output_filter.c
@@ -1,7 +1,7 @@
 /*
  * This file is part of LaTeXila.
  *
- * Copyright © 2009, 2010 Sébastien Wilmet
+ * Copyright © 2010 Sébastien Wilmet
  *
  * LaTeXila is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -27,6 +27,7 @@
 #include "print.h"
 #include "utils.h"
 #include "latex_output_filter.h"
+#include "log.h"
 
 static gboolean detect_badbox (const gchar *line);
 static gboolean detect_badbox_line (const gchar *badbox,
@@ -201,27 +202,30 @@ latex_output_filter_print_stats (void)
        }
        if (nb_badboxes > 1)
        {
-               gchar *tmp = g_strdup_printf (_("%s%d badboxes\n"), str, nb_badboxes);
+               gchar *tmp = g_strdup_printf (_("%s%d badboxes"), str, nb_badboxes);
                g_free (str);
                str = tmp;
        }
        else
        {
-               gchar *tmp = g_strdup_printf (_("%s%d badbox\n"), str, nb_badboxes);
+               gchar *tmp = g_strdup_printf (_("%s%d badbox"), str, nb_badboxes);
                g_free (str);
                str = tmp;
        }
 
-       print_log_add (latexila.action_log.text_view, str, FALSE);
+       print_output_info (str);
        flush_queue ();
        g_free (str);
 
+       // it's finish, we reset the counters
        nb_badboxes = 0;
        nb_warnings = 0;
        nb_errors = 0;
 
-       // if all the files in the stack are not popped
+       // if the file stack is not empty
        gint nb_files_in_stack = g_slist_length (stack_file);
+       if (nb_files_in_stack > 0)
+               print_warning ("the file stack was not empty!");
        for (int i = 0 ; i < nb_files_in_stack ; i++)
                pop_file_from_stack ();
 }
@@ -236,7 +240,7 @@ detect_badbox (const gchar *line)
                case START:
                        if (g_regex_match (reg_badbox, line, 0, NULL))
                        {
-                               msg.message_type = TYPE_BADBOX;
+                               msg.message_type = MESSAGE_TYPE_BADBOX;
                                nb_badboxes++;
 
                                if (detect_badbox_line (line, FALSE))
@@ -332,7 +336,7 @@ detect_warning (const gchar *line)
                        if (g_regex_match (reg_warning, line, 0, NULL))
                        {
                                nb_warnings++;
-                               msg.message_type = TYPE_WARNING;
+                               msg.message_type = MESSAGE_TYPE_WARNING;
 
                                strings = g_regex_split (reg_warning, line, 0);
 
@@ -351,7 +355,7 @@ detect_warning (const gchar *line)
                        else if (g_regex_match (reg_warning_no_file, line, 0, NULL))
                        {
                                nb_warnings++;
-                               msg.message_type = TYPE_WARNING;
+                               msg.message_type = MESSAGE_TYPE_WARNING;
                                strings = g_regex_split (reg_warning_no_file, line, 0);
                                msg.message = g_strdup (strings[1]);
                                g_strfreev (strings);
@@ -465,7 +469,7 @@ detect_error (const gchar *line)
                        {
                                nb_errors++;
                                nb_lines++;
-                               msg.message_type = TYPE_ERROR;
+                               msg.message_type = MESSAGE_TYPE_ERROR;
 
                                // the message is complete
                                if (line[strlen (line) - 1] == '.')
@@ -544,7 +548,7 @@ detect_other (const gchar *line)
        {
                msg.message = g_strdup (line);
                msg.line = NO_LINE;
-               msg.message_type = TYPE_OTHER;
+               msg.message_type = MESSAGE_TYPE_OTHER;
                print_msg ();
                return TRUE;
        }
@@ -798,49 +802,11 @@ top_file_on_stack_reliable (void)
 static void
 print_msg (void)
 {
-       gchar *str;
-       switch (msg.message_type)
-       {
-               case TYPE_ERROR:
-                       str = g_strdup ("[x] ");
-                       break;
-               case TYPE_WARNING:
-                       str = g_strdup ("[+] ");
-                       break;
-               case TYPE_BADBOX:
-                       str = g_strdup ("[-] ");
-                       break;
-               case TYPE_OTHER:
-                       str = g_strdup ("[ ] ");
-                       break;
-               default:
-                       break;
-       }
-
        gchar *filename = get_current_filename ();
-       if (filename != NULL)
-       {
-               gchar *tmp = g_strdup_printf ("%s%s:", str, filename);
-               g_free (str);
-               str = tmp;
-       }
-
-       if (msg.line != NO_LINE)
-       {
-               gchar *tmp = g_strdup_printf ("%s%d:", str, msg.line);
-               g_free (str);
-               str = tmp;
-       }
-
-       gchar *tmp = g_strdup_printf ("%s%s\n", str, msg.message);
-       g_free (str);
-       str = tmp;
-
-       print_log_add (latexila.action_log.text_view, str, msg.message_type == TYPE_ERROR);
+       print_output_message (filename, msg.line, msg.message, msg.message_type);
        flush_queue ();
-       g_free (str);
        
        msg.line = NO_LINE;
-       msg.message_type = TYPE_OTHER;
+       msg.message_type = MESSAGE_TYPE_OTHER;
        g_free (msg.message);
 }
diff --git a/src/latex_output_filter.h b/src/latex_output_filter.h
index c50af59..cc0c7d5 100644
--- a/src/latex_output_filter.h
+++ b/src/latex_output_filter.h
@@ -1,7 +1,7 @@
 /*
  * This file is part of LaTeXila.
  *
- * Copyright © 2009, 2010 Sébastien Wilmet
+ * Copyright © 2010 Sébastien Wilmet
  *
  * LaTeXila is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -20,6 +20,8 @@
 #ifndef LATEX_OUTPUT_FILTER_H
 #define LATEX_OUTPUT_FILTER_H
 
+#include "log.h"
+
 void latex_output_filter (const gchar *line);
 void latex_output_filter_init (void);
 void latex_output_filter_free (void);
@@ -53,12 +55,11 @@ enum message_type
 
 typedef struct
 {
-       enum message_type message_type;
+       enum output_message_type message_type;
        gchar *message;
        gint line;
 } message_t;
 
 #define BUFFER_SIZE 1024
-#define NO_LINE -1
 
 #endif /* LATEX_OUTPUT_FILTER_H */
diff --git a/src/log.c b/src/log.c
new file mode 100644
index 0000000..37ad211
--- /dev/null
+++ b/src/log.c
@@ -0,0 +1,364 @@
+/*
+ * This file is part of LaTeXila.
+ *
+ * Copyright © 2010 Sébastien Wilmet
+ *
+ * LaTeXila is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * LaTeXila is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with LaTeXila.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <gtk/gtk.h>
+
+#include "main.h"
+#include "log.h"
+
+static void cb_action_history_changed (GtkTreeSelection *selection,
+               gpointer user_data);
+static GtkListStore * get_new_output_list_store (void);
+static void scroll_to_end (GtkTreeIter *iter);
+
+static GtkTreeView *history_view;
+static GtkTreeView *output_view;
+
+void
+init_log_zone (GtkPaned *log_hpaned)
+{
+       /* action history */
+       {
+               GtkListStore *history_list_store = gtk_list_store_new (N_COLS_ACTION,
+                               G_TYPE_STRING, G_TYPE_POINTER);
+               
+               history_view = GTK_TREE_VIEW (gtk_tree_view_new_with_model (
+                                       GTK_TREE_MODEL (history_list_store)));
+               GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
+               GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes (
+                               _("Action history"), renderer, "text", COL_ACTION_TITLE, NULL); 
+               gtk_tree_view_append_column (history_view, column);
+               
+               GtkTreeSelection *select = gtk_tree_view_get_selection (history_view);
+               gtk_tree_selection_set_mode (select, GTK_SELECTION_SINGLE);
+               g_signal_connect (G_OBJECT (select), "changed",
+                               G_CALLBACK (cb_action_history_changed), NULL);
+
+               // with a scrollbar
+               GtkWidget *scrollbar = gtk_scrolled_window_new (NULL, NULL);
+               gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollbar),
+                               GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+               gtk_container_add (GTK_CONTAINER (scrollbar), GTK_WIDGET (history_view));
+               gtk_paned_add1 (log_hpaned, scrollbar);
+       }
+       
+       /* log details */
+       {
+               GtkListStore *output_list_store = get_new_output_list_store ();
+
+               // tree view with 3 columns: basename, line, message
+               output_view = GTK_TREE_VIEW (gtk_tree_view_new_with_model (
+                                       GTK_TREE_MODEL (output_list_store)));
+               g_object_unref (output_list_store);
+
+               // we can now show some text (output_view must be initialized)
+               print_output_normal (_("Welcome to LaTeXila!"));
+
+               gtk_tree_view_set_headers_visible (output_view, FALSE);
+               gtk_tree_view_set_tooltip_column (output_view, COL_OUTPUT_FILENAME);
+
+               GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
+               g_object_set (renderer, "weight-set", TRUE, NULL);
+
+               // basename
+               GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes (
+                               NULL, renderer,
+                               "text", COL_OUTPUT_BASENAME,
+                               "foreground", COL_OUTPUT_COLOR,
+                               "foreground-set", COL_OUTPUT_COLOR_SET,
+                               "weight", COL_OUTPUT_WEIGHT,
+                               NULL);
+               gtk_tree_view_append_column (output_view, column);
+
+               // line number
+               column = gtk_tree_view_column_new_with_attributes (
+                               NULL, renderer,
+                               "text", COL_OUTPUT_LINE_NUMBER,
+                               "foreground", COL_OUTPUT_COLOR,
+                               "foreground-set", COL_OUTPUT_COLOR_SET,
+                               "weight", COL_OUTPUT_WEIGHT,
+                               NULL);
+               gtk_tree_view_append_column (output_view, column);
+
+               // message
+               column = gtk_tree_view_column_new_with_attributes (
+                               NULL, renderer,
+                               "text", COL_OUTPUT_MESSAGE,
+                               "foreground", COL_OUTPUT_COLOR,
+                               "foreground-set", COL_OUTPUT_COLOR_SET,
+                               "weight", COL_OUTPUT_WEIGHT,
+                               NULL);
+               gtk_tree_view_append_column (output_view, column);
+
+               // with a scrollbar
+               GtkWidget *scrollbar = gtk_scrolled_window_new (NULL, NULL);
+               gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollbar),
+                               GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+               gtk_container_add (GTK_CONTAINER (scrollbar), GTK_WIDGET (output_view));
+               gtk_paned_add2 (log_hpaned, scrollbar);
+       }
+}
+
+static void
+cb_action_history_changed (GtkTreeSelection *selection, gpointer user_data)
+{
+       GtkTreeIter iter;
+       GtkTreeModel *history_model;
+       if (gtk_tree_selection_get_selected (selection, &history_model, &iter))
+       {
+               GtkTreeModel *output_model;
+               gtk_tree_model_get (history_model, &iter,
+                               COL_ACTION_OUTPUT_STORE, &output_model,
+                               -1);
+               gtk_tree_view_set_model (output_view, output_model);
+               output_view_columns_autosize ();
+       }
+}
+
+static GtkListStore *
+get_new_output_list_store (void)
+{
+       GtkListStore *output_list_store = gtk_list_store_new (N_COLS_OUTPUT,
+                       G_TYPE_STRING,          // basename
+                       G_TYPE_STRING,          // filename
+                       G_TYPE_STRING,          // line number
+                       G_TYPE_STRING,          // message
+                       G_TYPE_INT,                     // message type
+                       G_TYPE_STRING,          // color
+                       G_TYPE_BOOLEAN,         // color set
+                       G_TYPE_INT                      // weight
+                       );
+       return output_list_store;
+}
+
+void
+add_action (const gchar *title, const gchar *command)
+{
+       static gint num = 1;
+
+       GtkListStore *output_list_store = get_new_output_list_store ();
+       gtk_tree_view_set_model (output_view, GTK_TREE_MODEL (output_list_store));
+       g_object_unref (output_list_store);
+
+       // print title and command to the new list store
+       gchar *title_with_num = g_strdup_printf ("%d. %s", num, title);
+       print_output_title (title_with_num);
+
+    gchar *command_with_dolar = g_strdup_printf ("$ %s", command);
+       print_output_info (command_with_dolar);
+       g_free (command_with_dolar);
+
+       // append a new entry to the history action list
+       GtkTreeModel *history_tree_model = gtk_tree_view_get_model (history_view);
+       GtkTreeIter iter;
+       gtk_list_store_append (GTK_LIST_STORE (history_tree_model), &iter);
+       gtk_list_store_set (GTK_LIST_STORE (history_tree_model), &iter,
+                       COL_ACTION_TITLE, title_with_num,
+                       COL_ACTION_OUTPUT_STORE, output_list_store,
+                       -1);
+
+       // select the new entry
+       GtkTreeSelection *selection = gtk_tree_view_get_selection (history_view);
+       gtk_tree_selection_select_iter (selection, &iter);
+
+       // scroll to the end
+       GtkTreePath *path = gtk_tree_model_get_path (history_tree_model, &iter);
+       gtk_tree_view_scroll_to_cell (history_view, path, NULL, FALSE, 0, 0);
+
+       // delete the first entry
+       if (num > 5)
+       {
+               GtkTreeIter first;
+               gtk_tree_model_get_iter_first (history_tree_model, &first);
+               gtk_list_store_remove (GTK_LIST_STORE (history_tree_model), &first);
+       }
+
+       num++;
+       g_free (title_with_num);
+}
+
+void
+set_history_sensitivity (gboolean sensitive)
+{
+       gtk_widget_set_sensitive (GTK_WIDGET (history_view), sensitive);
+}
+
+void
+output_view_columns_autosize (void)
+{
+       gtk_tree_view_columns_autosize (output_view);
+}
+
+void
+print_output_title (const gchar *title)
+{
+       GtkListStore *list_store =
+               GTK_LIST_STORE (gtk_tree_view_get_model (output_view));
+       GtkTreeIter iter;
+       gtk_list_store_append (list_store, &iter);
+       gtk_list_store_set (list_store, &iter,
+                       COL_OUTPUT_BASENAME, INFO_MESSAGE,
+                       COL_OUTPUT_LINE_NUMBER, "",
+                       COL_OUTPUT_MESSAGE, title,
+                       COL_OUTPUT_MESSAGE_TYPE, MESSAGE_TYPE_OTHER,
+                       COL_OUTPUT_COLOR_SET, FALSE,
+                       COL_OUTPUT_WEIGHT, WEIGHT_BOLD,
+                       -1);
+       scroll_to_end (&iter);
+}
+
+void
+print_output_info (const gchar *info)
+{
+       GtkListStore *list_store =
+               GTK_LIST_STORE (gtk_tree_view_get_model (output_view));
+       GtkTreeIter iter;
+       gtk_list_store_append (list_store, &iter);
+       gtk_list_store_set (list_store, &iter,
+                       COL_OUTPUT_BASENAME, INFO_MESSAGE,
+                       COL_OUTPUT_LINE_NUMBER, "",
+                       COL_OUTPUT_MESSAGE, info,
+                       COL_OUTPUT_MESSAGE_TYPE, MESSAGE_TYPE_OTHER,
+                       COL_OUTPUT_COLOR_SET, FALSE,
+                       COL_OUTPUT_WEIGHT, WEIGHT_NORMAL,
+                       -1);
+       scroll_to_end (&iter);
+}
+
+// if message != NULL the exit_code is not taken into account
+void
+print_output_exit (const gint exit_code, const gchar *message)
+{
+       GtkListStore *list_store =
+               GTK_LIST_STORE (gtk_tree_view_get_model (output_view));
+       GtkTreeIter iter;
+       gtk_list_store_append (list_store, &iter);
+       gtk_list_store_set (list_store, &iter,
+                       COL_OUTPUT_BASENAME, INFO_MESSAGE,
+                       COL_OUTPUT_LINE_NUMBER, "",
+                       COL_OUTPUT_MESSAGE_TYPE, MESSAGE_TYPE_OTHER,
+                       COL_OUTPUT_COLOR_SET, TRUE,
+                       COL_OUTPUT_WEIGHT, WEIGHT_NORMAL,
+                       -1);
+
+       if (message != NULL)
+       {
+               gtk_list_store_set (list_store, &iter,
+                               COL_OUTPUT_MESSAGE, message,
+                               COL_OUTPUT_COLOR, COLOR_RED,
+                               -1);
+       }
+       else if (exit_code == 0)
+       {
+               gtk_list_store_set (list_store, &iter,
+                               COL_OUTPUT_MESSAGE, _("Done!"),
+                               COL_OUTPUT_COLOR, COLOR_GREEN,
+                               -1);
+       }
+       else
+       {
+               gchar *tmp = g_strdup_printf (_("Finished with exit code %d"), exit_code);
+               gtk_list_store_set (list_store, &iter,
+                               COL_OUTPUT_MESSAGE, tmp,
+                               COL_OUTPUT_COLOR, COLOR_RED,
+                               -1);
+               g_free (tmp);
+       }
+       scroll_to_end (&iter);
+}
+
+void
+print_output_message (const gchar *filename, const gint line_number,
+               const gchar *message, gint message_type)
+{
+       GtkListStore *list_store =
+               GTK_LIST_STORE (gtk_tree_view_get_model (output_view));
+
+       gchar *basename;
+       if (filename != NULL)
+               basename = g_path_get_basename (filename);
+       else
+               basename = g_strdup ("");
+
+       gchar *line_number_str;
+       if (line_number != NO_LINE)
+               line_number_str = g_strdup_printf ("%d", line_number);
+       else
+               line_number_str = g_strdup ("");
+
+       gchar *color;
+       switch (message_type)
+       {
+               case MESSAGE_TYPE_ERROR:
+                       color = COLOR_RED;
+                       break;
+               case MESSAGE_TYPE_WARNING:
+                       color = COLOR_ORANGE;
+                       break;
+               case MESSAGE_TYPE_BADBOX:
+                       color = COLOR_BROWN;
+                       break;
+               default:
+                       color = "black";
+                       break;
+       }
+
+       GtkTreeIter iter;
+       gtk_list_store_append (list_store, &iter);
+       gtk_list_store_set (list_store, &iter,
+                       COL_OUTPUT_BASENAME, basename, 
+                       COL_OUTPUT_FILENAME, filename != NULL ? filename : "",
+                       COL_OUTPUT_LINE_NUMBER, line_number_str,
+                       COL_OUTPUT_MESSAGE, message,
+                       COL_OUTPUT_MESSAGE_TYPE, message_type,
+                       COL_OUTPUT_COLOR, color,
+                       COL_OUTPUT_COLOR_SET, TRUE,
+                       COL_OUTPUT_WEIGHT, WEIGHT_NORMAL,
+                       -1);
+       scroll_to_end (&iter);
+
+       g_free (basename);
+       g_free (line_number_str);
+}
+
+void
+print_output_normal (const gchar *message)
+{
+       GtkListStore *list_store =
+               GTK_LIST_STORE (gtk_tree_view_get_model (output_view));
+       GtkTreeIter iter;
+       gtk_list_store_append (list_store, &iter);
+       gtk_list_store_set (list_store, &iter,
+                       COL_OUTPUT_BASENAME, "", 
+                       COL_OUTPUT_LINE_NUMBER, "",
+                       COL_OUTPUT_MESSAGE, message,
+                       COL_OUTPUT_MESSAGE_TYPE, MESSAGE_TYPE_OTHER,
+                       COL_OUTPUT_COLOR_SET, FALSE,
+                       COL_OUTPUT_WEIGHT, WEIGHT_NORMAL,
+                       -1);
+       scroll_to_end (&iter);
+}
+
+static void
+scroll_to_end (GtkTreeIter *iter)
+{
+       GtkTreeModel *tree_model = gtk_tree_view_get_model (output_view);
+       GtkTreePath *path = gtk_tree_model_get_path (tree_model, iter);
+       gtk_tree_view_scroll_to_cell (output_view, path, NULL, FALSE, 0, 0);
+}
diff --git a/src/log.h b/src/log.h
new file mode 100644
index 0000000..3c2e872
--- /dev/null
+++ b/src/log.h
@@ -0,0 +1,72 @@
+/*
+ * This file is part of LaTeXila.
+ *
+ * Copyright © 2010 Sébastien Wilmet
+ *
+ * LaTeXila is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * LaTeXila is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with LaTeXila.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef LOG_H
+#define LOG_H
+
+#define NO_LINE                        -1
+#define COLOR_RED              "#C00000"
+#define COLOR_ORANGE   "#FF7200"
+#define COLOR_BROWN            "#663106"
+#define COLOR_GREEN            "#009900"
+#define WEIGHT_NORMAL  400
+#define WEIGHT_BOLD            800
+#define INFO_MESSAGE   "*****"
+
+void init_log_zone (GtkPaned *log_hpaned);
+void add_action (const gchar *title, const gchar *command);
+void set_history_sensitivity (gboolean sensitive);
+void output_view_columns_autosize (void);
+
+void print_output_title (const gchar *title);
+void print_output_info (const gchar *info);
+void print_output_exit (const gint exit_code, const gchar *message);
+void print_output_message (const gchar *filename, const gint line_number,
+               const gchar *message, gint message_type);
+void print_output_normal (const gchar *message);
+
+enum history_action
+{
+       COL_ACTION_TITLE,
+       COL_ACTION_OUTPUT_STORE,
+       N_COLS_ACTION
+};
+
+enum output_message_type
+{
+       MESSAGE_TYPE_OTHER,
+       MESSAGE_TYPE_ERROR,
+       MESSAGE_TYPE_WARNING,
+       MESSAGE_TYPE_BADBOX
+};
+
+enum output_line
+{
+       COL_OUTPUT_BASENAME,
+       COL_OUTPUT_FILENAME,
+       COL_OUTPUT_LINE_NUMBER,
+       COL_OUTPUT_MESSAGE,
+       COL_OUTPUT_MESSAGE_TYPE,
+       COL_OUTPUT_COLOR,
+       COL_OUTPUT_COLOR_SET,
+       COL_OUTPUT_WEIGHT,
+       N_COLS_OUTPUT
+};
+
+#endif /* LOG_H */
diff --git a/src/main.c b/src/main.c
index c657b9d..109102b 100644
--- a/src/main.c
+++ b/src/main.c
@@ -31,6 +31,7 @@
 #include "ui.h"
 #include "templates.h"
 #include "latex_output_filter.h"
+#include "log.h"
 
 static gboolean option_version (const gchar *option_name, const gchar *value,
                gpointer data, GError **error);
@@ -40,7 +41,6 @@ static void init_source_view (GtkWidget *vbox_source_view);
 static void init_go_to_line (GtkWidget *vbox_source_view);
 static void init_find (GtkWidget *vbox_source_view);
 static void init_replace (GtkWidget *vbox_source_view);
-static void init_log_zone (void);
 static void init_statusbar (GtkWidget *main_vbox);
 
 latexila_t latexila = {NULL};
@@ -318,64 +318,6 @@ init_replace (GtkWidget *vbox_source_view)
        gtk_box_pack_start (GTK_BOX (hbox2), button_find, FALSE, FALSE, 0);
 }
 
-static void
-init_log_zone (void)
-{
-       // action history
-       GtkListStore *list_store = gtk_list_store_new (N_COLUMNS_ACTION,
-                       G_TYPE_STRING, G_TYPE_POINTER);
-       latexila.action_log.list_store = list_store;
-       
-       GtkWidget *list_view = gtk_tree_view_new_with_model (
-                       GTK_TREE_MODEL (list_store));
-       latexila.action_log.list_view = GTK_TREE_VIEW (list_view);
-       GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
-       GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes (
-                       _("Action history"), renderer, "text", COLUMN_ACTION_TITLE, NULL);      
-       gtk_tree_view_append_column (latexila.action_log.list_view, column);
-       
-       GtkTreeSelection *select =
-               gtk_tree_view_get_selection (latexila.action_log.list_view);
-       latexila.action_log.list_selection = select;
-       gtk_tree_selection_set_mode (select, GTK_SELECTION_SINGLE);
-       g_signal_connect (G_OBJECT (select), "changed",
-                       G_CALLBACK (cb_action_list_changed), NULL);
-
-       // with a scrollbar
-       GtkWidget *scrollbar = gtk_scrolled_window_new (NULL, NULL);
-       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollbar),
-                       GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-       gtk_paned_add1 (GTK_PANED (latexila.log_hpaned), scrollbar);
-       gtk_container_add (GTK_CONTAINER (scrollbar), list_view);
-       
-       // log details
-       GtkWidget *log_view = gtk_text_view_new ();
-       GtkTextBuffer *log_buffer = gtk_text_view_get_buffer (
-                       GTK_TEXT_VIEW (log_view));
-
-       latexila.action_log.text_view = GTK_TEXT_VIEW (log_view);
-       latexila.action_log.text_buffer = log_buffer;
-
-       gtk_text_buffer_set_text (log_buffer, _("Welcome to LaTeXila!"), -1);
-       gtk_text_view_set_editable (GTK_TEXT_VIEW (log_view), FALSE);
-       
-       // with a scrollbar
-       scrollbar = gtk_scrolled_window_new (NULL, NULL);
-       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollbar),
-                       GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-       gtk_paned_add2 (GTK_PANED (latexila.log_hpaned), scrollbar);
-       gtk_container_add (GTK_CONTAINER (scrollbar), log_view);
-
-       // tags
-       gtk_text_buffer_create_tag (log_buffer, "bold",
-                       "weight", PANGO_WEIGHT_BOLD,
-                       NULL);
-       gtk_text_buffer_create_tag (log_buffer, "error",
-                       "foreground", "red",
-                       NULL);
-       latexila.action_log.tag_table = gtk_text_buffer_get_tag_table (log_buffer);
-}
-
 static void
 init_statusbar (GtkWidget *main_vbox)
 {
@@ -505,7 +447,7 @@ main (int argc, char *argv[])
        gtk_paned_set_position (GTK_PANED (hpaned), latexila.prefs.log_hpaned_pos);
        gtk_paned_add2 (GTK_PANED (vpaned), hpaned);
 
-       init_log_zone ();
+       init_log_zone (latexila.log_hpaned);
 
        /* statusbar */
        init_statusbar (main_vbox);
diff --git a/src/main.h b/src/main.h
index 5c30ff1..4b25751 100644
--- a/src/main.h
+++ b/src/main.h
@@ -46,17 +46,6 @@ typedef struct
        GtkWidget               *title;
 } document_t;
 
-// the log zone
-typedef struct
-{
-       GtkListStore            *list_store;
-       GtkTreeView                     *list_view;
-       GtkTreeSelection        *list_selection;
-       GtkTextView                     *text_view;
-       GtkTextBuffer           *text_buffer;
-       GtkTextTagTable         *tag_table;
-} action_log_t;
-
 // symbols tables
 typedef struct
 {
@@ -150,7 +139,6 @@ typedef struct
 {
        GList                           *all_docs;
        document_t                      *active_doc;
-       action_log_t            action_log;
        symbols_t                       symbols;
        file_browser_t          file_browser;
        preferences_t           prefs;
@@ -171,12 +159,4 @@ typedef struct
 // sources (if this file is included)
 extern latexila_t latexila;
 
-// for the actions list in the log zone
-enum action
-{
-       COLUMN_ACTION_TITLE,
-       COLUMN_ACTION_TEXTBUFFER,
-       N_COLUMNS_ACTION
-};
-
 #endif /* MAIN_H */
diff --git a/src/print.c b/src/print.c
index 583d949..77c2750 100644
--- a/src/print.c
+++ b/src/print.c
@@ -20,57 +20,9 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdarg.h>
-#include <gtk/gtk.h>
 
 #include "print.h"
 
-void
-print_log (GtkTextBuffer *log_buffer, gchar *title, gchar *command,
-               gchar *command_output, gboolean error)
-{
-       gtk_text_buffer_set_text (log_buffer, "", -1);
-
-       GtkTextIter end;
-
-       // title (in bold)
-       gtk_text_buffer_get_end_iter (log_buffer, &end);
-       gtk_text_buffer_insert_with_tags_by_name (log_buffer, &end,
-                       title, -1, "bold", NULL);
-
-       // command
-       gtk_text_buffer_get_end_iter (log_buffer, &end);
-       gchar *command2 = g_strdup_printf ("\n$ %s\n", command);
-       gtk_text_buffer_insert (log_buffer, &end, command2, -1);
-       g_free (command2);
-
-       // command output
-       gtk_text_buffer_get_end_iter (log_buffer, &end);
-       if (error)
-               gtk_text_buffer_insert_with_tags_by_name (log_buffer, &end,
-                               command_output, -1, "error", NULL);
-       else
-               gtk_text_buffer_insert (log_buffer, &end, command_output, -1);
-}
-
-void
-print_log_add (GtkTextView *log, const gchar *text, gboolean error)
-{
-       GtkTextBuffer *log_buffer = gtk_text_view_get_buffer (log);
-       GtkTextIter end;
-
-       // insert the text to the end
-       gtk_text_buffer_get_end_iter (log_buffer, &end);
-       if (error)
-               gtk_text_buffer_insert_with_tags_by_name (log_buffer, &end, text, -1,
-                               "error", NULL);
-       else
-               gtk_text_buffer_insert (log_buffer, &end, text, -1);
-
-       // scroll to the end
-       gtk_text_buffer_get_end_iter (log_buffer, &end);
-       gtk_text_view_scroll_to_iter (log, &end, 0.0, FALSE, 0.0, 1.0);
-}
-
 void
 print_info (const char *format, ...)
 {
diff --git a/src/print.h b/src/print.h
index 93c0911..b8c8891 100644
--- a/src/print.h
+++ b/src/print.h
@@ -20,10 +20,6 @@
 #ifndef PRINT_H
 #define PRINT_H
 
-void print_log (GtkTextBuffer *log_buffer, gchar *title, gchar *command,
-               gchar *command_output, gboolean error);
-void print_log_add (GtkTextView *log, const gchar *text, gboolean error);
-
 void print_info (const char *, ...);
 void print_warning (const char *, ...);
 void print_error (const char *, ...);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]