xdg-user-dirs-gtk/update.c

404 lines
9.9 KiB
C

#include "config.h"
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
#include <libintl.h>
#include <locale.h>
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include <glib/gstdio.h>
#include "parse.h"
static XdgDirEntry *
find_dir_entry (XdgDirEntry *entries, const char *type)
{
int i;
for (i = 0; entries[i].type != NULL; i++)
{
if (strcmp (entries[i].type, type) == 0)
return &entries[i];
}
return NULL;
}
static XdgDirEntry *
find_dir_entry_by_path (XdgDirEntry *entries, const char *path)
{
int i;
for (i = 0; entries[i].type != NULL; i++)
{
if (strcmp (entries[i].path, path) == 0)
return &entries[i];
}
return NULL;
}
static gboolean
has_xdg_translation (void)
{
char *str;
const char *locale;
locale = setlocale (LC_MESSAGES, NULL);
if (strncmp (locale, "en_US", 5) == 0 ||
strcmp (locale, "C") == 0)
return TRUE;
str = "Desktop";
return dgettext ("xdg-user-dirs", str) != str;
}
static void
save_locale (void)
{
FILE *file;
char *user_locale_file;
char *locale, *dot;
user_locale_file = g_build_filename (g_get_user_config_dir (),
"user-dirs.locale", NULL);
file = fopen (user_locale_file, "w");
g_free (user_locale_file);
if (file == NULL)
{
fprintf (stderr, "Can't save user-dirs.locale\n");
return;
}
locale = g_strdup (setlocale (LC_MESSAGES, NULL));
/* Skip encoding part */
dot = strchr (locale, '.');
if (dot)
*dot = 0;
fprintf (file, "%s", locale);
g_free (locale);
fclose (file);
}
static void
update_locale (XdgDirEntry *old_entries)
{
XdgDirEntry *new_entries, *entry;
GtkWidget *dialog, *vbox;
int exit_status;
int fd;
char *filename;
char *cmdline;
int response;
int i, j;
GtkListStore *list_store;
GtkTreeIter iter;
GtkWidget *treeview, *check;
GtkCellRenderer *cell;
GtkWidget *scrolledwindow;
GtkWidget *label;
char *std_out, *std_err;
gboolean has_changes;
fd = g_file_open_tmp ("dirs-XXXXXX", &filename, NULL);
if (fd == -1)
return;
close (fd);
cmdline = g_strdup_printf (XDG_USER_DIRS_UPDATE " --force --dummy-output %s", filename);
if (!g_spawn_command_line_sync (cmdline, &std_out, &std_err, &exit_status, NULL))
{
g_free (std_out);
g_free (std_err);
g_free (cmdline);
g_unlink (filename);
g_free (filename);
return;
}
g_free (std_out);
g_free (std_err);
g_free (cmdline);
if (!WIFEXITED(exit_status) || WEXITSTATUS(exit_status) != 0)
return;
new_entries = parse_xdg_dirs (filename);
g_unlink (filename);
g_free (filename);
list_store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
has_changes = FALSE;
for (i = 0; old_entries[i].type != NULL; i++)
{
for (j = 0; new_entries[j].type != NULL; j++)
{
if (strcmp (old_entries[i].type, new_entries[j].type) == 0)
break;
}
if (new_entries[j].type != NULL &&
strcmp (old_entries[i].path, new_entries[j].path) != 0)
{
char *from, *to;
from = g_filename_display_name (old_entries[i].path);
to = g_filename_display_name (new_entries[j].path);
gtk_list_store_append (list_store, &iter);
gtk_list_store_set (list_store, &iter,
0, from, 1, to, -1);
g_free (from);
g_free (to);
has_changes = TRUE;
}
}
for (j = 0; new_entries[j].type != NULL; j++)
{
for (i = 0; old_entries[i].type != NULL; i++)
{
if (strcmp (old_entries[i].type, new_entries[j].type) == 0)
break;
}
if (old_entries[i].type == NULL)
{
char *to;
to = g_filename_display_name (new_entries[j].path);
gtk_list_store_append (list_store, &iter);
gtk_list_store_set (list_store, &iter,
0, "-", 1, to, -1);
g_free (to);
has_changes = TRUE;
}
}
if (!has_changes)
{
g_object_unref (list_store);
return;
}
dialog = gtk_message_dialog_new (NULL, 0,
GTK_MESSAGE_WARNING,
GTK_BUTTONS_NONE,
_("Update standard folders to current language?"));
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
_("You have logged in in a new language. You can automatically update the names of some standard folders in your home folder to match this language. The update would change the following folders:"));
gtk_dialog_add_buttons (GTK_DIALOG (dialog),
_("_Keep Old Names"), GTK_RESPONSE_NO,
_("_Update Names"), GTK_RESPONSE_YES,
NULL);
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_NO);
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
vbox, TRUE, TRUE, 0);
gtk_widget_show (vbox);
scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
GTK_POLICY_NEVER,
GTK_POLICY_NEVER);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow),
GTK_SHADOW_IN);
gtk_box_pack_start (GTK_BOX (vbox), scrolledwindow, TRUE, TRUE, 0);
treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (list_store));
gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)),
GTK_SELECTION_NONE);
cell = gtk_cell_renderer_text_new ();
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview),
-1, _("Current folder name"),
cell,
"text", 0,
NULL);
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview),
-1, _("New folder name"),
cell,
"text", 1,
NULL);
gtk_container_add (GTK_CONTAINER (scrolledwindow),
treeview);
gtk_widget_show_all (scrolledwindow);
label = gtk_label_new (_("Note that existing content will not be moved."));
gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
gtk_label_set_selectable (GTK_LABEL (label), TRUE);
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_widget_show (label);
gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
check = gtk_check_button_new_with_mnemonic (_("_Don't ask me this again"));
gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
gtk_widget_show (check);
response = gtk_dialog_run (GTK_DIALOG (dialog));
if (response == GTK_RESPONSE_YES)
{
if (!g_spawn_command_line_sync (XDG_USER_DIRS_UPDATE " --force", NULL, NULL, &exit_status, NULL) ||
!WIFEXITED(exit_status) ||
WEXITSTATUS(exit_status) != 0)
{
GtkWidget *error;
error = gtk_message_dialog_new (NULL, 0,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_OK,
_("There was an error updating the folders"));
gtk_dialog_run (GTK_DIALOG (error));
gtk_widget_destroy (error);
}
else
{
/* Change succeeded, remove any leftover empty directories */
for (i = 0; old_entries[i].type != NULL; i++)
{
/* Never remove homedir */
if (strcmp (old_entries[i].path, g_get_home_dir ()) == 0)
continue;
/* If the old path is used by the new config, don't remove */
entry = find_dir_entry_by_path (new_entries, old_entries[i].path);
if (entry)
continue;
/* Remove the dir, will fail if not empty */
g_rmdir (old_entries[i].path);
}
}
}
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check)))
{
save_locale ();
}
g_free (new_entries);
gtk_widget_destroy (dialog);
g_object_unref (list_store);
}
int
main (int argc, char *argv[])
{
XdgDirEntry *old_entries, *new_entries, *entry;
XdgDirEntry *desktop_entry;
GtkBookmark *bookmark;
GList *bookmarks, *l;
char *old_locale;
char *locale, *dot;
int i;
gboolean modified_bookmarks;
char *uri;
setlocale (LC_ALL, "");
bindtextdomain (GETTEXT_PACKAGE, GLIBLOCALEDIR);
bindtextdomain ("xdg-user-dirs", GLIBLOCALEDIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE);
old_entries = parse_xdg_dirs (NULL);
old_locale = parse_xdg_dirs_locale ();
locale = g_strdup (setlocale (LC_MESSAGES, NULL));
dot = strchr (locale, '.');
if (dot)
*dot = 0;
if (old_locale && *old_locale != 0 &&
strcmp (old_locale, locale) != 0 &&
has_xdg_translation ())
{
gtk_init (&argc, &argv);
update_locale (old_entries);
}
new_entries = parse_xdg_dirs (NULL);
bookmarks = parse_gtk_bookmarks ();
modified_bookmarks = FALSE;
if (bookmarks == NULL)
{
char *make_bm_for[] = {
"DOCUMENTS",
"MUSIC",
"PICTURES",
"VIDEOS",
"DOWNLOAD",
NULL};
/* No previous bookmarks. Generate standard ones */
desktop_entry = find_dir_entry (new_entries, "DESKTOP");
for (i = 0; make_bm_for[i] != NULL; i++)
{
entry = find_dir_entry (new_entries, make_bm_for[i]);
if (entry && strcmp (entry->path, g_get_home_dir ()) != 0 &&
(desktop_entry == NULL || strcmp (entry->path, desktop_entry->path) != 0))
{
uri = g_filename_to_uri (entry->path, NULL, NULL);
if (uri)
{
modified_bookmarks = TRUE;
bookmark = g_new0 (GtkBookmark, 1);
bookmark->uri = uri;
bookmarks = g_list_append (bookmarks, bookmark);
}
}
}
}
else
{
/* Map old bookmarks that were moved */
for (l = bookmarks; l != NULL; l = l->next)
{
char *path;
bookmark = l->data;
path = g_filename_from_uri (bookmark->uri, NULL, NULL);
if (path)
{
entry = find_dir_entry_by_path (old_entries, path);
if (entry)
{
entry = find_dir_entry (new_entries, entry->type);
if (entry)
{
uri = g_filename_to_uri (entry->path, NULL, NULL);
if (uri)
{
modified_bookmarks = TRUE;
g_free (bookmark->uri);
bookmark->uri = uri;
}
}
}
g_free (path);
}
}
}
if (modified_bookmarks)
save_gtk_bookmarks (bookmarks);
g_free (new_entries);
g_free (old_entries);
return 0;
}