Tree of tag thunar-4.20.7 (commit df0e054) from https://gitlab.xfce.org/xfce/thunar. Upstream history is not included here to keep the repository small.
431 lines
13 KiB
C
431 lines
13 KiB
C
/* vi:set et ai sw=2 sts=2 ts=2: */
|
|
/*-
|
|
* Copyright (c) 2015 Jonas Kümmerlin <rgcjonas@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 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 "config.h"
|
|
#endif
|
|
|
|
#include "thunar/thunar-location-bar.h"
|
|
#include "thunar/thunar-location-buttons.h"
|
|
#include "thunar/thunar-location-entry.h"
|
|
#include "thunar/thunar-navigator.h"
|
|
#include "thunar/thunar-preferences.h"
|
|
#include "thunar/thunar-private.h"
|
|
#include "thunar/thunar-util.h"
|
|
#include "thunar/thunar-window.h"
|
|
|
|
|
|
|
|
struct _ThunarLocationBarClass
|
|
{
|
|
GtkBinClass __parent__;
|
|
|
|
/* signals */
|
|
void (*entry_done) (void);
|
|
void (*reload_requested) (void); /* UNUSED */
|
|
};
|
|
|
|
struct _ThunarLocationBar
|
|
{
|
|
GtkBin __parent__;
|
|
|
|
ThunarPreferences *preferences;
|
|
|
|
ThunarFile *current_directory;
|
|
|
|
GtkWidget *locationEntry;
|
|
GtkWidget *locationButtons;
|
|
|
|
gboolean is_searching;
|
|
};
|
|
|
|
|
|
|
|
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_settings_changed (ThunarLocationBar *bar);
|
|
static void
|
|
thunar_location_bar_on_enry_edit_done (ThunarLocationEntry *entry,
|
|
ThunarLocationBar *bar);
|
|
static void
|
|
thunar_location_bar_request_temp_entry (ThunarLocationBar *bar,
|
|
const gchar *initial_text);
|
|
|
|
|
|
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 = NULL;
|
|
|
|
/* Override ThunarNavigator's properties */
|
|
g_object_class_override_property (gobject_class, PROP_CURRENT_DIRECTORY, "current-directory");
|
|
|
|
/* install signals */
|
|
|
|
/**
|
|
* 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)
|
|
{
|
|
bar->preferences = thunar_preferences_get ();
|
|
|
|
bar->current_directory = NULL;
|
|
bar->locationEntry = NULL;
|
|
bar->locationButtons = NULL;
|
|
|
|
thunar_location_bar_settings_changed (bar);
|
|
|
|
g_signal_connect_swapped (bar->preferences, "notify::last-location-bar", G_CALLBACK (thunar_location_bar_settings_changed), bar);
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
thunar_location_bar_finalize (GObject *object)
|
|
{
|
|
ThunarLocationBar *bar = THUNAR_LOCATION_BAR (object);
|
|
|
|
_thunar_return_if_fail (THUNAR_IS_LOCATION_BAR (bar));
|
|
|
|
/* disconnect from the preferences */
|
|
g_signal_handlers_disconnect_by_func (bar->preferences, thunar_location_bar_settings_changed, bar);
|
|
g_object_unref (bar->preferences);
|
|
|
|
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 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, "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_temp_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);
|
|
|
|
thunar_location_bar_settings_changed (bar);
|
|
g_signal_emit_by_name (bar, "entry-done");
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
thunar_location_bar_request_temp_entry (ThunarLocationBar *bar,
|
|
const gchar *initial_text)
|
|
{
|
|
thunar_location_bar_request_entry (bar, initial_text, TRUE);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* 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.
|
|
* @temporary_till_focus_lost : Revert to the previous location bar style when focus got lost
|
|
*
|
|
* 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,
|
|
gboolean temporary_till_focus_lost)
|
|
{
|
|
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);
|
|
}
|
|
|
|
if (temporary_till_focus_lost)
|
|
{
|
|
thunar_location_entry_enable_edit_done_once (THUNAR_LOCATION_ENTRY (child));
|
|
g_signal_connect (child, "edit-done", G_CALLBACK (thunar_location_bar_on_enry_edit_done), bar);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
thunar_location_bar_settings_changed (ThunarLocationBar *bar)
|
|
{
|
|
gchar *last_location_bar;
|
|
GType type;
|
|
|
|
g_object_get (bar->preferences, "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);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* thunar_location_bar_cancel_search
|
|
* @bar : The #ThunarLocationBar
|
|
*
|
|
* Cancels the search for the location bar and its children.
|
|
*/
|
|
void
|
|
thunar_location_bar_cancel_search (ThunarLocationBar *bar)
|
|
{
|
|
if (bar->locationEntry != NULL)
|
|
thunar_location_entry_cancel_search (THUNAR_LOCATION_ENTRY (bar->locationEntry));
|
|
|
|
/* Recover the previous location bar style (BUTTONS/ENTRY) after search is done */
|
|
thunar_location_bar_settings_changed (bar);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* thunar_location_bar_get_search_query:
|
|
* @entry : a #ThunarLocationBar.
|
|
*
|
|
* Returns a copy of the search query in the text field of @entry or "" if the path_entry doesn't contain
|
|
* a search query.
|
|
*
|
|
* It's the responsibility of the caller to free the returned string using `g_free`.
|
|
**/
|
|
gchar *
|
|
thunar_location_bar_get_search_query (ThunarLocationBar *entry)
|
|
{
|
|
return (entry->locationEntry != NULL) ? thunar_location_entry_get_search_query (THUNAR_LOCATION_ENTRY (entry->locationEntry)) : g_strdup ("");
|
|
}
|