Merge bgo593793-filechooser-recent-folders-master branch.
The file chooser now starts up in recent-files mode, or in recent-folders mode, if the caller didn't set a current_folder on it. Setting a current_folder is now discouraged, so that the file chooser can have a chance of presenting useful locations to the user. See https://live.gnome.org/DocumentCentricGnome/Help%20the%20user%20choose%20a%20place%20to%20put%20a%20new%20file for the rationale behind these changes.
This commit is contained in:
@@ -1070,31 +1070,26 @@ gtk_file_chooser_get_filename (GtkFileChooser *chooser)
|
||||
* @chooser: a #GtkFileChooser
|
||||
* @filename: (type filename): the filename to set as current
|
||||
*
|
||||
* Sets @filename as the current filename for the file chooser, by changing
|
||||
* to the file's parent folder and actually selecting the file in list. If
|
||||
* the @chooser is in %GTK_FILE_CHOOSER_ACTION_SAVE mode, the file's base name
|
||||
* will also appear in the dialog's file name entry.
|
||||
*
|
||||
* If the file name isn't in the current folder of @chooser, then the current
|
||||
* folder of @chooser will be changed to the folder containing @filename. This
|
||||
* is equivalent to a sequence of gtk_file_chooser_unselect_all() followed by
|
||||
* gtk_file_chooser_select_filename().
|
||||
* Sets @filename as the current filename for the file chooser, by changing to
|
||||
* the file's parent folder and actually selecting the file in list; all other
|
||||
* files will be unselected. If the @chooser is in
|
||||
* %GTK_FILE_CHOOSER_ACTION_SAVE mode, the file's base name will also appear in
|
||||
* the dialog's file name entry.
|
||||
*
|
||||
* Note that the file must exist, or nothing will be done except
|
||||
* for the directory change.
|
||||
*
|
||||
* If you are implementing a <guimenuitem>File/Save As...</guimenuitem> dialog,
|
||||
* you should use this function if you already have a file name to which the
|
||||
* user may save; for example, when the user opens an existing file and then
|
||||
* does <guimenuitem>File/Save As...</guimenuitem> on it. If you don't have
|
||||
* a file name already — for example, if the user just created a new
|
||||
* file and is saving it for the first time, do not call this function.
|
||||
* Instead, use something similar to this:
|
||||
* You should use this function only when implementing a <guimenuitem>File/Save
|
||||
* As...</guimenuitem> dialog for which you already have a file name to which
|
||||
* the user may save. For example, when the user opens an existing file and
|
||||
* then does <guimenuitem>File/Save As...</guimenuitem> on it to save a copy or
|
||||
* a modified version. If you don't have a file name already — for
|
||||
* example, if the user just created a new file and is saving it for the first
|
||||
* time, do not call this function. Instead, use something similar to this:
|
||||
* |[
|
||||
* if (document_is_new)
|
||||
* {
|
||||
* /* the user just created a new document */
|
||||
* gtk_file_chooser_set_current_folder (chooser, default_folder_for_saving);
|
||||
* gtk_file_chooser_set_current_name (chooser, "Untitled document");
|
||||
* }
|
||||
* else
|
||||
@@ -1103,9 +1098,12 @@ gtk_file_chooser_get_filename (GtkFileChooser *chooser)
|
||||
* gtk_file_chooser_set_filename (chooser, existing_filename);
|
||||
* }
|
||||
* ]|
|
||||
*
|
||||
* In the first case, the file chooser will present the user with useful suggestions
|
||||
* as to where to save his new file. In the second case, the file's existing location
|
||||
* is already known, so the file chooser will use it.
|
||||
*
|
||||
* Return value: %TRUE if both the folder could be changed and the file was
|
||||
* selected successfully, %FALSE otherwise.
|
||||
* Return value: Not useful.
|
||||
*
|
||||
* Since: 2.4
|
||||
**/
|
||||
@@ -1128,8 +1126,9 @@ gtk_file_chooser_set_filename (GtkFileChooser *chooser,
|
||||
* folder of @chooser, then the current folder of @chooser will
|
||||
* be changed to the folder containing @filename.
|
||||
*
|
||||
* Return value: %TRUE if both the folder could be changed and the file was
|
||||
* selected successfully, %FALSE otherwise.
|
||||
* Return value: Not useful.
|
||||
*
|
||||
* See also: gtk_file_chooser_set_filename()
|
||||
*
|
||||
* Since: 2.4
|
||||
**/
|
||||
@@ -1240,8 +1239,11 @@ gtk_file_chooser_get_filenames (GtkFileChooser *chooser)
|
||||
* The user will be shown the full contents of the current folder,
|
||||
* plus user interface elements for navigating to other folders.
|
||||
*
|
||||
* Return value: %TRUE if the folder could be changed successfully, %FALSE
|
||||
* otherwise.
|
||||
* In general, you should not use this function. See the <link
|
||||
* linkend="gtkfilechooserdialog-setting-up">section on setting up a file
|
||||
* chooser dialog</link> for the rationale behind this.
|
||||
*
|
||||
* Return value: Not useful.
|
||||
*
|
||||
* Since: 2.4
|
||||
**/
|
||||
@@ -1312,7 +1314,8 @@ gtk_file_chooser_get_current_folder (GtkFileChooser *chooser)
|
||||
* Sets the current name in the file selector, as if entered
|
||||
* by the user. Note that the name passed in here is a UTF-8
|
||||
* string rather than a filename. This function is meant for
|
||||
* such uses as a suggested name in a "Save As..." dialog.
|
||||
* such uses as a suggested name in a "Save As..." dialog. You can
|
||||
* pass "Untitled.doc" or a similarly suitable suggestion for the @name.
|
||||
*
|
||||
* If you want to preselect a particular existing file, you should use
|
||||
* gtk_file_chooser_set_filename() or gtk_file_chooser_set_uri() instead.
|
||||
@@ -1375,25 +1378,20 @@ gtk_file_chooser_get_uri (GtkFileChooser *chooser)
|
||||
* list. If the @chooser is %GTK_FILE_CHOOSER_ACTION_SAVE mode, the URI's base
|
||||
* name will also appear in the dialog's file name entry.
|
||||
*
|
||||
* If the URI isn't in the current folder of @chooser, then the current folder
|
||||
* of @chooser will be changed to the folder containing @uri. This is equivalent
|
||||
* to a sequence of gtk_file_chooser_unselect_all() followed by
|
||||
* gtk_file_chooser_select_uri().
|
||||
*
|
||||
* Note that the URI must exist, or nothing will be done except for the
|
||||
* directory change.
|
||||
* If you are implementing a <guimenuitem>File/Save As...</guimenuitem> dialog,
|
||||
* you should use this function if you already have a file name to which the
|
||||
* user may save; for example, when the user opens an existing file and then
|
||||
* does <guimenuitem>File/Save As...</guimenuitem> on it. If you don't have
|
||||
* a file name already — for example, if the user just created a new
|
||||
* file and is saving it for the first time, do not call this function.
|
||||
* Instead, use something similar to this:
|
||||
*
|
||||
* You should use this function only when implementing a <guimenuitem>File/Save
|
||||
* As...</guimenuitem> dialog for which you already have a file name to which
|
||||
* the user may save. For example, whenthe user opens an existing file and then
|
||||
* does <guimenuitem>File/Save As...</guimenuitem> on it to save a copy or a
|
||||
* modified version. If you don't have a file name already — for example,
|
||||
* if the user just created a new file and is saving it for the first time, do
|
||||
* not call this function. Instead, use something similar to this:
|
||||
* |[
|
||||
* if (document_is_new)
|
||||
* {
|
||||
* /* the user just created a new document */
|
||||
* gtk_file_chooser_set_current_folder_uri (chooser, default_folder_for_saving);
|
||||
* gtk_file_chooser_set_current_name (chooser, "Untitled document");
|
||||
* }
|
||||
* else
|
||||
@@ -1403,8 +1401,12 @@ gtk_file_chooser_get_uri (GtkFileChooser *chooser)
|
||||
* }
|
||||
* ]|
|
||||
*
|
||||
* Return value: %TRUE if both the folder could be changed and the URI was
|
||||
* selected successfully, %FALSE otherwise.
|
||||
*
|
||||
* In the first case, the file chooser will present the user with useful suggestions
|
||||
* as to where to save his new file. In the second case, the file's existing location
|
||||
* is already known, so the file chooser will use it.
|
||||
*
|
||||
* Return value: Not useful.
|
||||
*
|
||||
* Since: 2.4
|
||||
**/
|
||||
@@ -1427,8 +1429,7 @@ gtk_file_chooser_set_uri (GtkFileChooser *chooser,
|
||||
* file in the current folder of @chooser, then the current folder of
|
||||
* @chooser will be changed to the folder containing @filename.
|
||||
*
|
||||
* Return value: %TRUE if both the folder could be changed and the URI was
|
||||
* selected successfully, %FALSE otherwise.
|
||||
* Return value: Not useful.
|
||||
*
|
||||
* Since: 2.4
|
||||
**/
|
||||
@@ -1545,6 +1546,10 @@ gtk_file_chooser_get_uris (GtkFileChooser *chooser)
|
||||
* The user will be shown the full contents of the current folder,
|
||||
* plus user interface elements for navigating to other folders.
|
||||
*
|
||||
* In general, you should not use this function. See the <link
|
||||
* linkend="gtkfilechooserdialog-setting-up">section on setting up a file
|
||||
* chooser dialog</link> for the rationale behind this.
|
||||
*
|
||||
* Return value: %TRUE if the folder could be changed successfully, %FALSE
|
||||
* otherwise.
|
||||
*
|
||||
@@ -1661,8 +1666,7 @@ gtk_file_chooser_get_current_folder_file (GtkFileChooser *chooser)
|
||||
* Selects the file referred to by @file. An internal function. See
|
||||
* _gtk_file_chooser_select_uri().
|
||||
*
|
||||
* Return value: %TRUE if both the folder could be changed and the path was
|
||||
* selected successfully, %FALSE otherwise.
|
||||
* Return value: Not useful.
|
||||
*
|
||||
* Since: 2.14
|
||||
**/
|
||||
@@ -1760,8 +1764,7 @@ gtk_file_chooser_get_files (GtkFileChooser *chooser)
|
||||
* }
|
||||
* ]|
|
||||
*
|
||||
* Return value: %TRUE if both the folder could be changed and the file was
|
||||
* selected successfully, %FALSE otherwise.
|
||||
* Return value: Not useful.
|
||||
*
|
||||
* Since: 2.14
|
||||
**/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -93,10 +93,7 @@
|
||||
* gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
|
||||
*
|
||||
* if (user_edited_a_new_document)
|
||||
* {
|
||||
* gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), default_folder_for_saving);
|
||||
* gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), "Untitled document");
|
||||
* }
|
||||
* gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), "Untitled document");
|
||||
* else
|
||||
* gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (dialog), filename_for_existing_document);
|
||||
*
|
||||
@@ -113,6 +110,59 @@
|
||||
* </programlisting></informalexample>
|
||||
* </para>
|
||||
* </example>
|
||||
* <section id="gtkfilechooserdialog-setting-up">
|
||||
* <title>Setting up a file chooser dialog</title>
|
||||
* There are various cases in which you may need to use a #GtkFileChooserDialog:
|
||||
* <itemizedlist>
|
||||
* <listitem>
|
||||
* <para>
|
||||
* To select a file for opening, as for a
|
||||
* <guimenuitem>File/Open</guimenuitem> command. Use
|
||||
* #GTK_FILE_CHOOSER_ACTION_OPEN.
|
||||
* </para>
|
||||
* </listitem>
|
||||
*
|
||||
* <listitem>
|
||||
* <para>
|
||||
* To save a file for the first time, as for a
|
||||
* <guimenuitem>File/Save</guimenuitem> command. Use
|
||||
* #GTK_FILE_CHOOSER_ACTION_SAVE, and suggest a name such as
|
||||
* "Untitled" with gtk_file_chooser_set_current_name().
|
||||
* </para>
|
||||
* </listitem>
|
||||
*
|
||||
* <listitem>
|
||||
* <para>
|
||||
* To save a file under a different name, as for a
|
||||
* <guimenuitem>File/Save As</guimenuitem> command. Use
|
||||
* #GTK_FILE_CHOOSER_ACTION_SAVE, and set the existing filename
|
||||
* with gtk_file_chooser_set_filename().
|
||||
* </para>
|
||||
* </listitem>
|
||||
*
|
||||
* <listitem>
|
||||
* <para>
|
||||
* To choose a folder instead of a file. Use
|
||||
* #GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER.
|
||||
* </para>
|
||||
* </listitem>
|
||||
* </itemizedlist>
|
||||
* <note>
|
||||
* <para>
|
||||
* Old versions of the file chooser's documentation suggested
|
||||
* using gtk_file_chooser_set_current_folder() in various
|
||||
* situations, with the intention of letting the application
|
||||
* suggest a reasonable default folder. This is no longer
|
||||
* considered to be a good policy, as now the file chooser is
|
||||
* able to make good suggestions on its own. In general, you
|
||||
* should only cause the file chooser to show a specific folder
|
||||
* when it is appropriate to use gtk_file_chooser_set_filename()
|
||||
* - i.e. when you are doing a <guimenuitem>File/Save
|
||||
* As</guimenuitem> command <emphasis>and</emphasis> you already
|
||||
* have a file saved somewhere.
|
||||
* </para>
|
||||
* </note>
|
||||
* </section>
|
||||
* <section id="gtkfilechooserdialog-response-codes">
|
||||
* <title>Response Codes</title>
|
||||
* #GtkFileChooserDialog inherits from #GtkDialog, so buttons that
|
||||
|
||||
@@ -1563,7 +1563,6 @@ refresh_current_folder_and_file_part (GtkFileChooserEntry *chooser_entry,
|
||||
|
||||
error = NULL;
|
||||
if (!chooser_entry->file_system ||
|
||||
!chooser_entry->base_folder ||
|
||||
!_gtk_file_system_parse (chooser_entry->file_system,
|
||||
chooser_entry->base_folder, text,
|
||||
&folder_file, &file_part, &error))
|
||||
@@ -1831,7 +1830,6 @@ _gtk_file_chooser_entry_set_base_folder (GtkFileChooserEntry *chooser_entry,
|
||||
g_object_ref (chooser_entry->base_folder);
|
||||
|
||||
clear_completions (chooser_entry);
|
||||
_gtk_file_chooser_entry_select_filename (chooser_entry);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -162,13 +162,12 @@ struct _GtkFileChooserDefault
|
||||
|
||||
/* Save mode widgets */
|
||||
GtkWidget *save_widgets;
|
||||
GtkWidget *save_widgets_table;
|
||||
|
||||
GtkWidget *save_folder_label;
|
||||
GtkWidget *save_folder_combo;
|
||||
GtkWidget *save_expander;
|
||||
|
||||
/* The file browsing widgets */
|
||||
GtkWidget *browse_widgets;
|
||||
GtkWidget *browse_widgets_box;
|
||||
GtkWidget *browse_shortcuts_tree_view;
|
||||
GtkWidget *browse_shortcuts_add_button;
|
||||
GtkWidget *browse_shortcuts_remove_button;
|
||||
@@ -184,6 +183,11 @@ struct _GtkFileChooserDefault
|
||||
GtkWidget *browse_path_bar_hbox;
|
||||
GtkSizeGroup *browse_path_bar_size_group;
|
||||
GtkWidget *browse_path_bar;
|
||||
GtkWidget *browse_special_mode_icon;
|
||||
GtkWidget *browse_special_mode_label;
|
||||
GtkWidget *browse_select_a_folder_info_bar;
|
||||
GtkWidget *browse_select_a_folder_label;
|
||||
GtkWidget *browse_select_a_folder_icon;
|
||||
|
||||
GtkFileSystemModel *browse_files_model;
|
||||
char *browse_files_last_selected_name;
|
||||
@@ -196,7 +200,6 @@ struct _GtkFileChooserDefault
|
||||
GtkFileSystemModel *search_model;
|
||||
|
||||
/* OPERATION_MODE_RECENT */
|
||||
GtkWidget *recent_hbox;
|
||||
GtkRecentManager *recent_manager;
|
||||
GtkFileSystemModel *recent_model;
|
||||
guint load_recent_id;
|
||||
@@ -222,11 +225,6 @@ struct _GtkFileChooserDefault
|
||||
*/
|
||||
GtkTreeModel *shortcuts_pane_filter_model;
|
||||
|
||||
/* Filter for the "Save in folder" combo. We filter out the Search row and
|
||||
* its separator.
|
||||
*/
|
||||
GtkTreeModel *shortcuts_combo_filter_model;
|
||||
|
||||
/* Handles */
|
||||
GSList *loading_shortcuts;
|
||||
GSList *reload_icon_cancellables;
|
||||
@@ -298,11 +296,9 @@ struct _GtkFileChooserDefault
|
||||
guint list_sort_ascending : 1;
|
||||
guint changing_folder : 1;
|
||||
guint shortcuts_current_folder_active : 1;
|
||||
guint expand_folders : 1;
|
||||
guint has_home : 1;
|
||||
guint has_desktop : 1;
|
||||
guint has_search : 1;
|
||||
guint has_recent : 1;
|
||||
guint show_size_column : 1;
|
||||
guint create_folders : 1;
|
||||
|
||||
|
||||
@@ -360,3 +360,59 @@ delegate_confirm_overwrite (GtkFileChooser *chooser,
|
||||
g_signal_emit_by_name (data, "confirm-overwrite", &conf);
|
||||
return conf;
|
||||
}
|
||||
|
||||
static GFile *
|
||||
get_parent_for_uri (const char *uri)
|
||||
{
|
||||
GFile *file;
|
||||
GFile *parent;
|
||||
|
||||
file = g_file_new_for_uri (uri);
|
||||
parent = g_file_get_parent (file);
|
||||
|
||||
g_object_unref (file);
|
||||
return parent;
|
||||
|
||||
}
|
||||
|
||||
/* Extracts the parent folders out of the supplied list of GtkRecentInfo* items, and returns
|
||||
* a list of GFile* for those unique parents.
|
||||
*/
|
||||
GList *
|
||||
_gtk_file_chooser_extract_recent_folders (GList *infos)
|
||||
{
|
||||
GList *l;
|
||||
GList *result;
|
||||
GHashTable *folders;
|
||||
|
||||
result = NULL;
|
||||
|
||||
folders = g_hash_table_new (g_file_hash, (GEqualFunc) g_file_equal);
|
||||
|
||||
for (l = infos; l; l = l->next)
|
||||
{
|
||||
GtkRecentInfo *info = l->data;
|
||||
const char *uri;
|
||||
GFile *parent;
|
||||
|
||||
uri = gtk_recent_info_get_uri (info);
|
||||
parent = get_parent_for_uri (uri);
|
||||
|
||||
if (parent)
|
||||
{
|
||||
if (!g_hash_table_lookup (folders, parent))
|
||||
{
|
||||
g_hash_table_insert (folders, parent, (gpointer) 1);
|
||||
result = g_list_prepend (result, g_object_ref (parent));
|
||||
}
|
||||
|
||||
g_object_unref (parent);
|
||||
}
|
||||
}
|
||||
|
||||
result = g_list_reverse (result);
|
||||
|
||||
g_hash_table_destroy (folders);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -52,6 +52,8 @@ void _gtk_file_chooser_set_delegate (GtkFileChooser *receiver,
|
||||
|
||||
GQuark _gtk_file_chooser_delegate_get_quark (void) G_GNUC_CONST;
|
||||
|
||||
GList *_gtk_file_chooser_extract_recent_folders (GList *infos);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_FILE_CHOOSER_UTILS_H__ */
|
||||
|
||||
@@ -708,9 +708,22 @@ _gtk_file_system_parse (GtkFileSystem *file_system,
|
||||
if (str[0] == '~' || g_path_is_absolute (str) || is_uri)
|
||||
file = g_file_parse_name (str);
|
||||
else
|
||||
file = g_file_resolve_relative_path (base_file, str);
|
||||
{
|
||||
if (base_file)
|
||||
file = g_file_resolve_relative_path (base_file, str);
|
||||
else
|
||||
{
|
||||
*folder = NULL;
|
||||
*file_part = NULL;
|
||||
g_set_error (error,
|
||||
GTK_FILE_CHOOSER_ERROR,
|
||||
GTK_FILE_CHOOSER_ERROR_BAD_FILENAME,
|
||||
_("Invalid path"));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_file_equal (base_file, file))
|
||||
if (base_file && g_file_equal (base_file, file))
|
||||
{
|
||||
/* this is when user types '.', could be the
|
||||
* beginning of a hidden file, ./ or ../
|
||||
|
||||
@@ -44,9 +44,6 @@
|
||||
<key name='show-hidden' type='b'>
|
||||
<default>false</default>
|
||||
</key>
|
||||
<key name='expand-folders' type='b'>
|
||||
<default>false</default>
|
||||
</key>
|
||||
<key name='show-size-column' type='b'>
|
||||
<default>true</default>
|
||||
</key>
|
||||
|
||||
Reference in New Issue
Block a user