1 /*  cssed (c) Iago Rubio 2003, 2005 - A tiny CSS editor.
2  *
3  *  This program is free software; you can redistribute it and/or modify
4  *  it under the terms of the GNU General Public License as published by
5  *  the Free Software Foundation; either version 2 of the License, or
6  *  (at your option) any later version.
7  *
8  *  This program is distributed in the hope that it will be useful,
9  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  *  GNU Library General Public License for more details.
12  *
13  *  You should have received a copy of the GNU General Public License
14  *  along with this program; if not, write to the Free Software
15  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16  */
17 
18 #ifdef HAVE_CONFIG_H
19 #  include <config.h>
20 #endif
21 
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <string.h>
25 #include <stdio.h>
26 
27 #include <gdk/gdkkeysyms.h>
28 #include <gtk/gtk.h>
29 #include <gmodule.h>
30 
31 #include "cssedwindow.h"
32 #include "plugin.h"
33 #include "support.h"
34 #include "utils.h"
35 
36 #define GLADE_HOOKUP_OBJECT(component,widget,name) \
37   g_object_set_data_full (G_OBJECT (component), name, \
38     gtk_widget_ref (widget), (GDestroyNotify) gtk_widget_unref)
39 
40 #define GLADE_HOOKUP_OBJECT_NO_REF(component,widget,name) \
41   g_object_set_data (G_OBJECT (component), name, widget)
42 
43 // util func
44 void
scan_and_output_dir(CssedWindow * window,gchar * dirname,GtkListStore * list_store)45 scan_and_output_dir (CssedWindow * window, gchar * dirname,
46 		     			GtkListStore * list_store)
47 {
48 	GDir *dir;
49 	GError *error = NULL;
50 	GPatternSpec *pattern;
51 	G_CONST_RETURN gchar *filename;
52 	GtkTreeIter iter;
53 	CssedPlugin *plugin;
54 
55 #ifdef WIN32
56 	pattern = g_pattern_spec_new ("*.dll");
57 #else
58 	pattern = g_pattern_spec_new ("*.so");
59 #endif
60 
61 	dir = g_dir_open (dirname, 0, &error);
62 
63 	if (dir != NULL)
64 	{
65 		gtk_list_store_clear (list_store);
66 		filename = g_dir_read_name (dir);
67 		while (filename)
68 		{
69 			if (g_pattern_match (pattern, strlen (filename), filename, NULL))
70 			{
71 				gchar *fullname = g_build_filename (dirname, filename, NULL);
72 				if ((plugin =cssed_get_plugin_if_file_loaded (window, fullname)
73 					 ) == NULL )
74 				{
75 					gtk_list_store_append (list_store,
76 							       &iter);
77 					gtk_list_store_set (list_store, &iter,
78 							    0, fullname,
79 								1, "",
80 								2, "",
81 								3, FALSE,
82 								-1);
83 				}
84 				else
85 				{
86 					gtk_list_store_append (list_store,   &iter);
87 					gtk_list_store_set (list_store, &iter,
88 							    0, fullname, 1,
89 							    plugin->name, 2,
90 							    plugin->
91 							    description, 3,
92 							    TRUE, -1);
93 				}
94 				g_free (fullname);
95 			}
96 			filename = g_dir_read_name (dir);
97 		}
98 		g_dir_close (dir);
99 		g_pattern_spec_free (pattern);
100 	}else{
101 		g_error_free(error);
102 	}
103 }
104 
105 // callbacks
106 void
on_dialog_close(GtkDialog * dialog,gpointer user_data)107 on_dialog_close (GtkDialog * dialog, gpointer user_data)
108 {
109 	gtk_widget_destroy (GTK_WIDGET (dialog));
110 }
111 
112 
113 void
on_button_refresh_clicked(GtkButton * button,gpointer user_data)114 on_button_refresh_clicked (GtkButton * button, gpointer user_data)
115 {
116 	CssedWindow *window;
117 	GtkTreeModel *model;
118 	GtkWidget *view;
119 	gchar *plugins_dir;
120 
121 	window = CSSED_WINDOW (user_data);
122 	view = lookup_widget (GTK_WIDGET (button), "treeview_plugins");
123 	model = gtk_tree_view_get_model (GTK_TREE_VIEW (view));
124 
125 	plugins_dir = g_build_filename(PACKAGE_LIB_DIR,"plugins", NULL);
126 	scan_and_output_dir (window, plugins_dir, GTK_LIST_STORE (model));
127 	g_free(plugins_dir);
128 }
129 
130 
131 void
on_button_load_clicked(GtkButton * button,gpointer user_data)132 on_button_load_clicked (GtkButton * button, gpointer user_data)
133 {
134 	CssedWindow *window;
135 	CssedPlugin *plugin;
136 	GtkTreeSelection *select;
137 	GtkTreeModel *model;
138 	GtkTreeView *view;
139 	GtkTreeIter iter;
140 	gchar *path;
141 
142 
143 	window = CSSED_WINDOW (user_data);
144 	view = (GtkTreeView *) lookup_widget (GTK_WIDGET (button),
145 					      "treeview_plugins");
146 	model = gtk_tree_view_get_model (view);
147 	select = gtk_tree_view_get_selection (view);
148 
149 	if (gtk_tree_selection_get_selected (select, NULL, &iter))
150 	{
151 		gtk_tree_model_get (model, &iter, 0, &path, -1);
152 		if (cssed_is_plugin_file_loaded (window, path))
153 		{
154 			//errmsg = g_strdup_printf (_("Plugin is loaded\n%s\n\nPlease click Refresh if the dialog shows inaccurate values"),
155 			//			  				path);
156 			cssed_error_message (_("Plugin loaded"), _("Plugin is loaded\n%s\n\nPlease click Refresh if the dialog shows inaccurate values"), path);
157 			//g_free (errmsg);
158 		}
159 		else
160 		{
161 			plugin = cssed_init_plugin (window, path);
162 			if (plugin)
163 			{
164 				cssed_load_plugin (plugin);
165 				gtk_list_store_set (GTK_LIST_STORE (model),
166 						    &iter, 0, path, 1,
167 						    plugin->name, 2,
168 						    plugin->description, 3,
169 						    TRUE, -1);
170 			}
171 		}
172 		g_free (path);
173 	}
174 }
175 
176 
177 void
on_button_unload_clicked(GtkButton * button,gpointer user_data)178 on_button_unload_clicked (GtkButton * button, gpointer user_data)
179 {
180 	CssedWindow *window;
181 	CssedPlugin *plugin;
182 	GtkTreeSelection *select;
183 	GtkTreeModel *model;
184 	GtkTreeView *view;
185 	GtkTreeIter iter;
186 	gchar *path;
187 
188 
189 	window = CSSED_WINDOW (user_data);
190 	view = (GtkTreeView*) lookup_widget (GTK_WIDGET (button),"treeview_plugins");
191 	model = gtk_tree_view_get_model (view);
192 	select = gtk_tree_view_get_selection (view);
193 
194 	if (gtk_tree_selection_get_selected (select, NULL, &iter))
195 	{
196 		gtk_tree_model_get (model, &iter, 0, &path, -1);
197 		if ((plugin =
198 		     cssed_get_plugin_if_file_loaded (window, path)) != NULL)
199 		{
200 			cssed_unload_plugin (plugin);
201 			gtk_list_store_set (GTK_LIST_STORE (model), &iter,
202 					    0, path,
203 					    1, "",
204 						2, "",
205 						3, FALSE,
206 						-1);
207 		}
208 		else
209 		{
210 			//errmsg = g_strdup_printf (_("Plugin is not loaded\n%s\n\nPlease click Refresh if the dialog shows false values"), path);
211 			cssed_error_message (_("Not loaded"), _("Plugin is not loaded\n%s\n\nPlease click Refresh if the dialog shows false values"));
212 			//g_free (errmsg);
213 		}
214 		g_free (path);
215 	}
216 }
217 
218 
219 void
on_button_close_clicked(GtkButton * button,gpointer user_data)220 on_button_close_clicked (GtkButton * button, gpointer user_data)
221 {
222 	gtk_widget_destroy (GTK_WIDGET (user_data));
223 }
224 
225 // create UI
226 GtkWidget *
create_plugins_dialog(CssedWindow * window)227 create_plugins_dialog (CssedWindow * window)
228 {
229 	GtkWidget *dialog;
230 	GtkWidget *dialog_vbox;
231 	GtkWidget *scrolledwindow;
232 	GtkWidget *treeview_plugins;
233 	GtkWidget *dialog_action_area;
234 	GtkWidget *button_refresh;
235 	GtkWidget *button_load;
236 	GtkWidget *alignment2;
237 	GtkWidget *hbox2;
238 	GtkWidget *image2;
239 	GtkWidget *label2;
240 	GtkWidget *button_unload;
241 	GtkWidget *alignment3;
242 	GtkWidget *hbox3;
243 	GtkWidget *image3;
244 	GtkWidget *label3;
245 	GtkWidget *button_close;
246 	// list store and stuff
247 	GtkListStore *store;
248 	GtkTreeViewColumn *col_file;
249 	GtkTreeViewColumn *col_name;
250 	GtkTreeViewColumn *col_description;
251 	GtkTreeViewColumn *col_loaded;
252 	GtkCellRenderer *text_renderer;
253 	GtkCellRenderer *bool_renderer;
254 	// window widget
255 	GtkWidget *main_window;
256 	gchar *plugins_dir;
257 
258 	dialog = gtk_dialog_new ();
259 	gtk_window_set_title (GTK_WINDOW (dialog), _("Plugins dialog"));
260 	main_window = cssed_window_get_window_widget( window );
261 	gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (main_window));
262 	gtk_window_set_default_size (GTK_WINDOW (dialog), 650, 400);
263 
264 	dialog_vbox = GTK_DIALOG (dialog)->vbox;
265 	gtk_widget_show (dialog_vbox);
266 
267 	scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
268 	gtk_widget_show (scrolledwindow);
269 	gtk_box_pack_start (GTK_BOX (dialog_vbox), scrolledwindow, TRUE, TRUE,
270 			    0);
271 
272 	treeview_plugins = gtk_tree_view_new ();
273 	gtk_widget_show (treeview_plugins);
274 	gtk_container_add (GTK_CONTAINER (scrolledwindow), treeview_plugins);
275 
276 
277 	store = gtk_list_store_new (4, 	G_TYPE_STRING,
278 				    				G_TYPE_STRING,
279 				    				G_TYPE_STRING,
280 									G_TYPE_BOOLEAN);
281 
282 	gtk_tree_view_set_model (GTK_TREE_VIEW (treeview_plugins),
283 				 					GTK_TREE_MODEL (store));
284 	g_object_unref(store);
285 
286 	text_renderer = gtk_cell_renderer_text_new ();
287 	bool_renderer = gtk_cell_renderer_toggle_new ();
288 
289 	col_file =
290 		gtk_tree_view_column_new_with_attributes (_("File"),
291 							  text_renderer,
292 							  "markup", 0, NULL);
293 	col_name =
294 		gtk_tree_view_column_new_with_attributes (_("Name"),
295 							  text_renderer,
296 							  "markup", 1, NULL);
297 	col_description =
298 		gtk_tree_view_column_new_with_attributes (_("Description"),
299 							  text_renderer,
300 							  "markup", 2, NULL);
301 	col_loaded =
302 		gtk_tree_view_column_new_with_attributes (_("Loaded"),
303 							  bool_renderer,
304 							  "active", 3, NULL);
305 
306 	gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview_plugins),
307 					   TRUE);
308 
309 	gtk_tree_view_insert_column (GTK_TREE_VIEW (treeview_plugins),
310 				     			col_file, 0);
311 	gtk_tree_view_insert_column (GTK_TREE_VIEW (treeview_plugins),
312 				     			col_name, 1);
313 	gtk_tree_view_insert_column (GTK_TREE_VIEW (treeview_plugins),
314 				     			col_description, 2);
315 	gtk_tree_view_insert_column (GTK_TREE_VIEW (treeview_plugins),
316 				     			col_loaded, 3);
317 
318 
319 	dialog_action_area = GTK_DIALOG (dialog)->action_area;
320 	gtk_widget_show (dialog_action_area);
321 	gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area),
322 				   				GTK_BUTTONBOX_END);
323 
324 	button_refresh = gtk_button_new_from_stock ("gtk-refresh");
325 	gtk_widget_show (button_refresh);
326 	gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button_refresh, 0);
327 	GTK_WIDGET_SET_FLAGS (button_refresh, GTK_CAN_DEFAULT);
328 
329 	button_load = gtk_button_new ();
330 	gtk_widget_show (button_load);
331 	gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button_load, 0);
332 	GTK_WIDGET_SET_FLAGS (button_load, GTK_CAN_DEFAULT);
333 
334 	alignment2 = gtk_alignment_new (0.5, 0.5, 0, 0);
335 	gtk_widget_show (alignment2);
336 	gtk_container_add (GTK_CONTAINER (button_load), alignment2);
337 
338 	hbox2 = gtk_hbox_new (FALSE, 2);
339 	gtk_widget_show (hbox2);
340 	gtk_container_add (GTK_CONTAINER (alignment2), hbox2);
341 
342 	image2 = gtk_image_new_from_stock ("gtk-yes", GTK_ICON_SIZE_BUTTON);
343 	gtk_widget_show (image2);
344 	gtk_box_pack_start (GTK_BOX (hbox2), image2, FALSE, FALSE, 0);
345 
346 	label2 = gtk_label_new_with_mnemonic (_("Load"));
347 	gtk_widget_show (label2);
348 	gtk_box_pack_start (GTK_BOX (hbox2), label2, FALSE, FALSE, 0);
349 	gtk_label_set_justify (GTK_LABEL (label2), GTK_JUSTIFY_LEFT);
350 
351 	button_unload = gtk_button_new ();
352 	gtk_widget_show (button_unload);
353 	gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button_unload, 0);
354 	GTK_WIDGET_SET_FLAGS (button_unload, GTK_CAN_DEFAULT);
355 
356 	alignment3 = gtk_alignment_new (0.5, 0.5, 0, 0);
357 	gtk_widget_show (alignment3);
358 	gtk_container_add (GTK_CONTAINER (button_unload), alignment3);
359 
360 	hbox3 = gtk_hbox_new (FALSE, 2);
361 	gtk_widget_show (hbox3);
362 	gtk_container_add (GTK_CONTAINER (alignment3), hbox3);
363 
364 	image3 = gtk_image_new_from_stock ("gtk-no", GTK_ICON_SIZE_BUTTON);
365 	gtk_widget_show (image3);
366 	gtk_box_pack_start (GTK_BOX (hbox3), image3, FALSE, FALSE, 0);
367 
368 	label3 = gtk_label_new_with_mnemonic (_("Unload"));
369 	gtk_widget_show (label3);
370 	gtk_box_pack_start (GTK_BOX (hbox3), label3, FALSE, FALSE, 0);
371 	gtk_label_set_justify (GTK_LABEL (label3), GTK_JUSTIFY_LEFT);
372 
373 	button_close = gtk_button_new_from_stock ("gtk-close");
374 	gtk_widget_show (button_close);
375 	gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button_close,
376 				      GTK_RESPONSE_CLOSE);
377 	GTK_WIDGET_SET_FLAGS (button_close, GTK_CAN_DEFAULT);
378 
379 	g_signal_connect ((gpointer) dialog, "close",
380 			  G_CALLBACK (on_dialog_close), NULL);
381 	g_signal_connect ((gpointer) button_refresh, "clicked",
382 			  G_CALLBACK (on_button_refresh_clicked), window);
383 	g_signal_connect ((gpointer) button_load, "clicked",
384 			  G_CALLBACK (on_button_load_clicked), window);
385 	g_signal_connect ((gpointer) button_unload, "clicked",
386 			  G_CALLBACK (on_button_unload_clicked), window);
387 	g_signal_connect ((gpointer) button_close, "clicked",
388 			  G_CALLBACK (on_button_close_clicked), dialog);
389 
390 	/* Store pointers to all widgets, for use by lookup_widget(). */
391 	GLADE_HOOKUP_OBJECT_NO_REF (dialog, dialog, "dialog");
392 	GLADE_HOOKUP_OBJECT (dialog, treeview_plugins, "treeview_plugins");
393 	GLADE_HOOKUP_OBJECT (dialog, button_refresh, "button_refresh");
394 	GLADE_HOOKUP_OBJECT (dialog, button_load, "button_load");
395 	GLADE_HOOKUP_OBJECT (dialog, button_unload, "button_unload");
396 	GLADE_HOOKUP_OBJECT (dialog, button_close, "button_close");
397 
398 	// fill the tree
399 	plugins_dir = g_build_filename(PACKAGE_LIB_DIR,"plugins", NULL);
400 	scan_and_output_dir (window, plugins_dir, GTK_LIST_STORE (store));
401 	g_free(plugins_dir);
402 
403 	return dialog;
404 }
405 
406