/* nautilus-action-bar.c * * Copyright (C) 2016 Georges Basile Stavracas Neto * * 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 . */ #include "nautilus-action-bar.h" #include "nautilus-clipboard.h" #include "nautilus-file.h" #include "nautilus-previewer.h" #include "nautilus-action-bar-box.h" #include #include #define UPDATE_STATUS_TIMEOUT 300 //ms struct _NautilusActionBar { GtkBox parent; GtkWidget *loading_label; GtkWidget *paste_button; GtkWidget *primary_label; GtkWidget *stack; NautilusWindowSlot *slot; gint update_status_timeout_id; }; G_DEFINE_TYPE (NautilusActionBar, nautilus_action_bar, GTK_TYPE_BOX) enum { PROP_0, PROP_SLOT, N_PROPS }; static void open_preslot_cb (NautilusActionBar *actionbar) { GtkWidget *toplevel; GdkWindow *window; GList *selection; gchar *uri; guint xid; xid = 0; uri = NULL; selection = nautilus_window_slot_get_selection (actionbar->slot); /* Only preslot 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) { guint count; char *first_item_name; g_autofree gchar *primary_text = NULL; count = 0; first_item_name = NULL; count = g_list_length (selection); if (count == 1) { first_item_name = nautilus_file_get_display_name (selection->data); primary_text = g_strdup_printf (_("ā€œ%sā€ selected"), first_item_name); } else { primary_text = g_strdup_printf (_("%'d items selected"), count); } nautilus_file_list_free (selection); if (primary_text != NULL) { gtk_label_set_label (GTK_LABEL (actionbar->primary_label), 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("%'d item", "%'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. */ g_clear_pointer (&description, g_free); g_clear_pointer (&file, nautilus_file_unref); } static gboolean real_update_status (gpointer data) { NautilusActionBar *actionbar = data; if (actionbar->slot != NULL && nautilus_window_slot_get_loading (actionbar->slot)) { gtk_label_set_label (GTK_LABEL (actionbar->loading_label), nautilus_window_slot_get_searching (actionbar->slot) ? _("Searching") : _("Loading")); gtk_stack_set_visible_child_name (GTK_STACK (actionbar->stack), "loading_bar"); } else { GList *selection; gint number_of_files = 0; if (actionbar->slot != NULL) { selection = nautilus_window_slot_get_selection (actionbar->slot); number_of_files = g_list_length (selection); } if (number_of_files == 0) { gtk_stack_set_visible_child_name (GTK_STACK (actionbar->stack), "background_bar"); } else if (number_of_files == 1) { setup_single_file_selection (actionbar, selection->data); gtk_stack_set_visible_child_name (GTK_STACK (actionbar->stack), "selection_bar"); } else { setup_multiple_files_selection (actionbar, selection); gtk_stack_set_visible_child_name (GTK_STACK (actionbar->stack), "selection_bar"); } } actionbar->update_status_timeout_id = 0; return G_SOURCE_REMOVE; } static void update_status (NautilusActionBar *actionbar) { g_print ("update status\n"); 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->slot != NULL) { g_signal_handlers_disconnect_by_data (self->slot, self); g_clear_object (&self->slot); } G_OBJECT_CLASS (nautilus_action_bar_parent_class)->dispose (object); } void nautilus_action_bar_set_slot (NautilusActionBar *self, NautilusWindowSlot *slot) { g_object_set (self, "slot", slot, NULL); } 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_SLOT: g_value_set_object (value, self->slot); 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_SLOT: { g_print ("setting slot\n"); if (self->slot != NULL) { g_signal_handlers_disconnect_by_data (self->slot, self); } g_set_object (&self->slot, g_value_get_object (value)); if (self->slot != NULL) { g_signal_connect_swapped (self->slot, "notify::selection", G_CALLBACK (update_status), self); g_signal_connect_swapped (self->slot, "notify::loading", G_CALLBACK (update_status), self); g_signal_connect_swapped (self->slot, "notify::searching", G_CALLBACK (update_status), self); g_object_notify (object, "slot"); } } 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::slot: * * The slot related to this actionbar. */ g_object_class_install_property (object_class, PROP_SLOT, g_param_spec_object ("slot", "Current slot of the window", "Current slot of the window", NAUTILUS_TYPE_WINDOW_SLOT, G_PARAM_READWRITE)); 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, stack); gtk_widget_class_bind_template_callback (widget_class, open_preslot_cb); gtk_widget_class_set_css_name (widget_class, "actionbar"); } static void nautilus_action_bar_init (NautilusActionBar *self) { g_type_ensure (NAUTILUS_TYPE_ACTION_BAR_BOX); 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 } NautilusActionBar* nautilus_action_bar_new (void) { return NAUTILUS_ACTION_BAR (g_object_new (NAUTILUS_TYPE_ACTION_BAR, NULL)); }