summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libcaja-private/caja-file.c9
-rw-r--r--libcaja-private/caja-search-directory.c6
-rw-r--r--libcaja-private/caja-search-directory.h3
-rw-r--r--libcaja-private/caja-search-engine-simple.c80
-rw-r--r--libcaja-private/caja-search-engine.c10
-rw-r--r--libcaja-private/caja-search-engine.h2
-rw-r--r--src/caja-navigation-window-pane.c26
-rw-r--r--src/file-manager/fm-icon-view.c59
-rw-r--r--src/file-manager/fm-list-view.c69
9 files changed, 252 insertions, 12 deletions
diff --git a/libcaja-private/caja-file.c b/libcaja-private/caja-file.c
index faea7993..2fc9c030 100644
--- a/libcaja-private/caja-file.c
+++ b/libcaja-private/caja-file.c
@@ -149,7 +149,8 @@ static GQuark attribute_name_q,
attribute_where_q,
attribute_link_target_q,
attribute_volume_q,
- attribute_free_space_q;
+ attribute_free_space_q,
+ attribute_location_q;
static void caja_file_info_iface_init (CajaFileInfoIface *iface);
static char * caja_file_get_owner_as_string (CajaFile *file,
@@ -6504,7 +6505,7 @@ caja_file_get_deep_directory_count_as_string (CajaFile *file)
* set includes "name", "type", "mime_type", "size", "size_on_disk", "deep_size", "deep_size_on_disk",
* "deep_directory_count", "deep_file_count", "deep_total_count", "date_modified", "date_changed",
* "date_accessed", "date_permissions", "owner", "group", "permissions", "octal_permissions", "uri", "where",
- * "link_target", "volume", "free_space", "selinux_context", "trashed_on", "trashed_orig_path"
+ * "link_target", "location", "volume", "free_space", "selinux_context", "trashed_on", "trashed_orig_path"
*
* Returns: Newly allocated string ready to display to the user, or NULL
* if the value is unknown or @attribute_name is not supported.
@@ -6605,6 +6606,9 @@ caja_file_get_string_attribute_q (CajaFile *file, GQuark attribute_q)
if (attribute_q == attribute_link_target_q) {
return caja_file_get_symbolic_link_target_path (file);
}
+ if (attribute_q == attribute_location_q) {
+ return caja_file_get_parent_uri_for_display (file);
+ }
if (attribute_q == attribute_volume_q) {
return caja_file_get_volume_name (file);
}
@@ -8624,6 +8628,7 @@ caja_file_class_init (CajaFileClass *class)
attribute_link_target_q = g_quark_from_static_string ("link_target");
attribute_volume_q = g_quark_from_static_string ("volume");
attribute_free_space_q = g_quark_from_static_string ("free_space");
+ attribute_location_q = g_quark_from_static_string ("location");
G_OBJECT_CLASS (class)->finalize = finalize;
G_OBJECT_CLASS (class)->constructor = caja_file_constructor;
diff --git a/libcaja-private/caja-search-directory.c b/libcaja-private/caja-search-directory.c
index da2e133b..fbd3f17e 100644
--- a/libcaja-private/caja-search-directory.c
+++ b/libcaja-private/caja-search-directory.c
@@ -846,6 +846,12 @@ caja_search_directory_get_query (CajaSearchDirectory *search)
return NULL;
}
+CajaSearchEngine *
+caja_search_directory_get_engine (CajaSearchDirectory *search)
+{
+ return search->details->engine;
+}
+
CajaSearchDirectory *
caja_search_directory_new_from_saved_search (const char *uri)
{
diff --git a/libcaja-private/caja-search-directory.h b/libcaja-private/caja-search-directory.h
index 4214f097..95c7d07a 100644
--- a/libcaja-private/caja-search-directory.h
+++ b/libcaja-private/caja-search-directory.h
@@ -27,6 +27,7 @@
#include "caja-directory.h"
#include "caja-query.h"
+#include "caja-search-engine.h"
#define CAJA_TYPE_SEARCH_DIRECTORY caja_search_directory_get_type()
#define CAJA_SEARCH_DIRECTORY(obj) \
@@ -70,4 +71,6 @@ CajaQuery *caja_search_directory_get_query (CajaSearchDirectory *search);
void caja_search_directory_set_query (CajaSearchDirectory *search,
CajaQuery *query);
+CajaSearchEngine *caja_search_directory_get_engine (CajaSearchDirectory *search);
+
#endif /* CAJA_SEARCH_DIRECTORY_H */
diff --git a/libcaja-private/caja-search-engine-simple.c b/libcaja-private/caja-search-engine-simple.c
index aae74d23..dd87b56c 100644
--- a/libcaja-private/caja-search-engine-simple.c
+++ b/libcaja-private/caja-search-engine-simple.c
@@ -24,12 +24,14 @@
#include <config.h>
#include <string.h>
#include <glib.h>
+#include <fnmatch.h>
#include <gio/gio.h>
#include <eel/eel-gtk-macros.h>
#include "caja-search-engine-simple.h"
+#include "caja-global-preferences.h"
#define BATCH_SIZE 500
@@ -42,6 +44,7 @@ typedef struct
GList *mime_types;
GList *tags;
char **words;
+ gboolean use_globs;
GQueue *directories; /* GFiles */
@@ -51,6 +54,7 @@ typedef struct
GList *uri_hits;
gint64 timestamp;
gint64 size;
+ gboolean search_hidden_files;
} SearchThreadData;
struct CajaSearchEngineSimpleDetails
@@ -60,6 +64,7 @@ struct CajaSearchEngineSimpleDetails
SearchThreadData *active_search;
gboolean query_finished;
+ gboolean show_hidden_files;
};
G_DEFINE_TYPE (CajaSearchEngineSimple,
@@ -68,6 +73,18 @@ G_DEFINE_TYPE (CajaSearchEngineSimple,
static CajaSearchEngineClass *parent_class = NULL;
+static gboolean
+text_has_glob (const char *text)
+{
+ if (!text)
+ return FALSE;
+
+ return (strchr (text, '*') != NULL ||
+ strchr (text, '?') != NULL ||
+ strchr (text, '[') != NULL ||
+ strchr (text, ']') != NULL);
+}
+
static void
finalize (GObject *object)
{
@@ -113,12 +130,23 @@ search_thread_data_new (CajaSearchEngineSimple *engine,
g_queue_push_tail (data->directories, location);
text = caja_query_get_text (query);
- normalized = g_utf8_normalize (text, -1, G_NORMALIZE_NFD);
- lower = g_utf8_strdown (normalized, -1);
- data->words = g_strsplit (lower, " ", -1);
+ data->use_globs = text && text_has_glob (text);
+
+ if (data->use_globs)
+ {
+ /* For globs, keep original case and don't normalize */
+ data->words = g_strsplit (text, " ", -1);
+ }
+ else
+ {
+ /* For substring matching, normalize and lowercase */
+ normalized = g_utf8_normalize (text, -1, G_NORMALIZE_NFD);
+ lower = g_utf8_strdown (normalized, -1);
+ data->words = g_strsplit (lower, " ", -1);
+ g_free (lower);
+ g_free (normalized);
+ }
g_free (text);
- g_free (lower);
- g_free (normalized);
data->tags = caja_query_get_tags (query);
data->mime_types = caja_query_get_mime_types (query);
@@ -126,6 +154,8 @@ search_thread_data_new (CajaSearchEngineSimple *engine,
data->size = caja_query_get_size (query);
data->contained_text = caja_query_get_contained_text (query);
+ data->search_hidden_files = engine->details->show_hidden_files;
+
data->cancellable = g_cancellable_new ();
return data;
@@ -483,7 +513,7 @@ visit_directory (GFile *dir, SearchThreadData *data)
while ((info = g_file_enumerator_next_file (enumerator, data->cancellable, NULL)) != NULL)
{
- if (g_file_info_get_is_hidden (info))
+ if (g_file_info_get_is_hidden (info) && !data->search_hidden_files)
{
goto next;
}
@@ -499,12 +529,31 @@ visit_directory (GFile *dir, SearchThreadData *data)
g_free (normalized);
hit = TRUE;
- for (i = 0; data->words[i] != NULL; i++)
+ if (data->use_globs)
{
- if (strstr (lower_name, data->words[i]) == NULL)
+ /* Use glob pattern matching with case-insensitive comparison */
+ for (i = 0; data->words[i] != NULL; i++)
{
- hit = FALSE;
- break;
+ char *lower_pattern = g_utf8_strdown (data->words[i], -1);
+ if (fnmatch (lower_pattern, lower_name, 0) != 0)
+ {
+ hit = FALSE;
+ g_free (lower_pattern);
+ break;
+ }
+ g_free (lower_pattern);
+ }
+ }
+ else
+ {
+ /* Use substring matching */
+ for (i = 0; data->words[i] != NULL; i++)
+ {
+ if (strstr (lower_name, data->words[i]) == NULL)
+ {
+ hit = FALSE;
+ break;
+ }
}
}
g_free (lower_name);
@@ -721,6 +770,15 @@ caja_search_engine_simple_set_query (CajaSearchEngine *engine, CajaQuery *query)
}
static void
+caja_search_engine_simple_set_show_hidden_files (CajaSearchEngine *engine, gboolean show_hidden_files)
+{
+ CajaSearchEngineSimple *simple;
+
+ simple = CAJA_SEARCH_ENGINE_SIMPLE (engine);
+ simple->details->show_hidden_files = show_hidden_files;
+}
+
+static void
caja_search_engine_simple_class_init (CajaSearchEngineSimpleClass *class)
{
GObjectClass *gobject_class;
@@ -733,6 +791,7 @@ caja_search_engine_simple_class_init (CajaSearchEngineSimpleClass *class)
engine_class = CAJA_SEARCH_ENGINE_CLASS (class);
engine_class->set_query = caja_search_engine_simple_set_query;
+ engine_class->set_show_hidden_files = caja_search_engine_simple_set_show_hidden_files;
engine_class->start = caja_search_engine_simple_start;
engine_class->stop = caja_search_engine_simple_stop;
engine_class->is_indexed = caja_search_engine_simple_is_indexed;
@@ -742,6 +801,7 @@ static void
caja_search_engine_simple_init (CajaSearchEngineSimple *engine)
{
engine->details = g_new0 (CajaSearchEngineSimpleDetails, 1);
+ engine->details->show_hidden_files = g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_SHOW_HIDDEN_FILES);
}
CajaSearchEngine *
diff --git a/libcaja-private/caja-search-engine.c b/libcaja-private/caja-search-engine.c
index d8d9d9a8..9dd6ab2e 100644
--- a/libcaja-private/caja-search-engine.c
+++ b/libcaja-private/caja-search-engine.c
@@ -125,6 +125,16 @@ caja_search_engine_set_query (CajaSearchEngine *engine, CajaQuery *query)
}
void
+caja_search_engine_set_show_hidden_files (CajaSearchEngine *engine, gboolean show_hidden_files)
+{
+ g_return_if_fail (CAJA_IS_SEARCH_ENGINE (engine));
+
+ if (CAJA_SEARCH_ENGINE_GET_CLASS (engine)->set_show_hidden_files != NULL) {
+ CAJA_SEARCH_ENGINE_GET_CLASS (engine)->set_show_hidden_files (engine, show_hidden_files);
+ }
+}
+
+void
caja_search_engine_start (CajaSearchEngine *engine)
{
g_return_if_fail (CAJA_IS_SEARCH_ENGINE (engine));
diff --git a/libcaja-private/caja-search-engine.h b/libcaja-private/caja-search-engine.h
index 90bd6593..773901a1 100644
--- a/libcaja-private/caja-search-engine.h
+++ b/libcaja-private/caja-search-engine.h
@@ -46,6 +46,7 @@ typedef struct
/* VTable */
void (*set_query) (CajaSearchEngine *engine, CajaQuery *query);
+ void (*set_show_hidden_files) (CajaSearchEngine *engine, gboolean show_hidden_files);
void (*start) (CajaSearchEngine *engine);
void (*stop) (CajaSearchEngine *engine);
gboolean (*is_indexed) (CajaSearchEngine *engine);
@@ -63,6 +64,7 @@ gboolean caja_search_engine_enabled (void);
CajaSearchEngine* caja_search_engine_new (void);
void caja_search_engine_set_query (CajaSearchEngine *engine, CajaQuery *query);
+void caja_search_engine_set_show_hidden_files (CajaSearchEngine *engine, gboolean show_hidden_files);
void caja_search_engine_start (CajaSearchEngine *engine);
void caja_search_engine_stop (CajaSearchEngine *engine);
gboolean caja_search_engine_is_indexed (CajaSearchEngine *engine);
diff --git a/src/caja-navigation-window-pane.c b/src/caja-navigation-window-pane.c
index 19669411..5e870d45 100644
--- a/src/caja-navigation-window-pane.c
+++ b/src/caja-navigation-window-pane.c
@@ -26,6 +26,7 @@
#include <libcaja-private/caja-global-preferences.h>
#include <libcaja-private/caja-window-slot-info.h>
+#include <libcaja-private/caja-window-info.h>
#include <libcaja-private/caja-view-factory.h>
#include <libcaja-private/caja-entry.h>
@@ -139,6 +140,31 @@ search_bar_activate_callback (CajaSearchBar *bar,
caja_query_set_location (query, current_uri);
g_free (current_uri);
}
+
+ /* Set hidden files visibility based on current window setting */
+ {
+ CajaWindow *window;
+ CajaWindowShowHiddenFilesMode mode;
+ gboolean show_hidden_files = FALSE;
+
+ window = slot->pane->window;
+ mode = caja_window_info_get_hidden_files_mode (CAJA_WINDOW_INFO (window));
+
+ if (mode == CAJA_WINDOW_SHOW_HIDDEN_FILES_ENABLE)
+ {
+ show_hidden_files = TRUE;
+ }
+ else if (mode == CAJA_WINDOW_SHOW_HIDDEN_FILES_DEFAULT)
+ {
+ show_hidden_files = g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_SHOW_HIDDEN_FILES);
+ }
+
+ CajaSearchEngine *engine = caja_search_directory_get_engine (search_directory);
+ if (engine) {
+ caja_search_engine_set_show_hidden_files (engine, show_hidden_files);
+ }
+ }
+
caja_search_directory_set_query (search_directory, query);
g_object_unref (query);
}
diff --git a/src/file-manager/fm-icon-view.c b/src/file-manager/fm-icon-view.c
index 25708184..c17bedf6 100644
--- a/src/file-manager/fm-icon-view.c
+++ b/src/file-manager/fm-icon-view.c
@@ -38,6 +38,7 @@
#include <sys/wait.h>
#include <eel/eel-background.h>
+#include <eel/eel-canvas.h>
#include <eel/eel-glib-extensions.h>
#include <eel/eel-gtk-extensions.h>
#include <eel/eel-gtk-macros.h>
@@ -48,11 +49,14 @@
#include <libcaja-private/caja-clipboard-monitor.h>
#include <libcaja-private/caja-directory-background.h>
#include <libcaja-private/caja-directory.h>
+#include <libcaja-private/caja-search-directory.h>
#include <libcaja-private/caja-dnd.h>
#include <libcaja-private/caja-file-utilities.h>
#include <libcaja-private/caja-ui-utilities.h>
#include <libcaja-private/caja-global-preferences.h>
+#include <libcaja-private/caja-icon-canvas-item.h>
#include <libcaja-private/caja-icon-container.h>
+#include <libcaja-private/caja-icon-private.h>
#include <libcaja-private/caja-icon-dnd.h>
#include <libcaja-private/caja-link.h>
#include <libcaja-private/caja-metadata.h>
@@ -3114,6 +3118,58 @@ focus_in_event_callback (GtkWidget *widget, GdkEventFocus *event, gpointer user_
return FALSE;
}
+static gboolean
+icon_container_query_tooltip_callback (GtkWidget *widget,
+ gint x,
+ gint y,
+ gboolean keyboard_tip,
+ GtkTooltip *tooltip,
+ FMIconView *icon_view)
+{
+ CajaIconContainer *icon_container;
+ EelCanvasItem *item;
+ CajaFile *file;
+ char *location_text;
+
+ /* Only show tooltips in search directories */
+ if (!CAJA_IS_SEARCH_DIRECTORY (fm_directory_view_get_model (FM_DIRECTORY_VIEW (icon_view))))
+ {
+ return FALSE;
+ }
+
+ icon_container = CAJA_ICON_CONTAINER (widget);
+
+ /* Get the canvas item at the cursor position */
+ item = eel_canvas_get_item_at (EEL_CANVAS (icon_container), x, y);
+ if (item == NULL || !CAJA_IS_ICON_CANVAS_ITEM (item))
+ {
+ return FALSE;
+ }
+
+ /* Get the file from the canvas item's user_data */
+ CajaIcon *icon = CAJA_ICON_CANVAS_ITEM (item)->user_data;
+ file = CAJA_FILE (icon->data);
+ if (file == NULL)
+ {
+ return FALSE;
+ }
+
+ /* Get the location attribute */
+ location_text = caja_file_get_string_attribute_with_default (file, "location");
+ if (location_text == NULL || location_text[0] == '\0')
+ {
+ g_free (location_text);
+ return FALSE;
+ }
+
+ /* Set tooltip text with file location */
+ gtk_tooltip_set_text (tooltip, location_text);
+
+ g_free (location_text);
+
+ return TRUE;
+}
+
static CajaIconContainer *
create_icon_container (FMIconView *icon_view)
{
@@ -3122,9 +3178,12 @@ create_icon_container (FMIconView *icon_view)
icon_container = fm_icon_container_new (icon_view);
gtk_widget_set_can_focus (GTK_WIDGET (icon_container), TRUE);
+ gtk_widget_set_has_tooltip (GTK_WIDGET (icon_container), TRUE);
g_signal_connect_object (icon_container, "focus_in_event",
G_CALLBACK (focus_in_event_callback), icon_view, 0);
+ g_signal_connect_object (icon_container, "query-tooltip",
+ G_CALLBACK (icon_container_query_tooltip_callback), icon_view, 0);
g_signal_connect_object (icon_container, "activate",
G_CALLBACK (icon_container_activate_callback), icon_view, 0);
g_signal_connect_object (icon_container, "activate_alternate",
diff --git a/src/file-manager/fm-list-view.c b/src/file-manager/fm-list-view.c
index b5a61459..57b5862c 100644
--- a/src/file-manager/fm-list-view.c
+++ b/src/file-manager/fm-list-view.c
@@ -48,6 +48,7 @@
#include <libcaja-private/caja-column-utilities.h>
#include <libcaja-private/caja-debug-log.h>
#include <libcaja-private/caja-directory-background.h>
+#include <libcaja-private/caja-search-directory.h>
#include <libcaja-private/caja-dnd.h>
#include <libcaja-private/caja-file-dnd.h>
#include <libcaja-private/caja-file-utilities.h>
@@ -1640,6 +1641,70 @@ focus_in_event_callback (GtkWidget *widget, GdkEventFocus *event, gpointer user_
return FALSE;
}
+static gboolean
+tree_view_query_tooltip_callback (GtkWidget *widget,
+ gint x,
+ gint y,
+ gboolean keyboard_tip,
+ GtkTooltip *tooltip,
+ FMListView *list_view)
+{
+ GtkTreeView *tree_view;
+ GtkTreePath *path;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ CajaFile *file;
+ char *location_text;
+
+ /* Only show tooltips in search directories */
+ if (!CAJA_IS_SEARCH_DIRECTORY (fm_directory_view_get_model (FM_DIRECTORY_VIEW (list_view))))
+ {
+ return FALSE;
+ }
+
+ tree_view = GTK_TREE_VIEW (widget);
+
+ /* Get the tree path at the cursor position */
+ if (!gtk_tree_view_get_path_at_pos (tree_view, x, y, &path, NULL, NULL, NULL))
+ {
+ return FALSE;
+ }
+
+ model = gtk_tree_view_get_model (tree_view);
+ if (!gtk_tree_model_get_iter (model, &iter, path))
+ {
+ gtk_tree_path_free (path);
+ return FALSE;
+ }
+
+ /* Get the file from the model */
+ gtk_tree_model_get (model, &iter, FM_LIST_MODEL_FILE_COLUMN, &file, -1);
+ if (file == NULL)
+ {
+ gtk_tree_path_free (path);
+ return FALSE;
+ }
+
+ /* Get the location attribute */
+ location_text = caja_file_get_string_attribute_with_default (file, "location");
+ if (location_text == NULL || location_text[0] == '\0')
+ {
+ g_free (location_text);
+ caja_file_unref (file);
+ gtk_tree_path_free (path);
+ return FALSE;
+ }
+
+ /* Set tooltip text with file location */
+ gtk_tooltip_set_text (tooltip, location_text);
+
+ g_free (location_text);
+ caja_file_unref (file);
+ gtk_tree_path_free (path);
+
+ return TRUE;
+}
+
static gint
get_icon_scale_callback (FMListModel *model,
FMListView *view)
@@ -1664,6 +1729,8 @@ create_and_set_up_tree_view (FMListView *view)
NULL);
gtk_tree_view_set_enable_search (view->details->tree_view, TRUE);
+ gtk_widget_set_has_tooltip (GTK_WIDGET (view->details->tree_view), TRUE);
+
/* Don't handle backspace key. It's used to open the parent folder. */
binding_set = gtk_binding_set_by_class (GTK_WIDGET_GET_CLASS (view->details->tree_view));
gtk_binding_entry_remove (binding_set, GDK_KEY_BackSpace, 0);
@@ -1723,6 +1790,8 @@ create_and_set_up_tree_view (FMListView *view)
g_signal_connect_object (view->details->tree_view, "focus_in_event",
G_CALLBACK(focus_in_event_callback), view, 0);
+ g_signal_connect_object (view->details->tree_view, "query-tooltip",
+ G_CALLBACK (tree_view_query_tooltip_callback), view, 0);
view->details->model = g_object_new (FM_TYPE_LIST_MODEL, NULL);
gtk_tree_view_set_model (view->details->tree_view, GTK_TREE_MODEL (view->details->model));