summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorges Basile Stavracas Neto <georges.stavracas@gmail.com>2016-03-02 00:59:06 -0300
committerCarlos Soriano <csoriano@gnome.org>2018-03-25 23:18:09 +0200
commite0b0869821c95fe3589294a9eaf29f2469a746d4 (patch)
tree11dd2be7752597d50c9ba2036ec0d26ef95cde99
parent2cbb2607760488ffd609880203c22fdf60c38cf6 (diff)
downloadnautilus-e0b0869821c95fe3589294a9eaf29f2469a746d4.tar.gz
action-bar: implement NautilusActionBar
The new NautilusActionBar class handles everything needed to be an usable actionbar as envisioned by the available mockups.
-rw-r--r--src/meson.build4
-rw-r--r--src/nautilus-action-bar.c526
-rw-r--r--src/nautilus-action-bar.h39
-rw-r--r--src/nautilus-files-view.c576
-rw-r--r--src/nautilus-files-view.h2
-rw-r--r--src/nautilus-places-view.c7
-rw-r--r--src/nautilus-view.c16
-rw-r--r--src/nautilus-view.h6
-rw-r--r--src/nautilus-window-slot.c24
-rw-r--r--src/resources/css/Adwaita.css14
-rw-r--r--src/resources/nautilus.gresource.xml1
-rw-r--r--src/resources/ui/nautilus-action-bar.ui357
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>