diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 5bcefd22fd..c386323ae5 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -414,6 +414,7 @@ gtk_private_h_sources = \ gtkbindingsprivate.h \ gtkbitmaskprivate.h \ gtkbitmaskprivateimpl.h \ + gtkbookmarksmanager.h \ gtkborderimageprivate.h \ gtkboxprivate.h \ gtkbuilderprivate.h \ @@ -605,6 +606,7 @@ gtk_base_c_sources = \ gtkbbox.c \ gtkbin.c \ gtkbindings.c \ + gtkbookmarksmanager.c \ gtkborder.c \ gtkborderimage.c \ gtkbox.c \ diff --git a/gtk/gtkbookmarksmanager.c b/gtk/gtkbookmarksmanager.c new file mode 100644 index 0000000000..b998c4aa33 --- /dev/null +++ b/gtk/gtkbookmarksmanager.c @@ -0,0 +1,431 @@ +/* -*- Mode: C; c-file-style: "gnu"; tab-width: 8 -*- */ +/* GTK - The GIMP Toolkit + * gtkbookmarksmanager.c: Utilities to manage and monitor ~/.gtk-bookmarks + * Copyright (C) 2003, Red Hat, Inc. + * Copyright (C) 2007-2008 Carlos Garnacho + * Copyright (C) 2011 Suse + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + * + * Authors: Federico Mena Quintero + */ + +#include "config.h" + +#include + +#include + +#include "gtkbookmarksmanager.h" +#include "gtkfilechooser.h" /* for the GError types */ + +static void +_gtk_bookmark_free (GtkBookmark *bookmark) +{ + g_object_unref (bookmark->file); + g_free (bookmark->label); + g_slice_free (GtkBookmark, bookmark); +} + +static GFile * +get_bookmarks_file (void) +{ + GFile *file; + gchar *filename; + + filename = g_build_filename (g_get_home_dir (), ".gtk-bookmarks", NULL); + file = g_file_new_for_path (filename); + g_free (filename); + + return file; +} + +static GSList * +read_bookmarks (GFile *file) +{ + gchar *contents; + gchar **lines, *space; + GSList *bookmarks = NULL; + gint i; + + if (!g_file_load_contents (file, NULL, &contents, + NULL, NULL, NULL)) + return NULL; + + lines = g_strsplit (contents, "\n", -1); + + for (i = 0; lines[i]; i++) + { + GtkBookmark *bookmark; + + if (!*lines[i]) + continue; + + if (!g_utf8_validate (lines[i], -1, NULL)) + continue; + + bookmark = g_slice_new0 (GtkBookmark); + + if ((space = strchr (lines[i], ' ')) != NULL) + { + space[0] = '\0'; + bookmark->label = g_strdup (space + 1); + } + + bookmark->file = g_file_new_for_uri (lines[i]); + bookmarks = g_slist_prepend (bookmarks, bookmark); + } + + bookmarks = g_slist_reverse (bookmarks); + g_strfreev (lines); + g_free (contents); + + return bookmarks; +} + +static void +save_bookmarks (GFile *bookmarks_file, + GSList *bookmarks) +{ + GError *error = NULL; + GString *contents; + GSList *l; + + contents = g_string_new (""); + + for (l = bookmarks; l; l = l->next) + { + GtkBookmark *bookmark = l->data; + gchar *uri; + + uri = g_file_get_uri (bookmark->file); + if (!uri) + continue; + + g_string_append (contents, uri); + + if (bookmark->label) + g_string_append_printf (contents, " %s", bookmark->label); + + g_string_append_c (contents, '\n'); + g_free (uri); + } + + if (!g_file_replace_contents (bookmarks_file, + contents->str, + strlen (contents->str), + NULL, FALSE, 0, NULL, + NULL, &error)) + { + g_critical ("%s", error->message); + g_error_free (error); + } + + g_string_free (contents, TRUE); +} + +static void +notify_changed (GtkBookmarksManager *manager) +{ + manager->changed_func (manager->changed_func_data); +} + +static void +bookmarks_file_changed (GFileMonitor *monitor, + GFile *file, + GFile *other_file, + GFileMonitorEvent event, + gpointer data) +{ + GtkBookmarksManager *manager = data; + + switch (event) + { + case G_FILE_MONITOR_EVENT_CHANGED: + case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT: + case G_FILE_MONITOR_EVENT_CREATED: + case G_FILE_MONITOR_EVENT_DELETED: + g_slist_foreach (manager->bookmarks, (GFunc) _gtk_bookmark_free, NULL); + g_slist_free (manager->bookmarks); + + manager->bookmarks = read_bookmarks (file); + + gdk_threads_enter (); + notify_changed (manager); + gdk_threads_leave (); + break; + + default: + /* ignore at the moment */ + break; + } +} + +GtkBookmarksManager * +_gtk_bookmarks_manager_new (GtkBookmarksChangedFunc changed_func, gpointer changed_func_data) +{ + GtkBookmarksManager *manager; + GFile *bookmarks_file; + GError *error; + + g_return_val_if_fail (changed_func != NULL, NULL); + + manager = g_new0 (GtkBookmarksManager, 1); + + manager->changed_func = changed_func; + manager->changed_func_data = changed_func_data; + + bookmarks_file = get_bookmarks_file (); + manager->bookmarks = read_bookmarks (bookmarks_file); + + error = NULL; + manager->bookmarks_monitor = g_file_monitor_file (bookmarks_file, + G_FILE_MONITOR_NONE, + NULL, &error); + if (error) + { + g_warning ("%s", error->message); + g_error_free (error); + } + else + g_signal_connect (manager->bookmarks_monitor, "changed", + G_CALLBACK (bookmarks_file_changed), manager); + + g_object_unref (bookmarks_file); + + return manager; +} + +void +_gtk_bookmarks_manager_free (GtkBookmarksManager *manager) +{ + g_return_if_fail (manager != NULL); + + if (manager->bookmarks_monitor) + g_object_unref (manager->bookmarks_monitor); + + if (manager->bookmarks) + { + g_slist_foreach (manager->bookmarks, (GFunc) _gtk_bookmark_free, NULL); + g_slist_free (manager->bookmarks); + } + + g_free (manager); +} + +GSList * +_gtk_bookmarks_manager_list_bookmarks (GtkBookmarksManager *manager) +{ + GSList *bookmarks, *files = NULL; + + g_return_val_if_fail (manager != NULL, NULL); + + bookmarks = manager->bookmarks; + + while (bookmarks) + { + GtkBookmark *bookmark; + + bookmark = bookmarks->data; + bookmarks = bookmarks->next; + + files = g_slist_prepend (files, g_object_ref (bookmark->file)); + } + + return g_slist_reverse (files); +} + +gboolean +_gtk_bookmarks_manager_insert_bookmark (GtkBookmarksManager *manager, + GFile *file, + gint position, + GError **error) +{ + GSList *bookmarks; + GtkBookmark *bookmark; + gboolean result = TRUE; + GFile *bookmarks_file; + + g_return_val_if_fail (manager != NULL, FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + bookmarks = manager->bookmarks; + + while (bookmarks) + { + bookmark = bookmarks->data; + bookmarks = bookmarks->next; + + if (g_file_equal (bookmark->file, file)) + { + /* File is already in bookmarks */ + result = FALSE; + break; + } + } + + if (!result) + { + gchar *uri = g_file_get_uri (file); + + g_set_error (error, + GTK_FILE_CHOOSER_ERROR, + GTK_FILE_CHOOSER_ERROR_ALREADY_EXISTS, + "%s already exists in the bookmarks list", + uri); + + g_free (uri); + + return FALSE; + } + + bookmark = g_slice_new0 (GtkBookmark); + bookmark->file = g_object_ref (file); + + manager->bookmarks = g_slist_insert (manager->bookmarks, bookmark, position); + + bookmarks_file = get_bookmarks_file (); + save_bookmarks (bookmarks_file, manager->bookmarks); + g_object_unref (bookmarks_file); + + notify_changed (manager); + + return TRUE; +} + +gboolean +_gtk_bookmarks_manager_remove_bookmark (GtkBookmarksManager *manager, + GFile *file, + GError **error) +{ + GtkBookmark *bookmark; + GSList *bookmarks; + gboolean result = FALSE; + GFile *bookmarks_file; + + g_return_val_if_fail (manager != NULL, FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + if (!manager->bookmarks) + return FALSE; + + bookmarks = manager->bookmarks; + + while (bookmarks) + { + bookmark = bookmarks->data; + + if (g_file_equal (bookmark->file, file)) + { + result = TRUE; + manager->bookmarks = g_slist_remove_link (manager->bookmarks, bookmarks); + _gtk_bookmark_free (bookmark); + g_slist_free_1 (bookmarks); + break; + } + + bookmarks = bookmarks->next; + } + + if (!result) + { + gchar *uri = g_file_get_uri (file); + + g_set_error (error, + GTK_FILE_CHOOSER_ERROR, + GTK_FILE_CHOOSER_ERROR_NONEXISTENT, + "%s does not exist in the bookmarks list", + uri); + + g_free (uri); + + return FALSE; + } + + bookmarks_file = get_bookmarks_file (); + save_bookmarks (bookmarks_file, manager->bookmarks); + g_object_unref (bookmarks_file); + + notify_changed (manager); + + return TRUE; +} + +gchar * +_gtk_bookmarks_manager_get_bookmark_label (GtkBookmarksManager *manager, + GFile *file) +{ + GSList *bookmarks; + gchar *label = NULL; + + g_return_val_if_fail (manager != NULL, NULL); + g_return_val_if_fail (file != NULL, NULL); + + bookmarks = manager->bookmarks; + + while (bookmarks) + { + GtkBookmark *bookmark; + + bookmark = bookmarks->data; + bookmarks = bookmarks->next; + + if (g_file_equal (file, bookmark->file)) + { + label = g_strdup (bookmark->label); + break; + } + } + + return label; +} + +void +_gtk_bookmarks_manager_set_bookmark_label (GtkBookmarksManager *manager, + GFile *file, + const gchar *label) +{ + gboolean changed = FALSE; + GFile *bookmarks_file; + GSList *bookmarks; + + g_return_if_fail (manager != NULL); + g_return_if_fail (file != NULL); + + bookmarks = manager->bookmarks; + + while (bookmarks) + { + GtkBookmark *bookmark; + + bookmark = bookmarks->data; + bookmarks = bookmarks->next; + + if (g_file_equal (file, bookmark->file)) + { + g_free (bookmark->label); + bookmark->label = g_strdup (label); + changed = TRUE; + break; + } + } + + bookmarks_file = get_bookmarks_file (); + save_bookmarks (bookmarks_file, manager->bookmarks); + g_object_unref (bookmarks_file); + + if (changed) + notify_changed (manager); +} diff --git a/gtk/gtkbookmarksmanager.h b/gtk/gtkbookmarksmanager.h new file mode 100644 index 0000000000..ee98d875d6 --- /dev/null +++ b/gtk/gtkbookmarksmanager.h @@ -0,0 +1,73 @@ +/* -*- Mode: C; c-file-style: "gnu"; tab-width: 8 -*- */ +/* GTK - The GIMP Toolkit + * gtkbookmarksmanager.h: Utilities to manage and monitor ~/.gtk-bookmarks + * Copyright (C) 2003, Red Hat, Inc. + * Copyright (C) 2007-2008 Carlos Garnacho + * Copyright (C) 2011 Suse + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + * + * Authors: Federico Mena Quintero + */ + +#ifndef __GTK_BOOKMARKS_MANAGER_H__ +#define __GTK_BOOKMARKS_MANAGER_H__ + +#include + +typedef void (* GtkBookmarksChangedFunc) (gpointer data); + +typedef struct +{ + /* This list contains GtkBookmark structs */ + GSList *bookmarks; + + GFileMonitor *bookmarks_monitor; + + gpointer changed_func_data; + GtkBookmarksChangedFunc changed_func; +} GtkBookmarksManager; + +typedef struct +{ + GFile *file; + gchar *label; +} GtkBookmark; + +GtkBookmarksManager *_gtk_bookmarks_manager_new (GtkBookmarksChangedFunc changed_func, + gpointer changed_func_data); + + +void _gtk_bookmarks_manager_free (GtkBookmarksManager *manager); + +GSList *_gtk_bookmarks_manager_list_bookmarks (GtkBookmarksManager *manager); + +gboolean _gtk_bookmarks_manager_insert_bookmark (GtkBookmarksManager *manager, + GFile *file, + gint position, + GError **error); + +gboolean _gtk_bookmarks_manager_remove_bookmark (GtkBookmarksManager *manager, + GFile *file, + GError **error); + +gchar * _gtk_bookmarks_manager_get_bookmark_label (GtkBookmarksManager *manager, + GFile *file); + +void _gtk_bookmarks_manager_set_bookmark_label (GtkBookmarksManager *manager, + GFile *file, + const gchar *label); + +#endif /* __GTK_BOOKMARKS_MANAGER_H__ */ diff --git a/po/POTFILES.in b/po/POTFILES.in index 5006c06084..a8a1a99bb7 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -48,6 +48,7 @@ gtk/gtkassistant.c gtk/gtkbbox.c gtk/gtkbin.c gtk/gtkbindings.c +gtk/gtkbookmarksmanager.c gtk/gtkbox.c gtk/gtkbuildable.c gtk/gtkbuilder.c