r4379: Add a 'Manage Thumbnails' link to the Options box (Thomas Leonard).
[rox-filer/translations.git] / ROX-Filer / src / choices.c
blob8d761b3173a0c9e7ceb5063e74a7808fd0cd15ed
1 /*
2 * $Id$
4 * ROX-Filer, filer for the ROX desktop project
5 * Copyright (C) 2005, the ROX-Filer team.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
10 * any later version.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19 * Place, Suite 330, Boston, MA 02111-1307 USA
21 /* choices.c - code for handling loading and saving of user choices */
23 #include "config.h"
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <sys/param.h>
28 #include <fcntl.h>
29 #include <errno.h>
31 #include "global.h"
33 #include "gui_support.h"
35 #include "choices.h"
37 static gboolean saving_disabled = TRUE;
38 static gchar **dir_list = NULL;
39 static gchar **xdg_dir_list = NULL;
40 static int xdg_dir_count= 0 ;
42 static struct migration {
43 const char *dir;
44 const char *site;
45 int symlink;
46 } to_migrate[]={
47 {"ROX-Filer", SITE, TRUE},
48 {"SendTo", SITE, TRUE},
49 {"Templates", SITE, TRUE},
50 {"MIME-types", SITE, TRUE},
51 {"MIME-icons", SITE, TRUE},
52 {"MIME-thumb", SITE, TRUE},
54 {NULL, NULL, 0}
57 /* Static prototypes */
58 static gboolean exists(char *path);
59 static void migrate_choices(void);
61 /****************************************************************
62 * EXTERNAL INTERFACE *
63 ****************************************************************/
66 /* Reads in CHOICESPATH and constructs the directory list table.
67 * You must call this before using any other choices_* functions.
69 * If CHOICESPATH does not exist then a suitable default is used.
71 void choices_init(void)
73 char *choices;
74 const char *env;
75 char **dirs;
76 int i, n;
78 g_return_if_fail(dir_list == NULL);
80 /* Initialize old system */
81 choices = getenv("CHOICESPATH");
83 if (choices)
85 if (*choices != ':' && *choices != '\0')
86 saving_disabled = FALSE;
88 while (*choices == ':')
89 choices++;
91 if (*choices == '\0')
93 dir_list = g_new(char *, 1);
94 dir_list[0] = NULL;
96 else
97 dir_list = g_strsplit(choices, ":", 0);
99 else
101 saving_disabled = FALSE;
103 dir_list = g_new(gchar *, 4);
104 dir_list[0] = g_build_filename(g_get_home_dir(), "Choices",
105 NULL);
106 dir_list[1] = g_strdup("/usr/local/share/Choices");
107 dir_list[2] = g_strdup("/usr/share/Choices");
108 dir_list[3] = NULL;
111 /* Initialize new system */
112 env = getenv("XDG_CONFIG_DIRS");
113 if (!env)
114 env = "/etc/xdg";
115 dirs = g_strsplit(env, ":", 0);
116 g_return_if_fail(dirs != NULL);
117 for (n = 0; dirs[n]; n++)
119 for (i = n; i > 0; i--)
120 dirs[i] = dirs[i - 1];
121 env = getenv("XDG_CONFIG_HOME");
122 if (env)
123 dirs[0] = g_strdup(env);
124 else
125 dirs[0] = g_build_filename(g_get_home_dir(), ".config", NULL);
127 xdg_dir_list = dirs;
128 xdg_dir_count = n + 1;
130 #if 0
132 gchar **cdir = dir_list;
134 for(i=0; i<xdg_dir_count; i++)
135 g_print("[ XDG dir '%s' ]\n", xdg_dir_list[i]);
137 while (*cdir)
139 g_print("[ choices dir '%s' ]\n", *cdir);
140 cdir++;
143 g_print("[ saving is %s ]\n", saving_disabled ? "disabled"
144 : "enabled");
146 #endif
150 /* If our XDG choices directory does not yet exist, offer to move the
151 * old config over
153 void choices_migrate(void)
155 gchar *newpath;
157 /* Attempt migration */
158 newpath=choices_find_xdg_path_save(".", PROJECT, SITE, FALSE);
159 if(!exists(newpath) && !saving_disabled)
160 migrate_choices();
161 g_free(newpath);
164 void choices_free_list(GPtrArray *list)
166 guint i;
168 g_return_if_fail(list != NULL);
170 for (i = 0; i < list->len; i++)
171 g_free(g_ptr_array_index(list, i));
173 g_ptr_array_free(list, TRUE);
176 /* Get the pathname of a choices file to load. Eg:
178 * choices_find_path_load("menus", "ROX-Filer")
179 * -> "/usr/local/share/Choices/ROX-Filer/menus".
181 * The return values may be NULL - use built-in defaults.
182 * g_free() the result.
184 static gchar *choices_find_path_load(const char *leaf, const char *dir)
186 gchar **cdir = dir_list;
188 g_return_val_if_fail(dir_list != NULL, NULL);
190 for (; *cdir; cdir++)
192 gchar *path;
194 path = g_build_filename(*cdir, dir, leaf, NULL);
196 if (exists(path))
197 return path;
199 g_free(path);
202 return NULL;
205 /* Get the pathname of a choices file to load, using the XDG paths. Eg:
207 * choices_find_xdg_path_load("menus", "ROX-Filer", "rox.sourceforge.net")
208 * -> "/etc/xdg/rox.sourceforge.net/ROX-Filer/menus".
210 * Falls back on choices_find_path_load(leaf, dir) if it fails
211 * The return values may be NULL - use built-in defaults.
212 * g_free() the result.
214 gchar *choices_find_xdg_path_load(const char *leaf, const char *dir,
215 const char *site)
217 int i;
219 g_return_val_if_fail(dir_list != NULL, NULL);
221 for (i=0; i<xdg_dir_count; i++)
223 gchar *path;
225 if(site)
226 path = g_build_filename(xdg_dir_list[i], site,
227 dir, leaf, NULL);
228 else
229 path = g_build_filename(xdg_dir_list[i], dir,
230 leaf, NULL);
232 if (exists(path))
233 return path;
235 g_free(path);
238 return choices_find_path_load(leaf, dir);
241 /* Returns the pathname of a file to save to, or NULL if saving is
242 * disabled. If 'create' is TRUE then intermediate directories will
243 * be created (set this to FALSE if you just want to find out where
244 * a saved file would go without actually altering the filesystem).
246 * g_free() the result.
248 static gchar *choices_find_path_save(const char *leaf, const char *dir,
249 gboolean create)
251 gchar *path, *retval;
253 g_return_val_if_fail(dir_list != NULL, NULL);
255 if (saving_disabled)
256 return NULL;
258 if (create && !exists(dir_list[0]))
260 if (mkdir(dir_list[0], 0777))
261 g_warning("mkdir(%s): %s\n", dir_list[0],
262 g_strerror(errno));
265 path = g_build_filename(dir_list[0], dir, NULL);
266 if (create && !exists(path))
268 if (mkdir(path, 0777))
269 g_warning("mkdir(%s): %s\n", path, g_strerror(errno));
272 retval = g_build_filename(path, leaf, NULL);
273 g_free(path);
275 return retval;
278 /* Returns the pathname of a file to save to, or NULL if saving is
279 * disabled. If 'create' is TRUE then intermediate directories will
280 * be created (set this to FALSE if you just want to find out where
281 * a saved file would go without actually altering the filesystem).
283 * g_free() the result.
285 gchar *choices_find_xdg_path_save(const char *leaf, const char *dir,
286 const char *site, gboolean create)
288 gchar *path, *retval, *tmp;
290 g_return_val_if_fail(xdg_dir_list != NULL, NULL);
292 if (create && !exists(xdg_dir_list[0]))
294 if (mkdir(xdg_dir_list[0], 0777))
295 g_warning("mkdir(%s): %s\n", xdg_dir_list[0],
296 g_strerror(errno));
299 if(site)
301 path = g_build_filename(xdg_dir_list[0], site, NULL);
302 if (create && !exists(path))
304 if (mkdir(path, 0777))
305 g_warning("mkdir(%s): %s\n", path,
306 g_strerror(errno));
308 tmp=path;
309 } else {
310 tmp=g_strdup(xdg_dir_list[0]);
313 path = g_build_filename(tmp, dir, NULL);
314 g_free(tmp);
315 if (create && !exists(path))
317 if (mkdir(path, 0777))
318 g_warning("mkdir(%s): %s\n", path, g_strerror(errno));
321 retval = g_build_filename(path, leaf, NULL);
322 g_free(path);
324 return retval;
328 * Returns an array of the directories in XDG_CONFIG_HOME and XDG_CONFIG_DIRS
329 * which contain a subdirectory called 'dir' (optionally in a subdirectory
330 * called site).
332 * Lower-indexed results should override higher-indexed ones.
334 * Free the list using choices_free_list().
336 GPtrArray *choices_list_xdg_dirs(char *dir, char *site)
338 GPtrArray *list;
339 int i;
341 g_return_val_if_fail(xdg_dir_list != NULL, NULL);
343 list = g_ptr_array_new();
345 for (i=0; i<xdg_dir_count; i++)
347 guchar *path;
349 if(site)
350 path = g_build_filename(xdg_dir_list[i], site,
351 dir, NULL);
352 else
353 path = g_build_filename(xdg_dir_list[i], dir, NULL);
355 if (exists(path))
356 g_ptr_array_add(list, path);
357 else
358 g_free(path);
361 return list;
364 /****************************************************************
365 * INTERNAL FUNCTIONS *
366 ****************************************************************/
369 /* Returns TRUE if the object exists, FALSE if it doesn't */
370 static gboolean exists(char *path)
372 struct stat info;
374 return stat(path, &info) == 0;
377 #include <unistd.h>
378 #include <gtk/gtk.h>
380 static void migrate_choices(void)
382 gchar *opath, *npath;
383 int failed=0;
384 int i;
385 gchar *src, *dest;
386 gboolean migrated_something = FALSE;
388 npath=choices_find_xdg_path_save("...", PROJECT, SITE, FALSE);
389 opath=choices_find_path_save("...", PROJECT,FALSE);
392 dest=choices_find_xdg_path_save(".", PROJECT, SITE, TRUE);
393 g_free(dest);
396 for(i=0; to_migrate[i].dir; i++) {
397 src=g_build_filename(dir_list[0], to_migrate[i].dir, NULL);
398 dest=choices_find_xdg_path_save(NULL, NULL,
399 to_migrate[i].site, TRUE);
400 g_free(dest);
401 dest=choices_find_xdg_path_save(NULL,
402 to_migrate[i].dir,
403 to_migrate[i].site,
404 FALSE);
405 errno=0;
406 if(exists(src)) {
407 if(rename(src, dest)==0) {
408 if(to_migrate[i].symlink)
409 symlink(dest, src);
410 migrated_something = TRUE;
411 } else {
412 g_warning("rename(%s, %s): %s\n",
413 src, dest,
414 g_strerror(errno));
415 failed++;
417 } else if(to_migrate[i].symlink) {
419 if(!exists(dir_list[0])) {
420 if (mkdir(dir_list[0], 0777))
421 g_warning("mkdir(%s): %s\n",
422 dir_list[0],
423 g_strerror(errno));
425 symlink(dest, src);
428 g_free(src);
429 g_free(dest);
432 if (migrated_something)
434 gchar *failed_msg = NULL;
435 if (failed)
436 failed_msg = g_strdup_printf(_("%d directories could not be migrated"),
437 failed);
438 info_message(_("Choices have been moved from \n"
439 "%s\n "
440 "to the new location \n"
441 "%s\n%s"),
442 opath, npath, failed_msg ? failed_msg : "");
443 g_free(failed_msg);
446 g_free(opath);
447 g_free(npath);