diff options
-rw-r--r-- | src/meson.build | 4 | ||||
-rw-r--r-- | src/nautilus-action-bar.c | 526 | ||||
-rw-r--r-- | src/nautilus-action-bar.h | 39 | ||||
-rw-r--r-- | src/nautilus-files-view.c | 576 | ||||
-rw-r--r-- | src/nautilus-files-view.h | 2 | ||||
-rw-r--r-- | src/nautilus-places-view.c | 7 | ||||
-rw-r--r-- | src/nautilus-view.c | 16 | ||||
-rw-r--r-- | src/nautilus-view.h | 6 | ||||
-rw-r--r-- | src/nautilus-window-slot.c | 24 | ||||
-rw-r--r-- | src/resources/css/Adwaita.css | 14 | ||||
-rw-r--r-- | src/resources/nautilus.gresource.xml | 1 | ||||
-rw-r--r-- | src/resources/ui/nautilus-action-bar.ui | 357 |
12 files changed, 1012 insertions, 560 deletions
diff --git a/src/meson.build b/src/meson.build index 0979128c8..f54d16140 100644 --- a/src/meson.build +++ b/src/meson.build @@ -55,6 +55,8 @@ libnautilus_sources = [ 'gtk/nautilusgtkplacesviewprivate.h', 'gtk/nautilusgtkplacesviewrow.c', 'gtk/nautilusgtkplacesviewrowprivate.h', + 'nautilus-action-bar.c', + 'nautilus-action-bar.h', 'nautilus-application.c', 'nautilus-application.h', 'nautilus-bookmark-list.c', @@ -77,8 +79,6 @@ libnautilus_sources = [ 'nautilus-files-view.h', 'nautilus-files-view-dnd.c', 'nautilus-files-view-dnd.h', - 'nautilus-floating-bar.c', - 'nautilus-floating-bar.h', 'nautilus-freedesktop-dbus.c', 'nautilus-freedesktop-dbus.h', 'nautilus-list-model.c', diff --git a/src/nautilus-action-bar.c b/src/nautilus-action-bar.c new file mode 100644 index 000000000..f2f59532b --- /dev/null +++ b/src/nautilus-action-bar.c @@ -0,0 +1,526 @@ +/* nautilus-action-bar.c + * + * Copyright (C) 2016 Georges Basile Stavracas Neto <georges.stavracas@gmail.com> + * + * This program 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 3 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, see <http://www.gnu.org/licenses/>. + */ + +#include "nautilus-action-bar.h" +#include "nautilus-clipboard.h" +#include "nautilus-file.h" +#include "nautilus-previewer.h" + +#include <gdk/gdkx.h> + +#include <glib/gi18n.h> + +#define UPDATE_STATUS_TIMEOUT 200 //ms + +struct _NautilusActionBar +{ + GtkFrame parent; + + GtkWidget *loading_label; + GtkWidget *paste_button; + GtkWidget *primary_label; + GtkWidget *secondary_label; + GtkWidget *stack; + + NautilusView *view; + gint update_status_timeout_id; +}; + +G_DEFINE_TYPE (NautilusActionBar, nautilus_action_bar, GTK_TYPE_FRAME) + +enum { + PROP_0, + PROP_VIEW, + N_PROPS +}; + +static void +open_preview_cb (NautilusActionBar *actionbar) +{ + GtkWidget *toplevel; + GdkWindow *window; + GList *selection; + gchar *uri; + guint xid; + + xid = 0; + uri = NULL; + selection = nautilus_view_get_selection (actionbar->view); + + /* Only preview if exact 1 file is selected */ + if (g_list_length (selection) != 1) + goto out; + + uri = nautilus_file_get_uri (selection->data); + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (actionbar)); + +#ifdef GDK_WINDOWING_X11 + window = gtk_widget_get_window (toplevel); + if (GDK_IS_X11_WINDOW (window)) + xid = gdk_x11_window_get_xid (gtk_widget_get_window (toplevel)); +#endif + + nautilus_previewer_call_show_file (uri, xid, TRUE); + +out: + g_clear_pointer (&selection, nautilus_file_list_free); + g_clear_pointer (&uri, g_free); +} + +#if 0 +static void +update_paste_button (NautilusActionBar *self) +{ + NautilusClipboardMonitor *monitor; + NautilusClipboardInfo *info; + + monitor = nautilus_clipboard_monitor_get (); + info = nautilus_clipboard_monitor_get_clipboard_info (monitor); + + if (info) + { + gchar *label; + gint length; + + length = g_list_length (info->files); + + if (info->cut) + label = g_strdup_printf (g_dngettext(NULL, "Move %d file", "Move %d files", length), length); + else + label = g_strdup_printf (g_dngettext(NULL, "Paste %d file", "Paste %d files", length), length); + + gtk_widget_set_tooltip_text (self->paste_button, label); + + g_free (label); + } +} +#endif + +static void +setup_multiple_files_selection (NautilusActionBar *actionbar, + GList *selection) +{ + NautilusFile *file; + goffset non_folder_size; + gboolean non_folder_size_known; + guint non_folder_count, folder_count, folder_item_count; + gboolean folder_item_count_known; + guint file_item_count; + GList *p; + char *first_item_name; + char *non_folder_count_str; + char *non_folder_item_count_str; + char *folder_count_str; + char *folder_item_count_str; + gchar *primary_text; + gchar *secondary_text; + + folder_item_count_known = TRUE; + folder_count = 0; + folder_item_count = 0; + non_folder_count = 0; + non_folder_size_known = FALSE; + non_folder_size = 0; + first_item_name = NULL; + folder_count_str = NULL; + folder_item_count_str = NULL; + non_folder_count_str = NULL; + non_folder_item_count_str = NULL; + + for (p = selection; p != NULL; p = p->next) + { + file = p->data; + + if (nautilus_file_is_directory (file)) + { + folder_count++; + + if (nautilus_file_get_directory_item_count (file, &file_item_count, NULL)) + folder_item_count += file_item_count; + else + folder_item_count_known = FALSE; + } + else + { + non_folder_count++; + + if (!nautilus_file_can_get_size (file)) + { + non_folder_size_known = TRUE; + non_folder_size += nautilus_file_get_size (file); + } + } + + if (first_item_name == NULL) + first_item_name = nautilus_file_get_display_name (file); + } + + nautilus_file_list_free (selection); + + /* + * Break out cases for localization's sake. But note that there are still pieces + * being assembled in a particular order, which may be a problem for some localizers. + */ + if (folder_count != 0) + { + if (folder_count == 1 && non_folder_count == 0) + { + folder_count_str = g_strdup_printf (_("“%s” selected"), first_item_name); + } + else + { + folder_count_str = g_strdup_printf (ngettext("%'d folder selected", + "%'d folders selected", + folder_count), + folder_count); + } + + if (folder_count == 1) + { + if (!folder_item_count_known) + folder_item_count_str = g_strdup (""); + else + folder_item_count_str = g_strdup_printf (ngettext("(containing %'d item)", "(containing %'d items)", folder_item_count), + folder_item_count); + } + else + { + if (!folder_item_count_known) + { + folder_item_count_str = g_strdup (""); + } + else + { + /* translators: this is preceded with a string of form 'N folders' (N more than 1) */ + folder_item_count_str = g_strdup_printf (ngettext("(containing a total of %'d item)", + "(containing a total of %'d items)", + folder_item_count), + folder_item_count); + } + } + } + + if (non_folder_count != 0) + { + if (folder_count == 0) + { + if (non_folder_count == 1) { + non_folder_count_str = g_strdup_printf (_("“%s” selected"), first_item_name); + } else { + non_folder_count_str = g_strdup_printf (ngettext("%'d item selected", + "%'d items selected", + non_folder_count), + non_folder_count); + } + } + else + { + /* Folders selected also, use "other" terminology */ + non_folder_count_str = g_strdup_printf (ngettext("%'d other item selected", + "%'d other items selected", + non_folder_count), + non_folder_count); + } + + if (non_folder_size_known) + { + char *size_string; + + size_string = g_format_size (non_folder_size); + /* This is marked for translation in case a localiser + * needs to use something other than parentheses. The + * the message in parentheses is the size of the selected items. + */ + non_folder_item_count_str = g_strdup_printf (_("(%s)"), size_string); + g_free (size_string); + } + else + { + non_folder_item_count_str = g_strdup (""); + } + } + + if (folder_count == 0 && non_folder_count == 0) + { + primary_text = secondary_text = NULL; + } + else if (folder_count == 0) + { + primary_text = g_strdup_printf ("%s, %s", non_folder_count_str, non_folder_item_count_str); + secondary_text = NULL; + } + else if (non_folder_count == 0) + { + primary_text = g_strdup_printf ("%s %s", folder_count_str, folder_item_count_str); + secondary_text = NULL; + } + else + { + primary_text = g_strdup_printf ("%s %s", folder_count_str, folder_item_count_str); + secondary_text = g_strdup_printf ("%s, %s", non_folder_count_str, non_folder_item_count_str); + } + + gtk_label_set_label (GTK_LABEL (actionbar->primary_label), primary_text ? primary_text : ""); + gtk_label_set_label (GTK_LABEL (actionbar->secondary_label), secondary_text ? secondary_text : ""); + + g_free (first_item_name); + g_free (folder_count_str); + g_free (folder_item_count_str); + g_free (non_folder_count_str); + g_free (non_folder_item_count_str); + g_free (secondary_text); + g_free (primary_text); +} + +static void +setup_single_file_selection (NautilusActionBar *actionbar, + NautilusFile *file) +{ + gboolean is_directory; + gchar *description; + + description = NULL; + is_directory = nautilus_file_is_directory (file); + + /* Primary label is the file name */ + gtk_label_set_label (GTK_LABEL (actionbar->primary_label), nautilus_file_get_display_name (file)); + + /* + * If the selected item is a folder, display the number of + * children. Otherwise, display the file size. + */ + if (is_directory) + { + guint folder_children; + + if (nautilus_file_get_directory_item_count (file, &folder_children, NULL)) + { + description = g_strdup_printf (ngettext("Contains %'d item", "Contains %'d items", folder_children), + folder_children); + } + } + else + { + description = g_format_size (nautilus_file_get_size (file)); + } + + /* + * If there is no description available, we hide the second label so + * the filename is vertically centralized against the icon. + */ + gtk_widget_set_visible (actionbar->secondary_label, description != NULL); + gtk_label_set_label (GTK_LABEL (actionbar->secondary_label), description ? description : ""); + + g_clear_pointer (&description, g_free); + g_clear_pointer (&file, nautilus_file_unref); +} + +static gboolean +real_update_status (gpointer data) +{ + NautilusActionBar *actionbar = data; + + if (nautilus_view_is_loading (actionbar->view)) + { + gtk_label_set_label (GTK_LABEL (actionbar->loading_label), + nautilus_view_is_searching (actionbar->view) ? _("Searching") : _("Loading")); + + gtk_stack_set_visible_child_name (GTK_STACK (actionbar->stack), "loading"); + } + else + { + GList *selection; + gint number_of_files; + + selection = nautilus_view_get_selection (actionbar->view); + number_of_files = g_list_length (selection); + + if (number_of_files == 0) + { + gtk_label_set_label (GTK_LABEL (actionbar->primary_label), ""); + gtk_label_set_label (GTK_LABEL (actionbar->secondary_label), ""); + } + else if (number_of_files == 1) + { + setup_single_file_selection (actionbar, selection->data); + } + else + { + setup_multiple_files_selection (actionbar, selection); + } + + gtk_stack_set_visible_child_name (GTK_STACK (actionbar->stack), "main"); + } + + actionbar->update_status_timeout_id = 0; + + return G_SOURCE_REMOVE; +} + +static void +update_status (NautilusActionBar *actionbar) +{ + if (actionbar->update_status_timeout_id > 0) + { + g_source_remove (actionbar->update_status_timeout_id); + actionbar->update_status_timeout_id = 0; + } + + actionbar->update_status_timeout_id = g_timeout_add (UPDATE_STATUS_TIMEOUT, + real_update_status, + actionbar); +} + +static void +nautilus_action_bar_dispose (GObject *object) +{ + NautilusActionBar *self = NAUTILUS_ACTION_BAR (object); + + if (self->update_status_timeout_id > 0) + { + g_source_remove (self->update_status_timeout_id); + self->update_status_timeout_id = 0; + } + if (self->view != NULL) + { + g_signal_handlers_disconnect_by_data (self->view, self); + g_clear_object (&self->view); + } + + G_OBJECT_CLASS (nautilus_action_bar_parent_class)->dispose (object); +} + +static void +nautilus_action_bar_finalize (GObject *object) +{ + //g_signal_handlers_disconnect_by_func (nautilus_clipboard_monitor_get (), update_paste_button, self); + + + G_OBJECT_CLASS (nautilus_action_bar_parent_class)->finalize (object); +} + +static void +nautilus_action_bar_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NautilusActionBar *self = NAUTILUS_ACTION_BAR (object); + + switch (prop_id) + { + case PROP_VIEW: + g_value_set_object (value, self->view); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +nautilus_action_bar_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + NautilusActionBar *self = NAUTILUS_ACTION_BAR (object); + + switch (prop_id) + { + case PROP_VIEW: + if (g_set_object (&self->view, g_value_get_object (value))) + { + g_signal_connect_swapped (self->view, "notify::selection", G_CALLBACK (update_status), self); + g_signal_connect_swapped (self->view, "notify::is-loading", G_CALLBACK (update_status), self); + g_signal_connect_swapped (self->view, "notify::is-searching", G_CALLBACK (update_status), self); + g_object_notify (object, "view"); + } + + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +nautilus_action_bar_class_init (NautilusActionBarClass *klass) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = nautilus_action_bar_finalize; + object_class->dispose = nautilus_action_bar_dispose; + object_class->get_property = nautilus_action_bar_get_property; + object_class->set_property = nautilus_action_bar_set_property; + + /** + * NautilusActionBar::view: + * + * The view related to this actionbar. + */ + g_object_class_install_property (object_class, + PROP_VIEW, + g_param_spec_object ("view", + "View of the actionbar", + "The view related to this actionbar", + NAUTILUS_TYPE_VIEW, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/nautilus/ui/nautilus-action-bar.ui"); + + gtk_widget_class_bind_template_child (widget_class, NautilusActionBar, loading_label); + gtk_widget_class_bind_template_child (widget_class, NautilusActionBar, paste_button); + gtk_widget_class_bind_template_child (widget_class, NautilusActionBar, primary_label); + gtk_widget_class_bind_template_child (widget_class, NautilusActionBar, secondary_label); + gtk_widget_class_bind_template_child (widget_class, NautilusActionBar, stack); + + gtk_widget_class_bind_template_callback (widget_class, open_preview_cb); + + gtk_widget_class_set_css_name (widget_class, "actionbar"); +} + +static void +nautilus_action_bar_init (NautilusActionBar *self) +{ + gtk_widget_init_template (GTK_WIDGET (self)); + +#if 0 + update_paste_button (self); + + g_signal_connect_swapped (nautilus_clipboard_monitor_get (), "clipboard-changed", + G_CALLBACK (update_paste_button), self); +#endif +} + +/** + * nautilus_action_bar_new: + * @view: a #NautilusView + * + * Creates a new actionbar related to @view. + * + * Returns: (transfer full): a #NautilusActionBar + */ +GtkWidget* +nautilus_action_bar_new (NautilusView *view) +{ + return g_object_new (NAUTILUS_TYPE_ACTION_BAR, + "view", view, + NULL); +} diff --git a/src/nautilus-action-bar.h b/src/nautilus-action-bar.h new file mode 100644 index 000000000..0af85b3a9 --- /dev/null +++ b/src/nautilus-action-bar.h @@ -0,0 +1,39 @@ +/* nautilus-action-bar.h + * + * Copyright (C) 2016 Georges Basile Stavracas Neto <georges.stavracas@gmail.com> + * + * This program 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 3 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, see <http://www.gnu.org/licenses/>. + */ + +#ifndef NAUTILUS_ACTION_BAR_H +#define NAUTILUS_ACTION_BAR_H + +#include <gtk/gtk.h> + +#include "nautilus-view.h" + +G_BEGIN_DECLS + +#define NAUTILUS_TYPE_ACTION_BAR (nautilus_action_bar_get_type()) + +G_DECLARE_FINAL_TYPE (NautilusActionBar, nautilus_action_bar, NAUTILUS, ACTION_BAR, GtkFrame) + +GtkWidget* nautilus_action_bar_new (NautilusView *view); + +void nautilus_action_bar_set_show_thumbnail (NautilusActionBar *actionbar, + gboolean show_thumbnail); + +G_END_DECLS + +#endif /* NAUTILUS_ACTION_BAR_H */ diff --git a/src/nautilus-files-view.c b/src/nautilus-files-view.c index 35369757f..67fad118c 100644 --- a/src/nautilus-files-view.c +++ b/src/nautilus-files-view.c @@ -27,12 +27,12 @@ #include "nautilus-files-view.h" +#include "nautilus-action-bar.h" #include "nautilus-application.h" #include "nautilus-batch-rename-dialog.h" #include "nautilus-batch-rename-utilities.h" #include "nautilus-error-reporting.h" #include "nautilus-file-undo-manager.h" -#include "nautilus-floating-bar.h" #include "nautilus-view-icon-controller.h" #include "nautilus-list-view.h" #include "nautilus-canvas-view.h" @@ -115,9 +115,6 @@ #define SHORTCUTS_PATH "/nautilus/scripts-accels" -/* Delay to show the Loading... floating bar */ -#define FLOATING_BAR_LOADING_DELAY 200 /* ms */ - #define MIN_COMMON_FILENAME_PREFIX_LENGTH 4 enum @@ -180,7 +177,6 @@ typedef struct guint display_selection_idle_id; guint update_context_menus_timeout_id; - guint update_status_idle_id; guint reveal_selection_idle_id; guint display_pending_source_id; @@ -248,12 +244,6 @@ typedef struct GtkWidget *no_search_results_widget; GtkWidget *starred_is_empty_widget; - /* Floating bar */ - guint floating_bar_set_status_timeout_id; - guint floating_bar_loading_timeout_id; - guint floating_bar_set_passthrough_timeout_id; - GtkWidget *floating_bar; - /* Toolbar menu */ NautilusToolbarMenuSections *toolbar_menu_sections; GtkWidget *sort_menu; @@ -269,6 +259,9 @@ typedef struct GCancellable *starred_cancellable; NautilusTagManager *tag_manager; + + /* Action bar */ + GtkWidget *actionbar; } NautilusFilesViewPrivate; typedef struct @@ -292,8 +285,6 @@ static void open_one_in_new_window (gpointer data, gpointer callback_data); static void schedule_update_context_menus (NautilusFilesView *view); static void remove_update_context_menus_timeout_callback (NautilusFilesView *view); -static void schedule_update_status (NautilusFilesView *view); -static void remove_update_status_idle_callback (NautilusFilesView *view); static void reset_update_interval (NautilusFilesView *view); static void schedule_idle_display_of_pending_files (NautilusFilesView *view); static void unschedule_display_of_pending_files (NautilusFilesView *view); @@ -346,233 +337,6 @@ static const struct { GDK_KEY_ZoomOut, "zoom-out" }, }; -/* - * Floating Bar code - */ -static void -remove_loading_floating_bar (NautilusFilesView *view) -{ - NautilusFilesViewPrivate *priv; - - priv = nautilus_files_view_get_instance_private (view); - - if (priv->floating_bar_loading_timeout_id != 0) - { - g_source_remove (priv->floating_bar_loading_timeout_id); - priv->floating_bar_loading_timeout_id = 0; - } - - gtk_widget_hide (priv->floating_bar); - nautilus_floating_bar_cleanup_actions (NAUTILUS_FLOATING_BAR (priv->floating_bar)); -} - -static void -real_setup_loading_floating_bar (NautilusFilesView *view) -{ - NautilusFilesViewPrivate *priv; - - priv = nautilus_files_view_get_instance_private (view); - - nautilus_floating_bar_cleanup_actions (NAUTILUS_FLOATING_BAR (priv->floating_bar)); - nautilus_floating_bar_set_primary_label (NAUTILUS_FLOATING_BAR (priv->floating_bar), - nautilus_view_is_searching (NAUTILUS_VIEW (view)) ? _("Searching…") : _("Loading…")); - nautilus_floating_bar_set_details_label (NAUTILUS_FLOATING_BAR (priv->floating_bar), NULL); - nautilus_floating_bar_set_show_spinner (NAUTILUS_FLOATING_BAR (priv->floating_bar), priv->loading); - nautilus_floating_bar_add_action (NAUTILUS_FLOATING_BAR (priv->floating_bar), - "process-stop-symbolic", - NAUTILUS_FLOATING_BAR_ACTION_ID_STOP); - - gtk_widget_set_halign (priv->floating_bar, GTK_ALIGN_END); - gtk_widget_show (priv->floating_bar); -} - -static gboolean -setup_loading_floating_bar_timeout_cb (gpointer user_data) -{ - NautilusFilesView *view = user_data; - NautilusFilesViewPrivate *priv; - - priv = nautilus_files_view_get_instance_private (view); - - priv->floating_bar_loading_timeout_id = 0; - real_setup_loading_floating_bar (view); - - return FALSE; -} - -static void -setup_loading_floating_bar (NautilusFilesView *view) -{ - NautilusFilesViewPrivate *priv; - - priv = nautilus_files_view_get_instance_private (view); - - /* setup loading overlay */ - if (priv->floating_bar_set_status_timeout_id != 0) - { - g_source_remove (priv->floating_bar_set_status_timeout_id); - priv->floating_bar_set_status_timeout_id = 0; - } - - if (priv->floating_bar_loading_timeout_id != 0) - { - g_source_remove (priv->floating_bar_loading_timeout_id); - priv->floating_bar_loading_timeout_id = 0; - } - - priv->floating_bar_loading_timeout_id = - g_timeout_add (FLOATING_BAR_LOADING_DELAY, setup_loading_floating_bar_timeout_cb, view); -} - -static void -floating_bar_action_cb (NautilusFloatingBar *floating_bar, - gint action, - NautilusFilesView *view) -{ - NautilusFilesViewPrivate *priv; - - priv = nautilus_files_view_get_instance_private (view); - - if (action == NAUTILUS_FLOATING_BAR_ACTION_ID_STOP) - { - remove_loading_floating_bar (view); - nautilus_window_slot_stop_loading (priv->slot); - } -} - -static void -real_floating_bar_set_short_status (NautilusFilesView *view, - const gchar *primary_status, - const gchar *detail_status) -{ - NautilusFilesViewPrivate *priv; - - priv = nautilus_files_view_get_instance_private (view); - - if (priv->loading) - { - return; - } - - nautilus_floating_bar_cleanup_actions (NAUTILUS_FLOATING_BAR (priv->floating_bar)); - nautilus_floating_bar_set_show_spinner (NAUTILUS_FLOATING_BAR (priv->floating_bar), - FALSE); - - if (primary_status == NULL && detail_status == NULL) - { - gtk_widget_hide (priv->floating_bar); - nautilus_floating_bar_remove_hover_timeout (NAUTILUS_FLOATING_BAR (priv->floating_bar)); - return; - } - - nautilus_floating_bar_set_labels (NAUTILUS_FLOATING_BAR (priv->floating_bar), - primary_status, - detail_status); - - gtk_widget_show (priv->floating_bar); -} - -typedef struct -{ - gchar *primary_status; - gchar *detail_status; - NautilusFilesView *view; -} FloatingBarSetStatusData; - -static void -floating_bar_set_status_data_free (gpointer data) -{ - FloatingBarSetStatusData *status_data = data; - - g_free (status_data->primary_status); - g_free (status_data->detail_status); - - g_slice_free (FloatingBarSetStatusData, data); -} - -static gboolean -floating_bar_set_status_timeout_cb (gpointer data) -{ - NautilusFilesViewPrivate *priv; - - FloatingBarSetStatusData *status_data = data; - - priv = nautilus_files_view_get_instance_private (status_data->view); - - priv->floating_bar_set_status_timeout_id = 0; - real_floating_bar_set_short_status (status_data->view, - status_data->primary_status, - status_data->detail_status); - - return FALSE; -} - -static gboolean -remove_floating_bar_passthrough (gpointer data) -{ - NautilusFilesViewPrivate *priv; - - priv = nautilus_files_view_get_instance_private (NAUTILUS_FILES_VIEW (data)); - gtk_overlay_set_overlay_pass_through (GTK_OVERLAY (priv->overlay), - priv->floating_bar, FALSE); - priv->floating_bar_set_passthrough_timeout_id = 0; - - return G_SOURCE_REMOVE; -} - -static void -set_floating_bar_status (NautilusFilesView *view, - const gchar *primary_status, - const gchar *detail_status) -{ - GtkSettings *settings; - gint double_click_time; - FloatingBarSetStatusData *status_data; - NautilusFilesViewPrivate *priv; - - priv = nautilus_files_view_get_instance_private (view); - - if (priv->floating_bar_set_status_timeout_id != 0) - { - g_source_remove (priv->floating_bar_set_status_timeout_id); - priv->floating_bar_set_status_timeout_id = 0; - } - - settings = gtk_settings_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (view))); - g_object_get (settings, - "gtk-double-click-time", &double_click_time, - NULL); - - status_data = g_slice_new0 (FloatingBarSetStatusData); - status_data->primary_status = g_strdup (primary_status); - status_data->detail_status = g_strdup (detail_status); - status_data->view = view; - - if (priv->floating_bar_set_passthrough_timeout_id != 0) - { - g_source_remove (priv->floating_bar_set_passthrough_timeout_id); - priv->floating_bar_set_passthrough_timeout_id = 0; - } - /* Activate passthrough on the floating bar just long enough for a - * potential double click to happen, so to not interfere with it */ - gtk_overlay_set_overlay_pass_through (GTK_OVERLAY (priv->overlay), - priv->floating_bar, TRUE); - priv->floating_bar_set_passthrough_timeout_id = g_timeout_add ((guint) double_click_time, - remove_floating_bar_passthrough, - view); - - /* waiting for half of the double-click-time before setting - * the status seems to be a good approximation of not setting it - * too often and not delaying the statusbar too much. - */ - priv->floating_bar_set_status_timeout_id = - g_timeout_add_full (G_PRIORITY_DEFAULT, - (guint) (double_click_time / 2), - floating_bar_set_status_timeout_cb, - status_data, - floating_bar_set_status_data_free); -} - static char * real_get_backing_uri (NautilusFilesView *view) { @@ -3098,7 +2862,6 @@ nautilus_files_view_destroy (GtkWidget *object) } remove_update_context_menus_timeout_callback (view); - remove_update_status_idle_callback (view); if (priv->display_selection_idle_id != 0) { @@ -3112,24 +2875,6 @@ nautilus_files_view_destroy (GtkWidget *object) priv->reveal_selection_idle_id = 0; } - if (priv->floating_bar_set_status_timeout_id != 0) - { - g_source_remove (priv->floating_bar_set_status_timeout_id); - priv->floating_bar_set_status_timeout_id = 0; - } - - if (priv->floating_bar_loading_timeout_id != 0) - { - g_source_remove (priv->floating_bar_loading_timeout_id); - priv->floating_bar_loading_timeout_id = 0; - } - - if (priv->floating_bar_set_passthrough_timeout_id != 0) - { - g_source_remove (priv->floating_bar_set_passthrough_timeout_id); - priv->floating_bar_set_passthrough_timeout_id = 0; - } - g_signal_handlers_disconnect_by_func (nautilus_preferences, schedule_update_context_menus, view); g_signal_handlers_disconnect_by_func (nautilus_preferences, @@ -3138,8 +2883,6 @@ nautilus_files_view_destroy (GtkWidget *object) sort_directories_first_changed_callback, view); g_signal_handlers_disconnect_by_func (gtk_filechooser_preferences, show_hidden_files_changed_callback, view); - g_signal_handlers_disconnect_by_func (nautilus_window_state, - nautilus_files_view_display_selection_info, view); g_signal_handlers_disconnect_by_func (gnome_lockdown_preferences, schedule_update_context_menus, view); g_signal_handlers_disconnect_by_func (nautilus_trash_monitor_get (), @@ -3153,6 +2896,7 @@ nautilus_files_view_destroy (GtkWidget *object) g_clear_object (&priv->search_query); g_clear_object (&priv->location); + g_clear_object (&priv->actionbar); /* We don't own the slot, so no unref */ priv->slot = NULL; @@ -3188,216 +2932,6 @@ nautilus_files_view_finalize (GObject *object) G_OBJECT_CLASS (nautilus_files_view_parent_class)->finalize (object); } -/** - * nautilus_files_view_display_selection_info: - * - * Display information about the current selection, and notify the view frame of the changed selection. - * @view: NautilusFilesView for which to display selection info. - * - **/ -void -nautilus_files_view_display_selection_info (NautilusFilesView *view) -{ - g_autolist (NautilusFile) selection = NULL; - goffset non_folder_size; - gboolean non_folder_size_known; - guint non_folder_count, folder_count, folder_item_count; - gboolean folder_item_count_known; - guint file_item_count; - GList *p; - char *first_item_name; - char *non_folder_count_str; - char *non_folder_item_count_str; - char *folder_count_str; - char *folder_item_count_str; - char *primary_status; - char *detail_status; - NautilusFile *file; - - g_return_if_fail (NAUTILUS_IS_FILES_VIEW (view)); - - selection = nautilus_view_get_selection (NAUTILUS_VIEW (view)); - - folder_item_count_known = TRUE; - folder_count = 0; - folder_item_count = 0; - non_folder_count = 0; - non_folder_size_known = FALSE; - non_folder_size = 0; - first_item_name = NULL; - folder_count_str = NULL; - folder_item_count_str = NULL; - non_folder_count_str = NULL; - non_folder_item_count_str = NULL; - - for (p = selection; p != NULL; p = p->next) - { - file = p->data; - if (nautilus_file_is_directory (file)) - { - folder_count++; - if (nautilus_file_get_directory_item_count (file, &file_item_count, NULL)) - { - folder_item_count += file_item_count; - } - else - { - folder_item_count_known = FALSE; - } - } - else - { - non_folder_count++; - if (!nautilus_file_can_get_size (file)) - { - non_folder_size_known = TRUE; - non_folder_size += nautilus_file_get_size (file); - } - } - - if (first_item_name == NULL) - { - first_item_name = nautilus_file_get_display_name (file); - } - } - - /* Break out cases for localization's sake. But note that there are still pieces - * being assembled in a particular order, which may be a problem for some localizers. - */ - - if (folder_count != 0) - { - if (folder_count == 1 && non_folder_count == 0) - { - folder_count_str = g_strdup_printf (_("“%s” selected"), first_item_name); - } - else - { - folder_count_str = g_strdup_printf (ngettext ("%'d folder selected", - "%'d folders selected", - folder_count), - folder_count); - } - - if (folder_count == 1) - { - if (!folder_item_count_known) - { - folder_item_count_str = g_strdup (""); - } - else - { - folder_item_count_str = g_strdup_printf (ngettext ("(containing %'d item)", - "(containing %'d items)", - folder_item_count), - folder_item_count); - } - } - else - { - if (!folder_item_count_known) - { - folder_item_count_str = g_strdup (""); - } - else - { - /* translators: this is preceded with a string of form 'N folders' (N more than 1) */ - folder_item_count_str = g_strdup_printf (ngettext ("(containing a total of %'d item)", - "(containing a total of %'d items)", - folder_item_count), - folder_item_count); - } - } - } - - if (non_folder_count != 0) - { - if (folder_count == 0) - { - if (non_folder_count == 1) - { - non_folder_count_str = g_strdup_printf (_("“%s” selected"), - first_item_name); - } - else - { - non_folder_count_str = g_strdup_printf (ngettext ("%'d item selected", - "%'d items selected", - non_folder_count), - non_folder_count); - } - } - else - { - /* Folders selected also, use "other" terminology */ - non_folder_count_str = g_strdup_printf (ngettext ("%'d other item selected", - "%'d other items selected", - non_folder_count), - non_folder_count); - } - - if (non_folder_size_known) - { - char *size_string; - - size_string = g_format_size (non_folder_size); - /* This is marked for translation in case a localiser - * needs to use something other than parentheses. The - * the message in parentheses is the size of the selected items. - */ - non_folder_item_count_str = g_strdup_printf (_("(%s)"), size_string); - g_free (size_string); - } - else - { - non_folder_item_count_str = g_strdup (""); - } - } - - if (folder_count == 0 && non_folder_count == 0) - { - primary_status = NULL; - detail_status = NULL; - } - else if (folder_count == 0) - { - primary_status = g_strdup (non_folder_count_str); - detail_status = g_strdup (non_folder_item_count_str); - } - else if (non_folder_count == 0) - { - primary_status = g_strdup (folder_count_str); - detail_status = g_strdup (folder_item_count_str); - } - else - { - /* This is marked for translation in case a localizer - * needs to change ", " to something else. The comma - * is between the message about the number of folders - * and the number of items in those folders and the - * message about the number of other items and the - * total size of those items. - */ - primary_status = g_strdup_printf (_("%s %s, %s %s"), - folder_count_str, - folder_item_count_str, - non_folder_count_str, - non_folder_item_count_str); - detail_status = NULL; - } - - g_free (first_item_name); - g_free (folder_count_str); - g_free (folder_item_count_str); - g_free (non_folder_count_str); - g_free (non_folder_item_count_str); - - set_floating_bar_status (view, primary_status, detail_status); - - g_free (primary_status); - g_free (detail_status); -} - static void nautilus_files_view_set_location (NautilusView *view, GFile *location) @@ -3511,9 +3045,7 @@ done_loading (NautilusFilesView *view, if (!priv->in_destruction) { - remove_loading_floating_bar (view); schedule_update_context_menus (view); - schedule_update_status (view); nautilus_files_view_update_toolbar_menus (view); reset_update_interval (view); @@ -3534,9 +3066,8 @@ done_loading (NautilusFilesView *view, do_reveal = TRUE; } - if (selection) + if (selection != NULL) { - g_list_free_full (selection, g_object_unref); g_object_notify (G_OBJECT (view), "selection"); } @@ -3568,7 +3099,6 @@ done_loading (NautilusFilesView *view, nautilus_files_view_reveal_selection (view); } } - nautilus_files_view_display_selection_info (view); } priv->loading = FALSE; @@ -4157,7 +3687,6 @@ display_selection_info_idle_callback (gpointer data) g_object_ref (G_OBJECT (view)); priv->display_selection_idle_id = 0; - nautilus_files_view_display_selection_info (view); g_object_notify (G_OBJECT (view), "selection"); g_object_unref (G_OBJECT (view)); @@ -4421,9 +3950,6 @@ files_added_callback (NautilusDirectory *directory, queue_pending_files (view, directory, files, &priv->new_added_files); - /* The number of items could have changed */ - schedule_update_status (view); - nautilus_profile_end (NULL); } @@ -4450,9 +3976,6 @@ files_changed_callback (NautilusDirectory *directory, queue_pending_files (view, directory, files, &priv->new_changed_files); - /* The free space or the number of items could have changed */ - schedule_update_status (view); - /* A change in MIME type could affect the Open with menu, for * one thing, so we need to update menus when files change. */ @@ -4479,8 +4002,6 @@ done_loading_callback (NautilusDirectory *directory, */ unschedule_display_of_pending_files (view); schedule_timeout_display_of_pending_files (view, UPDATE_INTERVAL_MIN); - - remove_loading_floating_bar (view); } nautilus_profile_end (NULL); } @@ -8172,62 +7693,6 @@ schedule_update_context_menus (NautilusFilesView *view) } } -static void -remove_update_status_idle_callback (NautilusFilesView *view) -{ - NautilusFilesViewPrivate *priv; - - priv = nautilus_files_view_get_instance_private (view); - - if (priv->update_status_idle_id != 0) - { - g_source_remove (priv->update_status_idle_id); - priv->update_status_idle_id = 0; - } -} - -static gboolean -update_status_idle_callback (gpointer data) -{ - NautilusFilesViewPrivate *priv; - NautilusFilesView *view; - - view = NAUTILUS_FILES_VIEW (data); - priv = nautilus_files_view_get_instance_private (view); - nautilus_files_view_display_selection_info (view); - priv->update_status_idle_id = 0; - return FALSE; -} - -static void -schedule_update_status (NautilusFilesView *view) -{ - NautilusFilesViewPrivate *priv; - - g_assert (NAUTILUS_IS_FILES_VIEW (view)); - - priv = nautilus_files_view_get_instance_private (view); - - /* Make sure we haven't already destroyed it */ - if (priv->slot == NULL) - { - return; - } - - if (priv->loading) - { - /* Don't update status bar while loading the dir */ - return; - } - - if (priv->update_status_idle_id == 0) - { - priv->update_status_idle_id = - g_idle_add_full (G_PRIORITY_DEFAULT_IDLE - 20, - update_status_idle_callback, view, NULL); - } -} - /** * nautilus_files_view_notify_selection_changed: * @@ -8285,9 +7750,7 @@ file_changed_callback (NautilusFile *file, NautilusFilesView *view = NAUTILUS_FILES_VIEW (callback_data); schedule_changes (view); - schedule_update_context_menus (view); - schedule_update_status (view); } /** @@ -8318,8 +7781,6 @@ load_directory (NautilusFilesView *view, priv->loading = TRUE; - setup_loading_floating_bar (view); - /* Update menus when directory is empty, before going to new * location, so they won't have any false lingering knowledge * of old selection. @@ -9143,6 +8604,16 @@ nautilus_files_view_key_press_event (GtkWidget *widget, return GDK_EVENT_PROPAGATE; } +static GtkWidget * +nautilus_files_view_get_action_bar (NautilusView *view) +{ + NautilusFilesViewPrivate *priv; + + priv = nautilus_files_view_get_instance_private (NAUTILUS_FILES_VIEW (view)); + + return priv->actionbar; +} + static NautilusQuery * nautilus_files_view_get_search_query (NautilusView *view) { @@ -9267,6 +8738,7 @@ nautilus_files_view_is_loading (NautilusView *view) static void nautilus_files_view_iface_init (NautilusViewInterface *iface) { + iface->get_action_bar = nautilus_files_view_get_action_bar; iface->get_location = nautilus_files_view_get_location; iface->set_location = nautilus_files_view_set_location; iface->get_selection = nautilus_files_view_get_selection; @@ -9498,6 +8970,9 @@ nautilus_files_view_init (NautilusFilesView *view) gtk_container_add (GTK_CONTAINER (priv->overlay), priv->scrolled_window); + /* Actionbar */ + priv->actionbar = g_object_ref_sink (nautilus_action_bar_new (NAUTILUS_VIEW (view))); + /* Empty states */ builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/ui/nautilus-no-search-results.ui"); priv->no_search_results_widget = GTK_WIDGET (gtk_builder_get_object (builder, "no_search_results")); @@ -9531,17 +9006,6 @@ nautilus_files_view_init (NautilusFilesView *view) TRUE); g_object_unref (builder); - /* Floating bar */ - priv->floating_bar = nautilus_floating_bar_new (NULL, NULL, FALSE); - gtk_widget_set_halign (priv->floating_bar, GTK_ALIGN_END); - gtk_widget_set_valign (priv->floating_bar, GTK_ALIGN_END); - gtk_overlay_add_overlay (GTK_OVERLAY (priv->overlay), priv->floating_bar); - - g_signal_connect (priv->floating_bar, - "action", - G_CALLBACK (floating_bar_action_cb), - view); - priv->non_ready_files = g_hash_table_new_full (file_and_directory_hash, file_and_directory_equal, diff --git a/src/nautilus-files-view.h b/src/nautilus-files-view.h index ea51e53f7..bd7574193 100644 --- a/src/nautilus-files-view.h +++ b/src/nautilus-files-view.h @@ -246,8 +246,6 @@ NautilusFilesView * nautilus_files_view_new (guint NautilusWindowSlot *nautilus_files_view_get_nautilus_window_slot (NautilusFilesView *view); char * nautilus_files_view_get_uri (NautilusFilesView *view); -void nautilus_files_view_display_selection_info (NautilusFilesView *view); - /* Wrappers for signal emitters. These are normally called * only by NautilusFilesView itself. They have corresponding signals * that observers might want to connect with. diff --git a/src/nautilus-places-view.c b/src/nautilus-places-view.c index 63300b063..f3151d691 100644 --- a/src/nautilus-places-view.c +++ b/src/nautilus-places-view.c @@ -253,6 +253,12 @@ nautilus_places_view_set_location (NautilusView *view, } } +static GtkWidget * +nautilus_places_view_get_action_bar (NautilusView *view) +{ + return NULL; +} + static GList * nautilus_places_view_get_selection (NautilusView *view) { @@ -334,6 +340,7 @@ nautilus_places_view_get_view_id (NautilusView *view) static void nautilus_places_view_iface_init (NautilusViewInterface *iface) { + iface->get_action_bar = nautilus_places_view_get_action_bar; iface->get_location = nautilus_places_view_get_location; iface->set_location = nautilus_places_view_set_location; iface->get_selection = nautilus_places_view_get_selection; diff --git a/src/nautilus-view.c b/src/nautilus-view.c index d14682d6c..39205528d 100644 --- a/src/nautilus-view.c +++ b/src/nautilus-view.c @@ -86,6 +86,22 @@ nautilus_view_default_init (NautilusViewInterface *iface) } /** + * nautilus_view_get_action_bar: + * @view: a #NautilusView + * + * Retrieves the action bar of @view. + * + * Returns: (transfer none): a #GtkWidget or %NULL. + */ +GtkWidget* +nautilus_view_get_action_bar (NautilusView *view) +{ + g_return_val_if_fail (NAUTILUS_VIEW_GET_IFACE (view)->get_action_bar, NULL); + + return NAUTILUS_VIEW_GET_IFACE (view)->get_action_bar (view); +} + +/** * nautilus_view_get_icon: * @view: a #NautilusView * diff --git a/src/nautilus-view.h b/src/nautilus-view.h index 56452ef89..83c7622ff 100644 --- a/src/nautilus-view.h +++ b/src/nautilus-view.h @@ -44,6 +44,10 @@ struct _NautilusViewInterface GTypeInterface parent; guint (*get_view_id) (NautilusView *view); + + /* Action bar of the view */ + GtkWidget* (*get_action_bar) (NautilusView *view); + /* * Returns the menu sections that should be shown in the toolbar menu * when this view is active. Implementations must not return %NULL @@ -76,6 +80,8 @@ GIcon * nautilus_view_get_icon (guint guint nautilus_view_get_view_id (NautilusView *view); +GtkWidget* nautilus_view_get_action_bar (NautilusView *view); + NautilusToolbarMenuSections * nautilus_view_get_toolbar_menu_sections (NautilusView *view); GFile * nautilus_view_get_location (NautilusView *view); diff --git a/src/nautilus-window-slot.c b/src/nautilus-window-slot.c index c3260aeb0..a70ad452c 100644 --- a/src/nautilus-window-slot.c +++ b/src/nautilus-window-slot.c @@ -2748,8 +2748,21 @@ static void change_view (NautilusWindowSlot *self) { NautilusWindowSlotPrivate *priv; + NautilusView *view; + gboolean view_changed; priv = nautilus_window_slot_get_instance_private (self); + view = priv->new_content_view; + view_changed = priv->content_view != view; + + /* Remove the old actionbar before switching to the new view */ + if (view_changed && + priv->content_view && + nautilus_view_get_action_bar (priv->content_view)) + { + gtk_container_remove (GTK_CONTAINER (self), nautilus_view_get_action_bar (priv->content_view)); + } + /* Switch to the new content view. * Destroy the extra location widgets first, since they might hold * a pointer to the old view, which will possibly be destroyed inside @@ -2768,6 +2781,17 @@ change_view (NautilusWindowSlot *self) * add back the extra location widgets. */ nautilus_window_slot_setup_extra_location_widgets (self); + + /* Add the actionbar (if any) after the extra location widgets are set */ + if (view_changed && nautilus_view_get_action_bar (view)) + { + GtkWidget *actionbar; + + actionbar = nautilus_view_get_action_bar (view); + + gtk_box_pack_end (GTK_BOX (self), actionbar, FALSE, FALSE, 0); + gtk_widget_show (actionbar); + } } static void diff --git a/src/resources/css/Adwaita.css b/src/resources/css/Adwaita.css index 59ab22b02..74d7ac1aa 100644 --- a/src/resources/css/Adwaita.css +++ b/src/resources/css/Adwaita.css @@ -185,6 +185,13 @@ box-shadow: none; } +button.thumbnail-button { + padding: 0px; + margin: 0px; + border: 0px; + border-radius: 0px; +} + @define-color disk_space_unknown #888a85; @define-color disk_space_used #729fcf; @define-color disk_space_free #eeeeec; @@ -249,3 +256,10 @@ flowboxchild:selected > widget > box > .icon-background {background-color:black; flowboxchild > widget > .icon-item-background {padding:4px;} flowboxchild:selected > widget > .icon-item-background {padding:4px; background-color:#4a90d9; border-color:#4a90d9; border-style:solid; border-width:0px; border-radius:4px 4px 4px 4px;} +/* Action bar */ +actionbar +{ + border-top: 1px solid @borders; + /* Same as sidebar_bg_color in gtk */ + background-color: mix(@theme_bg_color, @theme_base_color, 0.5); +}
\ No newline at end of file diff --git a/src/resources/nautilus.gresource.xml b/src/resources/nautilus.gresource.xml index e114d34aa..25ca160a4 100644 --- a/src/resources/nautilus.gresource.xml +++ b/src/resources/nautilus.gresource.xml @@ -1,6 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <gresources> <gresource prefix="/org/gnome/nautilus"> + <file compressed="true">ui/nautilus-action-bar.ui</file> <file compressed="true">ui/nautilus-preferences-window.ui</file> <file compressed="true">ui/nautilus-search-popover.ui</file> <file>gtk/menus.ui</file> diff --git a/src/resources/ui/nautilus-action-bar.ui b/src/resources/ui/nautilus-action-bar.ui new file mode 100644 index 000000000..6be5cf11d --- /dev/null +++ b/src/resources/ui/nautilus-action-bar.ui @@ -0,0 +1,357 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface> + <requires lib="gtk+" version="3.18"/> + <template class="NautilusActionBar" parent="GtkFrame"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="vexpand">False</property> + <child> + <object class="GtkStack" id="stack"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="hexpand">True</property> + <property name="hhomogeneous">False</property> + <property name="transition_type">crossfade</property> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="valign">center</property> + <property name="border_width">6</property> + <property name="spacing">6</property> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="hexpand">True</property> + <property name="orientation">vertical</property> + <property name="valign">center</property> + <child> + <object class="GtkLabel" id="primary_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="vexpand">True</property> + <property name="ellipsize">end</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="secondary_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="ellipsize">end</property> + <property name="xalign">0</property> + <attributes> + <attribute name="scale" value="0.86"/> + </attributes> + <style> + <class name="dim-label"/> + </style> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="hexpand">False</property> + <property name="valign">center</property> + <style> + <class name="linked"/> + </style> + <child> + <object class="GtkButton" id="cut_button"> + <property name="visible" bind-source="cut_button" bind-property="sensitive" bind-flags="default" /> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="tooltip_text" translatable="yes">Cut item</property> + <property name="action_name">view.cut</property> + <child> + <object class="GtkImage"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="icon_name">edit-cut-symbolic</property> + </object> + </child> + <style> + <class name="image-button"/> + </style> + </object> + </child> + <child> + <object class="GtkButton" id="copy_button"> + <property name="visible" bind-source="copy_button" bind-property="sensitive" bind-flags="default" /> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="tooltip_text" translatable="yes">Copy item</property> + <property name="action_name">view.copy</property> + <child> + <object class="GtkImage"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="icon_name">edit-copy-symbolic</property> + </object> + </child> + <style> + <class name="image-button"/> + </style> + </object> + </child> + <child> + <object class="GtkButton" id="paste_button"> + <property name="visible" bind-source="paste_button" bind-property="sensitive" bind-flags="default" /> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="action_name">view.paste</property> + <child> + <object class="GtkImage"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="icon_name">edit-paste-symbolic</property> + </object> + </child> + <style> + <class name="image-button"/> + </style> + </object> + </child> + <child> + <object class="GtkButton" id="trash_button"> + <property name="visible" bind-source="trash_button" bind-property="sensitive" bind-flags="default" /> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="tooltip_text" translatable="yes">Move to trash</property> + <property name="action_name">view.move-to-trash</property> + <child> + <object class="GtkImage"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="icon_name">user-trash-symbolic</property> + </object> + </child> + <style> + <class name="image-button"/> + </style> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">end</property> + <property name="position">4</property> + </packing> + </child> + <child> + <object class="GtkMenuButton"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="menu_model">selection-menu</property> + <property name="valign">center</property> + <child> + <object class="GtkImage"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="icon_name">view-more-symbolic</property> + </object> + </child> + <style> + <class name="image-button"/> + </style> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">end</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="spacing">6</property> + <property name="valign">center</property> + <child> + <object class="GtkButton" id="rename_button"> + <property name="visible" bind-source="rename_button" bind-property="sensitive" bind-flags="default" /> + <property name="label" translatable="yes">Rename</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="tooltip_text" translatable="yes">Rename the selected file</property> + <property name="action_name">view.rename</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + <child> + <object class="GtkButton"> + <property name="visible">True</property> + <property name="label" translatable="yes">Open</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="tooltip_text" translatable="yes">Open the selected items</property> + <property name="action_name">view.open-with-default-application</property> + <style> + <class name="suggested-action"/> + </style> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + <child> + <object class="GtkButton"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="tooltip_text" translatable="yes">Create a new folder</property> + <property name="action_name">view.new-folder</property> + <child> + <object class="GtkImage"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="icon_name">folder-new-symbolic</property> + </object> + </child> + <style> + <class name="image-button"/> + </style> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">end</property> + <property name="position">2</property> + </packing> + </child> + </object> + <packing> + <property name="name">main</property> + </packing> + </child> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="valign">center</property> + <property name="border_width">6</property> + <property name="spacing">6</property> + <property name="valign">center</property> + <child> + <object class="GtkSpinner"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="active">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="loading_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Loading</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkButton"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="action_name">view.stop-loading</property> + <child> + <object class="GtkImage"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="icon_name">process-stop-symbolic</property> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">end</property> + <property name="position">2</property> + </packing> + </child> + </object> + <packing> + <property name="name">loading</property> + <property name="position">1</property> + </packing> + </child> + </object> + </child> + </template> + <menu id="selection-menu"> + <section> + <item> + <attribute name="label" translatable="yes">Open in New Window</attribute> + <attribute name="action">view.open-item-new-window</attribute> + </item> + <item> + <attribute name="label" translatable="yes">Open in New Tab</attribute> + <attribute name="action">view.open-item-new-tab</attribute> + </item> + </section> + <section> + <item> + <attribute name="label" translatable="yes">Copy To…</attribute> + <attribute name="action">view.copy-to</attribute> + </item> + <item> + <attribute name="label" translatable="yes">Move To…</attribute> + <attribute name="action">view.move-to</attribute> + </item> + <item> + <attribute name="label" translatable="yes">New Folder With Selection…</attribute> + <attribute name="action">view.new-folder-with-selection</attribute> + </item> + </section> + <section> + <item> + <attribute name="label" translatable="yes">Properties</attribute> + <attribute name="action">view.properties</attribute> + </item> + </section> + </menu> +</interface> |