Little UI fix.
[lxde/lxappearance.git] / src / icon-theme.c
CommitLineData
0cd84ed6
HJYP
1/*
2 * icon-theme.c
3 *
4 * Copyright 2010 PCMan <pcman.tw@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301, USA.
20 */
21
22#include "icon-theme.h"
15c155a6
HJYP
23#include "lxappearance2.h"
24#include <string.h>
2800b8a3 25#include "utils.h"
0cd84ed6 26
15c155a6
HJYP
27gint icon_theme_cmp_name(IconTheme* t, const char* name)
28{
29 return strcmp(t->name, name);
30}
31
32gint icon_theme_cmp_disp_name(IconTheme* t1, IconTheme* t2)
33{
34 return g_utf8_collate(t1->disp_name, t2->disp_name);
35}
36
37static void icon_theme_free(IconTheme* theme)
38{
39 g_free(theme->comment);
40 g_free(theme->name);
41 if(theme->disp_name != theme->name)
42 g_free(theme->disp_name);
43 g_slice_free(IconTheme, theme);
44}
45
9f90caed 46void load_icon_themes_from_dir(const char* theme_dir, GKeyFile* kf)
15c155a6
HJYP
47{
48 GDir* dir = g_dir_open(theme_dir, 0, NULL);
49 if(dir)
50 {
51 const char* name;
52 while(name = g_dir_read_name(dir))
53 {
54 /* skip "default" */
55 if(G_UNLIKELY(strcmp(name, "default") == 0))
56 continue;
57 /* test if we already have this in list */
58 if(!g_slist_find_custom(app.icon_themes, name, (GCompareFunc)icon_theme_cmp_name))
59 {
60 IconTheme* theme = g_slice_new0(IconTheme);
61 char* index_theme;
62 char* cursor_subdir;
63
64 theme->name = g_strdup(name);
65 index_theme = g_build_filename(theme_dir, name, "index.theme", NULL);
66 if(g_key_file_load_from_file(kf, index_theme, 0, NULL))
67 {
68 /* skip hidden ones */
69 if(!g_key_file_get_boolean(kf, "Icon Theme", "Hidden", NULL))
70 {
71 theme->disp_name = g_key_file_get_locale_string(kf, "Icon Theme", "Name", NULL, NULL);
72 /* test if this is a icon theme or it's a cursor theme */
73 theme->comment = g_key_file_get_locale_string(kf, "Icon Theme", "Comment", NULL, NULL);
74
75 /* icon theme must have this key, so it has icons if it has this key */
76 theme->has_icon = g_key_file_has_key(kf, "Icon Theme", "Directories", NULL);
77 }
78 }
79 else
80 theme->disp_name = theme->name;
81 g_free(index_theme);
82
83 cursor_subdir = g_build_filename(theme_dir, name, "cursors", NULL);
84 /* it contains a cursor theme */
85 if(g_file_test(cursor_subdir, G_FILE_TEST_IS_DIR))
86 theme->has_cursor = TRUE;
87 g_free(cursor_subdir);
88
89 if(theme->has_icon || theme->has_cursor)
9f90caed
HJYP
90 app.icon_themes = g_slist_insert_sorted(app.icon_themes, theme,
91 (GCompareFunc)icon_theme_cmp_disp_name);
15c155a6
HJYP
92 else /* this dir contains no icon or cursor theme, drop it. */
93 icon_theme_free(theme);
94 }
95 }
96 g_dir_close(dir);
97 }
98}
99
100static void load_icon_themes()
101{
102 const char* const *dirs = g_get_system_data_dirs();
103 const char* const *pdir;
104 char* dir_path;
105 GKeyFile* kf = g_key_file_new();
106
107 dir_path = g_build_filename(g_get_home_dir(), ".icons", NULL);
108 load_icon_themes_from_dir(dir_path, kf);
109 g_free(dir_path);
110
111 dir_path = g_build_filename(g_get_user_data_dir(), "icons", NULL);
112 load_icon_themes_from_dir(dir_path, kf);
113 g_free(dir_path);
114
115 for(pdir = dirs; *pdir; ++pdir)
116 {
117 dir_path = g_build_filename(*pdir, "icons", NULL);
118 load_icon_themes_from_dir(dir_path, kf);
119 g_free(dir_path);
120 }
121 g_key_file_free(kf);
15c155a6
HJYP
122}
123
124static void icon_sizes_init(GtkBuilder* b)
125{
126 const char* names[] = {
127 "gtk-menu",
128 "gtk-button",
129 "gtk-small-toolbar",
130 "gtk-large-toolbar",
131 "gtk-dnd",
132 "gtk-dialog"
133 };
134 char* sizes_str;
d023f0a4 135 g_object_get(gtk_settings_get_default(), "gtk-icon-sizes", &sizes_str, NULL);
15c155a6
HJYP
136 g_debug("%s", sizes_str);
137}
0cd84ed6 138
4e409096
HJYP
139static void on_icon_theme_sel_changed(GtkTreeSelection* tree_sel, gpointer user_data)
140{
141 GtkTreeModel* model;
142 GtkTreeIter it;
143 if(gtk_tree_selection_get_selected(tree_sel, &model, &it))
144 {
145 IconTheme* theme;
146 gtk_tree_model_get(model, &it, 1, &theme, -1);
147 if(g_strcmp0(theme->name, app.icon_theme))
148 {
149 g_free(app.icon_theme);
150 app.icon_theme = g_strdup(theme->name);
151 g_object_set(gtk_settings_get_default(), "gtk-icon-theme-name", app.icon_theme, NULL);
152
153 lxappearance_changed();
154 }
155 }
156}
157
2800b8a3
HJYP
158static void on_install_theme_clicked(GtkButton* btn, gpointer user_data)
159{
160 install_icon_theme(gtk_widget_get_toplevel(btn));
161}
162
0cd84ed6
HJYP
163void icon_theme_init(GtkBuilder* b)
164{
15c155a6
HJYP
165 GSList* l;
166 GtkTreeIter it;
167 GtkTreeIter icon_theme_sel_it = {0};
168 GtkTreeIter cursor_theme_sel_it = {0};
169 GtkTreeSelection* sel;
170
171 app.icon_theme_store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_POINTER);
172 app.cursor_theme_store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_POINTER);
173 app.icon_theme_view = GTK_WIDGET(gtk_builder_get_object(b, "icon_theme_view"));
174 app.cursor_theme_view = GTK_WIDGET(gtk_builder_get_object(b, "cursor_theme_view"));
175
0cd84ed6 176 /* load icon themes */
15c155a6
HJYP
177 load_icon_themes();
178
179 for(l = app.icon_themes; l; l=l->next)
180 {
181 IconTheme* theme = (IconTheme*)l->data;
182
183 if(theme->has_icon)
184 {
185 gtk_list_store_insert_with_values(app.icon_theme_store, &it, -1, 0, theme->disp_name, 1, theme, -1);
186 if(!icon_theme_sel_it.user_data)
187 {
188 if(strcmp(theme->name, app.icon_theme) == 0)
189 icon_theme_sel_it = it;
190 }
191 }
192
193 if(theme->has_cursor)
194 {
195 gtk_list_store_insert_with_values(app.cursor_theme_store, &it, -1, 0, theme->disp_name, 1, theme, -1);
196 if(!cursor_theme_sel_it.user_data)
197 {
198 if(g_strcmp0(theme->name, app.cursor_theme) == 0)
199 cursor_theme_sel_it = it;
200 }
201 }
202 }
203
204 /* select the currently used theme from the list */
205 gtk_tree_view_set_model(app.icon_theme_view, GTK_TREE_MODEL(app.icon_theme_store));
206 sel = gtk_tree_view_get_selection(app.icon_theme_view);
207 if(icon_theme_sel_it.user_data)
e597424e
HJYP
208 {
209 GtkTreePath* tp = gtk_tree_model_get_path(GTK_TREE_MODEL(app.icon_theme_store), &icon_theme_sel_it);
15c155a6 210 gtk_tree_selection_select_iter(sel, &icon_theme_sel_it);
e597424e
HJYP
211 gtk_tree_view_scroll_to_cell(app.icon_theme_view, tp, NULL, FALSE, 0, 0);
212 gtk_tree_path_free(tp);
213 }
4e409096 214 g_signal_connect(sel, "changed", G_CALLBACK(on_icon_theme_sel_changed), NULL);
15c155a6
HJYP
215
216 gtk_tree_view_set_model(app.cursor_theme_view, GTK_TREE_MODEL(app.cursor_theme_store));
217 sel = gtk_tree_view_get_selection(app.cursor_theme_view);
218 if(cursor_theme_sel_it.user_data)
e597424e
HJYP
219 {
220 GtkTreePath* tp = gtk_tree_model_get_path(GTK_TREE_MODEL(app.cursor_theme_store), &cursor_theme_sel_it);
15c155a6 221 gtk_tree_selection_select_iter(sel, &cursor_theme_sel_it);
e597424e
HJYP
222 gtk_tree_view_scroll_to_cell(app.cursor_theme_view, tp, NULL, FALSE, 0, 0);
223 gtk_tree_path_free(tp);
224 }
0cd84ed6
HJYP
225
226 /* load "gtk-icon-sizes" */
15c155a6 227 icon_sizes_init(b);
2800b8a3
HJYP
228
229 GtkWidget* btn = gtk_builder_get_object(b, "install_icon_theme");
230 g_signal_connect(btn, "clicked", G_CALLBACK(on_install_theme_clicked), NULL);
0cd84ed6 231}