/* * gtkatlantic - the gtk+ monopd client, enjoy network monopoly games * * * Copyright (C) 2002-2004 Rochet Sylvain * * gtkatlantic 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 2 of the License, or * (at your option) any later version. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include "global.h" #include "theme.h" #include "parser.h" #include "interface.h" #include "callback.h" #include "readpng.h" #include "config.h" /* refresh themes database */ void theme_build_database() { DIR *d; struct dirent *dir; guchar *path, *path2; guint32 i; /* first free all the database */ for(i = 0; i < MAX_THEMES; i++) { if(!data->theme[i].open) continue; theme_del_entry(i); } /* user home theme */ path = g_strconcat(global->path_home, "themes/", NULL); d = opendir (path); if(d) { while (1) { dir = readdir(d); if(!dir) break; if(dir->d_name[0] == '.') continue; path2 = g_strconcat(path, dir->d_name, "/", NULL); theme_add_entry(path2); g_free(path2); } closedir (d); } g_free(path); /* global theme */ path = g_strconcat(PACKAGE_DATA_DIR, "/themes/", NULL); d = opendir (path); if(d) { while (1) { dir = readdir(d); if(!dir) break; if(dir->d_name[0] == '.') continue; path2 = g_strconcat(path, dir->d_name, "/", NULL); theme_add_entry(path2); g_free(path2); } closedir (d); } g_free(path); } gboolean theme_get_valid_slot(guint32 *themeslot) { guint32 i; if(!data) return(FALSE); for(i = 0; i < MAX_THEMES; i++) if(!data->theme[i].open) { *themeslot = i; return(TRUE); } return(FALSE); } void theme_del_entry(guint32 slot) { if(!data->theme[slot].open) return; g_free(data->theme[slot].path); g_free(data->theme[slot].path_preview); g_free(data->theme[slot].path_conf); g_free(data->theme[slot].name); g_free(data->theme[slot].type); g_free(data->theme[slot].version); g_free(data->theme[slot].author); g_free(data->theme[slot].email); data->theme[slot].open = FALSE; } void theme_add_entry(guchar *path) { guint32 slot, area = 0; guchar *path2, *str, *ident; struct stat s; FILE *file; guchar *name = 0, *type = 0, *version = 0, *author = 0, *email = 0, *preview = 0; /* get properties of this theme, name, author, preview file, ... */ path2 = g_strconcat(path, "theme.conf", NULL); /* detect invalid theme */ if(stat(path2, &s) < 0) { g_free(path2); return; } /* parse general group */ file = fopen(path2, "r"); if (!file) return; str = g_malloc0(512); for( fgets(str, 512, file) ; !feof(file) ; fgets(str, 512, file) ) { if (str[0] == '[') { if(! strncmp(str, "[general]", 9) ) area = THEME_FILE_SECTION_GENERAL; else area = 0; } else if(area == THEME_FILE_SECTION_GENERAL) { ident = parser_get_identifier(str); if(!ident) continue; if(! strcmp(ident, "theme") ) { name = parser_get_data(str, "name"); type = parser_get_data(str, "type"); version = parser_get_data(str, "version"); } else if(! strcmp(ident, "author") ) { author = parser_get_data(str, "name"); email = parser_get_data(str, "email"); } else if(! strcmp(ident, "misc") ) { preview = parser_get_data(str, "preview"); } g_free(ident); } } fclose(file); g_free(str); /* giving up if theme provide no name or no type */ if(!name || !type) return; /* fill the theme database */ if(! theme_get_valid_slot(&slot) ) return; data->theme[slot].path = g_strdup(path); data->theme[slot].path_preview = g_strconcat(path, preview, NULL); g_free(preview); data->theme[slot].path_conf = g_strconcat(path, "theme.conf", NULL); data->theme[slot].open = TRUE; data->theme[slot].name = name; data->theme[slot].type = type; data->theme[slot].version = version; data->theme[slot].author = author; data->theme[slot].email = email; } void theme_build_selection_win() { GtkWidget *ThemeWin; GtkWidget *VBox; GtkWidget *HBox; GtkWidget *VBoxLeft; GtkWidget *ScrollThemeList; GtkWidget *ThemeCList; GtkWidget *HBoxButtons; GtkWidget *Button; GtkWidget *VBoxInfo; GtkWidget *TableInfo; GtkWidget *Alignment; GtkWidget *Label; GtkWidget *PreviewFrame; GtkWidget *tmp; guchar *str; if(global->ThemeWin) return; global->ThemeWin = ThemeWin = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(ThemeWin), "GtkAtlantic: Theme Selection"); gtk_window_set_policy(GTK_WINDOW(ThemeWin), FALSE, TRUE, TRUE); gtk_widget_realize(ThemeWin); gdk_window_set_icon(ThemeWin->window, NULL, global->icon_pixmap, global->icon_mask); gtk_signal_connect(GTK_OBJECT(ThemeWin), "delete_event", (GtkSignalFunc)CallBack_ThemeWin_Delete, NULL); gtk_signal_connect(GTK_OBJECT(ThemeWin), "destroy", (GtkSignalFunc)CallBack_ThemeWin_Destroyed, NULL); VBox = gtk_vbox_new(FALSE, 0); gtk_container_set_border_width(GTK_CONTAINER(VBox), 5); gtk_container_add(GTK_CONTAINER(ThemeWin), VBox); HBox = gtk_hbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(VBox), HBox, TRUE, TRUE, 0); VBoxLeft = gtk_vbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(HBox), VBoxLeft, TRUE, TRUE, 0); /* theme list */ ScrollThemeList = gtk_scrolled_window_new(NULL, NULL); gtk_widget_set_usize(ScrollThemeList, 140, 0); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ScrollThemeList), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_box_pack_start(GTK_BOX(VBoxLeft), ScrollThemeList, TRUE, TRUE, 0); ThemeCList = gtk_clist_new(2); gtk_clist_set_column_auto_resize(GTK_CLIST(ThemeCList), 0, TRUE); gtk_clist_set_column_auto_resize(GTK_CLIST(ThemeCList), 1, TRUE); gtk_clist_set_column_visibility(GTK_CLIST(ThemeCList), 1, FALSE); gtk_clist_column_titles_passive(GTK_CLIST(ThemeCList)); gtk_clist_set_reorderable(GTK_CLIST(ThemeCList), TRUE); gtk_clist_set_selection_mode(GTK_CLIST(ThemeCList), GTK_SELECTION_SINGLE); gtk_object_set_data(GTK_OBJECT(ThemeWin), "theme_list", ThemeCList); gtk_container_add(GTK_CONTAINER(ScrollThemeList), ThemeCList); gtk_signal_connect(GTK_OBJECT(ThemeCList), "unselect_row", (GtkSignalFunc)Callback_ThemeList_Unselect, NULL); gtk_signal_connect_after(GTK_OBJECT(ThemeCList), "select_row", (GtkSignalFunc)Callback_ThemeList_Select, NULL); /* hbox for buttons */ HBoxButtons = gtk_hbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(VBoxLeft), HBoxButtons, FALSE, FALSE, 0); Button = gtk_button_new_with_label("Apply"); gtk_signal_connect(GTK_OBJECT(Button), "clicked", (GtkSignalFunc)CallBack_Theme_Apply, NULL); gtk_box_pack_start(GTK_BOX(HBoxButtons), Button, TRUE, TRUE, 0); Button = gtk_button_new_with_label("Cancel"); gtk_signal_connect(GTK_OBJECT(Button), "clicked", (GtkSignalFunc)CallBack_ThemeWin_Delete, NULL); gtk_box_pack_start(GTK_BOX(HBoxButtons), Button, TRUE, TRUE, 0); /* vbox for themes */ VBoxInfo = gtk_vbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(HBox), VBoxInfo, TRUE, TRUE, 0); /* table which contain theme infos */ TableInfo = gtk_table_new (6, 2, FALSE); gtk_table_set_col_spacings(GTK_TABLE(TableInfo), 5); gtk_table_set_row_spacings(GTK_TABLE(TableInfo), 2); gtk_box_pack_start(GTK_BOX(VBoxInfo), TableInfo, FALSE, FALSE, 0); Alignment = gtk_alignment_new(0.0, 0.5, 0.0, 0.0); // gtk_table_attach(GTK_TABLE(TableInfo), Alignment, 0, 1, 0, 1, GTK_FILL | GTK_EXPAND | GTK_SHRINK, GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0); gtk_table_attach(GTK_TABLE(TableInfo), Alignment, 0, 1, 0, 1, GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 0, 0); Label = gtk_label_new("Name:"); gtk_container_add(GTK_CONTAINER(Alignment), Label); Alignment = gtk_alignment_new(0.0, 0.5, 0.0, 0.0); gtk_table_attach(GTK_TABLE(TableInfo), Alignment, 1, 2, 0, 1, GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 0, 0); Label = gtk_label_new(""); gtk_object_set_data(GTK_OBJECT(ThemeWin), "theme_name", Label); gtk_container_add(GTK_CONTAINER(Alignment), Label); Alignment = gtk_alignment_new(0.0, 0.5, 0.0, 0.0); gtk_table_attach(GTK_TABLE(TableInfo), Alignment, 0, 1, 1, 2, GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 0, 0); Label = gtk_label_new("Type:"); gtk_container_add(GTK_CONTAINER(Alignment), Label); Alignment = gtk_alignment_new(0.0, 0.5, 0.0, 0.0); gtk_table_attach(GTK_TABLE(TableInfo), Alignment, 1, 2, 1, 2, GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 0, 0); Label = gtk_label_new(""); gtk_object_set_data(GTK_OBJECT(ThemeWin), "theme_type", Label); gtk_container_add(GTK_CONTAINER(Alignment), Label); Alignment = gtk_alignment_new(0.0, 0.5, 0.0, 0.0); gtk_table_attach(GTK_TABLE(TableInfo), Alignment, 0, 1, 2, 3, GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 0, 0); Label = gtk_label_new("Version:"); gtk_container_add(GTK_CONTAINER(Alignment), Label); Alignment = gtk_alignment_new(0.0, 0.5, 0.0, 0.0); gtk_table_attach(GTK_TABLE(TableInfo), Alignment, 1, 2, 2, 3, GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 0, 0); Label = gtk_label_new(""); gtk_object_set_data(GTK_OBJECT(ThemeWin), "theme_version", Label); gtk_container_add(GTK_CONTAINER(Alignment), Label); Alignment = gtk_alignment_new(0.0, 0.5, 0.0, 0.0); gtk_table_attach(GTK_TABLE(TableInfo), Alignment, 0, 1, 3, 4, GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 0, 0); Label = gtk_label_new("Author:"); gtk_container_add(GTK_CONTAINER(Alignment), Label); Alignment = gtk_alignment_new(0.0, 0.5, 0.0, 0.0); gtk_table_attach(GTK_TABLE(TableInfo), Alignment, 1, 2, 3, 4, GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 0, 0); Label = gtk_label_new(""); gtk_object_set_data(GTK_OBJECT(ThemeWin), "theme_author", Label); gtk_container_add(GTK_CONTAINER(Alignment), Label); Alignment = gtk_alignment_new(0.0, 0.5, 0.0, 0.0); gtk_table_attach(GTK_TABLE(TableInfo), Alignment, 0, 1, 4, 5, GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 0, 0); Label = gtk_label_new("Email:"); gtk_container_add(GTK_CONTAINER(Alignment), Label); Alignment = gtk_alignment_new(0.0, 0.5, 0.0, 0.0); gtk_table_attach(GTK_TABLE(TableInfo), Alignment, 1, 2, 4, 5, GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 0, 0); Label = gtk_label_new(""); gtk_object_set_data(GTK_OBJECT(ThemeWin), "theme_email", Label); gtk_container_add(GTK_CONTAINER(Alignment), Label); Alignment = gtk_alignment_new(0.0, 0.5, 0.0, 0.0); gtk_table_attach(GTK_TABLE(TableInfo), Alignment, 0, 1, 5, 6, GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 0, 0); Label = gtk_label_new("Location:"); gtk_container_add(GTK_CONTAINER(Alignment), Label); Alignment = gtk_alignment_new(0.0, 0.5, 0.0, 0.0); gtk_table_attach(GTK_TABLE(TableInfo), Alignment, 1, 2, 5, 6, GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 0, 0); Label = gtk_label_new(""); gtk_object_set_data(GTK_OBJECT(ThemeWin), "theme_location", Label); gtk_container_add(GTK_CONTAINER(Alignment), Label); /* preview */ PreviewFrame = gtk_frame_new("Preview"); gtk_box_pack_start(GTK_BOX(VBoxInfo), PreviewFrame, TRUE, TRUE, 0); Alignment = gtk_alignment_new(0.5, 0.5, 0.0, 0.0); gtk_object_set_data(GTK_OBJECT(ThemeWin), "theme_preview_container", Alignment); gtk_widget_set_usize(Alignment, 400, 245); gtk_container_add(GTK_CONTAINER(PreviewFrame), Alignment); tmp = gtk_label_new("No preview available"); gtk_object_set_data(GTK_OBJECT(ThemeWin), "theme_preview_data", tmp); gtk_container_add(GTK_CONTAINER(Alignment), tmp); gtk_object_set_data(GTK_OBJECT(global->ThemeWin), "theme_preview_image", 0); str = g_strdup_printf("%d", -1); gtk_object_set_data_full(GTK_OBJECT(global->ThemeWin), "theme_preview_selected", str, g_free); gtk_widget_show_all(ThemeWin); } void theme_fill_selection_list() { guint32 i; gint32 row; gchar *txt[10]; GtkWidget *List; List = gtk_object_get_data(GTK_OBJECT(global->ThemeWin), "theme_list"); /* build theme list */ gtk_clist_freeze(GTK_CLIST(List)); gtk_clist_clear(GTK_CLIST(List)); for(i = 0 ; i < MAX_THEMES ; i++) { if(data->theme[i].open) { txt[0] = data->theme[i].name; txt[1] = g_strdup_printf("%d", i); row = gtk_clist_append(GTK_CLIST(List), txt); gtk_clist_set_selectable(GTK_CLIST(List), row, TRUE); g_free(txt[1]); } } gtk_clist_thaw(GTK_CLIST(List)); } void theme_preview_free() { GtkWidget *Alignment; GtkWidget *Preview; guchar *buf = 0; /* free all preview data */ Alignment = gtk_object_get_data(GTK_OBJECT(global->ThemeWin), "theme_preview_container"); Preview = gtk_object_get_data(GTK_OBJECT(global->ThemeWin), "theme_preview_data"); gtk_widget_destroy(Preview); buf = gtk_object_get_data(GTK_OBJECT(global->ThemeWin), "theme_preview_image"); if(buf) g_free(buf); gtk_object_set_data(GTK_OBJECT(global->ThemeWin), "theme_preview_image", 0); } void theme_display(gint32 themeid) { GtkWidget *Label; GtkWidget *Alignment; GtkWidget *Preview; guchar *buf = 0, *tmp; guint32 width, height; if(! data->theme[themeid].open) return; Label = gtk_object_get_data(GTK_OBJECT(global->ThemeWin), "theme_name"); gtk_label_set_text(GTK_LABEL(Label), data->theme[themeid].name); Label = gtk_object_get_data(GTK_OBJECT(global->ThemeWin), "theme_type"); gtk_label_set_text(GTK_LABEL(Label), data->theme[themeid].type); Label = gtk_object_get_data(GTK_OBJECT(global->ThemeWin), "theme_version"); gtk_label_set_text(GTK_LABEL(Label), data->theme[themeid].version); Label = gtk_object_get_data(GTK_OBJECT(global->ThemeWin), "theme_author"); gtk_label_set_text(GTK_LABEL(Label), data->theme[themeid].author); Label = gtk_object_get_data(GTK_OBJECT(global->ThemeWin), "theme_email"); gtk_label_set_text(GTK_LABEL(Label), data->theme[themeid].email); Label = gtk_object_get_data(GTK_OBJECT(global->ThemeWin), "theme_location"); gtk_label_set_text(GTK_LABEL(Label), data->theme[themeid].path); tmp = g_strdup_printf("%d", themeid); gtk_object_set_data_full(GTK_OBJECT(global->ThemeWin), "theme_preview_selected", tmp, g_free); /* free all preview data */ Alignment = gtk_object_get_data(GTK_OBJECT(global->ThemeWin), "theme_preview_container"); Preview = gtk_object_get_data(GTK_OBJECT(global->ThemeWin), "theme_preview_data"); theme_preview_free(); /* put new preview data */ if(! (buf = theme_preview_read(themeid, &width, &height)) ) { Preview = gtk_label_new("No preview available"); gtk_object_set_data(GTK_OBJECT(global->ThemeWin), "theme_preview_data", Preview); gtk_container_add(GTK_CONTAINER(Alignment), Preview); gtk_widget_show_all(Alignment); return; } /* put preview image */ gtk_object_set_data(GTK_OBJECT(global->ThemeWin), "theme_preview_image", buf); tmp = g_strdup_printf("%d", width); gtk_object_set_data_full(GTK_OBJECT(global->ThemeWin), "theme_preview_width", tmp, g_free); tmp = g_strdup_printf("%d", height); gtk_object_set_data_full(GTK_OBJECT(global->ThemeWin), "theme_preview_height", tmp, g_free); Preview = gtk_drawing_area_new(); gtk_drawing_area_size( GTK_DRAWING_AREA (Preview), width, height); gtk_object_set_data(GTK_OBJECT(global->ThemeWin), "theme_preview_data", Preview); gtk_container_add(GTK_CONTAINER(Alignment), Preview); gtk_signal_connect (GTK_OBJECT (Preview), "expose_event", GTK_SIGNAL_FUNC (on_theme_preview_expose), NULL); gtk_widget_show_all(Alignment); } guchar* theme_preview_read(gint32 themeid, guint32 *width, guint32 *height) { struct stat s; guchar *path = data->theme[themeid].path_preview; guchar *buf; png_structp png_ptr; png_infop info_ptr; _png_imagedata png_imagedata; FILE *infile; if(! data->theme[themeid].open) return FALSE; /* simple test */ if(! path) return FALSE; if(stat(path, &s) < 0) { return FALSE; } /* load preview image */ if (! (infile = fopen(path, "rb")) ) { fprintf(stderr, "can't open file [%s]\n", path); return FALSE; } if (! readpng_init(infile, &png_ptr, &info_ptr, &png_imagedata) != 0) { fprintf(stderr, "[%s] is not a valid PNG file\n", path); fclose(infile); return FALSE; } *width = png_imagedata.width; *height = png_imagedata.height; if(! readpng_decode_image(&png_ptr, &info_ptr, &png_imagedata, TRUE) ) { fprintf(stderr, "Unable to decode PNG image: [%s]\n", path); return FALSE; } fclose(infile); buf = readpng_get_image(&png_imagedata); readpng_cleanup(&png_ptr, &info_ptr, &png_imagedata); return buf; } void theme_load(gint32 themeid) { printf("%d\n", themeid); return; }