/* vi:set et ai sw=2 sts=2 ts=2: */ /*- * Copyright (c) 2015 Jonas Kümmerlin * * 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 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include struct _ThunarLocationBarClass { GtkBinClass __parent__; /* signals */ void (*reload_requested) (void); void (*entry_done) (void); }; struct _ThunarLocationBar { GtkBin __parent__; ThunarFile *current_directory; GtkWidget *locationEntry; GtkWidget *locationButtons; }; enum { PROP_0, PROP_CURRENT_DIRECTORY, }; static void thunar_location_bar_navigator_init (ThunarNavigatorIface *iface); static void thunar_location_bar_finalize (GObject *object); static void thunar_location_bar_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); static void thunar_location_bar_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); static ThunarFile *thunar_location_bar_get_current_directory (ThunarNavigator *navigator); static void thunar_location_bar_set_current_directory (ThunarNavigator *navigator, ThunarFile *current_directory); static GtkWidget *thunar_location_bar_install_widget (ThunarLocationBar *bar, GType type); static void thunar_location_bar_reload_requested (ThunarLocationBar *bar); static gboolean thunar_location_bar_settings_changed (ThunarLocationBar *bar); static void thunar_location_bar_on_enry_edit_done (ThunarLocationEntry *entry, ThunarLocationBar *bar); G_DEFINE_TYPE_WITH_CODE (ThunarLocationBar, thunar_location_bar, GTK_TYPE_BIN, G_IMPLEMENT_INTERFACE (THUNAR_TYPE_NAVIGATOR, thunar_location_bar_navigator_init)); GtkWidget * thunar_location_bar_new (void) { return gtk_widget_new (THUNAR_TYPE_LOCATION_BAR, NULL); } static void thunar_location_bar_class_init (ThunarLocationBarClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); gobject_class->get_property = thunar_location_bar_get_property; gobject_class->set_property = thunar_location_bar_set_property; gobject_class->finalize = thunar_location_bar_finalize; klass->reload_requested = exo_noop; /* Override ThunarNavigator's properties */ g_object_class_override_property (gobject_class, PROP_CURRENT_DIRECTORY, "current-directory"); /* install signals */ /** * ThunarLocationBar::reload-requested: * @location_bar : a #ThunarLocationBar. * * Emitted by @location_bar whenever the user clicked a "reload" button **/ g_signal_new ("reload-requested", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (ThunarLocationBarClass, reload_requested), NULL, NULL, NULL, G_TYPE_NONE, 0); /** * ThunarLocationBar::entry-done: * @location_bar : a #ThunarLocationBar. * * Emitted by @location_bar exactly once after an entry has been requested using * #thunar_location_bar_request_entry and the user has finished editing the entry. **/ g_signal_new ("entry-done", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (ThunarLocationBarClass, entry_done), NULL, NULL, NULL, G_TYPE_NONE, 0); } static void thunar_location_bar_init (ThunarLocationBar *bar) { ThunarPreferences *preferences = thunar_preferences_get (); bar->current_directory = NULL; bar->locationEntry = NULL; bar->locationButtons = NULL; thunar_location_bar_settings_changed (bar); g_signal_connect_object (preferences, "notify::last-location-bar", G_CALLBACK (thunar_location_bar_settings_changed), bar, G_CONNECT_SWAPPED); } static void thunar_location_bar_finalize (GObject *object) { ThunarLocationBar *bar = THUNAR_LOCATION_BAR (object); _thunar_return_if_fail (THUNAR_IS_LOCATION_BAR (bar)); if (bar->locationEntry) g_object_unref (bar->locationEntry); if (bar->locationButtons) g_object_unref (bar->locationButtons); /* release from the current_directory */ thunar_navigator_set_current_directory (THUNAR_NAVIGATOR (bar), NULL); (*G_OBJECT_CLASS (thunar_location_bar_parent_class)->finalize) (object); } static void thunar_location_bar_navigator_init (ThunarNavigatorIface *iface) { iface->set_current_directory = thunar_location_bar_set_current_directory; iface->get_current_directory = thunar_location_bar_get_current_directory; } static void thunar_location_bar_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { switch (prop_id) { case PROP_CURRENT_DIRECTORY: g_value_set_object (value, thunar_navigator_get_current_directory (THUNAR_NAVIGATOR (object))); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void thunar_location_bar_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { switch (prop_id) { case PROP_CURRENT_DIRECTORY: thunar_navigator_set_current_directory (THUNAR_NAVIGATOR (object), g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static ThunarFile * thunar_location_bar_get_current_directory (ThunarNavigator *navigator) { return THUNAR_LOCATION_BAR (navigator)->current_directory; } static void thunar_location_bar_set_current_directory (ThunarNavigator *navigator, ThunarFile *current_directory) { ThunarLocationBar *bar = THUNAR_LOCATION_BAR (navigator); GtkWidget *child; if (bar->current_directory) g_object_unref (bar->current_directory); bar->current_directory = current_directory; if (current_directory) g_object_ref (current_directory); if ((child = gtk_bin_get_child (GTK_BIN (bar))) && THUNAR_IS_NAVIGATOR (child)) thunar_navigator_set_current_directory (THUNAR_NAVIGATOR (child), current_directory); g_object_notify (G_OBJECT (bar), "current-directory"); } static void thunar_location_bar_reload_requested (ThunarLocationBar *bar) { g_signal_emit_by_name (bar, "reload-requested"); } static GtkWidget * thunar_location_bar_install_widget (ThunarLocationBar *bar, GType type) { GtkWidget *installedWidget, *child; /* check if the the right type is already installed */ if ((child = gtk_bin_get_child (GTK_BIN (bar))) && G_TYPE_CHECK_INSTANCE_TYPE (child, type)) return child; if (type == THUNAR_TYPE_LOCATION_ENTRY) { if (bar->locationEntry == NULL) { bar->locationEntry = gtk_widget_new (THUNAR_TYPE_LOCATION_ENTRY, "current-directory", NULL, NULL); g_object_ref (bar->locationEntry); g_signal_connect_swapped (bar->locationEntry, "reload-requested", G_CALLBACK (thunar_location_bar_reload_requested), bar); g_signal_connect_swapped (bar->locationEntry, "change-directory", G_CALLBACK (thunar_navigator_change_directory), THUNAR_NAVIGATOR (bar)); g_signal_connect_swapped (bar->locationEntry, "open-new-tab", G_CALLBACK (thunar_navigator_open_new_tab), THUNAR_NAVIGATOR (bar)); } installedWidget = bar->locationEntry; } else { if (bar->locationButtons == NULL) { bar->locationButtons = gtk_widget_new (THUNAR_TYPE_LOCATION_BUTTONS, "current-directory", NULL, NULL); g_object_ref (bar->locationButtons); g_signal_connect_swapped (bar->locationButtons, "entry-requested", G_CALLBACK (thunar_location_bar_request_entry), bar); g_signal_connect_swapped (bar->locationButtons, "change-directory", G_CALLBACK (thunar_navigator_change_directory), THUNAR_NAVIGATOR (bar)); g_signal_connect_swapped (bar->locationButtons, "open-new-tab", G_CALLBACK (thunar_navigator_open_new_tab), THUNAR_NAVIGATOR (bar)); } installedWidget = bar->locationButtons; } thunar_navigator_set_current_directory (THUNAR_NAVIGATOR (installedWidget), bar->current_directory); if ((child = gtk_bin_get_child (GTK_BIN (bar)))) gtk_container_remove (GTK_CONTAINER (bar), child); gtk_container_add (GTK_CONTAINER (bar), installedWidget); gtk_widget_show (installedWidget); return installedWidget; } static void thunar_location_bar_on_enry_edit_done (ThunarLocationEntry *entry, ThunarLocationBar *bar) { g_signal_handlers_disconnect_by_func (entry, thunar_location_bar_on_enry_edit_done, bar); g_object_ref (bar); g_idle_add_full (G_PRIORITY_HIGH_IDLE, (GSourceFunc)thunar_location_bar_settings_changed, bar, g_object_unref); g_signal_emit_by_name (bar, "entry-done"); } /** * thunar_location_bar_request_entry * @bar : The #ThunarLocationBar * @initial_text : The initial text to be placed inside the entry, or NULL to * use the path of the current directory. * * Makes the location bar display an entry with the given text and places the cursor * accordingly. If the currently displayed location widget is a path bar, it will be * temporarily swapped for an entry widget and swapped back once the user completed * (or aborted) the input. */ void thunar_location_bar_request_entry (ThunarLocationBar *bar, const gchar *initial_text) { GtkWidget *child; child = gtk_bin_get_child (GTK_BIN (bar)); _thunar_return_if_fail (child != NULL && GTK_IS_WIDGET (child)); if (THUNAR_IS_LOCATION_ENTRY (child)) { /* already have an entry */ thunar_location_entry_accept_focus (THUNAR_LOCATION_ENTRY (child), initial_text); } else { /* not an entry => temporarily replace it */ child = thunar_location_bar_install_widget (bar, THUNAR_TYPE_LOCATION_ENTRY); thunar_location_entry_accept_focus (THUNAR_LOCATION_ENTRY (child), initial_text); } g_signal_connect (child, "edit-done", G_CALLBACK (thunar_location_bar_on_enry_edit_done), bar); } static gboolean thunar_location_bar_settings_changed (ThunarLocationBar *bar) { gchar *last_location_bar; GType type; g_object_get (thunar_preferences_get(), "last-location-bar", &last_location_bar, NULL); /* validate it */ if (!strcmp (last_location_bar, g_type_name (THUNAR_TYPE_LOCATION_BUTTONS))) type = THUNAR_TYPE_LOCATION_BUTTONS; else if (!strcmp (last_location_bar, g_type_name (THUNAR_TYPE_LOCATION_ENTRY))) type = THUNAR_TYPE_LOCATION_ENTRY; else type = THUNAR_TYPE_LOCATION_ENTRY; /* fallback */ g_free (last_location_bar); thunar_location_bar_install_widget (bar, type); return FALSE; }