diff options
author | Federico Mena Quintero <federico@gnome.org> | 2013-03-07 17:20:16 -0600 |
---|---|---|
committer | Federico Mena Quintero <federico@gnome.org> | 2013-03-07 20:45:58 -0600 |
commit | 67f5e595a796a8321d6dc7737c58476564998c07 (patch) | |
tree | 8a4cdb0ca36ccd86a764ff766db54a2db51d7ba2 /gtk/gtkfilechooserbutton.c | |
parent | 1074aa0c49f647ed4b2a969618051c59da5aad01 (diff) | |
download | gtk+-67f5e595a796a8321d6dc7737c58476564998c07.tar.gz |
filechooserbutton: Don't show the (None) item when the combo box is popped up
This is surprisingly tricky, since the (None) item *has* to be a visible item while
the combo box is *not* popped up, so that it can show its contents. But the item
has to be *not* visible when the combo box is popped up.
Also, update the whole button's selection, not just the underlying dialog's, when
the combo box changes its selection - based on a patch by Paul Davis in
https://bugzilla.gnome.org/show_bug.cgi?id=691040#c20
Signed-off-by: Federico Mena Quintero <federico@gnome.org>
Diffstat (limited to 'gtk/gtkfilechooserbutton.c')
-rw-r--r-- | gtk/gtkfilechooserbutton.c | 120 |
1 files changed, 101 insertions, 19 deletions
diff --git a/gtk/gtkfilechooserbutton.c b/gtk/gtkfilechooserbutton.c index 427cdf482f..d61a4d940b 100644 --- a/gtk/gtkfilechooserbutton.c +++ b/gtk/gtkfilechooserbutton.c @@ -326,6 +326,9 @@ static void fs_bookmarks_changed_cb (GtkFileSystem *fs, static void combo_box_changed_cb (GtkComboBox *combo_box, gpointer user_data); +static void combo_box_notify_popup_shown_cb (GObject *object, + GParamSpec *pspec, + gpointer user_data); static void button_clicked_cb (GtkButton *real_button, gpointer user_data); @@ -531,9 +534,12 @@ gtk_file_chooser_button_init (GtkFileChooserButton *button) G_TYPE_POINTER /* CANCELLABLE_COLUMN */)); priv->combo_box = gtk_combo_box_new (); - priv->combo_box_changed_id = - g_signal_connect (priv->combo_box, "changed", - G_CALLBACK (combo_box_changed_cb), button); + priv->combo_box_changed_id = g_signal_connect (priv->combo_box, "changed", + G_CALLBACK (combo_box_changed_cb), button); + + g_signal_connect (priv->combo_box, "notify::popup-shown", + G_CALLBACK (combo_box_notify_popup_shown_cb), button); + gtk_box_pack_start (GTK_BOX (button), priv->combo_box, TRUE, TRUE, 0); gtk_widget_set_halign (priv->combo_box, GTK_ALIGN_FILL); @@ -2341,6 +2347,34 @@ filter_model_visible_func (GtkTreeModel *model, } } break; + case ROW_TYPE_EMPTY_SELECTION: + { + gboolean popup_shown; + + g_object_get (priv->combo_box, + "popup-shown", &popup_shown, + NULL); + + if (popup_shown) + retval = FALSE; + else + { + GFile *selected; + + /* When the combo box is not popped up... */ + + selected = get_selected_file (button); + if (selected) + retval = FALSE; /* ... nonempty selection means the ROW_TYPE_EMPTY_SELECTION is *not* visible... */ + else + retval = TRUE; /* ... and empty selection means the ROW_TYPE_EMPTY_SELECTION *is* visible */ + + if (selected) + g_object_unref (selected); + } + + break; + } default: retval = TRUE; break; @@ -2382,7 +2416,22 @@ combo_box_row_separator_func (GtkTreeModel *model, return (type == ROW_TYPE_BOOKMARK_SEPARATOR || type == ROW_TYPE_CURRENT_FOLDER_SEPARATOR || type == ROW_TYPE_OTHER_SEPARATOR); -} +} + +static void +select_combo_box_row_no_notify (GtkFileChooserButton *button, int pos) +{ + GtkFileChooserButtonPrivate *priv = button->priv; + GtkTreeIter iter, filter_iter; + + gtk_tree_model_iter_nth_child (priv->model, &iter, NULL, pos); + gtk_tree_model_filter_convert_child_iter_to_iter (GTK_TREE_MODEL_FILTER (priv->filter_model), + &filter_iter, &iter); + + g_signal_handler_block (priv->combo_box, priv->combo_box_changed_id); + gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->combo_box), &filter_iter); + g_signal_handler_unblock (priv->combo_box, priv->combo_box_changed_id); +} static void update_combo_box (GtkFileChooserButton *button) @@ -2450,14 +2499,11 @@ update_combo_box (GtkFileChooserButton *button) if (!row_found) { gint pos; - GtkTreeIter filter_iter; /* If it hasn't been found already, update & select the current-folder row. */ if (file) { model_update_current_folder (button, file); - gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter_model)); - pos = model_get_type_position (button, ROW_TYPE_CURRENT_FOLDER); } else @@ -2467,13 +2513,9 @@ update_combo_box (GtkFileChooserButton *button) pos = model_get_type_position (button, ROW_TYPE_EMPTY_SELECTION); } - gtk_tree_model_iter_nth_child (priv->model, &iter, NULL, pos); - gtk_tree_model_filter_convert_child_iter_to_iter (GTK_TREE_MODEL_FILTER (priv->filter_model), - &filter_iter, &iter); + gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter_model)); - g_signal_handler_block (priv->combo_box, priv->combo_box_changed_id); - gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->combo_box), &filter_iter); - g_signal_handler_unblock (priv->combo_box, priv->combo_box_changed_id); + select_combo_box_row_no_notify (button, pos); } if (file) @@ -2761,21 +2803,17 @@ combo_box_changed_cb (GtkComboBox *combo_box, case ROW_TYPE_SHORTCUT: case ROW_TYPE_BOOKMARK: case ROW_TYPE_CURRENT_FOLDER: - gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (priv->dialog)); if (data) - gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (priv->dialog), - data, NULL); + gtk_file_chooser_button_set_current_folder (GTK_FILE_CHOOSER (button), data, NULL); break; case ROW_TYPE_VOLUME: { GFile *base_file; - gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (priv->dialog)); base_file = _gtk_file_system_volume_get_root (data); if (base_file) { - gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (priv->dialog), - base_file, NULL); + gtk_file_chooser_button_set_current_folder (GTK_FILE_CHOOSER (button), base_file, NULL); g_object_unref (base_file); } } @@ -2789,6 +2827,50 @@ combo_box_changed_cb (GtkComboBox *combo_box, } } +/* Calback for the "notify::popup-shown" signal on the combo box. + * When the combo is popped up, we don't want the ROW_TYPE_EMPTY_SELECTION to be visible + * at all; otherwise we would be showing a "(None)" item in the combo box's popup. + * + * However, when the combo box is *not* popped up, we want the empty-selection row + * to be visible depending on the selection. + * + * Since all that is done through the filter_model_visible_func(), this means + * that we need to refilter the model when the combo box pops up - hence the + * present signal handler. + */ +static void +combo_box_notify_popup_shown_cb (GObject *object, + GParamSpec *pspec, + gpointer user_data) +{ + GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (user_data); + GtkFileChooserButtonPrivate *priv = button->priv; + gboolean popup_shown; + + g_object_get (priv->combo_box, + "popup-shown", &popup_shown, + NULL); + + /* Indicate that the ROW_TYPE_EMPTY_SELECTION will change visibility... */ + gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter_model)); + + /* If the combo box popup got dismissed, go back to showing the ROW_TYPE_EMPTY_SELECTION if needed */ + if (!popup_shown) + { + GFile *selected = get_selected_file (button); + + if (!selected) + { + int pos; + + pos = model_get_type_position (button, ROW_TYPE_EMPTY_SELECTION); + select_combo_box_row_no_notify (button, pos); + } + else + g_object_unref (selected); + } +} + /* Button */ static void button_clicked_cb (GtkButton *real_button, |