show an error when the rc config file cannot be parsed, and refuse to load
[dana/obconf.git] / src / theme.c
1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
2
3    theme.h for ObConf, the configuration tool for Openbox
4    Copyright (c) 2003-2007   Dana Jansens
5    Copyright (c) 2003        Tim Riley
6
7    This program 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    See the COPYING file for a copy of the GNU General Public License.
18 */
19
20 #include "main.h"
21 #include "tree.h"
22 #include "preview_update.h"
23 #include "gettext.h"
24 #include "archive.h"
25 #include "theme.h"
26 #include "preview.h"
27
28 static gboolean mapping = FALSE;
29
30 static GList *themes;
31 static GtkListStore *theme_store;
32
33 static void add_theme_dir(const gchar *dirname);
34 static void on_theme_names_selection_changed(GtkTreeSelection *sel,
35                                              gpointer data);
36
37 void theme_setup_tab()
38 {
39     GtkCellRenderer *render;
40     GtkTreeViewColumn *column;
41     GtkTreeSelection *select;
42     GtkWidget *w;
43
44     mapping = TRUE;
45
46     w = get_widget("theme_names");
47
48     /* widget setup */
49     theme_store = gtk_list_store_new(3,
50                                      /* the theme name */
51                                      G_TYPE_STRING,
52                                      /* the theme preview */
53                                      GDK_TYPE_PIXBUF,
54                                      /* alignment of the preview */
55                                      G_TYPE_FLOAT);
56     gtk_tree_view_set_model(GTK_TREE_VIEW(w), GTK_TREE_MODEL(theme_store));
57     preview_update_set_tree_view(GTK_TREE_VIEW(w), theme_store);
58     g_object_unref (theme_store);
59
60     gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(w)),
61                                 GTK_SELECTION_SINGLE);
62
63     /* text column for the names */
64     render = gtk_cell_renderer_text_new();
65     column = gtk_tree_view_column_new_with_attributes
66         ("Name", render, "text", 0, NULL);
67     gtk_tree_view_append_column(GTK_TREE_VIEW(w), column);
68
69     /* pixbuf column, for theme previews */
70     render = gtk_cell_renderer_pixbuf_new();
71     column = gtk_tree_view_column_new_with_attributes
72         ("Preview", render, "pixbuf", 1, "xalign", 2, NULL);
73     gtk_tree_view_append_column(GTK_TREE_VIEW(w), column);
74
75     /* setup the selection handler */
76     select = gtk_tree_view_get_selection(GTK_TREE_VIEW (w));
77     gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE);
78     g_signal_connect (G_OBJECT(select), "changed",
79                       G_CALLBACK(on_theme_names_selection_changed),
80                       NULL);
81
82     mapping = FALSE;
83 }
84
85 static void on_theme_names_selection_changed(GtkTreeSelection *sel,
86                                              gpointer data)
87 {
88     GtkTreeIter iter;
89     GtkTreeModel *model;
90     const gchar *name;
91
92     if (mapping) return;
93
94     if(gtk_tree_selection_get_selected(sel, &model, &iter)) {
95         gtk_tree_model_get(model, &iter, 0, &name, -1);
96     }
97
98     if(name)
99       tree_set_string("theme/name", name);
100 }
101
102 void on_install_theme_clicked(GtkButton *w, gpointer data)
103 {
104     GtkWidget *d;
105     gint r;
106     gchar *path = NULL;
107     GtkFileFilter *filter;
108
109     d = gtk_file_chooser_dialog_new(_("Choose an Openbox theme"),
110                                     GTK_WINDOW(mainwin),
111                                     GTK_FILE_CHOOSER_ACTION_OPEN,
112                                     GTK_STOCK_OK, GTK_RESPONSE_OK,
113                                     GTK_STOCK_CANCEL, GTK_RESPONSE_NONE,
114                                     NULL);
115
116     gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER(d), FALSE);
117     filter = gtk_file_filter_new();
118     gtk_file_filter_set_name(filter, _("Openbox theme archives"));
119     gtk_file_filter_add_pattern(filter, "*.obt");
120     //gtk_file_filter_add_pattern(filter, "*.tgz");
121     //gtk_file_filter_add_pattern(filter, "*.tar.gz");
122     gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(d), filter);
123
124     r = gtk_dialog_run(GTK_DIALOG(d));
125     if (r == GTK_RESPONSE_OK)
126         path = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(d));
127     gtk_widget_destroy(d);
128
129     if (path != NULL) {
130         theme_install(path);
131         g_free(path);
132     }
133 }
134
135 void on_theme_archive_clicked(GtkButton *w, gpointer data)
136 {
137     GtkWidget *d;
138     gint r;
139     gchar *path = NULL;
140
141     d = gtk_file_chooser_dialog_new(_("Choose an Openbox theme"),
142                                     GTK_WINDOW(mainwin),
143                                     GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
144                                     GTK_STOCK_OK, GTK_RESPONSE_OK,
145                                     GTK_STOCK_CANCEL, GTK_RESPONSE_NONE,
146                                     NULL);
147
148     gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER(d), TRUE);
149     r = gtk_dialog_run(GTK_DIALOG(d));
150     if (r == GTK_RESPONSE_OK)
151         path = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(d));
152     gtk_widget_destroy(d);
153
154     if (path != NULL) {
155         archive_create(path);
156         g_free(path);
157     }
158 }
159
160 void theme_install(const gchar *path)
161 {
162     gchar *name;
163
164     if ((name = archive_install(path)))
165         tree_set_string("theme/name", name);
166     g_free(name);
167
168     theme_load_all();
169 }
170
171 void theme_load_all()
172 {
173     gchar *name;
174     gchar *p;
175     GList *it, *next;
176     gint i;
177     GtkWidget *w;
178     RrFont *active, *inactive, *menu_t, *menu_i, *osd;
179
180     mapping = TRUE;
181
182     w = get_widget("theme_names");
183     name = tree_get_string("theme/name", "TheBear");
184
185     for (it = themes; it; it = g_list_next(it))
186         g_free(it->data);
187     g_list_free(themes);
188     themes = NULL;
189
190     p = g_build_filename(g_get_home_dir(), ".themes", NULL);
191     add_theme_dir(p);
192     g_free(p);
193
194     {
195         GSList *it;
196         for (it = parse_xdg_data_dir_paths(); it; it = g_slist_next(it)) {
197             p = g_build_filename(it->data, "themes", NULL);
198             add_theme_dir(p);
199             g_free(p);
200         }
201     }
202
203     add_theme_dir(THEMEDIR);
204
205     themes = g_list_sort(themes, (GCompareFunc) strcasecmp);
206
207     gtk_list_store_clear(theme_store);
208
209     /* return to regular scheduled programming */
210     i = 0;
211     for (it = themes; it; it = next) {
212         GtkTreeIter iter;
213
214         next = g_list_next(it);
215
216         /* remove duplicates */
217         if (next && !strcmp(it->data, next->data)) {
218             g_free(it->data);
219             themes = g_list_delete_link(themes, it);
220             continue;
221         }
222
223         gtk_list_store_append(theme_store, &iter);
224         gtk_list_store_set(theme_store, &iter,
225                            0, it->data, /* the theme's name */
226                            1, NULL,     /* the preview is set later */
227                            2, 1.0,      /* all previews are right-aligned */
228                            -1);
229
230         if(!strcmp(name, it->data)) {
231             GtkTreePath *path;
232
233             path = gtk_tree_path_new_from_indices(i, -1);
234             gtk_tree_view_set_cursor(GTK_TREE_VIEW(w), path, NULL, FALSE);
235             gtk_tree_path_free(path);
236         }
237
238         ++i;
239     }
240
241     preview_update_all();
242
243     g_free(name);
244
245     mapping = FALSE;
246 }
247
248 static void add_theme_dir(const gchar *dirname)
249 {
250     GDir *dir;
251     const gchar *n;
252
253     if ((dir = g_dir_open(dirname, 0, NULL))) {
254         while ((n = g_dir_read_name(dir))) {
255             {
256                 gchar *full;
257                 full = g_build_filename(dirname, n, "openbox-3",
258                                         "themerc", NULL);
259                 if (!g_file_test(full,
260                                  G_FILE_TEST_IS_REGULAR |
261                                  G_FILE_TEST_IS_SYMLINK))
262                     n = NULL;
263                 g_free(full);
264             }
265
266             if (n) {
267                 themes = g_list_append(themes, g_strdup(n));
268             }
269         }
270         g_dir_close(dir);
271     }
272 }
273