filechooserentry: Remove completion feedback

Too much special code for no gain.

I did a totally unscientific questionnaire on GNOME IRC (assuming
autocompletion is for advanced users) and nobody even knew what this is.
So I suspect it's useless. Also, it's positioned completely wrong anyway
and nobody noticed so far. Last but not least, I'm trying to imitate
bash here and bash doesn't show feedback.
This commit is contained in:
Benjamin Otte 2011-11-07 02:30:06 +01:00
parent 93263dcd33
commit f7e5a773ff

View File

@ -76,10 +76,6 @@ struct _GtkFileChooserEntry
GtkTreeModel *completion_store;
GtkWidget *completion_feedback_window;
GtkWidget *completion_feedback_label;
guint completion_feedback_timeout_id;
guint current_folder_loaded : 1;
guint in_change : 1;
guint eat_tabs : 1;
@ -94,12 +90,9 @@ enum
N_COLUMNS
};
#define COMPLETION_FEEDBACK_TIMEOUT_MS 2000
static void gtk_file_chooser_entry_finalize (GObject *object);
static void gtk_file_chooser_entry_dispose (GObject *object);
static void gtk_file_chooser_entry_grab_focus (GtkWidget *widget);
static void gtk_file_chooser_entry_unmap (GtkWidget *widget);
static gboolean gtk_file_chooser_entry_key_press_event (GtkWidget *widget,
GdkEventKey *event);
static gboolean gtk_file_chooser_entry_focus_out_event (GtkWidget *widget,
@ -132,9 +125,6 @@ static RefreshStatus refresh_current_folder_and_file_part (GtkFileChooserEntry *
static void finished_loading_cb (GtkFileSystemModel *model,
GError *error,
GtkFileChooserEntry *chooser_entry);
static void remove_completion_feedback (GtkFileChooserEntry *chooser_entry);
static void pop_up_completion_feedback (GtkFileChooserEntry *chooser_entry,
const gchar *feedback);
G_DEFINE_TYPE (GtkFileChooserEntry, _gtk_file_chooser_entry, GTK_TYPE_ENTRY)
@ -166,7 +156,6 @@ gtk_file_chooser_entry_dispatch_properties_changed (GObject *object,
chooser_entry->load_complete_action = LOAD_COMPLETE_NOTHING;
remove_completion_feedback (chooser_entry);
gtk_editable_get_selection_bounds (editable, &start, &end);
text = gtk_editable_get_chars (editable, 0, MIN (start, end));
refresh_current_folder_and_file_part (chooser_entry, text);
@ -189,7 +178,6 @@ _gtk_file_chooser_entry_class_init (GtkFileChooserEntryClass *class)
gobject_class->dispatch_properties_changed = gtk_file_chooser_entry_dispatch_properties_changed;
widget_class->grab_focus = gtk_file_chooser_entry_grab_focus;
widget_class->unmap = gtk_file_chooser_entry_unmap;
widget_class->key_press_event = gtk_file_chooser_entry_key_press_event;
widget_class->focus_out_event = gtk_file_chooser_entry_focus_out_event;
@ -269,7 +257,6 @@ gtk_file_chooser_entry_dispose (GObject *object)
{
GtkFileChooserEntry *chooser_entry = GTK_FILE_CHOOSER_ENTRY (object);
remove_completion_feedback (chooser_entry);
discard_loading_and_current_folder_file (chooser_entry);
if (chooser_entry->completion_store)
@ -385,8 +372,6 @@ static void
clear_completions (GtkFileChooserEntry *chooser_entry)
{
chooser_entry->load_complete_action = LOAD_COMPLETE_NOTHING;
remove_completion_feedback (chooser_entry);
}
static void
@ -756,211 +741,6 @@ gtk_file_chooser_entry_grab_focus (GtkWidget *widget)
_gtk_file_chooser_entry_select_filename (GTK_FILE_CHOOSER_ENTRY (widget));
}
static void
gtk_file_chooser_entry_unmap (GtkWidget *widget)
{
GtkFileChooserEntry *chooser_entry = GTK_FILE_CHOOSER_ENTRY (widget);
remove_completion_feedback (chooser_entry);
GTK_WIDGET_CLASS (_gtk_file_chooser_entry_parent_class)->unmap (widget);
}
static gboolean
completion_feedback_window_draw_cb (GtkWidget *widget,
cairo_t *cr,
gpointer data)
{
/* Stolen from gtk_tooltip_paint_window() */
GtkFileChooserEntry *chooser_entry = GTK_FILE_CHOOSER_ENTRY (data);
GtkStyleContext *context;
context = gtk_widget_get_style_context (chooser_entry->completion_feedback_window);
gtk_render_background (context, cr, 0, 0,
gtk_widget_get_allocated_width (widget),
gtk_widget_get_allocated_height (widget));
gtk_render_frame (context, cr, 0, 0,
gtk_widget_get_allocated_width (widget),
gtk_widget_get_allocated_height (widget));
return FALSE;
}
static void
set_invisible_mouse_cursor (GdkWindow *window)
{
GdkDisplay *display;
GdkCursor *cursor;
display = gdk_window_get_display (window);
cursor = gdk_cursor_new_for_display (display, GDK_BLANK_CURSOR);
gdk_window_set_cursor (window, cursor);
g_object_unref (cursor);
}
static void
completion_feedback_window_realize_cb (GtkWidget *widget,
gpointer data)
{
/* We hide the mouse cursor inside the completion feedback window, since
* GtkEntry hides the cursor when the user types. We don't want the cursor to
* come back if the completion feedback ends up where the mouse is.
*/
set_invisible_mouse_cursor (gtk_widget_get_window (widget));
}
static void
create_completion_feedback_window (GtkFileChooserEntry *chooser_entry)
{
/* Stolen from gtk_tooltip_init() */
GtkWidget *window, *label;
GtkStyleContext *context;
window = gtk_window_new (GTK_WINDOW_POPUP);
gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_TOOLTIP);
gtk_widget_set_app_paintable (window, TRUE);
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
gtk_widget_set_name (window, "gtk-tooltip");
context = gtk_widget_get_style_context (window);
gtk_style_context_add_class (context, GTK_STYLE_CLASS_TOOLTIP);
g_signal_connect (window, "draw",
G_CALLBACK (completion_feedback_window_draw_cb), chooser_entry);
g_signal_connect (window, "realize",
G_CALLBACK (completion_feedback_window_realize_cb), chooser_entry);
/* FIXME: connect to motion-notify-event, and *show* the cursor when the mouse moves */
label = gtk_label_new (NULL);
gtk_widget_set_halign (label, GTK_ALIGN_CENTER);
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
/* FIXME: don't hardcode this */
gtk_widget_set_margin_left (label, 6);
gtk_widget_set_margin_right (label, 6);
gtk_widget_set_margin_top (label, 6);
gtk_widget_set_margin_bottom (label, 6);
gtk_container_add (GTK_CONTAINER (window), label);
gtk_widget_show (label);
chooser_entry->completion_feedback_window = window;
chooser_entry->completion_feedback_label = label;
}
static gboolean
completion_feedback_timeout_cb (gpointer data)
{
GtkFileChooserEntry *chooser_entry = GTK_FILE_CHOOSER_ENTRY (data);
chooser_entry->completion_feedback_timeout_id = 0;
remove_completion_feedback (chooser_entry);
return FALSE;
}
static void
install_completion_feedback_timer (GtkFileChooserEntry *chooser_entry)
{
if (chooser_entry->completion_feedback_timeout_id != 0)
g_source_remove (chooser_entry->completion_feedback_timeout_id);
chooser_entry->completion_feedback_timeout_id = gdk_threads_add_timeout (COMPLETION_FEEDBACK_TIMEOUT_MS,
completion_feedback_timeout_cb,
chooser_entry);
}
/* Gets the x position of the text cursor in the entry, in widget coordinates */
static void
get_entry_cursor_x (GtkFileChooserEntry *chooser_entry,
gint *x_ret)
{
/* FIXME: see the docs for gtk_entry_get_layout_offsets(). As an exercise for
* the reader, you have to implement support for the entry's scroll offset and
* RTL layouts and all the fancy Pango stuff.
*/
PangoLayout *layout;
gint layout_x, layout_y;
gint layout_index;
PangoRectangle strong_pos;
gint start_pos, end_pos;
layout = gtk_entry_get_layout (GTK_ENTRY (chooser_entry));
gtk_entry_get_layout_offsets (GTK_ENTRY (chooser_entry), &layout_x, &layout_y);
gtk_editable_get_selection_bounds (GTK_EDITABLE (chooser_entry), &start_pos, &end_pos);
layout_index = gtk_entry_text_index_to_layout_index (GTK_ENTRY (chooser_entry),
end_pos);
pango_layout_get_cursor_pos (layout, layout_index, &strong_pos, NULL);
*x_ret = layout_x + strong_pos.x / PANGO_SCALE;
}
static void
show_completion_feedback_window (GtkFileChooserEntry *chooser_entry)
{
/* More or less stolen from gtk_tooltip_position() */
GtkRequisition feedback_req;
GtkWidget *widget = GTK_WIDGET (chooser_entry);
gint entry_x, entry_y;
gint cursor_x;
GtkAllocation entry_allocation;
int feedback_x, feedback_y;
gtk_widget_get_preferred_size (chooser_entry->completion_feedback_window,
&feedback_req, NULL);
gdk_window_get_origin (gtk_widget_get_window (widget), &entry_x, &entry_y);
gtk_widget_get_allocation (widget, &entry_allocation);
get_entry_cursor_x (chooser_entry, &cursor_x);
/* FIXME: fit to the screen if we bump on the screen's edge */
/* cheap "half M-width", use height as approximation of character em-size */
feedback_x = entry_x + cursor_x + entry_allocation.height / 2;
feedback_y = entry_y + (entry_allocation.height - feedback_req.height) / 2;
gtk_window_move (GTK_WINDOW (chooser_entry->completion_feedback_window), feedback_x, feedback_y);
gtk_widget_show (chooser_entry->completion_feedback_window);
install_completion_feedback_timer (chooser_entry);
}
static void
pop_up_completion_feedback (GtkFileChooserEntry *chooser_entry,
const gchar *feedback)
{
if (chooser_entry->completion_feedback_window == NULL)
create_completion_feedback_window (chooser_entry);
gtk_label_set_text (GTK_LABEL (chooser_entry->completion_feedback_label), feedback);
show_completion_feedback_window (chooser_entry);
}
static void
remove_completion_feedback (GtkFileChooserEntry *chooser_entry)
{
if (chooser_entry->completion_feedback_window)
gtk_widget_destroy (chooser_entry->completion_feedback_window);
chooser_entry->completion_feedback_window = NULL;
chooser_entry->completion_feedback_label = NULL;
if (chooser_entry->completion_feedback_timeout_id != 0)
{
g_source_remove (chooser_entry->completion_feedback_timeout_id);
chooser_entry->completion_feedback_timeout_id = 0;
}
}
static void
explicitly_complete (GtkFileChooserEntry *chooser_entry)
{
@ -985,10 +765,6 @@ explicitly_complete (GtkFileChooserEntry *chooser_entry)
case NO_MATCH:
beep (chooser_entry);
/* translators: this text is shown when there are no completions
* for something the user typed in a file chooser entry
*/
pop_up_completion_feedback (chooser_entry, _("No match"));
break;
case NOTHING_INSERTED_COMPLETE:
@ -996,10 +772,6 @@ explicitly_complete (GtkFileChooserEntry *chooser_entry)
break;
case NOTHING_INSERTED_UNIQUE:
/* translators: this text is shown when there is exactly one completion
* for something the user typed in a file chooser entry
*/
pop_up_completion_feedback (chooser_entry, _("Sole completion"));
break;
case COMPLETED:
@ -1011,11 +783,6 @@ explicitly_complete (GtkFileChooserEntry *chooser_entry)
break;
case COMPLETE_BUT_NOT_UNIQUE:
/* translators: this text is shown when the text in a file chooser
* entry is a complete filename, but could be continued to find
* a longer match
*/
pop_up_completion_feedback (chooser_entry, _("Complete, but not unique"));
break;
default:
@ -1028,7 +795,7 @@ start_explicit_completion (GtkFileChooserEntry *chooser_entry)
{
RefreshStatus status;
gboolean is_error;
char *feedback_msg, *text;
char *text;
text = gtk_editable_get_chars (GTK_EDITABLE (chooser_entry),
0, gtk_editable_get_position (GTK_EDITABLE (chooser_entry)));
@ -1047,57 +814,24 @@ start_explicit_completion (GtkFileChooserEntry *chooser_entry)
else
{
chooser_entry->load_complete_action = LOAD_COMPLETE_EXPLICIT_COMPLETION;
/* Translators: this text is shown while the system is searching
* for possible completions for filenames in a file chooser entry. */
pop_up_completion_feedback (chooser_entry, _("Completing..."));
}
break;
case REFRESH_INVALID_INPUT:
is_error = TRUE;
/* Translators: this is shown in the feedback for Tab-completion in a file
* chooser's text entry, when the user enters an invalid path. */
feedback_msg = _("Invalid path");
break;
case REFRESH_INCOMPLETE_HOSTNAME:
is_error = TRUE;
if (chooser_entry->local_only)
{
/* hostnames in a local_only file chooser? user error */
/* Translators: this is shown in the feedback for Tab-completion in a
* file chooser's text entry when the user enters something like
* "sftp://blahblah" in an app that only supports local filenames. */
feedback_msg = _("Only local files may be selected");
}
else
{
/* Another option is to complete the hostname based on the remote volumes that are mounted */
/* Translators: this is shown in the feedback for Tab-completion in a
* file chooser's text entry when the user hasn't entered the first '/'
* after a hostname and yet hits Tab (such as "sftp://blahblah[Tab]") */
feedback_msg = _("Incomplete hostname; end it with '/'");
}
break;
case REFRESH_NONEXISTENT:
is_error = TRUE;
/* Translators: this is shown in the feedback for Tab-completion in a file
* chooser's text entry when the user enters a path that does not exist
* and then hits Tab */
feedback_msg = _("Path does not exist");
break;
case REFRESH_NOT_LOCAL:
is_error = TRUE;
feedback_msg = _("Only local files may be selected");
break;
default:
@ -1110,7 +844,6 @@ start_explicit_completion (GtkFileChooserEntry *chooser_entry)
g_assert (chooser_entry->current_folder_file == NULL);
beep (chooser_entry);
pop_up_completion_feedback (chooser_entry, feedback_msg);
chooser_entry->load_complete_action = LOAD_COMPLETE_NOTHING;
}
}
@ -1306,7 +1039,6 @@ finished_loading_cb (GtkFileSystemModel *model,
/* Since this came from explicit user action (Tab completion), we'll present errors visually */
beep (chooser_entry);
pop_up_completion_feedback (chooser_entry, error->message);
}
return;