diff -uprN caja-1.24.0/libcaja-private/org.mate.caja.gschema.xml caja-1.24.0-patched/libcaja-private/org.mate.caja.gschema.xml --- caja-1.24.0/libcaja-private/org.mate.caja.gschema.xml 2020-02-10 05:52:31.000000000 -0500 +++ caja-1.24.0-patched/libcaja-private/org.mate.caja.gschema.xml 2020-07-04 18:50:12.052105269 -0400 @@ -465,6 +465,7 @@ + @@ -473,6 +474,7 @@ + diff -uprN caja-1.24.0/src/caja-application.c caja-1.24.0-patched/src/caja-application.c --- caja-1.24.0/src/caja-application.c 2020-02-10 05:52:32.000000000 -0500 +++ caja-1.24.0-patched/src/caja-application.c 2020-07-04 18:12:47.480041444 -0400 @@ -76,6 +76,7 @@ #include "caja-self-check-functions.h" #include "caja-notes-viewer.h" #include "caja-emblem-sidebar.h" +#include "caja-bookmarks-sidebar.h" #include "caja-image-properties-page.h" #include "caja-desktop-window.h" #include "caja-spatial-window.h" @@ -2212,6 +2213,7 @@ caja_application_startup (GApplication * caja_history_sidebar_register (); caja_notes_viewer_register (); /* also property page */ caja_emblem_sidebar_register (); + caja_bookmarks_sidebar_register (); /* register property pages */ caja_image_properties_page_register (); diff -uprN caja-1.24.0/src/caja-bookmarks-sidebar.c caja-1.24.0-patched/src/caja-bookmarks-sidebar.c --- caja-1.24.0/src/caja-bookmarks-sidebar.c 1969-12-31 19:00:00.000000000 -0500 +++ caja-1.24.0-patched/src/caja-bookmarks-sidebar.c 2020-07-04 20:22:50.504120389 -0400 @@ -0,0 +1,537 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ + +/* + * Caja: Bookmarks sidebar + * + * Copyright (C) 2020 Gordon N. Squash. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library 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 library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Authors: Gordon N. Squash + * + * Based largely on the Caja Places sidebar and the Caja History sidebar. + * + */ + +#include + +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "caja-bookmark-list.h" +#include "caja-window.h" + +#include "caja-bookmarks-sidebar.h" + +#define CAJA_BOOKMARKS_SIDEBAR_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), CAJA_TYPE_BOOKMARKS_SIDEBAR, CajaBookmarksSidebarClass)) +#define CAJA_IS_BOOKMARKS_SIDEBAR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CAJA_TYPE_BOOKMARKS_SIDEBAR)) +#define CAJA_IS_BOOKMARKS_SIDEBAR_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), CAJA_TYPE_BOOKMARKS_SIDEBAR)) + +typedef struct +{ + GtkScrolledWindowClass parent; +} CajaBookmarksSidebarClass; + +typedef struct +{ + GObject parent; +} CajaBookmarksSidebarProvider; + +typedef struct +{ + GObjectClass parent; +} CajaBookmarksSidebarProviderClass; + + +enum +{ + BOOKMARKS_SIDEBAR_COLUMN_ICON, + BOOKMARKS_SIDEBAR_COLUMN_NAME, + BOOKMARKS_SIDEBAR_COLUMN_BOOKMARK, + BOOKMARKS_SIDEBAR_COLUMN_COUNT +}; + +static void caja_bookmarks_sidebar_iface_init (CajaSidebarIface *iface); +static void sidebar_provider_iface_init (CajaSidebarProviderIface *iface); +static GType caja_bookmarks_sidebar_provider_get_type (void); +static void caja_bookmarks_sidebar_style_updated (GtkWidget *widget); + +G_DEFINE_TYPE_WITH_CODE (CajaBookmarksSidebar, caja_bookmarks_sidebar, GTK_TYPE_SCROLLED_WINDOW, + G_IMPLEMENT_INTERFACE (CAJA_TYPE_SIDEBAR, + caja_bookmarks_sidebar_iface_init)); + +G_DEFINE_TYPE_WITH_CODE (CajaBookmarksSidebarProvider, caja_bookmarks_sidebar_provider, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (CAJA_TYPE_SIDEBAR_PROVIDER, + sidebar_provider_iface_init)); + + +static gboolean +is_built_in_bookmark (CajaFile *file) +{ + gboolean built_in; + gint idx; + + built_in = FALSE; + + for (idx = 0; idx < G_USER_N_DIRECTORIES; idx++) { + /* PUBLIC_SHARE and TEMPLATES are not in our built-in list */ + if (caja_file_is_user_special_directory (file, idx)) { + if (idx != G_USER_DIRECTORY_PUBLIC_SHARE && idx != G_USER_DIRECTORY_TEMPLATES) { + built_in = TRUE; + } + + break; + } + } + + return built_in; +} + + +static void +update_bookmarks (CajaBookmarksSidebar *sidebar) +{ + GtkListStore *store; + GtkTreeSelection *selection; + GtkTreeIter iter; + CajaBookmark *bookmark = NULL; + int bookmark_count = 0; + int index = 0; + + GFile *root; + CajaFile *file; + char *bookmark_uri; + + cairo_surface_t *surface = NULL; + char *name; + + store = GTK_LIST_STORE (gtk_tree_view_get_model (sidebar->tree_view)); + + gtk_list_store_clear (store); + + selection = GTK_TREE_SELECTION (gtk_tree_view_get_selection (sidebar->tree_view)); + + + bookmark_count = caja_bookmark_list_length (sidebar->bookmarks); + + for (index = 0; index < bookmark_count; index++) + { + + bookmark = caja_bookmark_list_item_at (sidebar->bookmarks, index); + + if (caja_bookmark_uri_known_not_to_exist (bookmark)) { + continue; + } + + bookmark_uri = caja_bookmark_get_uri (bookmark); + + root = caja_bookmark_get_location (bookmark); + file = caja_file_get (root); + + if (is_built_in_bookmark (file)) { + g_object_unref (root); + caja_file_unref (file); + continue; + } + + + surface = caja_bookmark_get_surface (bookmark, GTK_ICON_SIZE_MENU); + name = caja_bookmark_get_name (bookmark); + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, + BOOKMARKS_SIDEBAR_COLUMN_ICON, surface, + BOOKMARKS_SIDEBAR_COLUMN_NAME, name, + BOOKMARKS_SIDEBAR_COLUMN_BOOKMARK, bookmark, + -1); + + + // Select the bookmark if we're in the directory the bookmark points to. + if (g_strcmp0 (bookmark_uri, sidebar->current_uri) == 0) + gtk_tree_selection_select_iter (selection, &iter); + + + g_object_unref (root); + caja_file_unref (file); + g_free (bookmark_uri); + + if (surface != NULL) + { + cairo_surface_destroy (surface); + } + g_free (name); + } +} + +static void +open_selected_item (CajaBookmarksSidebar *sidebar, + GtkTreePath *path, + CajaWindowOpenFlags flags) +{ + CajaWindowSlotInfo *slot; + GtkTreeModel *model; + GtkTreeIter iter; + CajaBookmark *bookmark; + GFile *location; + + model = gtk_tree_view_get_model (sidebar->tree_view); + + if (!gtk_tree_model_get_iter (model, &iter, path)) + { + return; + } + + gtk_tree_model_get (model, &iter, BOOKMARKS_SIDEBAR_COLUMN_BOOKMARK, + &bookmark, -1); + + /* Navigate to the clicked location. */ + location = caja_bookmark_get_location (CAJA_BOOKMARK (bookmark)); + + slot = caja_window_info_get_active_slot (sidebar->window); + + caja_window_slot_info_open_location (slot, location, + CAJA_WINDOW_OPEN_ACCORDING_TO_MODE, + flags, NULL); + + g_object_unref (location); +} + +static void +row_activated_callback (GtkTreeView *tree_view, + GtkTreePath *path, + GtkTreeViewColumn *column, + gpointer user_data) +{ + CajaBookmarksSidebar *sidebar; + + sidebar = CAJA_BOOKMARKS_SIDEBAR (user_data); + g_assert (sidebar->tree_view == tree_view); + + open_selected_item (sidebar, path, 0); +} + + +static gboolean +button_press_event_callback (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data) +{ + CajaBookmarksSidebar *sidebar; + GtkTreePath *path; + + int open_flags = 0; + + + if (event->type == GDK_BUTTON_PRESS) + { + /** + * If the middle button was pressed, open the bookmark in a new tab. + */ + if (event->button == GDK_BUTTON_MIDDLE) + open_flags = CAJA_WINDOW_OPEN_FLAG_NEW_TAB; + + /** + * If the middle button was not pressed, don't do + * anything, since the action was already handled in + * row_activated_callback() (above). + */ + else + return FALSE; + } + + sidebar = CAJA_BOOKMARKS_SIDEBAR (user_data); + g_assert (sidebar->tree_view == GTK_TREE_VIEW (widget)); + + if (gtk_tree_view_get_path_at_pos (sidebar->tree_view, + event->x, event->y, + &path, NULL, NULL, NULL)) + { + open_selected_item (sidebar, + path, + open_flags); + + gtk_tree_path_free (path); + } + + return FALSE; +} + +static void +loading_uri_callback (CajaWindowInfo *window, + char *location, + CajaBookmarksSidebar *sidebar) +{ + GtkTreeModel *model; + GtkTreeIter iter; + gboolean valid; + CajaBookmark *bookmark; + char *uri; + + + if (strcmp (sidebar->current_uri, location) != 0) + { + GtkTreeSelection *selection; + + g_free (sidebar->current_uri); + sidebar->current_uri = g_strdup (location); + + /* set selection if any place matches location */ + selection = gtk_tree_view_get_selection (sidebar->tree_view); + gtk_tree_selection_unselect_all (selection); + + model = gtk_tree_view_get_model (sidebar->tree_view); + + valid = gtk_tree_model_get_iter_first (model, &iter); + + while (valid) + { + gtk_tree_model_get (model, &iter, + BOOKMARKS_SIDEBAR_COLUMN_BOOKMARK, &bookmark, + -1); + + uri = caja_bookmark_get_uri (bookmark); + + if (uri != NULL) + { + if (strcmp (uri, location) == 0) + { + g_free (uri); + gtk_tree_selection_select_iter (selection, &iter); + break; + } + g_free (uri); + } + valid = gtk_tree_model_iter_next (model, &iter); + } + } +} + +static void +caja_bookmarks_sidebar_init (CajaBookmarksSidebar *sidebar) +{ + GtkTreeView *tree_view; + GtkTreeViewColumn *col; + GtkCellRenderer *cell; + GtkListStore *store; + GtkTreeSelection *selection; + + tree_view = GTK_TREE_VIEW (gtk_tree_view_new ()); + gtk_tree_view_set_headers_visible (tree_view, FALSE); + gtk_widget_show (GTK_WIDGET (tree_view)); + + col = GTK_TREE_VIEW_COLUMN (gtk_tree_view_column_new ()); + + cell = gtk_cell_renderer_pixbuf_new (); + gtk_tree_view_column_pack_start (col, cell, FALSE); + gtk_tree_view_column_set_attributes (col, cell, + "surface", BOOKMARKS_SIDEBAR_COLUMN_ICON, + NULL); + + cell = gtk_cell_renderer_text_new (); + gtk_tree_view_column_pack_start (col, cell, TRUE); + gtk_tree_view_column_set_attributes (col, cell, + "text", BOOKMARKS_SIDEBAR_COLUMN_NAME, + NULL); + + gtk_tree_view_column_set_fixed_width (col, CAJA_ICON_SIZE_SMALLER); + gtk_tree_view_append_column (tree_view, col); + + store = gtk_list_store_new (BOOKMARKS_SIDEBAR_COLUMN_COUNT, + CAIRO_GOBJECT_TYPE_SURFACE, + G_TYPE_STRING, + CAJA_TYPE_BOOKMARK); + + gtk_tree_view_set_model (tree_view, GTK_TREE_MODEL (store)); + g_object_unref (store); + + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sidebar), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_hadjustment (GTK_SCROLLED_WINDOW (sidebar), NULL); + gtk_scrolled_window_set_vadjustment (GTK_SCROLLED_WINDOW (sidebar), NULL); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sidebar), GTK_SHADOW_IN); + gtk_scrolled_window_set_overlay_scrolling (GTK_SCROLLED_WINDOW (sidebar), FALSE); + + gtk_container_add (GTK_CONTAINER (sidebar), GTK_WIDGET (tree_view)); + gtk_widget_show (GTK_WIDGET (sidebar)); + + sidebar->tree_view = tree_view; + + selection = gtk_tree_view_get_selection (tree_view); + gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); + + g_signal_connect_object + (tree_view, "row_activated", + G_CALLBACK (row_activated_callback), sidebar, 0); + + g_signal_connect (tree_view, "button-press-event", + G_CALLBACK (button_press_event_callback), sidebar); + + + eel_gtk_tree_view_set_activate_on_single_click (sidebar->tree_view, TRUE); +} + +static void +caja_bookmarks_sidebar_finalize (GObject *object) +{ + CajaBookmarksSidebar *sidebar; + + sidebar = CAJA_BOOKMARKS_SIDEBAR (object); + + g_free (sidebar->current_uri); + + G_OBJECT_CLASS (caja_bookmarks_sidebar_parent_class)->finalize (object); +} + + + + +static void +caja_bookmarks_sidebar_class_init (CajaBookmarksSidebarClass *class) +{ + G_OBJECT_CLASS (class)->finalize = caja_bookmarks_sidebar_finalize; + + GTK_WIDGET_CLASS (class)->style_updated = caja_bookmarks_sidebar_style_updated; +} + +static const char * +caja_bookmarks_sidebar_get_sidebar_id (CajaSidebar *sidebar) +{ + return CAJA_BOOKMARKS_SIDEBAR_ID; +} + +static char * +caja_bookmarks_sidebar_get_tab_label (CajaSidebar *sidebar) +{ + return g_strdup (_("Bookmarks")); +} + +static char * +caja_bookmarks_sidebar_get_tab_tooltip (CajaSidebar *sidebar) +{ + return g_strdup (_("Show a list of your personal bookmarks")); +} + +static GdkPixbuf * +caja_bookmarks_sidebar_get_tab_icon (CajaSidebar *sidebar) +{ + return NULL; +} + +static void +caja_bookmarks_sidebar_is_visible_changed (CajaSidebar *sidebar, + gboolean is_visible) +{ + /* Do nothing */ +} + +static void +caja_bookmarks_sidebar_iface_init (CajaSidebarIface *iface) +{ + iface->get_sidebar_id = caja_bookmarks_sidebar_get_sidebar_id; + iface->get_tab_label = caja_bookmarks_sidebar_get_tab_label; + iface->get_tab_tooltip = caja_bookmarks_sidebar_get_tab_tooltip; + iface->get_tab_icon = caja_bookmarks_sidebar_get_tab_icon; + iface->is_visible_changed = caja_bookmarks_sidebar_is_visible_changed; +} + +static void +caja_bookmarks_sidebar_set_parent_window (CajaBookmarksSidebar *sidebar, + CajaWindowInfo *window) +{ + CajaWindowSlotInfo *slot; + + sidebar->window = window; + + slot = caja_window_info_get_active_slot (window); + + + sidebar->bookmarks = caja_bookmark_list_new (); + sidebar->current_uri = caja_window_slot_info_get_current_location (slot); + + g_signal_connect_object (sidebar->bookmarks, "contents_changed", + G_CALLBACK (update_bookmarks), + sidebar, G_CONNECT_SWAPPED); + + g_signal_connect_object (window, "loading_uri", + G_CALLBACK (loading_uri_callback), + sidebar, 0); + + + update_bookmarks (sidebar); +} + +static void +caja_bookmarks_sidebar_style_updated (GtkWidget *widget) +{ + CajaBookmarksSidebar *sidebar; + + sidebar = CAJA_BOOKMARKS_SIDEBAR (widget); + + update_bookmarks (sidebar); +} + +static CajaSidebar * +caja_bookmarks_sidebar_create (CajaSidebarProvider *provider, + CajaWindowInfo *window) +{ + CajaBookmarksSidebar *sidebar; + + sidebar = g_object_new (caja_bookmarks_sidebar_get_type (), NULL); + caja_bookmarks_sidebar_set_parent_window (sidebar, window); + g_object_ref_sink (sidebar); + + return CAJA_SIDEBAR (sidebar); +} + +static void +sidebar_provider_iface_init (CajaSidebarProviderIface *iface) +{ + iface->create = caja_bookmarks_sidebar_create; +} + +static void +caja_bookmarks_sidebar_provider_init (CajaBookmarksSidebarProvider *sidebar) +{ +} + +static void +caja_bookmarks_sidebar_provider_class_init (CajaBookmarksSidebarProviderClass *class) +{ +} + +void +caja_bookmarks_sidebar_register (void) +{ + caja_module_add_type (caja_bookmarks_sidebar_provider_get_type ()); +} + diff -uprN caja-1.24.0/src/caja-bookmarks-sidebar.h caja-1.24.0-patched/src/caja-bookmarks-sidebar.h --- caja-1.24.0/src/caja-bookmarks-sidebar.h 1969-12-31 19:00:00.000000000 -0500 +++ caja-1.24.0-patched/src/caja-bookmarks-sidebar.h 2020-07-04 19:28:39.828170892 -0400 @@ -0,0 +1,57 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ + +/* + * Caja: Bookmarks sidebar + * + * Copyright (C) 2020 Gordon N. Squash. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library 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 library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Authors: Gordon N. Squash + * + * Based largely on the Caja Places sidebar and the Caja History sidebar. + * + */ +#ifndef _CAJA_BOOKMARKS_SIDEBAR_H +#define _CAJA_BOOKMARKS_SIDEBAR_H + +#include + +#include +#include +#include + +#include "caja-bookmark-list.h" + +#define CAJA_BOOKMARKS_SIDEBAR_ID "bookmarks" + +#define CAJA_TYPE_BOOKMARKS_SIDEBAR caja_bookmarks_sidebar_get_type() +#define CAJA_BOOKMARKS_SIDEBAR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), CAJA_TYPE_BOOKMARKS_SIDEBAR, CajaBookmarksSidebar)) + +typedef struct +{ + GtkScrolledWindow parent; + GtkTreeView *tree_view; + CajaWindowInfo *window; + + char *current_uri; + CajaBookmarkList *bookmarks; +} CajaBookmarksSidebar; + +GType caja_bookmarks_sidebar_get_type (void); +void caja_bookmarks_sidebar_register (void); + +#endif diff -uprN caja-1.24.0/src/Makefile.am caja-1.24.0-patched/src/Makefile.am --- caja-1.24.0/src/Makefile.am 2020-02-10 05:52:32.000000000 -0500 +++ caja-1.24.0-patched/src/Makefile.am 2020-07-04 17:24:58.496036269 -0400 @@ -62,6 +62,8 @@ caja_SOURCES = \ caja-application.h \ caja-bookmark-list.c \ caja-bookmark-list.h \ + caja-bookmarks-sidebar.c \ + caja-bookmarks-sidebar.h \ caja-bookmarks-window.c \ caja-bookmarks-window.h \ caja-connect-server-dialog.c \