1 /*
2 * settings.c
3 *
4 *
5 * Authors:
6 * Richard Hult <rhult@hem.passagen.se>
7 * Ricardo Markiewicz <rmarkie@fi.uba.ar>
8 * Andres de Barbara <adebarbara@fi.uba.ar>
9 * Marc Lorber <lorber.marc@wanadoo.fr>
10 * Bernhard Schuster <bernhard@ahoi.io>
11 * Guido Trentalancia <guido@trentalancia.com>
12 *
13 * Web page: https://ahoi.io/project/oregano
14 *
15 * Copyright (C) 1999-2001 Richard Hult
16 * Copyright (C) 2003,2006 Ricardo Markiewicz
17 * Copyright (C) 2008-2012 Marc Lorber
18 * Copyright (C) 2013 Bernhard Schuster
19 * Copyright (C) 2017 Guido Trentalancia
20 *
21 * This program is free software; you can redistribute it and/or
22 * modify it under the terms of the GNU General Public License as
23 * published by the Free Software Foundation; either version 2 of the
24 * License, or (at your option) any later version.
25 *
26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
29 * General Public License for more details.
30 *
31 * You should have received a copy of the GNU General Public
32 * License along with this program; if not, write to the
33 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
34 * Boston, MA 02110-1301, USA.
35 */
36
37 #include <unistd.h>
38 #include <glib.h>
39 #include <stdio.h>
40 #include <glib/gi18n.h>
41
42 #include "oregano.h"
43 #include "string.h"
44 #include "settings.h"
45 #include "schematic.h"
46 #include "schematic-view.h"
47 #include "dialogs.h"
48 #include "oregano-utils.h"
49 #include "oregano-config.h"
50
51 typedef struct
52 {
53 Schematic *sm;
54 GtkWidget *pbox; // Property box
55
56 GtkWidget *w_show_splash;
57 GtkWidget *w_show_log;
58
59 GtkWidget *w_compress_files;
60 GtkWidget *w_engine;
61 } Settings;
62
63 #define SETTINGS(x) ((Settings *)(x))
64
65 GtkWidget *engine_path;
66 GtkWidget *button[OREGANO_ENGINE_COUNT];
67
apply_callback(GtkWidget * w,Settings * s)68 static void apply_callback (GtkWidget *w, Settings *s)
69 {
70 oregano.engine = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (s->w_engine), "id"));
71 oregano.compress_files = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (s->w_compress_files));
72 if (s->w_show_log)
73 oregano.show_log = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (s->w_show_log));
74 else
75 oregano.show_log = FALSE;
76 oregano.show_splash = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (s->w_show_splash));
77
78 oregano_config_save ();
79
80 gtk_widget_destroy (s->pbox);
81 s->pbox = NULL;
82 }
83
delete_event_callback(GtkWidget * w,GdkEvent * event,Settings * s)84 static void delete_event_callback (GtkWidget *w, GdkEvent *event, Settings *s)
85 {
86 apply_callback (w, s);
87 }
88
set_engine_name(GtkWidget * w,Settings * s)89 static void set_engine_name (GtkWidget *w, Settings *s)
90 {
91 int engine_id;
92 gchar *engine_name;
93
94 s->w_engine = w;
95 engine_id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (s->w_engine), "id"));
96
97 engine_name = oregano_engine_get_engine_name_by_index (engine_id);
98 if (g_find_program_in_path (engine_name) == NULL) {
99 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button[engine_id]))) {
100 GString *msg = g_string_new (_ ("Engine <span weight=\"bold\" size=\"large\">"));
101 msg = g_string_append (msg, engine_name);
102 msg = g_string_append (msg, _ ("</span> not found\nThe engine is unable to locate "
103 "the external program."));
104 oregano_warning_with_title (_ ("Warning"), msg->str);
105 g_string_free (msg, TRUE);
106 engine_id = (engine_id + 1) % OREGANO_ENGINE_COUNT;
107 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button[engine_id]), TRUE);
108 } else
109 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button[engine_id]), FALSE);
110 }
111 g_free (engine_name);
112 }
113
settings_new(Schematic * sm)114 gpointer settings_new (Schematic *sm)
115 {
116 Settings *s;
117
118 s = g_new0 (Settings, 1);
119 s->sm = sm;
120
121 return s;
122 }
123
settings_show(GtkWidget * widget,SchematicView * sv)124 void settings_show (GtkWidget *widget, SchematicView *sv)
125 {
126 gint i;
127 gboolean engine_available = FALSE;
128 gchar *engine_name;
129 GtkWidget *engine_group = NULL;
130 GtkWidget *w, *pbox, *toplevel;
131 GtkBuilder *gui;
132 GError *perror = NULL;
133 gchar *msg;
134 Settings *s;
135 Schematic *sm;
136
137 g_return_if_fail (sv != NULL);
138
139 for (i = 0; i < OREGANO_ENGINE_COUNT; i++) {
140 engine_name = oregano_engine_get_engine_name_by_index (i);
141 if (g_find_program_in_path(engine_name) != NULL) {
142 engine_available = TRUE;
143 }
144 g_free (engine_name);
145 }
146
147 if (!engine_available) {
148 gchar *msg;
149 msg = g_strdup_printf (_ ("No engine allowing analysis is available.\n"
150 "You need to install at least one engine ! \n"
151 "spice3, ngspice or gnucap."));
152 oregano_error_with_title (_ ("Could not create engine settings dialog"), msg);
153 g_free (msg);
154 }
155
156 if ((gui = gtk_builder_new ()) == NULL) {
157 oregano_error (_ ("Could not create settings dialog"));
158 return;
159 }
160 gtk_builder_set_translation_domain (gui, NULL);
161
162 sm = schematic_view_get_schematic (sv);
163 s = schematic_get_settings (sm);
164
165 // Only allow one instance of the property box per schematic.
166 if (GTK_WIDGET (SETTINGS (s)->pbox)) {
167 gdk_window_raise (gtk_widget_get_window (GTK_WIDGET (SETTINGS (s)->pbox)));
168 return;
169 }
170
171 if (gtk_builder_add_from_file (gui, OREGANO_UIDIR "/settings.ui", &perror) <= 0) {
172 msg = perror->message;
173 oregano_error_with_title (_ ("Could not create settings dialog"), msg);
174 g_error_free (perror);
175 return;
176 }
177
178 w = toplevel = GTK_WIDGET (gtk_builder_get_object (gui, "toplevel"));
179 if (!w) {
180 oregano_error (_ ("Could not create settings dialog"));
181 return;
182 }
183 g_signal_connect (G_OBJECT (w), "delete_event", G_CALLBACK (delete_event_callback), s);
184
185 pbox = toplevel;
186 s->pbox = GTK_WIDGET (pbox);
187
188 w = GTK_WIDGET (gtk_builder_get_object (gui, "close_bt"));
189 g_signal_connect (G_OBJECT (w), "clicked", G_CALLBACK (apply_callback), s);
190
191 w = GTK_WIDGET (gtk_builder_get_object (gui, "splash-enable"));
192 s->w_show_splash = w;
193 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), oregano.show_splash);
194
195 w = GTK_WIDGET (gtk_builder_get_object (gui, "compress-enable"));
196 s->w_compress_files = w;
197 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), oregano.compress_files);
198 if (engine_available) {
199 w = GTK_WIDGET (gtk_builder_get_object (gui, "log-enable"));
200 s->w_show_log = w;
201 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), oregano.show_log);
202 } else {
203 w = GTK_WIDGET (gtk_builder_get_object (gui, "log-enable"));
204 s->w_show_log = NULL;
205 gtk_widget_destroy (w);
206 }
207
208 w = GTK_WIDGET (gtk_builder_get_object (gui, "realtime-enable"));
209 gtk_widget_set_sensitive (w, FALSE);
210
211 if (engine_available) {
212 w = GTK_WIDGET (gtk_builder_get_object (gui, "engine_table"));
213 for (i = 0; i < OREGANO_ENGINE_COUNT; i++) {
214 engine_name = oregano_engine_get_engine_name_by_index (i);
215 if (engine_group)
216 button[i] = gtk_radio_button_new_with_label_from_widget (
217 GTK_RADIO_BUTTON (engine_group), engine_name);
218 else
219 button[i] = engine_group =
220 gtk_radio_button_new_with_label_from_widget (NULL, engine_name);
221 g_free (engine_name);
222 g_object_set_data (G_OBJECT (button[i]), "id", GUINT_TO_POINTER (i));
223
224 gtk_grid_attach (GTK_GRID (w), button[i], 0, i, 1, 1);
225 g_signal_connect (G_OBJECT (button[i]), "clicked", G_CALLBACK (set_engine_name), s);
226 }
227
228 } else {
229 w = GTK_WIDGET (gtk_builder_get_object (gui, "label50"));
230 gtk_widget_destroy (w);
231 }
232
233 // Is the engine available?
234 // In that case the button is active
235 engine_name = oregano_engine_get_engine_name_by_index (oregano.engine);
236 if (g_find_program_in_path (engine_name) != NULL)
237 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button[oregano.engine]), TRUE);
238 // Otherwise the button is inactive
239 else
240 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button[oregano.engine]), FALSE);
241 g_free (engine_name);
242
243 gtk_widget_show_all (toplevel);
244 }
245