1 /*
2    Copyright (C) 2002 Kai Sterker <kai.sterker@gmail.com>
3    Part of the Adonthell Project  <http://adonthell.nongnu.org>
4 
5    Dlgedit is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9 
10    Dlgedit is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with Dlgedit.  If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 /**
20  * @file gui_error.cc
21  *
22  * @author Kai Sterker
23  * @brief The error console
24  */
25 
26 #include <pango/pango-font.h>
27 #include "gui_dlgedit.h"
28 #include "gui_error.h"
29 
30 // callback for selecting an item from the list
on_list_select_child(GtkTreeSelection * selection,gpointer user_data)31 static void on_list_select_child (GtkTreeSelection *selection, gpointer user_data)
32 {
33     GtkTreeModel *model;
34     GtkTreeIter iter;
35 
36     // anything selected at all?
37     if (gtk_tree_selection_get_selected (selection, &model, &iter))
38     {
39         // don't show selection
40         gtk_tree_selection_unselect_iter (selection, &iter);
41 
42         // ignore edit command if in preview mode
43         if (GuiDlgedit::window->mode () == L10N_PREVIEW) return;
44 
45         DlgNode* node;
46         gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, 1, &node, -1);
47 
48         GuiGraph *graph = GuiDlgedit::window->graph ();
49 
50         // select the node where the error occurred
51         graph->deselectNode ();
52         graph->selectNode (node);
53 
54         // center the view on it
55         graph->centerNode ();
56 
57         // open the edit dialog
58         if (graph->editNode ())
59         {
60             // dialog closed with okay -> assume the error is fixed
61             gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
62 
63             // close error console if no items remain in the list
64             if (gtk_tree_model_iter_n_children (model, NULL) == 0)
65                 gtk_widget_hide (GTK_WIDGET (user_data));
66         }
67     }
68 }
69 
70 // callback for closing the window
on_close_clicked(GtkButton * button,gpointer user_data)71 static void on_close_clicked (GtkButton *button, gpointer user_data)
72 {
73     // only hide the window
74     gtk_widget_hide (GTK_WIDGET (user_data));
75 }
76 
77 // callback when the window is deleted
on_delete_window(GtkWidget * window)78 static void on_delete_window (GtkWidget *window)
79 {
80     gtk_widget_destroy (window);
81 
82     if (GuiError::console)
83         delete GuiError::console;
84 }
85 
86 // global pointer to the error console
87 GuiError *GuiError::console = NULL;
88 
89 // constructor
GuiError()90 GuiError::GuiError ()
91 {
92     GtkWidget *vbox;
93     GtkWidget *scrolled;
94     GtkWidget *hseparator1;
95     GtkWidget *buttonbox;
96     GtkWidget *close;
97 
98     // the error console window
99     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
100     g_object_set_data (G_OBJECT (window), "window", window);
101     gtk_widget_set_size_request (window, 400, 320);
102     gtk_window_set_title (GTK_WINDOW (window), "Error Console");
103     gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
104 
105     vbox = gtk_vbox_new (FALSE, 0);
106     g_object_ref (vbox);
107     g_object_set_data_full (G_OBJECT (window), "vbox", vbox, (GDestroyNotify)  g_object_unref);
108     gtk_widget_show (vbox);
109     gtk_container_add (GTK_CONTAINER (window), vbox);
110     gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
111 
112     // vertical scrollbar for the list
113     scrolled = gtk_scrolled_window_new (NULL, NULL);
114     g_object_ref (scrolled);
115     g_object_set_data_full (G_OBJECT (window), "scrolled", scrolled, (GDestroyNotify)  g_object_unref);
116     gtk_widget_show (scrolled);
117     gtk_box_pack_start (GTK_BOX (vbox), scrolled, TRUE, TRUE, 0);
118     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
119 
120     // the model
121     GtkListStore *model = gtk_list_store_new(4, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_STRING);
122 
123     // the list
124     list = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model));
125     g_object_ref (list);
126     gtk_tree_view_set_grid_lines(GTK_TREE_VIEW(list), GTK_TREE_VIEW_GRID_LINES_HORIZONTAL);
127     gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(list), FALSE);
128     g_object_set_data_full (G_OBJECT (window), "list", list, (GDestroyNotify)  g_object_unref);
129     gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled), list);
130     gtk_widget_show (list);
131 
132     // create the columns
133     GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
134     gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW(list), 0, "Errors", renderer, "text", 0, "font", 2, "foreground", 3, NULL);
135 
136     // tooltip for the list
137     gtk_widget_set_tooltip_text (window, "Click on an error to bring up the corresponding node");
138 
139     hseparator1 = gtk_hseparator_new ();
140     g_object_ref (hseparator1);
141     g_object_set_data_full (G_OBJECT (window), "hseparator1", hseparator1, (GDestroyNotify)  g_object_unref);
142     gtk_widget_show (hseparator1);
143     gtk_box_pack_start (GTK_BOX (vbox), hseparator1, FALSE, TRUE, 2);
144 
145     buttonbox = gtk_hbutton_box_new ();
146     g_object_ref (buttonbox);
147     g_object_set_data_full (G_OBJECT (window), "buttonbox", buttonbox, (GDestroyNotify)  g_object_unref);
148     gtk_widget_show (buttonbox);
149     gtk_box_pack_start (GTK_BOX (vbox), buttonbox, FALSE, TRUE, 0);
150     gtk_button_box_set_layout (GTK_BUTTON_BOX (buttonbox), GTK_BUTTONBOX_END);
151     gtk_box_set_spacing (GTK_BOX (buttonbox), 0);
152 
153     // close button
154     close = gtk_button_new_with_label ("Close");
155     g_object_ref (close);
156     g_object_set_data_full (G_OBJECT (window), "close", close, (GDestroyNotify)  g_object_unref);
157     gtk_widget_show (close);
158     gtk_container_add (GTK_CONTAINER (buttonbox), close);
159     gtk_container_set_border_width (GTK_CONTAINER (close), 2);
160     gtk_widget_set_can_default (close, TRUE);
161     gtk_widget_set_tooltip_text (close, "Hide the Error Console");
162 
163     // selection listener
164     GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(list));
165 
166     g_signal_connect (G_OBJECT (selection), "changed", G_CALLBACK(on_list_select_child), window);
167     g_signal_connect (G_OBJECT (close), "clicked", G_CALLBACK (on_close_clicked), window);
168     g_signal_connect (G_OBJECT (window), "delete_event", G_CALLBACK (on_delete_window), window);
169 
170     // give the focus to the close button
171     gtk_widget_grab_focus (close);
172     gtk_widget_grab_default (close);
173 
174     // make sure that there is only one error console
175     if (console) delete console;
176     console = this;
177 
178     // set transient for dialogue editor main window
179     gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (GuiDlgedit::window->getWindow ()));
180 }
181 
182 // dtor
~GuiError()183 GuiError::~GuiError ()
184 {
185     console = NULL;
186 }
187 
188 // empty the list
clear()189 void GuiError::clear ()
190 {
191     gtk_widget_hide (list);
192 
193     GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(list));
194     gtk_list_store_clear (GTK_LIST_STORE(model));
195 
196     gtk_widget_show (list);
197 }
198 
199 // add an error message to the list
add(std::string error,DlgNode * node)200 void GuiError::add (std::string error, DlgNode *node)
201 {
202     GtkTreeIter iter;
203     GdkColor color = { 0, 27500, 0, 0 };
204     GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(list));
205     gchar *font_color = gdk_color_to_string(&color);
206 
207     gtk_list_store_append(GTK_LIST_STORE(model), &iter);
208     gtk_list_store_set (GTK_LIST_STORE(model), &iter, 0, error.c_str(), 1, node, 2, "Fixed,Monospace 10", 3, font_color, -1);
209 
210     g_free(font_color);
211 }
212 
213 // display all error messages
display()214 void GuiError::display ()
215 {
216     // show the console
217     gtk_widget_show (window);
218 }
219