Started implementing nice interactive search

master
Yevgen Muntyan 2005-08-11 01:24:15 +00:00
parent 94f96dd0d2
commit 5d9e0c3691
1 changed files with 258 additions and 63 deletions

View File

@ -78,6 +78,8 @@ struct _MooFileViewPrivate {
gboolean show_two_dots;
History *history;
char *name_to_select;
char *temp_visible; /* tempporary visible name, for interactive search */
GtkTreeRowReference *temp_visible_row; /* row containing temp_visible (in the store) */
MooEditFileMgr *mgr;
GtkToggleButton *filter_button;
@ -217,7 +219,11 @@ enum {
COLUMN_PIXBUF = 1,
COLUMN_DISPLAY_NAME = 2,
COLUMN_SIZE = 3,
COLUMN_DATE = 4
COLUMN_DATE = 4,
COLUMN_COLOR = 5,
COLUMN_STYLE = 6,
COLUMN_STYLE_SET = 7,
NUM_COLUMNS
};
enum {
@ -421,12 +427,16 @@ static void moo_file_view_init (MooFileView *fileview)
history_init (fileview);
fileview->priv->store =
gtk_list_store_new (5,
MOO_TYPE_FILE,
GDK_TYPE_PIXBUF,
G_TYPE_STRING,
G_TYPE_STRING,
G_TYPE_STRING);
gtk_list_store_new (NUM_COLUMNS,
MOO_TYPE_FILE, /* COLUMN_FILE */
GDK_TYPE_PIXBUF, /* COLUMN_PIXBUF */
G_TYPE_STRING, /* COLUMN_DISPLAY_NAME */
G_TYPE_STRING, /* COLUMN_SIZE */
G_TYPE_STRING, /* COLUMN_DATE */
G_TYPE_STRING, /* COLUMN_COLOR */
PANGO_TYPE_STYLE, /* COLUMN_STYLE */
G_TYPE_BOOLEAN); /* COLUMN_STYLE_SET */
gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (fileview->priv->store),
COLUMN_FILE,
(GtkTreeIterCompareFunc) tree_compare_func,
@ -470,6 +480,9 @@ static void moo_file_view_finalize (GObject *object)
if (fileview->priv->current_filter)
g_object_unref (fileview->priv->current_filter);
g_free (fileview->priv->temp_visible);
gtk_tree_row_reference_free (fileview->priv->temp_visible_row);
disconnect_folder (fileview);
g_object_unref (fileview->priv->file_system);
@ -772,6 +785,16 @@ static void add_one_file (MooFileView *fileview,
moo_file_get_display_basename (file),
COLUMN_SIZE, NULL,
COLUMN_DATE, NULL, -1);
if (fileview->priv->name_to_select &&
!strcmp (fileview->priv->name_to_select,
moo_file_get_display_basename (file)))
{
g_free (fileview->priv->name_to_select);
fileview->priv->name_to_select = NULL;
moo_file_view_select_file (fileview,
moo_file_get_display_basename (file));
}
}
@ -1319,6 +1342,8 @@ static GtkWidget *create_treeview (MooFileView *fileview)
gtk_tree_view_column_pack_start (column, cell, TRUE);
gtk_tree_view_column_set_attributes (column, cell,
"text", COLUMN_DISPLAY_NAME,
"style", COLUMN_STYLE,
"style-set", COLUMN_STYLE_SET,
NULL);
#if 1
@ -1330,6 +1355,8 @@ static GtkWidget *create_treeview (MooFileView *fileview)
gtk_tree_view_column_pack_start (column, cell, FALSE);
gtk_tree_view_column_set_attributes (column, cell,
"text", COLUMN_SIZE,
"style", COLUMN_STYLE,
"style-set", COLUMN_STYLE_SET,
NULL);
column = gtk_tree_view_column_new ();
@ -1340,6 +1367,8 @@ static GtkWidget *create_treeview (MooFileView *fileview)
gtk_tree_view_column_pack_start (column, cell, FALSE);
gtk_tree_view_column_set_attributes (column, cell,
"text", COLUMN_DATE,
"style", COLUMN_STYLE,
"style-set", COLUMN_STYLE_SET,
NULL);
#endif
@ -1347,6 +1376,42 @@ static GtkWidget *create_treeview (MooFileView *fileview)
}
static GtkWidget *create_iconview (MooFileView *fileview)
{
GtkWidget *iconview;
GtkCellRenderer *cell;
iconview = moo_icon_view_new_with_model (fileview->priv->filter_model);
g_signal_connect (iconview, "key-press-event",
G_CALLBACK (moo_file_view_key_press),
fileview);
moo_icon_view_set_attributes (MOO_ICON_VIEW (iconview),
MOO_ICON_VIEW_CELL_PIXBUF,
"pixbuf", COLUMN_PIXBUF,
NULL);
moo_icon_view_set_attributes (MOO_ICON_VIEW (iconview),
MOO_ICON_VIEW_CELL_TEXT,
"text", COLUMN_DISPLAY_NAME,
"style", COLUMN_STYLE,
"style-set", COLUMN_STYLE_SET,
NULL);
cell = moo_icon_view_get_cell (MOO_ICON_VIEW (iconview),
MOO_ICON_VIEW_CELL_TEXT);
g_object_set (cell, "xalign", 0.0, NULL);
cell = moo_icon_view_get_cell (MOO_ICON_VIEW (iconview),
MOO_ICON_VIEW_CELL_PIXBUF);
g_object_set (cell, "xpad", 1, "ypad", 1, NULL);
g_signal_connect (iconview, "item-activated",
G_CALLBACK (icon_item_activated), fileview);
g_signal_connect (iconview, "button-press-event",
G_CALLBACK (icon_button_press), fileview);
return iconview;
}
static gboolean filter_visible_func (GtkTreeModel *model,
GtkTreeIter *iter,
MooFileView *fileview)
@ -1369,6 +1434,23 @@ static gboolean filter_visible_func (GtkTreeModel *model,
goto out;
}
if (fileview->priv->temp_visible &&
!strcmp (moo_file_get_basename (file), fileview->priv->temp_visible))
{
#if 1
GtkTreePath *tmp = NULL, *tmp2 = NULL;
g_assert (fileview->priv->temp_visible_row != NULL);
g_assert (gtk_tree_row_reference_valid (fileview->priv->temp_visible_row));
tmp = gtk_tree_row_reference_get_path (fileview->priv->temp_visible_row);
tmp2 = gtk_tree_model_get_path (model, iter);
g_assert (!gtk_tree_path_compare (tmp, tmp2));
gtk_tree_path_free (tmp);
gtk_tree_path_free (tmp2);
#endif
visible = TRUE;
goto out;
}
if (!fileview->priv->show_hidden_files && moo_file_test (file, MOO_FILE_IS_HIDDEN))
{
visible = FALSE;
@ -1752,40 +1834,6 @@ static void history_goto (MooFileView *fileview,
}
static GtkWidget *create_iconview (MooFileView *fileview)
{
GtkWidget *iconview;
GtkCellRenderer *cell;
iconview = moo_icon_view_new_with_model (fileview->priv->filter_model);
g_signal_connect (iconview, "key-press-event",
G_CALLBACK (moo_file_view_key_press),
fileview);
moo_icon_view_set_attributes (MOO_ICON_VIEW (iconview),
MOO_ICON_VIEW_CELL_PIXBUF,
"pixbuf", COLUMN_PIXBUF,
NULL);
moo_icon_view_set_attributes (MOO_ICON_VIEW (iconview),
MOO_ICON_VIEW_CELL_TEXT,
"text", COLUMN_DISPLAY_NAME,
NULL);
cell = moo_icon_view_get_cell (MOO_ICON_VIEW (iconview),
MOO_ICON_VIEW_CELL_TEXT);
g_object_set (cell, "xalign", 0.0, NULL);
cell = moo_icon_view_get_cell (MOO_ICON_VIEW (iconview),
MOO_ICON_VIEW_CELL_PIXBUF);
g_object_set (cell, "xpad", 1, "ypad", 1, NULL);
g_signal_connect (iconview, "item-activated",
G_CALLBACK (icon_item_activated), fileview);
g_signal_connect (iconview, "button-press-event",
G_CALLBACK (icon_button_press), fileview);
return iconview;
}
static void moo_file_view_set_property (GObject *object,
guint prop_id,
const GValue *value,
@ -1999,7 +2047,7 @@ static void fileview_set_filter (MooFileView *fileview,
if (filter && (gtk_file_filter_get_needed (filter) & GTK_FILE_FILTER_URI))
{
g_warning ("%s: The filter set wants uri, but i do not know "
"how to work with uri's. Ignoring");
"how to work with uri's. Ignoring", G_STRLOC);
return;
}
@ -2511,6 +2559,28 @@ static gboolean find_match (MooFileView *fileview,
/* Search entry
*/
static void set_temp_visible_attributes (MooFileView *fileview,
GtkTreePath *path,
gboolean set)
{
GtkTreeIter iter;
g_assert (path != NULL);
g_print ("%s\n", set ? "SET" : "UNSET");
gtk_tree_model_get_iter (GTK_TREE_MODEL (fileview->priv->store),
&iter, path);
if (set)
gtk_list_store_set (fileview->priv->store, &iter,
COLUMN_STYLE, PANGO_STYLE_ITALIC,
COLUMN_STYLE_SET, TRUE,
-1);
else
gtk_list_store_set (fileview->priv->store, &iter,
COLUMN_STYLE, PANGO_STYLE_NORMAL,
COLUMN_STYLE_SET, FALSE,
-1);
}
static gboolean search_entry_key_press (GtkWidget *entry,
GdkEventKey *event,
MooFileView *fileview);
@ -2535,9 +2605,9 @@ static void start_interactive_search (MooFileView *fileview)
g_signal_connect (entry, "key-press-event",
G_CALLBACK (search_entry_key_press),
fileview);
g_signal_connect (entry, "focus-out-event",
G_CALLBACK (search_entry_focus_out),
fileview);
g_signal_connect_after (entry, "focus-out-event",
G_CALLBACK (search_entry_focus_out),
fileview);
g_signal_connect (entry, "activate",
G_CALLBACK (search_entry_activate),
fileview);
@ -2547,7 +2617,8 @@ static void start_interactive_search (MooFileView *fileview)
}
static void stop_interactive_search (MooFileView *fileview)
static void stop_interactive_search (MooFileView *fileview,
gboolean focus_to_file_view)
{
GtkWidget *entry = GTK_WIDGET (fileview->priv->search_entry);
@ -2567,10 +2638,37 @@ static void stop_interactive_search (MooFileView *fileview)
fileview);
gtk_widget_hide (entry);
gtk_entry_set_text (GTK_ENTRY (entry), "");
gtk_widget_grab_focus (get_file_view_widget (fileview));
/* TODO: may it become invalid? */
if (fileview->priv->temp_visible_row &&
gtk_tree_row_reference_valid (fileview->priv->temp_visible_row))
{
GtkTreePath *temp_path =
gtk_tree_row_reference_get_path (fileview->priv->temp_visible_row);
g_assert (temp_path != NULL);
set_temp_visible_attributes (fileview, temp_path, FALSE);
}
if (fileview->priv->temp_visible_row)
{
g_assert (gtk_tree_row_reference_valid (fileview->priv->temp_visible_row));
gtk_tree_row_reference_free (fileview->priv->temp_visible_row);
fileview->priv->temp_visible_row = NULL;
g_free (fileview->priv->temp_visible);
fileview->priv->temp_visible = NULL;
gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER
(fileview->priv->filter_model));
}
else
{
g_assert (fileview->priv->temp_visible == NULL);
}
if (focus_to_file_view)
gtk_widget_grab_focus (get_file_view_widget (fileview));
}
@ -2591,7 +2689,7 @@ static gboolean moo_file_view_key_press (GtkWidget *widget,
if (fileview->priv->in_search)
{
g_warning ("%s: something wrong", G_STRLOC);
stop_interactive_search (fileview);
stop_interactive_search (fileview, FALSE);
return FALSE;
}
@ -2629,7 +2727,7 @@ static gboolean search_entry_key_press (G_GNUC_UNUSED GtkWidget *entry,
switch (event->keyval)
{
case GDK_Escape:
stop_interactive_search (fileview);
stop_interactive_search (fileview, TRUE);
return TRUE;
default:
@ -2638,11 +2736,12 @@ static gboolean search_entry_key_press (G_GNUC_UNUSED GtkWidget *entry,
}
static gboolean search_entry_focus_out (G_GNUC_UNUSED GtkWidget *entry,
static gboolean search_entry_focus_out (GtkWidget *entry,
G_GNUC_UNUSED GdkEventFocus *event,
MooFileView *fileview)
{
stop_interactive_search (fileview);
/* focus may be lost due to switching to other window, focus file list then */
stop_interactive_search (fileview, gtk_widget_is_focus (entry));
return FALSE;
}
@ -2650,19 +2749,73 @@ static gboolean search_entry_focus_out (G_GNUC_UNUSED GtkWidget *entry,
static void search_entry_activate (GtkWidget *entry,
MooFileView *fileview)
{
stop_interactive_search (fileview);
stop_interactive_search (fileview, TRUE);
activate_file_widget (fileview);
}
static void process_entry_text (MooFileView *fileview,
GtkEntry *entry,
const char *text);
static void search_entry_changed (GtkEntry *entry,
MooFileView *fileview)
{
const char *text = gtk_entry_get_text (entry);
g_return_if_fail (text != NULL);
process_entry_text (fileview, entry, text);
}
static void process_entry_text (MooFileView *fileview,
GtkEntry *entry,
const char *text)
{
GtkTreeIter iter, filter_iter;
const char *text;
GtkEntryCompletion *completion;
GtkListStore *completion_store;
gboolean need_to_refilter = FALSE;
gboolean need_to_clear_completion = TRUE;
text = gtk_entry_get_text (entry);
g_return_if_fail (text != NULL);
if (!strncmp (text, "./", 2))
return process_entry_text (fileview, entry, text + 2);
completion = gtk_entry_get_completion (entry);
g_assert (completion != NULL);
completion_store = GTK_LIST_STORE (gtk_entry_completion_get_model (completion));
g_assert (completion_store != NULL);
/* Check if some file was shown temporarily, and hide it */
if (fileview->priv->temp_visible)
{
/* if still the same filename is entered, don't do anything */
if (!strcmp (text, fileview->priv->temp_visible))
goto out;
if (fileview->priv->temp_visible_row &&
gtk_tree_row_reference_valid (fileview->priv->temp_visible_row))
{
GtkTreePath *temp_path =
gtk_tree_row_reference_get_path (fileview->priv->temp_visible_row);
g_assert (temp_path != NULL);
set_temp_visible_attributes (fileview, temp_path, FALSE);
}
gtk_tree_row_reference_free (fileview->priv->temp_visible_row);
fileview->priv->temp_visible_row = NULL;
g_free (fileview->priv->temp_visible);
fileview->priv->temp_visible = NULL;
need_to_refilter = TRUE;
}
if (!text[0])
{
file_widget_move_selection (fileview, NULL);
goto out;
}
/* first, try if this is a file in the list */
if (find_match (fileview, text, &iter, FALSE))
{
GtkTreePath *filter_path, *path;
@ -2673,24 +2826,66 @@ static void search_entry_changed (GtkEntry *entry,
filter_path = gtk_tree_model_filter_convert_child_path_to_path (
GTK_TREE_MODEL_FILTER (fileview->priv->filter_model), path);
/* file is not currently visible, check if full name was typed in,
and show the file if it's the case */
if (!filter_path)
{
gtk_tree_path_free (path);
file_widget_move_selection (fileview, NULL);
MooFile *file = NULL;
gtk_tree_model_get (GTK_TREE_MODEL (fileview->priv->store),
&iter, COLUMN_FILE, &file, -1);
if (file && !strcmp (moo_file_get_display_basename (file), text))
{
/* full name of hidden file was typed in, show it */
fileview->priv->temp_visible =
g_strdup (moo_file_get_display_basename (file));
fileview->priv->temp_visible_row =
gtk_tree_row_reference_new (GTK_TREE_MODEL (fileview->priv->store), path);
gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER
(fileview->priv->filter_model));
need_to_refilter = FALSE;
set_temp_visible_attributes (fileview, path, TRUE);
filter_path = gtk_tree_model_filter_convert_child_path_to_path (
GTK_TREE_MODEL_FILTER (fileview->priv->filter_model), path);
g_assert (filter_path != NULL);
gtk_tree_model_get_iter (fileview->priv->filter_model,
&filter_iter, filter_path);
file_widget_move_selection (fileview, &filter_iter);
}
else
{
/* only some part of name of hidden file was typed in,
deselect currently selected file */
file_widget_move_selection (fileview, NULL);
}
moo_file_unref (file);
}
/* file is visible,just move cursor there */
else
{
gtk_tree_model_get_iter (fileview->priv->filter_model,
&filter_iter, filter_path);
file_widget_move_selection (fileview, &filter_iter);
gtk_tree_path_free (path);
gtk_tree_path_free (filter_path);
}
gtk_tree_path_free (path);
gtk_tree_path_free (filter_path);
goto out;
}
else
{
file_widget_move_selection (fileview, NULL);
}
/* typed text is not a filename in the list, try completion */
file_widget_move_selection (fileview, NULL);
out:
if (need_to_refilter)
gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER
(fileview->priv->filter_model));
if (need_to_clear_completion)
gtk_list_store_clear (completion_store);
}