From 9a11f29b8751341fb2965e4efd5586b6e8d9af92 Mon Sep 17 00:00:00 2001 From: Teemu Ikonen Date: Fri, 10 Nov 2023 17:43:41 +0200 Subject: [PATCH] Port file chooser to phones By Adrien Plazas --- gtk/gtkfilechooserdialog.c | 2 +- gtk/gtkfilechooserwidget.c | 165 +++++++++++++++++++++++++++------ gtk/gtkplacesview.c | 24 +++++ gtk/ui/gtkfilechooserwidget.ui | 87 ++++++++++++----- gtk/ui/gtkplacesview.ui | 3 +- 5 files changed, 226 insertions(+), 55 deletions(-) diff --git a/gtk/gtkfilechooserdialog.c b/gtk/gtkfilechooserdialog.c index db1d8f6de7..cf4229afa3 100644 --- a/gtk/gtkfilechooserdialog.c +++ b/gtk/gtkfilechooserdialog.c @@ -532,7 +532,7 @@ setup_save_entry (GtkFileChooserDialog *dialog) need_entry = action == GTK_FILE_CHOOSER_ACTION_SAVE || action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER; - if (need_entry && !dialog->priv->has_entry) + if (need_entry && !dialog->priv->has_entry && FALSE) { GtkWidget *box; GtkWidget *label; diff --git a/gtk/gtkfilechooserwidget.c b/gtk/gtkfilechooserwidget.c index 0496fd2f35..32a32aac62 100644 --- a/gtk/gtkfilechooserwidget.c +++ b/gtk/gtkfilechooserwidget.c @@ -31,6 +31,7 @@ #include "gtkcheckmenuitem.h" #include "gtkclipboard.h" #include "gtkcomboboxtext.h" +#include "gtkcssprovider.h" #include "gtkdragsource.h" #include "gtkdragdest.h" #include "gtkentry.h" @@ -80,6 +81,8 @@ #include "gtkseparator.h" #include "gtkmodelbutton.h" #include "gtkgesturelongpress.h" +#include "hdy-clamp-private.h" +#include "hdy-flap-private.h" #include @@ -225,7 +228,8 @@ struct _GtkFileChooserWidgetPrivate { GtkWidget *save_widgets_table; /* The file browsing widgets */ - GtkWidget *browse_widgets_hpaned; + GtkWidget *flap; + GtkWidget *browse_box; GtkWidget *browse_header_revealer; GtkWidget *browse_header_stack; GtkWidget *browse_files_stack; @@ -379,6 +383,7 @@ struct _GtkFileChooserWidgetPrivate { guint create_folders : 1; guint auto_selecting_first_row : 1; guint browse_files_interaction_frozen : 1; + guint location_visible : 1; }; #define MAX_LOADING_TIME 500 @@ -426,6 +431,7 @@ enum { MODEL_COL_TIME_TEXT, MODEL_COL_LOCATION_TEXT, MODEL_COL_ELLIPSIZE, + MODEL_COL_DISPLAY, MODEL_COL_NUM_COLUMNS }; @@ -445,7 +451,8 @@ enum { G_TYPE_STRING, /* MODEL_COL_DATE_TEXT */ \ G_TYPE_STRING, /* MODEL_COL_TIME_TEXT */ \ G_TYPE_STRING, /* MODEL_COL_LOCATION_TEXT */ \ - PANGO_TYPE_ELLIPSIZE_MODE /* MODEL_COL_ELLIPSIZE */ + PANGO_TYPE_ELLIPSIZE_MODE, /* MODEL_COL_ELLIPSIZE */ \ + G_TYPE_STRING /* MODEL_COL_DISPLAY */ #define DEFAULT_RECENT_FILES_LIMIT 50 @@ -1289,6 +1296,9 @@ places_sidebar_open_location_cb (GtkPlacesSidebar *sidebar, operation_mode_set (impl, OPERATION_MODE_RECENT); else change_folder_and_display_error (impl, location, clear_entry); + + if (gtk_hdy_flap_get_folded (GTK_HDY_FLAP (priv->flap))) + gtk_hdy_flap_set_reveal_flap (GTK_HDY_FLAP (priv->flap), FALSE); } /* Callback used when the places sidebar needs us to display an error message */ @@ -1846,6 +1856,24 @@ open_folder_cb (GSimpleAction *action, } G_GNUC_END_IGNORE_DEPRECATIONS +static void +update_show_columns (GtkFileChooserWidget *impl) +{ + GtkFileChooserWidgetPrivate *priv = impl->priv; + gboolean folded = gtk_hdy_flap_get_folded (GTK_HDY_FLAP (priv->flap)); + + gtk_tree_view_column_set_visible (priv->list_size_column, + priv->show_size_column && !folded); + gtk_tree_view_column_set_visible (priv->list_type_column, + priv->show_type_column && !folded); + gtk_tree_view_column_set_visible (priv->list_time_column, !folded); + g_object_set (priv->list_time_renderer, + "visible", priv->show_time && !folded, + NULL); + + clear_model_cache (impl, MODEL_COL_DISPLAY); +} + /* callback used when the "Show Hidden Files" menu item is toggled */ static void change_show_hidden_state (GSimpleAction *action, @@ -1870,8 +1898,7 @@ change_show_size_state (GSimpleAction *action, g_simple_action_set_state (action, state); priv->show_size_column = g_variant_get_boolean (state); - gtk_tree_view_column_set_visible (priv->list_size_column, - priv->show_size_column); + update_show_columns (impl); } /* Callback used when the "Show Type Column" menu item is toggled */ @@ -1886,8 +1913,8 @@ change_show_type_state (GSimpleAction *action, g_simple_action_set_state (action, state); priv->show_type_column = g_variant_get_boolean (state); - gtk_tree_view_column_set_visible (priv->list_type_column, - priv->show_type_column); + update_show_columns (impl); + } static void @@ -1952,11 +1979,9 @@ update_time_renderer_visible (GtkFileChooserWidget *impl) { GtkFileChooserWidgetPrivate *priv = impl->priv; - g_object_set (priv->list_time_renderer, - "visible", priv->show_time, - NULL); clear_model_cache (impl, MODEL_COL_DATE_TEXT); clear_model_cache (impl, MODEL_COL_TIME_TEXT); + update_show_columns (impl); gtk_widget_queue_draw (priv->browse_files_tree_view); } @@ -2637,7 +2662,7 @@ location_entry_setup (GtkFileChooserWidget *impl) _gtk_file_chooser_entry_set_action (GTK_FILE_CHOOSER_ENTRY (priv->location_entry), priv->action); _gtk_file_chooser_entry_set_file_filter (GTK_FILE_CHOOSER_ENTRY (priv->location_entry), priv->current_filter); - gtk_entry_set_width_chars (GTK_ENTRY (priv->location_entry), 45); + gtk_entry_set_activates_default (GTK_ENTRY (priv->location_entry), TRUE); } @@ -2684,6 +2709,8 @@ save_widgets_create (GtkFileChooserWidget *impl) { GtkFileChooserWidgetPrivate *priv = impl->priv; GtkWidget *vbox; + GtkWidget *clamp; + GtkWidget *separator; GtkWidget *widget; if (priv->save_widgets != NULL || @@ -2705,14 +2732,19 @@ save_widgets_create (GtkFileChooserWidget *impl) return; } - vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); - gtk_style_context_add_class (gtk_widget_get_style_context (vbox), "search-bar"); + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); - gtk_container_set_border_width (GTK_CONTAINER (vbox), 0); + clamp = gtk_hdy_clamp_new (); + gtk_widget_show (clamp); + gtk_container_add (GTK_CONTAINER (vbox), clamp); + + separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL); + gtk_widget_show (separator); + gtk_container_add (GTK_CONTAINER (vbox), separator); priv->save_widgets_table = gtk_grid_new (); - gtk_container_set_border_width (GTK_CONTAINER (priv->save_widgets_table), 10); - gtk_box_pack_start (GTK_BOX (vbox), priv->save_widgets_table, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (priv->save_widgets_table), 6); + gtk_container_add (GTK_CONTAINER (clamp), priv->save_widgets_table); gtk_widget_show (priv->save_widgets_table); gtk_grid_set_row_spacing (GTK_GRID (priv->save_widgets_table), 12); gtk_grid_set_column_spacing (GTK_GRID (priv->save_widgets_table), 12); @@ -2878,6 +2910,9 @@ places_sidebar_show_other_locations_with_flags_cb (GtkPlacesSidebar *sidebar update_preview_widget_visibility (impl); operation_mode_set (impl, OPERATION_MODE_OTHER_LOCATIONS); + + if (gtk_hdy_flap_get_folded (GTK_HDY_FLAP (priv->flap))) + gtk_hdy_flap_set_reveal_flap (GTK_HDY_FLAP (priv->flap), FALSE); } static void @@ -2940,7 +2975,8 @@ update_extra_and_filters (GtkFileChooserWidget *impl) { gtk_widget_set_visible (impl->priv->extra_and_filters, gtk_widget_get_visible (impl->priv->extra_align) || - gtk_widget_get_visible (impl->priv->filter_combo_hbox)); + gtk_widget_get_visible (impl->priv->filter_combo_hbox) || + gtk_hdy_flap_get_folded (GTK_HDY_FLAP (impl->priv->flap))); } /* Sets the extra_widget by packing it in the appropriate place */ @@ -3755,7 +3791,7 @@ change_icon_theme (GtkFileChooserWidget *impl) profile_start ("start", NULL); - if (gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &width, &height)) + if (gtk_icon_size_lookup (GTK_ICON_SIZE_DND, &width, &height)) priv->icon_size = MAX (width, height); else priv->icon_size = FALLBACK_ICON_SIZE; @@ -3888,7 +3924,6 @@ settings_load (GtkFileChooserWidget *impl) gint sort_column; GtkSortType sort_order; StartupMode startup_mode; - gint sidebar_width; GSettings *settings; settings = _gtk_file_chooser_get_settings_for_widget (GTK_WIDGET (impl)); @@ -3898,7 +3933,6 @@ settings_load (GtkFileChooserWidget *impl) show_type_column = g_settings_get_boolean (settings, SETTINGS_KEY_SHOW_TYPE_COLUMN); sort_column = g_settings_get_enum (settings, SETTINGS_KEY_SORT_COLUMN); sort_order = g_settings_get_enum (settings, SETTINGS_KEY_SORT_ORDER); - sidebar_width = g_settings_get_int (settings, SETTINGS_KEY_SIDEBAR_WIDTH); startup_mode = g_settings_get_enum (settings, SETTINGS_KEY_STARTUP_MODE); sort_directories_first = g_settings_get_boolean (settings, SETTINGS_KEY_SORT_DIRECTORIES_FIRST); date_format = g_settings_get_enum (settings, SETTINGS_KEY_DATE_FORMAT); @@ -3907,9 +3941,8 @@ settings_load (GtkFileChooserWidget *impl) if (!priv->show_hidden_set) set_show_hidden (impl, show_hidden); priv->show_size_column = show_size_column; - gtk_tree_view_column_set_visible (priv->list_size_column, show_size_column); priv->show_type_column = show_type_column; - gtk_tree_view_column_set_visible (priv->list_type_column, show_type_column); + update_show_columns (impl); priv->sort_column = sort_column; priv->sort_order = sort_order; @@ -3924,7 +3957,6 @@ settings_load (GtkFileChooserWidget *impl) */ update_time_renderer_visible (impl); - gtk_paned_set_position (GTK_PANED (priv->browse_widgets_hpaned), sidebar_width); } static void @@ -3945,8 +3977,6 @@ settings_save (GtkFileChooserWidget *impl) g_settings_set_boolean (settings, SETTINGS_KEY_SORT_DIRECTORIES_FIRST, priv->sort_directories_first); g_settings_set_enum (settings, SETTINGS_KEY_SORT_COLUMN, priv->sort_column); g_settings_set_enum (settings, SETTINGS_KEY_SORT_ORDER, priv->sort_order); - g_settings_set_int (settings, SETTINGS_KEY_SIDEBAR_WIDTH, - gtk_paned_get_position (GTK_PANED (priv->browse_widgets_hpaned))); g_settings_set_enum (settings, SETTINGS_KEY_DATE_FORMAT, priv->show_time ? DATE_FORMAT_WITH_TIME : DATE_FORMAT_REGULAR); g_settings_set_enum (settings, SETTINGS_KEY_TYPE_FORMAT, priv->type_format); @@ -4416,13 +4446,18 @@ update_columns (GtkFileChooserWidget *impl, { GtkFileChooserWidgetPrivate *priv = impl->priv; gboolean need_resize = FALSE; + gboolean folded = gtk_hdy_flap_get_folded (GTK_HDY_FLAP (priv->flap)); + + priv->location_visible = location_visible; - if (gtk_tree_view_column_get_visible (priv->list_location_column) != location_visible) + if (gtk_tree_view_column_get_visible (priv->list_location_column) != (location_visible && !folded)) { - gtk_tree_view_column_set_visible (priv->list_location_column, location_visible); + gtk_tree_view_column_set_visible (priv->list_location_column, location_visible && !folded); need_resize = TRUE; } + clear_model_cache (impl, MODEL_COL_DISPLAY); + if (g_strcmp0 (gtk_tree_view_column_get_title (priv->list_time_column), time_title) != 0) { gtk_tree_view_column_set_title (priv->list_time_column, time_title); @@ -5303,6 +5338,47 @@ file_system_model_set (GtkFileSystemModel *model, g_object_unref (home_location); } break; + case MODEL_COL_DISPLAY: + { + gchar *metadata_str; + gchar* metadata[7]; + int i = 0; + + #define APPEND_COLUMN(column) {\ + GValue val = { 0, }; \ + gchar *ret; \ + g_value_init (&val, G_TYPE_STRING); \ + file_system_model_set (model, file, info, column, &val, data); \ + ret = g_value_get_string (&val); \ + if (ret && *ret) \ + metadata[i++] = g_markup_escape_text (ret, -1); \ + g_value_unset (&val); \ + } + + APPEND_COLUMN(MODEL_COL_NAME) + APPEND_COLUMN(MODEL_COL_DATE_TEXT) + + if (priv->show_time) + APPEND_COLUMN(MODEL_COL_TIME_TEXT) + + if (priv->show_type_column) + APPEND_COLUMN(MODEL_COL_TYPE) + + if (priv->show_size_column) + APPEND_COLUMN(MODEL_COL_SIZE_TEXT) + + if (priv->operation_mode == OPERATION_MODE_RECENT) + APPEND_COLUMN(MODEL_COL_LOCATION_TEXT) + + metadata[i] = NULL; + metadata_str = g_strjoinv (" · ", &metadata[1]); + g_value_take_string (value, g_strdup_printf ("%s\n%s", metadata[0], metadata_str)); + + while (i > 0) + g_free (metadata[--i]); + g_free (metadata_str); + } + break; default: g_assert_not_reached (); break; @@ -8106,6 +8182,7 @@ static void update_cell_renderer_attributes (GtkFileChooserWidget *impl) { GtkFileChooserWidgetPrivate *priv = impl->priv; + gboolean folded = gtk_hdy_flap_get_folded (GTK_HDY_FLAP (priv->flap)); gtk_tree_view_column_set_attributes (priv->list_name_column, priv->list_pixbuf_renderer, @@ -8114,7 +8191,8 @@ update_cell_renderer_attributes (GtkFileChooserWidget *impl) NULL); gtk_tree_view_column_set_attributes (priv->list_name_column, priv->list_name_renderer, - "text", MODEL_COL_NAME, + folded ? "markup" : "text", + folded ? MODEL_COL_DISPLAY : MODEL_COL_NAME, "ellipsize", MODEL_COL_ELLIPSIZE, "sensitive", MODEL_COL_IS_SENSITIVE, NULL); @@ -8152,6 +8230,20 @@ update_cell_renderer_attributes (GtkFileChooserWidget *impl) update_time_renderer_visible (impl); } +static void +flap_folded_cb (GtkFileChooserWidget *impl) +{ + GtkFileChooserWidgetPrivate *priv = impl->priv; + gboolean folded = gtk_hdy_flap_get_folded (GTK_HDY_FLAP (priv->flap)); + + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->browse_files_tree_view), !folded); + + update_show_columns (impl); + update_cell_renderer_attributes (impl); + update_extra_and_filters (impl); + update_columns (impl, priv->location_visible, gtk_tree_view_column_get_title (priv->list_time_column)); +} + static void location_set_user_text (GtkFileChooserWidget *impl, const gchar *path) @@ -8688,12 +8780,13 @@ gtk_file_chooser_widget_class_init (GtkFileChooserWidgetClass *class) "/org/gtk/libgtk/ui/gtkfilechooserwidget.ui"); /* A *lot* of widgets that we need to handle .... */ - gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, browse_widgets_hpaned); gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, browse_files_stack); gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, places_sidebar); gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, places_view); gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, browse_files_tree_view); gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, browse_files_swin); + gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, flap); + gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, browse_box); gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, browse_header_revealer); gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, browse_header_stack); gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, browse_new_folder_button); @@ -8755,6 +8848,7 @@ gtk_file_chooser_widget_class_init (GtkFileChooserWidgetClass *class) gtk_widget_class_bind_template_callback (widget_class, rename_file_name_changed); gtk_widget_class_bind_template_callback (widget_class, rename_file_rename_clicked); gtk_widget_class_bind_template_callback (widget_class, rename_file_end); + gtk_widget_class_bind_template_callback (widget_class, flap_folded_cb); gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_FILE_CHOOSER_WIDGET_ACCESSIBLE); gtk_widget_class_set_css_name (widget_class, "filechooser"); @@ -8831,6 +8925,19 @@ post_process_ui (GtkFileChooserWidget *impl) gtk_popover_set_relative_to (GTK_POPOVER (impl->priv->rename_file_popover), impl->priv->browse_files_tree_view); add_actions (impl); + + { + GtkCssProvider *provider; + + provider = gtk_css_provider_new (); + gtk_css_provider_load_from_data (provider, "placessidebar { border: none; }", -1, NULL); + + gtk_style_context_add_provider (gtk_widget_get_style_context (impl->priv->places_sidebar), + GTK_STYLE_PROVIDER (provider), + GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + } + + update_extra_and_filters (impl); } void @@ -8888,6 +8995,8 @@ gtk_file_chooser_widget_init (GtkFileChooserWidget *impl) /* Ensure GTK+ private types used by the template * definition before calling gtk_widget_init_template() */ + g_type_ensure (GTK_TYPE_HDY_CLAMP); + g_type_ensure (GTK_TYPE_HDY_FLAP); g_type_ensure (GTK_TYPE_PATH_BAR); g_type_ensure (GTK_TYPE_PLACES_VIEW); diff --git a/gtk/gtkplacesview.c b/gtk/gtkplacesview.c index 89f7acef2c..fd17820016 100644 --- a/gtk/gtkplacesview.c +++ b/gtk/gtkplacesview.c @@ -26,6 +26,7 @@ #include "gtkmarshalers.h" #include "gtkplacesviewprivate.h" #include "gtkplacesviewrowprivate.h" +#include "gtkprivate.h" #include "gtktypebuiltins.h" /** @@ -94,6 +95,9 @@ struct _GtkPlacesViewPrivate guint fetching_networks : 1; guint loading : 1; guint destroyed : 1; + + GtkWidget *connect_label; + GSettings *settings; }; static void mount_volume (GtkPlacesView *view, @@ -409,6 +413,8 @@ gtk_places_view_destroy (GtkWidget *widget) g_cancellable_cancel (priv->cancellable); g_cancellable_cancel (priv->networks_fetching_cancellable); + g_clear_object (&priv->settings); + GTK_WIDGET_CLASS (gtk_places_view_parent_class)->destroy (widget); } @@ -2211,6 +2217,14 @@ listbox_sort_func (GtkListBoxRow *row1, return retval; } +static void +update_connect_label (GtkPlacesView *self) +{ + GtkPlacesViewPrivate *priv = gtk_places_view_get_instance_private (self); + + gtk_widget_set_visible (priv->connect_label, !_gtk_get_is_phone ()); +} + static void gtk_places_view_constructed (GObject *object) { @@ -2260,6 +2274,15 @@ gtk_places_view_constructed (GObject *object) "volume-removed", G_CALLBACK (update_places), object); + + priv->settings = _gtk_get_purism_settings (); + + if (priv->settings) + g_signal_connect_object (priv->settings, "changed::is-phone", + G_CALLBACK (update_connect_label), object, + G_CONNECT_SWAPPED); + + update_connect_label (GTK_PLACES_VIEW (object)); } static void @@ -2386,6 +2409,7 @@ gtk_places_view_class_init (GtkPlacesViewClass *klass) gtk_widget_class_bind_template_child_private (widget_class, GtkPlacesView, stack); gtk_widget_class_bind_template_child_private (widget_class, GtkPlacesView, server_adresses_popover); gtk_widget_class_bind_template_child_private (widget_class, GtkPlacesView, available_protocols_grid); + gtk_widget_class_bind_template_child_private (widget_class, GtkPlacesView, connect_label); gtk_widget_class_bind_template_callback (widget_class, on_address_entry_text_changed); gtk_widget_class_bind_template_callback (widget_class, on_address_entry_show_help_pressed); diff --git a/gtk/ui/gtkfilechooserwidget.ui b/gtk/ui/gtkfilechooserwidget.ui index 6e7c21dcc9..f72edd5de8 100644 --- a/gtk/ui/gtkfilechooserwidget.ui +++ b/gtk/ui/gtkfilechooserwidget.ui @@ -9,14 +9,20 @@ 1 vertical - + 1 - + 0 + + + 1 + 1 never 1 1 + 1 + 200 Places @@ -29,13 +35,17 @@ - - 0 - 0 - + + + + 1 + + - + 1 vertical @@ -110,6 +120,9 @@ pathbar + + + 1 1 @@ -125,7 +138,12 @@ location + + + + + 1 1 @@ -137,10 +155,10 @@ Search Layer - + 1 - 45 + True @@ -158,6 +176,8 @@ search + + 0 @@ -171,9 +191,15 @@ - + 1 - 12 + end + never + False + False + False + slide + 1 @@ -223,6 +249,7 @@ 6 + 5 @@ -351,6 +378,8 @@ 1 No Results Found + center + True @@ -365,6 +394,8 @@ 1 Try a different search + center + True @@ -380,19 +411,15 @@ - - 1 - - + vertical 12 + - - 0 - 1 - @@ -401,9 +428,6 @@ - - 0 - @@ -419,15 +443,30 @@ 1 + + + + + Show locations + 1 + 1 + + + 1 + view-sidebar-symbolic + + + + - 1 + 1 12 - 1 + 1 12 diff --git a/gtk/ui/gtkplacesview.ui b/gtk/ui/gtkplacesview.ui index 5ede5900ba..d68aab0aa9 100644 --- a/gtk/ui/gtkplacesview.ui +++ b/gtk/ui/gtkplacesview.ui @@ -300,7 +300,7 @@ - + 1 1 0 @@ -336,7 +336,6 @@ 1 1 1 - 20 Enter server address… dialog-question-symbolic address_entry_completion -- 2.39.2