]>
Commit | Line | Data |
---|---|---|
1775dd11 MG |
1 | /*======================================================================== |
2 | Gtk Theme Switch, a fast and small Gtk theme switching utility that has a | |
3 | GUI and console interface. | |
4 | ||
5 | Copyright (C) 2009 Maher Awamy <muhri@muhri.net> | |
6 | Aaron Lehmann <aaronl@vitelus.com> | |
7 | Joshua Kwan <joshk@triplehelix.org> | |
8 | Pedro Villavicencio Garrido <pvillavi@gnome.cl> | |
9 | Denis Briand <denis@narcan.fr> | |
10 | ||
11 | This program is free software; you can redistribute it and/or modify | |
12 | it under the terms of the GNU General Public License as published by | |
13 | the Free Software Foundation; either version 2 of the License, or | |
14 | (at your option) any later version. | |
15 | ||
16 | This program is distributed in the hope that it will be useful, | |
17 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 | GNU General Public License for more details. | |
20 | ||
21 | You should have received a copy of the GNU General Public License along | |
22 | with this program; if not, write to the Free Software Foundation, Inc., | |
23 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
24 | =========================================================================*/ | |
25 | ||
26 | #include <gtk/gtk.h> | |
27 | #include <sys/types.h> | |
28 | #include <sys/stat.h> | |
29 | #include <sys/wait.h> | |
30 | #include <sys/types.h> | |
31 | #include <unistd.h> | |
32 | #include <dirent.h> | |
33 | #include <stdio.h> | |
34 | #include <stdlib.h> | |
35 | #include <string.h> | |
36 | #include <fcntl.h> | |
37 | #include <signal.h> | |
38 | #include <errno.h> | |
39 | ||
40 | static GList *get_dirs(void); | |
41 | static void preview_clicked(GtkWidget *button, gpointer data); | |
42 | static void update_newfont (void); | |
43 | static void apply_clicked(GtkWidget *button, gpointer data); | |
44 | static void usage(void); | |
45 | static void backup_gtkrc(gchar *path_to_gtkrc); | |
46 | static void ok_clicked(gchar *rc); | |
47 | static void preview_ok_clicked(gchar *rc); | |
48 | #ifdef SWITCH_GTK2 | |
49 | static GtkTreeModel *create_model (void); | |
50 | void clist_insert (GtkTreeView *clist); | |
51 | #endif | |
52 | static void dock(void); | |
53 | #ifndef SWITCH_GTK2 | |
54 | static int rightclick (GtkWidget *w, GdkEventButton *event, gpointer data); | |
55 | static void clist_insert(GtkWidget *clist); | |
56 | #endif | |
57 | static void preview(gchar *rc_file); | |
58 | static void preview_window(gchar *rc_file); | |
59 | static void send_refresh_signal(void); | |
60 | static short is_themedir (gchar *path, gchar **rc_file); | |
61 | static short is_installed_theme (gchar *path, gchar **rc_file); | |
62 | static short install_tarball (gchar *path, gchar **rc_file); | |
63 | static int switcheroo (gchar *actual); | |
64 | static void install_clicked (GtkWidget *w, gpointer data); | |
65 | static void install_ok_clicked (GtkWidget *w, gpointer data); | |
66 | static void search_for_theme_or_die_trying (gchar *actual, gchar **rc_file); | |
67 | static void set_font (GtkWidget *w, GtkWidget *dialog); | |
68 | static void font_browse_clicked (GtkWidget *w, gpointer data); | |
69 | static short fgrep_gtkrc_for (gchar *needle); | |
70 | static GList *compare_glists (GList *t1, GList *t2, GCompareFunc cmpfunc); | |
71 | void quit_preview(); | |
72 | void quit(); | |
73 | void hide_stuff(); | |
74 | void show_stuff(); | |
75 | void on_eventbox_click(); | |
76 | ||
77 | #define INIT_GTK if (!using_gtk) { gtk_init (&argc, &argv); using_gtk = 1; } | |
78 | ||
79 | ||
80 | /* globals */ | |
81 | GHashTable *hash; | |
82 | GList *glist=NULL; | |
83 | GSList *kids=NULL; | |
84 | gint preview_counter = 0; | |
85 | ||
86 | gchar *homedir, /* we use it a lot, so keep it handy */ | |
87 | *execname, /* == argv[0] */ | |
88 | *newfont; /* The name of a new font to use as the default if the user has | |
89 | selected one. Otherwise NULL. */ | |
90 | ||
91 | GtkWidget *dockwin, *combo=NULL, *font_entry, *use_font_button, *box, *install_button, *browse; | |
92 | gint hidden = 1; | |
93 | /*end globals */ | |
94 | ||
95 | static short fgrep_gtkrc_for (gchar *needle) | |
96 | { | |
97 | gchar *path_to_gtkrc = g_strdup_printf("%s/.gtkrc-2.0", homedir); | |
98 | FILE *gtkrc = fopen(path_to_gtkrc, "r"); | |
99 | char tempbuf[16384], *commentsearch; | |
100 | g_free (path_to_gtkrc); | |
101 | ||
102 | if (!gtkrc) | |
103 | return 0; | |
104 | ||
105 | while (!feof (gtkrc)) | |
106 | { | |
107 | fgets (tempbuf, 16383, gtkrc); | |
108 | /* Strip comments */ | |
109 | for (commentsearch = tempbuf; *commentsearch != '\0'; ++commentsearch) | |
110 | if (*commentsearch == '#') { *commentsearch = '\0'; break; } | |
111 | if (strstr(tempbuf, needle)) | |
112 | { | |
113 | fclose (gtkrc); | |
114 | return 1; | |
115 | } | |
116 | } | |
117 | fclose (gtkrc); | |
118 | return 0; | |
119 | } | |
120 | ||
121 | static GList* | |
122 | get_dirs (void) | |
123 | { | |
124 | gchar *dirname, *localthemedir, *globalthemedir, *dname; | |
125 | DIR *dir; | |
126 | struct dirent *dent; | |
127 | struct stat stats; | |
128 | gchar *origdir=g_get_current_dir(); /* back up cwd */ | |
129 | GList *list=0; | |
130 | ||
131 | dirname = g_strconcat(homedir,"/.themes",NULL); | |
132 | chdir (dirname); | |
133 | dir = opendir (dirname); | |
134 | if (dir) | |
135 | { | |
136 | /* ONE copy of the local theme directory for putting in the hash */ | |
137 | /* NB: Don't g_free() it!! */ | |
138 | localthemedir = g_strdup(dirname); | |
139 | ||
140 | while ((dent = readdir (dir))) | |
141 | { | |
142 | gchar* gtkrc_path = g_strconcat(dent->d_name, "/gtk-2.0/gtkrc", NULL); | |
143 | stat(dent->d_name,&stats); | |
144 | if (!S_ISDIR(stats.st_mode)) continue; | |
145 | if (strcmp(dent->d_name,"." ) == 0) continue; | |
146 | if (strcmp(dent->d_name,"..") == 0) continue; | |
147 | if (access(gtkrc_path, R_OK) == -1) continue; | |
148 | ||
149 | dname = g_strdup(dent->d_name); | |
150 | g_hash_table_insert (hash, dname, localthemedir); | |
151 | list = g_list_insert_sorted(list, dname, (GCompareFunc)strcmp); | |
152 | g_free(gtkrc_path); | |
153 | } | |
154 | ||
155 | closedir(dir); | |
156 | } | |
157 | ||
158 | g_free(dirname); | |
159 | ||
160 | dirname = gtk_rc_get_theme_dir(); | |
161 | chdir (dirname); | |
162 | dir = opendir (dirname); | |
163 | if (dir) | |
164 | { | |
165 | /* ONE copy of the global theme directory for putting in the hash */ | |
166 | /* NB: Don't g_free() it!! */ | |
167 | globalthemedir = g_strdup(dirname); | |
168 | ||
169 | while ((dent = readdir (dir))) | |
170 | { | |
171 | gchar* gtkrc_path = g_strconcat(dent->d_name,"/gtk-2.0/gtkrc",NULL); | |
172 | stat(dent->d_name,&stats); | |
173 | if (!S_ISDIR(stats.st_mode)) continue; | |
174 | if (strcmp(dent->d_name, "." ) == 0) continue; | |
175 | if (strcmp(dent->d_name, "..") == 0) continue; | |
176 | if (access(gtkrc_path, R_OK) == -1) continue; | |
177 | ||
178 | dname = g_strdup(dent->d_name); | |
179 | g_hash_table_insert (hash, dname, globalthemedir); | |
180 | list = g_list_insert_sorted(list, dname, (GCompareFunc)strcmp); | |
181 | g_free(gtkrc_path); | |
182 | } | |
183 | ||
184 | closedir(dir); | |
185 | } | |
186 | ||
187 | g_free(dirname); | |
188 | ||
189 | chdir(origdir); /* Go back to where we were */ | |
190 | g_free(origdir); /* Now go play like a good little program */ | |
191 | ||
192 | return list; | |
193 | } | |
194 | ||
195 | /* Find the first element in t2 that does not exist in t1. | |
196 | * Uses the supplied cmpfunc() for determining equality of list->data | |
197 | * strcmp() is the recommended compare function */ | |
198 | static GList* | |
199 | compare_glists (GList *t1, GList *t2, GCompareFunc cmpfunc) | |
200 | { | |
201 | GList *tmp1; | |
202 | for (; t2; t2=t2->next) | |
203 | { | |
204 | short matched = 0; | |
205 | for (tmp1=t1; tmp1; tmp1=tmp1->next) | |
206 | if ((*cmpfunc)(tmp1->data, t2->data) == 0) { matched = 1; break; } | |
207 | if (!matched) return t2; | |
208 | } | |
209 | return 0; | |
210 | } | |
211 | ||
212 | static void | |
213 | preview_clicked(GtkWidget *button, gpointer data) | |
214 | { | |
215 | G_CONST_RETURN gchar *entry; | |
216 | gchar *dir; | |
217 | gchar *rc; | |
218 | gchar *actual; | |
219 | ||
220 | entry = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(combo)->entry)); | |
221 | dir = g_hash_table_lookup(hash,entry); | |
222 | dir = g_strconcat(dir,"/",NULL); | |
223 | rc = g_strconcat(dir,entry,NULL); | |
224 | actual = g_strconcat(dir,entry,NULL); | |
225 | rc = g_strconcat(rc,"/gtk-2.0/gtkrc",NULL); | |
226 | update_newfont (); | |
227 | preview(rc); | |
228 | g_free(rc); | |
229 | g_free(actual); | |
230 | } | |
231 | ||
232 | /* Update 'newfont' */ | |
233 | static void update_newfont (void) | |
234 | { | |
235 | if (newfont) g_free (newfont); | |
236 | ||
237 | if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(use_font_button))) | |
238 | { | |
239 | G_CONST_RETURN gchar *newerfont = gtk_entry_get_text (GTK_ENTRY(font_entry)); | |
240 | if (newerfont && newerfont[0]) | |
241 | { | |
242 | newfont = g_strdup(newerfont); | |
243 | } | |
244 | } | |
245 | else newfont = NULL; | |
246 | } | |
247 | ||
248 | static void | |
249 | apply_clicked(GtkWidget *button, gpointer data) | |
250 | { | |
251 | G_CONST_RETURN gchar *entry = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(combo)->entry)); | |
252 | gchar *dir = g_hash_table_lookup(hash,entry); | |
253 | gchar *name = g_strdup_printf ("%s/%s/gtk-2.0/gtkrc", dir, entry); | |
254 | /* GtkStyle *style;*/ | |
255 | ||
256 | update_newfont (); | |
257 | ||
258 | ok_clicked(name); | |
259 | g_free(name); | |
260 | ||
261 | /* make sure we get the ClientEvent ourselves */ | |
262 | while (gtk_events_pending()) | |
263 | gtk_main_iteration(); | |
264 | ||
265 | /* sync the font field with the GTK font */ | |
266 | /* style = gtk_rc_get_style (font_entry); | |
267 | if (style && style->rc_style) | |
268 | gtk_entry_set_text (GTK_ENTRY(font_entry), pango_font_description_to_string(style->rc_style->font_desc));*/ | |
269 | } | |
270 | ||
271 | static void | |
272 | usage (void) | |
273 | { | |
274 | printf("\ | |
275 | %s command line options:\n\ | |
276 | -h[elp]\t\t\t(display this help message)\n\ | |
277 | -d[ock]\t\t\t(open dock)\n\ | |
278 | file\t\t\t(switch to theme (install if theme is a tarball))\n\ | |
279 | -p[review] file\t\t(preview a theme (installs if file is a tarball))\n\ | |
280 | -i[nstall] theme.tar.gz\t(install a .tar.gz)\n\ | |
281 | -f[ont] fontstring\t(set GTK's main font to fontstring)\n\n\ | |
282 | \ | |
283 | Passing no command line arguments will cause %s to start in dock-mode)\n\n\ | |
284 | \ | |
285 | \"file\" represents any one of (looked for in the listed order):\n\ | |
286 | 1) An absoulte or relative path to a GTK theme directory.\n\ | |
287 | A directory is considered a theme directory if it contains a\n\ | |
288 | gtk/gtkrc file.\n\ | |
289 | 2) A gzipped tar file which expands to a GTK theme directory as explained in 1).\n\ | |
290 | 3) A GTK theme directory with the name passed located in ~/.themes.\n\ | |
291 | 4) A GTK theme directory with the name passed located in the global\n\ | |
292 | \"gtk_themedir\"\n\ | |
293 | If none of these files are located and found to be correct, the program will\n\ | |
294 | exit with an error.\n", | |
295 | execname, execname); | |
296 | } | |
297 | ||
298 | static void | |
299 | write_rc_file (gchar *include_file, gchar *path) | |
300 | { | |
301 | FILE *gtkrc = fopen(path, "w"); | |
302 | /*XXX XXX*/ | |
303 | if (gtkrc == NULL) { | |
304 | GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW(dockwin), | |
305 | GTK_DIALOG_DESTROY_WITH_PARENT, | |
306 | GTK_MESSAGE_ERROR, | |
307 | GTK_BUTTONS_CLOSE, | |
308 | "Unable to save your preferences to %s: %s.", | |
309 | path,strerror(errno) ); | |
310 | gtk_window_set_title(GTK_WINDOW(dialog), "Error"); | |
311 | gtk_dialog_run (GTK_DIALOG (dialog)); | |
312 | gtk_widget_destroy (dialog); | |
313 | quit(); | |
314 | } | |
315 | /* the caps stuff is bullshit for gnome */ | |
316 | fprintf(gtkrc, "# -- THEME AUTO-WRITTEN BY gtk-theme-switch2 DO NOT EDIT\ninclude \"%s\"\n\n", include_file); | |
317 | if (newfont) | |
318 | /* User set a custom font to overrride defaults. */ | |
319 | fprintf (gtkrc, "style \"user-font\"\n{\n font_name=\"%s\"\n}\nwidget_class \"*\" style \"user-font\"\n\n", newfont); | |
320 | fprintf(gtkrc, "include \"%s/.gtkrc-2.0.mine\"\n\n# -- THEME AUTO-WRITTEN BY gtk-theme-switch2 DO NOT EDIT\n", homedir); | |
321 | fclose (gtkrc); | |
322 | } | |
323 | ||
324 | static void | |
325 | backup_gtkrc(gchar *path_to_gtkrc) | |
326 | { | |
327 | FILE *gtkrc; | |
328 | if (!(gtkrc = fopen(path_to_gtkrc, "r"))) | |
329 | return; | |
330 | int c; | |
331 | FILE *gtkrc_backup = fopen(g_strdup_printf("%s/.gtkrc-2.0.bak", homedir),"w"); | |
332 | ||
333 | while((c = fgetc(gtkrc)) != EOF){ | |
334 | fputc(c, gtkrc_backup); | |
335 | } | |
336 | ||
337 | fclose(gtkrc); | |
338 | fclose(gtkrc_backup); | |
339 | } | |
340 | ||
341 | static void | |
342 | ok_clicked (gchar *rc_file) | |
343 | { | |
344 | /* Write the config file to disk */ | |
345 | gchar *path_to_gtkrc = g_strdup_printf("%s/.gtkrc-2.0", homedir); | |
346 | backup_gtkrc(path_to_gtkrc); | |
347 | write_rc_file (rc_file, path_to_gtkrc); | |
348 | send_refresh_signal(); | |
349 | g_free(path_to_gtkrc); | |
350 | } | |
351 | ||
352 | static void | |
353 | preview_ok_clicked (gchar *rc_file) | |
354 | { | |
355 | /* Write the config file to disk */ | |
356 | gchar *path_to_gtkrc = g_strdup_printf("%s/.gtkrc-2.0", homedir); | |
357 | rename (rc_file, path_to_gtkrc); | |
358 | send_refresh_signal(); | |
359 | g_free(path_to_gtkrc); | |
360 | } | |
361 | ||
362 | static void | |
363 | install_clicked (GtkWidget *w, gpointer data) | |
364 | { | |
365 | GtkWidget *checkbutton = gtk_check_button_new_with_label ("Switch to theme after installation"); | |
366 | GtkWidget *fs = gtk_file_selection_new ("Select a GTK theme tarball"); | |
367 | g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(fs)->ok_button), "clicked", G_CALLBACK(install_ok_clicked), fs); | |
368 | g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(fs)->cancel_button), "clicked", G_CALLBACK(gtk_widget_destroy), (gpointer)fs); | |
369 | gtk_box_pack_start (GTK_BOX(GTK_FILE_SELECTION(fs)->main_vbox), checkbutton, FALSE, FALSE, 0); | |
370 | gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(checkbutton), FALSE); | |
371 | g_object_set_data (G_OBJECT(fs), "checkbutton", checkbutton); | |
372 | gtk_widget_show(checkbutton); | |
373 | gtk_widget_show(fs); | |
374 | } | |
375 | ||
376 | static void | |
377 | install_ok_clicked (GtkWidget *w, gpointer data) | |
378 | { | |
379 | gchar *rc_file, *beginning_of_theme_name, *thn; | |
380 | G_CONST_RETURN gchar *filename; | |
381 | gint i, pos; | |
382 | short slashes=0; | |
383 | gboolean cbstate=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g_object_get_data(G_OBJECT(data), "checkbutton"))); | |
384 | filename = gtk_file_selection_get_filename(GTK_FILE_SELECTION(data)); | |
385 | thn = g_strdup(filename); | |
386 | search_for_theme_or_die_trying(thn, &rc_file); | |
387 | g_free(thn); | |
388 | gtk_widget_destroy(GTK_WIDGET(data)); | |
389 | /* ok, we're like evil or something, but that won't stop us */ | |
390 | for (i=strlen(rc_file); i != 0; --i) | |
391 | { | |
392 | if (rc_file[i] == '/') ++slashes; | |
393 | if (slashes == 2) { rc_file[i] = '\0'; break; } | |
394 | } | |
395 | beginning_of_theme_name = rc_file; | |
396 | for (i=strlen(rc_file) /*different*/; i != 0; --i) | |
397 | { | |
398 | if (rc_file[i] == '/') { beginning_of_theme_name = &rc_file[i+1]; break; } | |
399 | } | |
400 | /* we've been very naugthy, but we should have the theme's NAME now.. | |
401 | * it's about time. */ | |
402 | /* get the list item that contains this */ | |
403 | pos = g_list_position (glist, g_list_find_custom (glist, beginning_of_theme_name, (GCompareFunc) strcmp)); | |
404 | if (pos != -1) | |
405 | /* set combo's item to the newly-installed theme */ | |
406 | /*FIXME gtk_list_select_item(GTK_LIST(GTK_COMBO(combo)->list), pos);*/ | |
407 | ||
408 | if (cbstate) /* checkbutton pressed */ | |
409 | apply_clicked(NULL, NULL); | |
410 | ||
411 | /* I guess we should free this... */ | |
412 | g_free (rc_file); | |
413 | } | |
414 | ||
415 | static void | |
416 | set_font (GtkWidget *w, GtkWidget *dialog) | |
417 | { | |
418 | if (newfont) g_free (newfont); | |
419 | newfont = gtk_font_selection_dialog_get_font_name (GTK_FONT_SELECTION_DIALOG(dialog)); | |
420 | gtk_entry_set_text (GTK_ENTRY(font_entry), newfont); | |
421 | gtk_widget_destroy (dialog); | |
422 | } | |
423 | ||
424 | static void | |
425 | font_browse_clicked (GtkWidget *w, gpointer data) | |
426 | { | |
427 | GtkWidget *font_dialog; | |
428 | font_dialog = gtk_font_selection_dialog_new ("Select Font"); | |
429 | gtk_font_selection_dialog_set_preview_text (GTK_FONT_SELECTION_DIALOG(font_dialog), "Gtk Theme Switch"); | |
430 | /* gtk_font_selection_dialog_set_font_name (GTK_FONT_SELECTION_DIALOG(font_dialog), gtk_entry_get_text(GTK_ENTRY(font_entry)));*/ | |
431 | g_signal_connect (G_OBJECT(GTK_FONT_SELECTION_DIALOG(font_dialog)->ok_button), "clicked", G_CALLBACK(set_font), (gpointer)font_dialog); | |
432 | g_signal_connect_swapped (G_OBJECT(GTK_FONT_SELECTION_DIALOG(font_dialog)->cancel_button), "clicked", G_CALLBACK(gtk_widget_destroy), (gpointer)font_dialog); | |
433 | ||
434 | gtk_widget_show (font_dialog); | |
435 | } | |
436 | ||
437 | void quit() | |
438 | { | |
439 | GSList *l; | |
440 | for (l = kids; l ; l=l->next) { | |
441 | kill(GPOINTER_TO_INT(l->data), 9); | |
442 | } | |
443 | exit(0); | |
444 | } | |
445 | ||
446 | static void | |
447 | dock (void) | |
448 | { | |
449 | GtkWidget *label, *button, *pixmap, *evbox; | |
450 | GtkTooltips *tips; | |
451 | ||
452 | dockwin = gtk_dialog_new(); | |
453 | gtk_widget_realize(dockwin); | |
454 | gtk_window_set_title(GTK_WINDOW(dockwin),"Theme Dock"); | |
455 | /* gtk_window_set_policy(GTK_WINDOW(dockwin), TRUE, TRUE, FALSE);*/ | |
456 | gtk_window_set_resizable(GTK_WINDOW(dockwin), TRUE); | |
457 | g_signal_connect(G_OBJECT(dockwin),"destroy",G_CALLBACK(quit),NULL); | |
458 | box = gtk_hbox_new(FALSE, 0); | |
459 | gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dockwin)->vbox), box, FALSE, FALSE, 0); | |
460 | tips = gtk_tooltips_new(); | |
461 | label = gtk_label_new("Theme: "); | |
462 | gtk_box_pack_start(GTK_BOX(box),label,FALSE,FALSE,FALSE); | |
463 | ||
464 | combo = gtk_combo_new(); | |
465 | glist = get_dirs(); | |
466 | gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist); | |
467 | gtk_box_pack_start(GTK_BOX(box),combo,TRUE,TRUE,FALSE); | |
468 | ||
469 | pixmap = gtk_image_new_from_stock(GTK_STOCK_ADD, GTK_ICON_SIZE_BUTTON); | |
470 | ||
471 | evbox = gtk_event_box_new(); | |
472 | ||
473 | gtk_tooltips_set_tip(tips,evbox,"click here for more options","private"); | |
474 | gtk_widget_set_events(evbox, GDK_BUTTON_PRESS); | |
475 | g_signal_connect(G_OBJECT(evbox), "button_press_event", G_CALLBACK(on_eventbox_click), NULL); | |
476 | ||
477 | gtk_container_add(GTK_CONTAINER(evbox), pixmap); | |
478 | gtk_box_pack_start(GTK_BOX(box),evbox,FALSE,FALSE,FALSE); | |
479 | gtk_widget_show_all(box); | |
480 | ||
481 | box = gtk_hbox_new(FALSE, 0); | |
482 | gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dockwin)->vbox), box, FALSE, FALSE, 0); | |
483 | ||
484 | use_font_button = gtk_check_button_new_with_label("Use font: "); | |
485 | gtk_box_pack_start(GTK_BOX(box), use_font_button, FALSE, FALSE, 0); | |
486 | gtk_widget_show(use_font_button); | |
487 | ||
488 | font_entry = gtk_entry_new(); | |
489 | gtk_box_pack_start(GTK_BOX(box), font_entry, TRUE, TRUE, 0); | |
490 | gtk_widget_show(font_entry); | |
491 | if (newfont) | |
492 | { | |
493 | gtk_entry_set_text (GTK_ENTRY(font_entry), newfont); | |
494 | gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(use_font_button), TRUE); | |
495 | g_free (newfont); | |
496 | } | |
497 | else | |
498 | { | |
499 | /* GtkStyle *style = gtk_rc_get_style (font_entry); | |
500 | if (style && style->rc_style) | |
501 | gtk_entry_set_text (GTK_ENTRY(font_entry), pango_font_description_to_string(style->rc_style->font_desc));*/ | |
502 | } | |
503 | ||
504 | newfont = g_strdup(gtk_entry_get_text(GTK_ENTRY(font_entry))); | |
505 | ||
506 | if (newfont != 0 && newfont[0]) | |
507 | { | |
508 | /* Very dirty hack... | |
509 | We want to only set the checkbutton to TRUE if the user specified | |
510 | the font. If the name occurs in their ~/.gtkrc file, they probably did. | |
511 | If it isn't, they probably didn't. So, "grep" the file for the font string. */ | |
512 | if (fgrep_gtkrc_for(newfont)) | |
513 | gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(use_font_button), TRUE); | |
514 | } | |
515 | ||
516 | browse = gtk_button_new_with_label("Browse..."); | |
517 | g_signal_connect(G_OBJECT(browse), "clicked", G_CALLBACK(font_browse_clicked), NULL); | |
518 | gtk_box_pack_start(GTK_BOX(box), browse, FALSE, FALSE, 0); | |
519 | ||
520 | button = gtk_button_new_with_label("Apply"); | |
521 | g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(apply_clicked),NULL); | |
522 | gtk_box_pack_start(GTK_BOX(GTK_DIALOG (dockwin)->action_area),button,TRUE,TRUE,FALSE); | |
523 | gtk_widget_show(button); | |
524 | ||
525 | button = gtk_button_new_with_label("Preview"); | |
526 | g_signal_connect(GTK_OBJECT(button),"clicked",G_CALLBACK(preview_clicked),NULL); | |
527 | gtk_box_pack_start(GTK_BOX(GTK_DIALOG (dockwin)->action_area),button,TRUE,TRUE,FALSE); | |
528 | gtk_widget_show(button); | |
529 | ||
530 | install_button = gtk_button_new_with_label("Install New Theme"); | |
531 | g_signal_connect(G_OBJECT(install_button), "clicked", G_CALLBACK(install_clicked), NULL); | |
532 | gtk_box_pack_start(GTK_BOX(GTK_DIALOG (dockwin)->action_area),install_button,TRUE,TRUE,FALSE); | |
533 | ||
534 | gtk_widget_show(dockwin); | |
535 | ||
536 | } | |
537 | ||
538 | void on_eventbox_click() | |
539 | { | |
540 | if (hidden) { | |
541 | show_stuff(); | |
542 | } else { | |
543 | hide_stuff(); | |
544 | } | |
545 | } | |
546 | ||
547 | void hide_stuff() | |
548 | { | |
549 | gtk_widget_hide(box); | |
550 | gtk_widget_hide(install_button); | |
551 | gtk_widget_hide(browse); | |
552 | hidden = 1; | |
553 | } | |
554 | ||
555 | void show_stuff() | |
556 | { | |
557 | gtk_widget_show(box); | |
558 | gtk_widget_show(install_button); | |
559 | gtk_widget_show(browse); | |
560 | hidden = 0; | |
561 | } | |
562 | ||
563 | ||
564 | static GtkTreeModel * | |
565 | create_model (void) | |
566 | { | |
567 | ||
568 | GtkListStore *store; | |
569 | GtkTreeIter iter; | |
570 | gint i; | |
571 | gchar *stuff[4][2] = { { "blah1", "blah2" }, | |
572 | { "blah3", "blah4" }, | |
573 | { "blah5", "blah6" }, | |
574 | { "blah7", "blah8" } }; | |
575 | ||
576 | /* create list store */ | |
577 | store = gtk_list_store_new (2, | |
578 | G_TYPE_STRING, | |
579 | G_TYPE_STRING); | |
580 | ||
581 | /* add data to the list store */ | |
582 | for (i = 0; i < 4; i++) | |
583 | { | |
584 | gtk_list_store_append (store, &iter); | |
585 | gtk_list_store_set (store, &iter, | |
586 | 0, stuff[i][0], | |
587 | 1, stuff[i][1], | |
588 | -1); | |
589 | } | |
590 | ||
591 | return GTK_TREE_MODEL (store); | |
592 | } | |
593 | ||
594 | ||
595 | static void | |
596 | preview (gchar *rc_file) | |
597 | { | |
598 | FILE *pipe; | |
599 | gint got_it = 0, it_died = 0; | |
600 | gchar *line; | |
601 | gchar *path = g_strdup_printf ("%s/.gtkrc.tmp-%i", homedir, preview_counter); | |
602 | gchar *command = g_strdup_printf ("%s -_dont-use-this %s &", execname, path); | |
603 | write_rc_file (rc_file, path); | |
604 | ||
605 | pipe = popen(command,"r"); | |
606 | ||
607 | if (pipe == NULL) { | |
608 | g_print("gts: error previewing\n"); | |
609 | return; | |
610 | } | |
611 | ||
612 | fcntl(fileno(pipe), F_SETFL, O_NONBLOCK); | |
613 | ||
614 | line = (gchar *)g_malloc(1024); | |
615 | while(!feof(pipe)) { | |
616 | fgets(line,1024,pipe); | |
617 | line[strlen(line)-1] = '\0'; | |
618 | if (!got_it && !g_strncasecmp(line,"pid=",4)) { | |
619 | kids = g_slist_append(kids,GINT_TO_POINTER(atoi(line+4))); | |
620 | got_it = 1; | |
621 | } else if (!it_died && !g_strncasecmp(line,"die=",4)) { | |
622 | kids = g_slist_remove(kids,GINT_TO_POINTER(atoi(line+4))); | |
623 | it_died = 1; | |
624 | break; | |
625 | } | |
626 | ||
627 | while (gtk_events_pending()) | |
628 | gtk_main_iteration(); | |
629 | usleep(50000); | |
630 | } | |
631 | ||
632 | pclose(pipe); | |
633 | g_free (line); | |
634 | g_free (path); | |
635 | g_free (command); | |
636 | ++preview_counter; | |
637 | } | |
638 | ||
639 | static void | |
640 | preview_window (gchar *rc_file) | |
641 | { | |
642 | ||
643 | GtkWidget *label; | |
644 | GtkWidget *win; | |
645 | GtkWidget *button; | |
646 | GtkWidget *toggle_button; | |
647 | GtkWidget *check_button; | |
648 | GtkWidget *sw; | |
649 | GtkWidget *clist; | |
650 | GtkWidget *vbox; | |
651 | GtkWidget *hbox; | |
652 | GtkWidget *radio; | |
653 | GtkWidget *radio2; | |
654 | GtkWidget *radio3; | |
655 | GtkWidget *ok; | |
656 | GtkWidget *cancel; | |
657 | GtkWidget *hbox2; | |
658 | GtkWidget *notebook; | |
659 | GtkWidget *text; | |
660 | GtkTreeModel *model; | |
661 | /* GtkWidget *popup; | |
662 | GtkWidget *item;*/ | |
663 | GtkTextBuffer *buff; | |
664 | gint argc=1; | |
665 | gchar **argv = &execname; | |
666 | gchar *default_files[] = { rc_file, NULL}; | |
667 | gchar *bb = "Type some text here\nto check if your\ntheme has a problem\nwith the text widget.\nAlso right-click here\nfor a popup-menu sample.\n"; | |
668 | GSList *group; | |
669 | ||
670 | gtk_rc_set_default_files (default_files); | |
671 | gtk_init (&argc, &argv); | |
672 | ||
673 | win = gtk_window_new(GTK_WINDOW_TOPLEVEL); | |
674 | gtk_window_set_title(GTK_WINDOW(win), "Gtk Theme Switch theme preview"); | |
675 | /* gtk_window_set_policy(GTK_WINDOW(win), TRUE, TRUE, FALSE);*/ | |
676 | g_signal_connect(G_OBJECT(win), "destroy", G_CALLBACK(quit_preview), NULL); | |
677 | ||
678 | vbox = gtk_vbox_new(FALSE,0); | |
679 | notebook = gtk_notebook_new(); | |
680 | gtk_container_add (GTK_CONTAINER(win), notebook); | |
681 | label = gtk_label_new("Page 1"); | |
682 | gtk_notebook_append_page (GTK_NOTEBOOK(notebook), vbox, label); | |
683 | label = gtk_label_new("Label"); | |
684 | button = gtk_button_new_with_label("Button"); | |
685 | toggle_button = gtk_toggle_button_new_with_label("Toggle Button"); | |
686 | check_button = gtk_check_button_new_with_label("Check Button"); | |
687 | hbox = gtk_hbox_new(FALSE,0); | |
688 | radio = gtk_radio_button_new_with_label(NULL,"Radio 1"); | |
689 | group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio)); | |
690 | radio2 = gtk_radio_button_new_with_label(group,"Radio 2"); | |
691 | group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio2)); | |
692 | radio3 = gtk_radio_button_new_with_label(group,"Radio 3"); | |
693 | gtk_box_pack_start((GtkBox*)hbox,radio,FALSE,FALSE,FALSE); | |
694 | gtk_box_pack_start((GtkBox*)hbox,radio2,FALSE,FALSE,FALSE); | |
695 | gtk_box_pack_start((GtkBox*)hbox,radio3,FALSE,FALSE,FALSE); | |
696 | sw = gtk_scrolled_window_new(NULL,NULL); | |
697 | gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),GTK_POLICY_AUTOMATIC,GTK_POLICY_AUTOMATIC); | |
698 | model = create_model(); | |
699 | clist = gtk_tree_view_new_with_model(model); | |
700 | gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (clist), TRUE); | |
701 | gtk_tree_view_set_search_column (GTK_TREE_VIEW (clist),0); | |
702 | g_object_unref (G_OBJECT (model)); | |
703 | ||
704 | ok = gtk_button_new_with_label("Ok"); | |
705 | g_signal_connect_swapped(G_OBJECT(ok),"clicked",G_CALLBACK(preview_ok_clicked), (gpointer) rc_file); | |
706 | cancel = gtk_button_new_with_label("Cancel"); | |
707 | g_signal_connect_swapped(G_OBJECT(cancel),"clicked",G_CALLBACK(quit_preview),NULL); | |
708 | hbox2 = gtk_hbox_new(FALSE,0); | |
709 | gtk_box_pack_start((GtkBox*)hbox2,ok,TRUE,TRUE,FALSE); | |
710 | gtk_box_pack_start((GtkBox*)hbox2,cancel,TRUE,TRUE,FALSE); | |
711 | gtk_container_add(GTK_CONTAINER(sw),clist); | |
712 | gtk_box_pack_start((GtkBox*)vbox,label,FALSE,FALSE,FALSE); | |
713 | gtk_box_pack_start((GtkBox*)vbox,button,FALSE,FALSE,FALSE); | |
714 | gtk_box_pack_start((GtkBox*)vbox,toggle_button,FALSE,FALSE,FALSE); | |
715 | gtk_box_pack_start((GtkBox*)vbox,check_button,FALSE,FALSE,FALSE); | |
716 | gtk_box_pack_start((GtkBox*)vbox,hbox,FALSE,FALSE,FALSE); | |
717 | gtk_box_pack_start((GtkBox*)vbox,sw,TRUE,TRUE,FALSE); | |
718 | gtk_box_pack_start((GtkBox*)vbox,hbox2,FALSE,FALSE,FALSE); | |
719 | ||
720 | vbox = gtk_vbox_new (FALSE, 0); | |
721 | label = gtk_label_new ("Page 2"); | |
722 | gtk_notebook_append_page (GTK_NOTEBOOK(notebook), vbox, label); | |
723 | label = gtk_label_new ("Insensitive Label"); | |
724 | gtk_widget_set_sensitive (label, 0); | |
725 | gtk_box_pack_start (GTK_BOX(vbox), label, FALSE, FALSE, 0); | |
726 | button = gtk_button_new_with_label ("Insensitive Button"); | |
727 | gtk_widget_set_sensitive (button, 0); | |
728 | gtk_box_pack_start (GTK_BOX(vbox), button, FALSE, FALSE, 0); | |
729 | sw = gtk_scrolled_window_new (NULL, NULL); | |
730 | gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); | |
731 | buff = gtk_text_buffer_new(NULL); | |
732 | gtk_text_buffer_set_text(buff,bb, strlen(bb)); | |
733 | text = gtk_text_view_new(); | |
734 | gtk_text_view_set_buffer(GTK_TEXT_VIEW(text), buff); | |
735 | ||
736 | gtk_container_add (GTK_CONTAINER(sw), text); | |
737 | /* | |
738 | popup = gtk_menu_new (); | |
739 | gtk_widget_show (popup); | |
740 | item = gtk_menu_item_new_with_label ("Menu Entry 1"); | |
741 | gtk_widget_show (item); | |
742 | gtk_menu_append(GTK_MENU(popup), item); | |
743 | item = gtk_menu_item_new_with_label ("Menu Entry 2"); | |
744 | gtk_widget_show (item); | |
745 | gtk_menu_append(GTK_MENU(popup), item); | |
746 | item = gtk_menu_item_new_with_label ("Menu Entry 3"); | |
747 | gtk_widget_show (item); | |
748 | gtk_menu_append(GTK_MENU(popup), item); | |
749 | gtk_signal_connect(GTK_OBJECT(text), "button_press_event", GTK_SIGNAL_FUNC(rightclick), popup); | |
750 | */ | |
751 | gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0); | |
752 | ||
753 | label = gtk_label_new ("About"); | |
754 | vbox = gtk_vbox_new (FALSE, 0); | |
755 | gtk_notebook_append_page (GTK_NOTEBOOK(notebook), vbox, label); | |
756 | label = gtk_label_new ("Gtk Theme Switch\nby Maher Awamy <muhri@muhri.net>\nand Aaron Lehmann <aaronl@vitelus.com>\nhttp://www.muhri.net/nav.php3?node=gts"); | |
757 | gtk_box_pack_start (GTK_BOX(vbox), label, TRUE, TRUE, 0); | |
758 | ||
759 | clist_insert(GTK_TREE_VIEW(clist)); | |
760 | ||
761 | gtk_widget_show_all(win); | |
762 | ||
763 | ||
764 | g_print("pid=%d\n",getpid()); | |
765 | ||
766 | gtk_main (); | |
767 | ||
768 | unlink (rc_file); | |
769 | ||
770 | _exit (1); /* no change */ | |
771 | } | |
772 | ||
773 | void quit_preview() | |
774 | { | |
775 | g_print("die=%d\n",getpid()); | |
776 | gtk_main_quit(); | |
777 | } | |
778 | ||
779 | static void | |
780 | send_refresh_signal(void) | |
781 | { | |
782 | GdkEventClient event; | |
783 | event.type = GDK_CLIENT_EVENT; | |
784 | event.send_event = TRUE; | |
785 | event.window = NULL; | |
786 | event.message_type = gdk_atom_intern("_GTK_READ_RCFILES", FALSE); | |
787 | event.data_format = 8; | |
788 | gdk_event_send_clientmessage_toall((GdkEvent *)&event); | |
789 | } | |
790 | ||
791 | /* Sets rc_file to the rc_file of the theme if the result is true. | |
792 | * It is the caller's repsonsibility to free rc_file */ | |
793 | static short is_themedir (gchar *path, gchar **rc_file) | |
794 | { | |
795 | gchar *test_rc_file; | |
796 | struct stat info; | |
797 | test_rc_file = g_strdup_printf ("%s/gtk-2.0/gtkrc",path); | |
798 | if (stat(test_rc_file, &info) == 0 && (S_ISREG(info.st_mode) || S_ISLNK(info.st_mode))) | |
799 | { | |
800 | /* $path/gtk/gtkrc exists, and is a regular file */ | |
801 | *rc_file = test_rc_file; | |
802 | return 1; | |
803 | } | |
804 | else | |
805 | { | |
806 | g_free (test_rc_file); | |
807 | return 0; | |
808 | } | |
809 | } | |
810 | ||
811 | static short install_tarball (gchar *path, gchar **rc_file) | |
812 | { | |
813 | gchar *command, *themedir; | |
814 | gint result; | |
815 | GList *new_list, *new_theme; | |
816 | ||
817 | themedir = g_strdup_printf ("%s/.themes", homedir); | |
818 | ||
819 | if (path[0] != '/') | |
820 | { | |
821 | gchar *cwd = g_get_current_dir(); | |
822 | command = g_strdup_printf ("tar --directory %s -xzf %s/%s 2>/dev/null", themedir, cwd, path); | |
823 | g_free (cwd); | |
824 | } | |
825 | else | |
826 | command = g_strdup_printf ("tar --directory %s -xzf %s 2>/dev/null", themedir, path); | |
827 | ||
828 | /* Ensure that ~/.themes exists */ | |
829 | mkdir (themedir, S_IRUSR | S_IWUSR | S_IXUSR); | |
830 | ||
831 | result = system(command); | |
832 | g_free (command); | |
833 | g_free (themedir); | |
834 | if (result != EXIT_SUCCESS) | |
835 | return 0; | |
836 | /* We don't do that anymore. Now we find the first new directory | |
837 | * in either themedir, and presume that to be the name of the new theme. | |
838 | * NOT FOOLPROOF, but good as long as you don't mess with stuff while the | |
839 | * program is running. At least better than deriving the theme name from | |
840 | * the tarball name. Ugh. */ | |
841 | ||
842 | new_list = get_dirs(); | |
843 | new_theme = compare_glists(glist, new_list, (GCompareFunc)strcmp); | |
844 | if (new_theme) | |
845 | { | |
846 | result = is_installed_theme(new_theme->data, rc_file); | |
847 | g_list_foreach (glist, (GFunc)g_free, NULL); | |
848 | g_list_free (glist); | |
849 | glist = new_list; | |
850 | /* Update combo, but only in dock mode */ | |
851 | if (combo) gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist); | |
852 | } | |
853 | else | |
854 | { | |
855 | gchar *interestingpath, basename[1024]; | |
856 | g_list_foreach (new_list, (GFunc)g_free, NULL); | |
857 | g_list_free (new_list); | |
858 | /* fall back to our old hack if no new dir was created, say if the theme | |
859 | * was already installed... */ | |
860 | ||
861 | /* Set rc_file to our best darn guess of the resultant gtk theme | |
862 | * dir/gtk/gtkrc. This is very tricky. The hack that is used to is | |
863 | * to return the segment in path between the last slash and the | |
864 | * first dot or dash after that. */ | |
865 | interestingpath = &path[strlen(path)-1]; | |
866 | while (interestingpath != path && *(interestingpath-1) != '/') interestingpath--; | |
867 | strcpy (basename, interestingpath); | |
868 | for (interestingpath = &basename[0]; *interestingpath != '\0'; ++interestingpath) | |
869 | { | |
870 | if (*interestingpath == '-' || *interestingpath == '.') | |
871 | { | |
872 | *interestingpath = '\0'; | |
873 | break; | |
874 | } | |
875 | } | |
876 | result = is_installed_theme(basename, rc_file); | |
877 | } | |
878 | ||
879 | return result; | |
880 | } | |
881 | ||
882 | static short | |
883 | is_installed_theme (gchar *path, gchar **rc_file) | |
884 | { | |
885 | gchar *gtk_rc_theme_dir = gtk_rc_get_theme_dir(); | |
886 | /* don't strlen things twice when computing the size to use for fullpath */ | |
887 | gint path_len = strlen(path), homedir_len = strlen(homedir); | |
888 | /* ditto with get_theme_dir */ | |
889 | gint gtk_rc_theme_dir_len = strlen(gtk_rc_theme_dir); | |
890 | gchar *fullpath = (gchar *) g_malloc (MAX(homedir_len+path_len+10, | |
891 | gtk_rc_theme_dir_len+path_len+1)); | |
892 | short result; | |
893 | ||
894 | /* use memcpy since we already have the lengths */ | |
895 | memcpy (fullpath, homedir, homedir_len); | |
896 | memcpy (fullpath+homedir_len, "/.themes/", 9); | |
897 | /* add 1 to length so we get the null char too */ | |
898 | memcpy (fullpath+homedir_len+9, path, path_len+1); | |
899 | ||
900 | if (is_themedir(fullpath, rc_file)) | |
901 | { | |
902 | g_free(fullpath); | |
903 | return 1; | |
904 | } | |
905 | memcpy (fullpath, gtk_rc_theme_dir, gtk_rc_theme_dir_len); | |
906 | /* add 1 to length so we get the null char too */ | |
907 | memcpy (fullpath+gtk_rc_theme_dir_len, path, path_len+1); | |
908 | ||
909 | result = is_themedir(fullpath, rc_file); | |
910 | ||
911 | g_free(fullpath); | |
912 | ||
913 | return result; | |
914 | } | |
915 | ||
916 | static void | |
917 | search_for_theme_or_die_trying (gchar *actual, gchar **rc_file) | |
918 | { | |
919 | if (!is_themedir(actual, rc_file) && | |
920 | !install_tarball(actual, rc_file) && | |
921 | !is_installed_theme(actual, rc_file)) | |
922 | { | |
923 | fprintf (stderr, "\ | |
924 | %s: Sorry, \"%s\" does not appear to be a valid theme directory or tarball!\n", execname, actual); | |
925 | exit (EXIT_FAILURE); | |
926 | } | |
927 | } | |
928 | ||
929 | static gint | |
930 | switcheroo (gchar *actual) | |
931 | { | |
932 | gchar *rc_file; | |
933 | search_for_theme_or_die_trying (actual, &rc_file); | |
934 | /* If we get here, we actually found the theme */ | |
935 | ok_clicked(rc_file); | |
936 | g_free (rc_file); | |
937 | return EXIT_SUCCESS; | |
938 | } | |
939 | ||
940 | ||
941 | ||
942 | int main (int argc, char *argv[]) | |
943 | { | |
944 | gchar *rc_file; | |
945 | gchar *actual; | |
946 | gint i; | |
947 | gint result = EXIT_SUCCESS; | |
948 | GSList *l=NULL; | |
949 | short using_gtk = 0; | |
950 | ||
951 | newfont = 0; | |
952 | execname = argv[0]; | |
953 | homedir = getenv("HOME"); | |
954 | hash = g_hash_table_new (g_str_hash, g_str_equal); | |
955 | ||
956 | if (argc == 1) /* start in dock mode auto if no args */ | |
957 | { | |
958 | INIT_GTK | |
959 | dock(); | |
960 | } | |
961 | ||
962 | else if (strcmp(argv[1], "-_dont-use-this") == 0) | |
963 | { | |
964 | preview_window (argv[2]); /* GARGARGAR */ | |
965 | } /* hehe, aaronl is crazy */ | |
966 | ||
967 | for (i=1; i != argc; ++i) | |
968 | { | |
969 | if (argv[i][0] == '-') | |
970 | { | |
971 | /* Single-arg commands/options */ | |
972 | if (argv[i][1] == 'd') | |
973 | { | |
974 | INIT_GTK | |
975 | dock(); | |
976 | continue; | |
977 | } | |
978 | ||
979 | /* Double-arg commands/options */ | |
980 | if (i+1 != argc) | |
981 | { | |
982 | if (argv[i][1] == 'p') | |
983 | { | |
984 | glist = get_dirs (); | |
985 | actual = argv[++i]; | |
986 | if (!is_themedir(actual, &rc_file) && !install_tarball(actual, &rc_file) && !is_installed_theme(actual, &rc_file)) | |
987 | { | |
988 | fprintf (stderr, "\ | |
989 | %s: Sorry, \"%s\" does not appear to be a valid theme directory or tarball!\n", execname, actual); | |
990 | result = EXIT_FAILURE; | |
991 | } | |
992 | else | |
993 | { | |
994 | preview (rc_file); | |
995 | g_free (rc_file); | |
996 | } | |
997 | continue; | |
998 | } | |
999 | ||
1000 | if (argv[i][1] == 'i') | |
1001 | { | |
1002 | actual = argv[++i]; | |
1003 | if (!install_tarball(actual, &rc_file)) | |
1004 | { | |
1005 | fprintf (stderr, "\ | |
1006 | %s: Sorry, \"%s\" does not appear to be a valid theme tarball!\n", execname, actual); | |
1007 | } | |
1008 | result = EXIT_FAILURE; | |
1009 | continue; | |
1010 | } | |
1011 | ||
1012 | if (argv[i][1] == 'f') | |
1013 | { | |
1014 | newfont = g_strdup (argv[++i]); | |
1015 | continue; | |
1016 | } | |
1017 | } | |
1018 | ||
1019 | /* if this starts with a minus, it's either an unrecognized command | |
1020 | * or -help. Perfect */ | |
1021 | usage(); | |
1022 | result = EXIT_FAILURE; | |
1023 | continue; | |
1024 | } | |
1025 | /* got here... fallback and assume it's a theme */ | |
1026 | glist = get_dirs (); | |
1027 | gtk_init (&argc, &argv); | |
1028 | result |= switcheroo(argv[i]); | |
1029 | } | |
1030 | ||
1031 | if (using_gtk) { | |
1032 | gtk_main(); | |
1033 | for (l=kids;l;l=l->next) { | |
1034 | kill(GPOINTER_TO_INT(l->data), 9); | |
1035 | ||
1036 | } | |
1037 | } | |
1038 | ||
1039 | return result; | |
1040 | } | |
1041 | ||
1042 | void clist_insert(GtkTreeView *clist) | |
1043 | { | |
1044 | GtkCellRenderer *renderer; | |
1045 | GtkTreeViewColumn *column; | |
1046 | ||
1047 | ||
1048 | renderer = gtk_cell_renderer_text_new(); | |
1049 | column = gtk_tree_view_column_new_with_attributes("Column 1", | |
1050 | renderer, | |
1051 | "text", | |
1052 | 0, | |
1053 | NULL); | |
1054 | ||
1055 | ||
1056 | gtk_tree_view_column_set_sort_column_id(column, 0); | |
1057 | gtk_tree_view_append_column(clist, column); | |
1058 | ||
1059 | ||
1060 | renderer = gtk_cell_renderer_text_new(); | |
1061 | ||
1062 | column = gtk_tree_view_column_new_with_attributes("Column2", | |
1063 | renderer, | |
1064 | "text", | |
1065 | 1, | |
1066 | NULL); | |
1067 | ||
1068 | gtk_tree_view_column_set_sort_column_id(column, 1); | |
1069 | gtk_tree_view_append_column(clist, column); | |
1070 | ||
1071 | return; | |
1072 | } |