1 /*
2  *     gtkatlantic - the gtk+ monopd client, enjoy network monopoly games
3  *
4  *
5  *  Copyright © 2002-2015 Sylvain Rochet
6  *
7  *  gtkatlantic is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; see the file COPYING. If not, see
19  *  <http://www.gnu.org/licenses/>.
20  */
21 
22 #include "config.h"
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <gtk/gtk.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <gtk/gtk.h>
31 
32 #include <dirent.h>
33 
34 #include "global.h"
35 #include "theme.h"
36 #include "parser.h"
37 #include "interface.h"
38 #include "callback.h"
39 
40 
41 /* refresh themes database */
theme_build_database()42 void theme_build_database()   {
43 
44 	DIR *d;
45 	struct dirent *dir;
46 	gchar *path, *path2;
47 	guint32 i;
48 
49 	/* first free all the database */
50 	for(i = 0; i < MAX_THEMES; i++)  {
51 
52 		if(!data->theme[i].open)  continue;
53 		theme_del_entry(i);
54 	}
55 
56 	/* user home theme */
57 	if (global->path_home) {
58 		path = g_strconcat(global->path_home, "/themes", NULL);
59 		d = opendir (path);
60 
61 		if(d)  {
62 
63 			while (1) {
64 
65 				dir = readdir(d);
66 				if(!dir) break;
67 
68 				if(dir->d_name[0] == '.')  continue;
69 
70 				path2 = g_strconcat(path, "/", dir->d_name, "/", NULL);
71 				theme_add_entry(path2);
72 				g_free(path2);
73 			}
74 			closedir (d);
75 		}
76 		g_free(path);
77 	}
78 
79 	/* global theme */
80 	d = opendir (PACKAGE_DATA_DIR "/themes");
81 	if (d) {
82 
83 		while (1) {
84 
85 			dir = readdir(d);
86 			if(!dir) break;
87 
88 			if(dir->d_name[0] == '.')  continue;
89 
90 			path2 = g_strconcat(PACKAGE_DATA_DIR "/themes/", dir->d_name, "/", NULL);
91 			theme_add_entry(path2);
92 			g_free(path2);
93 		}
94 		closedir (d);
95 	}
96 }
97 
98 
theme_get_valid_slot(guint32 * themeslot)99 gboolean theme_get_valid_slot(guint32 *themeslot)  {
100 
101 	guint32 i;
102 
103 	if(!data) return(FALSE);
104 
105 	for(i = 0; i < MAX_THEMES; i++)
106 		if(!data->theme[i].open) {
107 
108 			*themeslot = i;
109 			return(TRUE);
110 		}
111 
112 	return(FALSE);
113 }
114 
115 
theme_del_entry(guint32 slot)116 void theme_del_entry(guint32 slot) {
117 
118 	if(!data->theme[slot].open) return;
119 
120 	g_free(data->theme[slot].path);
121 	g_free(data->theme[slot].path_preview);
122 	g_free(data->theme[slot].path_conf);
123 
124 	g_free(data->theme[slot].name);
125 	g_free(data->theme[slot].type);
126 	g_free(data->theme[slot].version);
127 	g_free(data->theme[slot].author);
128 	g_free(data->theme[slot].email);
129 
130 	data->theme[slot].open = FALSE;
131 }
132 
133 
theme_add_entry(gchar * path)134 void theme_add_entry(gchar *path)  {
135 
136 	guint32 slot, area = 0;
137 	gchar *path2, str[512], *ident;
138 	struct stat s;
139 	FILE *file;
140 	char *ret;
141 
142 	gchar *name = 0, *type = 0, *version = 0, *author = 0, *email = 0, *preview = 0;
143 
144 	/* get properties of this theme, name, author, preview file, ... */
145 	path2 = g_strconcat(path, "theme.conf", NULL);
146 
147 	/* detect invalid theme */
148 	if(stat(path2, &s) < 0)  {
149 
150 		g_free(path2);
151 		return;
152 	}
153 
154 	/* parse general group */
155 	file = fopen(path2, "r");
156 	if (!file) return;
157 
158 	for (ret = fgets(str, 512, file); ret && !feof(file); ret = fgets(str, 512, file)) {
159 
160 		if (str[0] == '[')  {
161 
162 			if(! strncmp(str, "[general]", 9) )  area = THEME_FILE_SECTION_GENERAL;
163 			else area = 0;
164 		}
165 
166 		else  if(area == THEME_FILE_SECTION_GENERAL)  {
167 
168 			ident = parser_get_identifier(str);
169 			if(!ident)  continue;
170 
171 			if(! strcmp(ident, "theme") )  {
172 
173 				name = parser_get_data(str, "name");
174 				type = parser_get_data(str, "type");
175 				version = parser_get_data(str, "version");
176 
177 			} else if(! strcmp(ident, "author") )  {
178 
179 				author = parser_get_data(str, "name");
180 				email = parser_get_data(str, "email");
181 
182 			} else if(! strcmp(ident, "misc") )  {
183 
184 				preview = parser_get_data(str, "preview");
185 			}
186 
187 			g_free(ident);
188 		}
189 	}
190 	fclose(file);
191 
192 
193 	/* giving up if theme provide no name or no type */
194 	if(!name  ||  !type)  return;
195 
196 
197 	/* fill the theme database */
198 	if(! theme_get_valid_slot(&slot) )  return;
199 
200 	data->theme[slot].path = g_strdup(path);
201 	data->theme[slot].path_preview = g_strconcat(path, preview, NULL);
202 	g_free(preview);
203 	data->theme[slot].path_conf = g_strconcat(path, "theme.conf", NULL);
204 
205 	data->theme[slot].open = TRUE;
206 	data->theme[slot].name = name;
207 	data->theme[slot].type = type;
208 	data->theme[slot].version = version;
209 	data->theme[slot].author = author;
210 	data->theme[slot].email = email;
211 }
212 
213 
theme_build_selection_win()214 void theme_build_selection_win()  {
215 
216 	GtkWidget *ThemeWin;
217 		GtkWidget *VBox;
218 			GtkWidget *HBox;
219 				GtkWidget *VBoxLeft;
220 					GtkWidget *ScrollThemeList;
221 						GtkWidget *ThemeCList;
222 					GtkWidget *HBoxButtons;
223 						GtkWidget *Button;
224 				GtkWidget *VBoxInfo;
225 					GtkWidget *GridInfo;
226 						GtkWidget *Label;
227 				GtkWidget *PreviewFrame;
228 
229 	GtkWidget *tmp;
230 	gchar *str;
231 	GtkTreeSelection *select;
232 	GtkCellRenderer *renderer;
233 	GtkTreeViewColumn *column;
234 	GtkListStore *store;
235 
236 	if(global->ThemeWin)  return;
237 
238 	global->ThemeWin = ThemeWin = gtk_window_new(GTK_WINDOW_TOPLEVEL);
239 	gtk_window_set_title(GTK_WINDOW(ThemeWin), "GtkAtlantic: Theme Selection");
240 	g_signal_connect(G_OBJECT(ThemeWin), "delete_event", G_CALLBACK(CallBack_ThemeWin_Delete), NULL);
241 	g_signal_connect(G_OBJECT(ThemeWin), "destroy", G_CALLBACK(CallBack_ThemeWin_Destroyed), NULL);
242 
243 	VBox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
244 	gtk_container_set_border_width(GTK_CONTAINER(VBox), 5);
245 	gtk_container_add(GTK_CONTAINER(ThemeWin), VBox);
246 
247 	HBox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
248 	gtk_box_pack_start(GTK_BOX(VBox), HBox, TRUE, TRUE, 0);
249 
250 	VBoxLeft = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
251 	gtk_box_pack_start(GTK_BOX(HBox), VBoxLeft, TRUE, TRUE, 0);
252 
253 	/* theme list */
254 	ScrollThemeList = gtk_scrolled_window_new(NULL, NULL);
255 	gtk_widget_set_size_request(ScrollThemeList, 140, -1);
256 	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ScrollThemeList), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
257 	gtk_box_pack_start(GTK_BOX(VBoxLeft), ScrollThemeList, TRUE, TRUE, 0);
258 
259 	ThemeCList = gtk_tree_view_new();
260 	g_object_set_data(G_OBJECT(ThemeWin), "theme_list", ThemeCList);
261 	gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(ThemeCList), FALSE);
262 	gtk_container_add(GTK_CONTAINER(ScrollThemeList), ThemeCList);
263 	select = gtk_tree_view_get_selection(GTK_TREE_VIEW(ThemeCList));
264 	gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE);
265 	g_signal_connect(G_OBJECT(select), "changed", G_CALLBACK(Callback_ThemeList_Select), NULL);
266 
267 	renderer = gtk_cell_renderer_text_new();
268 	column = gtk_tree_view_column_new_with_attributes("Theme", renderer, "text", THEMELIST_COLUMN_NAME, NULL);
269 	gtk_tree_view_append_column(GTK_TREE_VIEW(ThemeCList), column);
270 
271 	store = gtk_list_store_new(TRADEPLAYERLIST_COLUMN_NUM, G_TYPE_STRING, G_TYPE_INT);
272 	gtk_tree_view_set_model(GTK_TREE_VIEW(ThemeCList), GTK_TREE_MODEL(store));
273 	g_object_unref(store);
274 
275 	/* hbox for buttons */
276 	HBoxButtons = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
277 	gtk_box_pack_start(GTK_BOX(VBoxLeft), HBoxButtons, FALSE, FALSE, 0);
278 
279 	Button = gtk_button_new_with_label("Apply");
280 	g_signal_connect(G_OBJECT(Button), "clicked", G_CALLBACK(CallBack_Theme_Apply), NULL);
281 	gtk_box_pack_start(GTK_BOX(HBoxButtons), Button, TRUE, TRUE, 0);
282 
283 	Button = gtk_button_new_with_label("Cancel");
284 	g_signal_connect(G_OBJECT(Button), "clicked", G_CALLBACK(CallBack_ThemeWin_Delete), NULL);
285 	gtk_box_pack_start(GTK_BOX(HBoxButtons), Button, TRUE, TRUE, 0);
286 
287 	/* vbox for themes */
288 	VBoxInfo = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
289 	gtk_box_pack_start(GTK_BOX(HBox), VBoxInfo, TRUE, TRUE, 0);
290 
291 	/* table which contain theme infos */
292 	GridInfo = gtk_grid_new();
293 	gtk_grid_set_column_spacing(GTK_GRID(GridInfo), 5);
294 	gtk_grid_set_row_spacing(GTK_GRID(GridInfo), 2);
295 	gtk_box_pack_start(GTK_BOX(VBoxInfo), GridInfo, FALSE, FALSE, 0);
296 
297 	Label = gtk_label_new("Name:");
298 	gtk_widget_set_halign(Label, GTK_ALIGN_START);
299 	gtk_widget_set_valign(Label, GTK_ALIGN_CENTER);
300 	gtk_grid_attach(GTK_GRID(GridInfo), Label, 0, 0, 1, 1);
301 
302 	Label = gtk_label_new("");
303 	gtk_widget_set_halign(Label, GTK_ALIGN_START);
304 	gtk_widget_set_valign(Label, GTK_ALIGN_CENTER);
305 	g_object_set_data(G_OBJECT(ThemeWin), "theme_name", Label);
306 	gtk_grid_attach(GTK_GRID(GridInfo), Label, 1, 0, 1, 1);
307 
308 	Label = gtk_label_new("Type:");
309 	gtk_widget_set_halign(Label, GTK_ALIGN_START);
310 	gtk_widget_set_valign(Label, GTK_ALIGN_CENTER);
311 	gtk_grid_attach(GTK_GRID(GridInfo), Label, 0, 1, 1, 1);
312 
313 	Label = gtk_label_new("");
314 	gtk_widget_set_halign(Label, GTK_ALIGN_START);
315 	gtk_widget_set_valign(Label, GTK_ALIGN_CENTER);
316 	g_object_set_data(G_OBJECT(ThemeWin), "theme_type", Label);
317 	gtk_grid_attach(GTK_GRID(GridInfo), Label, 1, 1, 1, 1);
318 
319 	Label = gtk_label_new("Version:");
320 	gtk_widget_set_halign(Label, GTK_ALIGN_START);
321 	gtk_widget_set_valign(Label, GTK_ALIGN_CENTER);
322 	gtk_grid_attach(GTK_GRID(GridInfo), Label, 0, 2, 1, 1);
323 
324 	Label = gtk_label_new("");
325 	gtk_widget_set_halign(Label, GTK_ALIGN_START);
326 	gtk_widget_set_valign(Label, GTK_ALIGN_CENTER);
327 	g_object_set_data(G_OBJECT(ThemeWin), "theme_version", Label);
328 	gtk_grid_attach(GTK_GRID(GridInfo), Label, 1, 2, 1, 1);
329 
330 	Label = gtk_label_new("Author:");
331 	gtk_widget_set_halign(Label, GTK_ALIGN_START);
332 	gtk_widget_set_valign(Label, GTK_ALIGN_CENTER);
333 	gtk_grid_attach(GTK_GRID(GridInfo), Label, 0, 3, 1, 1);
334 
335 	Label = gtk_label_new("");
336 	gtk_widget_set_halign(Label, GTK_ALIGN_START);
337 	gtk_widget_set_valign(Label, GTK_ALIGN_CENTER);
338 	g_object_set_data(G_OBJECT(ThemeWin), "theme_author", Label);
339 	gtk_grid_attach(GTK_GRID(GridInfo), Label, 1, 3, 1, 1);
340 
341 	Label = gtk_label_new("Email:");
342 	gtk_widget_set_halign(Label, GTK_ALIGN_START);
343 	gtk_widget_set_valign(Label, GTK_ALIGN_CENTER);
344 	gtk_grid_attach(GTK_GRID(GridInfo), Label, 0, 4, 1, 1);
345 
346 	Label = gtk_label_new("");
347 	gtk_widget_set_halign(Label, GTK_ALIGN_START);
348 	gtk_widget_set_valign(Label, GTK_ALIGN_CENTER);
349 	g_object_set_data(G_OBJECT(ThemeWin), "theme_email", Label);
350 	gtk_grid_attach(GTK_GRID(GridInfo), Label, 1, 4, 1, 1);
351 
352 	Label = gtk_label_new("Location:");
353 	gtk_widget_set_halign(Label, GTK_ALIGN_START);
354 	gtk_widget_set_valign(Label, GTK_ALIGN_CENTER);
355 	gtk_grid_attach(GTK_GRID(GridInfo), Label, 0, 5, 1, 1);
356 
357 	Label = gtk_label_new("");
358 	gtk_widget_set_halign(Label, GTK_ALIGN_START);
359 	gtk_widget_set_valign(Label, GTK_ALIGN_CENTER);
360 	g_object_set_data(G_OBJECT(ThemeWin), "theme_location", Label);
361 	gtk_grid_attach(GTK_GRID(GridInfo), Label, 1, 5, 1, 1);
362 
363 	/* preview */
364 	PreviewFrame = gtk_frame_new("Preview");
365 	gtk_box_pack_start(GTK_BOX(VBoxInfo), PreviewFrame, TRUE, TRUE, 0);
366 	gtk_widget_set_size_request(PreviewFrame, 400, 245);
367 	g_object_set_data(G_OBJECT(ThemeWin), "theme_preview_container", PreviewFrame);
368 
369 	tmp = gtk_label_new("No preview available");
370 	gtk_widget_set_halign(tmp, GTK_ALIGN_CENTER);
371 	gtk_widget_set_valign(tmp, GTK_ALIGN_CENTER);
372 	g_object_set_data(G_OBJECT(ThemeWin), "theme_preview_data", tmp);
373 	gtk_container_add(GTK_CONTAINER(PreviewFrame), tmp);
374 
375 	str = g_strdup_printf("%d", -1);
376 	g_object_set_data_full(G_OBJECT(global->ThemeWin), "theme_preview_selected", str, g_free);
377 
378 	gtk_widget_show_all(ThemeWin);
379 }
380 
381 
theme_fill_selection_list()382 void theme_fill_selection_list()  {
383 
384 	guint32 i;
385 	GtkWidget *ThemeList;
386 	GtkListStore *store;
387 
388 	ThemeList = g_object_get_data(G_OBJECT(global->ThemeWin), "theme_list");
389 
390 	/* build theme list */
391 	store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(ThemeList)));
392 	gtk_list_store_clear(store);
393 
394 	for(i = 0 ; i < MAX_THEMES ; i++)  {
395 		GtkTreeIter iter;
396 
397 		if (!data->theme[i].open) {
398 			continue;
399 		}
400 
401 		gtk_list_store_append(store, &iter);
402 		gtk_list_store_set(store, &iter,
403 		  THEMELIST_COLUMN_NAME, data->theme[i].name,
404 		  THEMELIST_COLUMN_ID, i,
405 		  -1);
406 	}
407 }
408 
409 
theme_preview_free()410 void theme_preview_free()  {
411 	GtkWidget *Preview;
412 
413 	/* free all preview data */
414 	Preview = g_object_get_data(G_OBJECT(global->ThemeWin), "theme_preview_data");
415 	gtk_widget_destroy(Preview);
416 	g_object_set_data(G_OBJECT(global->ThemeWin), "theme_preview_data", NULL);
417 }
418 
419 
theme_display(gint32 themeid)420 void theme_display(gint32 themeid)  {
421 
422 	GtkWidget *Label;
423 	GtkWidget *Frame;
424 	GtkWidget *Preview;
425 	GdkPixbuf *pixbuf = NULL;
426 	gchar *tmp;
427 
428 	if(! data->theme[themeid].open)  return;
429 
430 	Label = g_object_get_data(G_OBJECT(global->ThemeWin), "theme_name");
431 	gtk_label_set_text(GTK_LABEL(Label), data->theme[themeid].name);
432 
433 	Label = g_object_get_data(G_OBJECT(global->ThemeWin), "theme_type");
434 	gtk_label_set_text(GTK_LABEL(Label), data->theme[themeid].type);
435 
436 	Label = g_object_get_data(G_OBJECT(global->ThemeWin), "theme_version");
437 	gtk_label_set_text(GTK_LABEL(Label), data->theme[themeid].version);
438 
439 	Label = g_object_get_data(G_OBJECT(global->ThemeWin), "theme_author");
440 	gtk_label_set_text(GTK_LABEL(Label), data->theme[themeid].author);
441 
442 	Label = g_object_get_data(G_OBJECT(global->ThemeWin), "theme_email");
443 	gtk_label_set_text(GTK_LABEL(Label), data->theme[themeid].email);
444 
445 	Label = g_object_get_data(G_OBJECT(global->ThemeWin), "theme_location");
446 	gtk_label_set_text(GTK_LABEL(Label), data->theme[themeid].path);
447 
448 	tmp = g_strdup_printf("%d", themeid);
449 	g_object_set_data_full(G_OBJECT(global->ThemeWin), "theme_preview_selected", tmp, g_free);
450 
451 	/* free all preview data */
452 	theme_preview_free();
453 
454 	Frame = g_object_get_data(G_OBJECT(global->ThemeWin), "theme_preview_container");
455 
456 	/* put new preview data */
457 	if(! (pixbuf = theme_preview_read(themeid)) )  {
458 
459 		Preview = gtk_label_new("No preview available");
460 		g_object_set_data(G_OBJECT(global->ThemeWin), "theme_preview_data", Preview);
461 		gtk_container_add(GTK_CONTAINER(Frame), Preview);
462 		gtk_widget_show_all(Frame);
463 		return;
464 	}
465 
466 	/* put preview image */
467 	Preview = gtk_image_new_from_pixbuf(pixbuf);
468 	gtk_widget_set_halign(Preview, GTK_ALIGN_CENTER);
469 	gtk_widget_set_valign(Preview, GTK_ALIGN_CENTER);
470 	g_object_set_data(G_OBJECT(global->ThemeWin), "theme_preview_data", Preview);
471 	gtk_container_add(GTK_CONTAINER(Frame), Preview);
472 	gtk_widget_show_all(Frame);
473 	g_object_unref(pixbuf);
474 }
475 
476 
theme_preview_read(gint32 themeid)477 GdkPixbuf *theme_preview_read(gint32 themeid)  {
478 	gchar *path = data->theme[themeid].path_preview;
479 	GdkPixbuf *pixbuf = NULL;
480 	GError *err = NULL;
481 
482 	if (!data->theme[themeid].open)  return NULL;
483 	if (path == NULL)  return NULL;
484 
485 	/* load preview image */
486 	pixbuf = gdk_pixbuf_new_from_file(path, &err);
487 	if (!pixbuf) {
488 		fprintf(stderr, "error while loading %s: %s\n", path, err ? err->message : "(unknown)");
489 		g_error_free(err);
490 	}
491 	return pixbuf;
492 }
493 
494 
theme_load(gint32 themeid)495 void theme_load(gint32 themeid)  {
496 
497 	printf("%d\n", themeid);
498 	return;
499 }
500