#include <string.h>
#include <time.h>
+\f
+
+/* Profiling stuff */
+
+#define PROFILE_FILE_CHOOSER
+#ifdef PROFILE_FILE_CHOOSER
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef G_OS_WIN32
+#include <io.h>
+#endif
+
+#ifndef F_OK
+#define F_OK 0
+#endif
+
+#define PROFILE_INDENT 4
+static int profile_indent;
+
+static void
+profile_add_indent (int indent)
+{
+ profile_indent += indent;
+ if (profile_indent < 0)
+ g_error ("You screwed up your indentation");
+}
+
+void
+_gtk_file_chooser_profile_log (const char *func, int indent, const char *msg1, const char *msg2)
+{
+ char *str;
+
+ if (indent < 0)
+ profile_add_indent (indent);
+
+ if (profile_indent == 0)
+ str = g_strdup_printf ("MARK: %s %s %s", func, msg1 ? msg1 : "", msg2 ? msg2 : "");
+ else
+ str = g_strdup_printf ("MARK: %*c %s %s %s", profile_indent - 1, ' ', func, msg1 ? msg1 : "", msg2 ? msg2 : "");
+
+ access (str, F_OK);
+ g_free (str);
+
+ if (indent > 0)
+ profile_add_indent (indent);
+}
+
+#define profile_start(x, y) _gtk_file_chooser_profile_log (G_STRFUNC, PROFILE_INDENT, x, y)
+#define profile_end(x, y) _gtk_file_chooser_profile_log (G_STRFUNC, -PROFILE_INDENT, x, y)
+#define profile_msg(x, y) _gtk_file_chooser_profile_log (NULL, 0, x, y)
+#else
+#define profile_start(x, y)
+#define profile_end(x, y)
+#define profile_msg(x, y)
+#endif
+
+\f
+
typedef struct _GtkFileChooserDefaultClass GtkFileChooserDefaultClass;
#define GTK_FILE_CHOOSER_DEFAULT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_FILE_CHOOSER_DEFAULT, GtkFileChooserDefaultClass))
guint use_preview_label : 1;
guint select_multiple : 1;
guint show_hidden : 1;
+ guint do_overwrite_confirmation : 1;
guint list_sort_ascending : 1;
guint changing_folder : 1;
guint shortcuts_current_folder_active : 1;
static const int num_file_list_source_targets = (sizeof (file_list_source_targets)
/ sizeof (file_list_source_targets[0]));
+/* Target types for dropping into the file list */
+static const GtkTargetEntry file_list_dest_targets[] = {
+ { "text/uri-list", 0, TEXT_URI_LIST }
+};
+
+static const int num_file_list_dest_targets = (sizeof (file_list_dest_targets)
+ / sizeof (file_list_dest_targets[0]));
+
+
/* Interesting places in the shortcuts bar */
typedef enum {
SHORTCUTS_HOME,
static gboolean gtk_file_chooser_default_set_current_folder (GtkFileChooser *chooser,
const GtkFilePath *path,
GError **error);
+static gboolean gtk_file_chooser_default_update_current_folder (GtkFileChooser *chooser,
+ const GtkFilePath *path,
+ gboolean keep_trail,
+ GError **error);
static GtkFilePath * gtk_file_chooser_default_get_current_folder (GtkFileChooser *chooser);
static void gtk_file_chooser_default_set_current_name (GtkFileChooser *chooser,
const gchar *name);
GtkTreeIter *iter);
static void load_remove_timer (GtkFileChooserDefault *impl);
+static void browse_files_center_selected_row (GtkFileChooserDefault *impl);
static GObjectClass *parent_class;
static void
gtk_file_chooser_default_init (GtkFileChooserDefault *impl)
{
+ profile_start ("start", NULL);
+
impl->local_only = TRUE;
impl->preview_widget_active = TRUE;
impl->use_preview_label = TRUE;
impl->load_state = LOAD_EMPTY;
impl->pending_select_paths = NULL;
- gtk_widget_set_redraw_on_allocate (GTK_WIDGET (impl), TRUE);
gtk_box_set_spacing (GTK_BOX (impl), 12);
impl->tooltips = gtk_tooltips_new ();
g_object_ref (impl->tooltips);
gtk_object_sink (GTK_OBJECT (impl->tooltips));
+
+ profile_end ("end", NULL);
}
/* Frees the data columns for the specified iter in the shortcuts model*/
msg);
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
"%s", detail);
+
+ if (parent->group)
+ gtk_window_group_add_window (parent->group, GTK_WINDOW (dialog));
+
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
}
path, error);
}
+/* Shows an error about not being able to create a folder because a file with
+ * the same name is already there.
+ */
+static void
+error_creating_folder_over_existing_file_dialog (GtkFileChooserDefault *impl,
+ const GtkFilePath *path,
+ GError *error)
+{
+ error_dialog (impl,
+ _("The folder could not be created, as a file with the same name "
+ "already exists. Try using a different name for the folder, "
+ "or rename the file first."),
+ path, error);
+}
+
/* Shows an error dialog about not being able to create a filename */
static void
error_building_filename_dialog (GtkFileChooserDefault *impl,
gboolean result;
GtkFilePath *path_copy;
+ g_return_val_if_fail (path != NULL, FALSE);
+
+ profile_start ("start", (char *) path);
+
/* We copy the path because of this case:
*
* list_row_activated()
path_copy = gtk_file_path_copy (path);
error = NULL;
- result = _gtk_file_chooser_set_current_folder_path (GTK_FILE_CHOOSER (impl), path_copy, &error);
+ result = gtk_file_chooser_default_update_current_folder (GTK_FILE_CHOOSER (impl), path_copy, TRUE, &error);
if (!result)
error_changing_folder_dialog (impl, path_copy, error);
gtk_file_path_free (path_copy);
+ profile_end ("end", (char *) path);
+
return result;
}
{
GtkTreeIter iter;
+ profile_start ("start", NULL);
+
if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (impl->shortcuts_model), &iter))
- return;
+ goto out;
do {
gpointer data;
g_object_unref (pixbuf);
}
} while (gtk_tree_model_iter_next (GTK_TREE_MODEL (impl->shortcuts_model),&iter));
+
+ out:
+
+ profile_end ("end", NULL);
}
static void
GtkFileInfo *info;
GError *tmp = NULL;
+ profile_start ("start", (char *) path);
+
parent_path = NULL;
info = NULL;
g_error_free (tmp);
}
+ profile_end ("end", (char *) path);
+
return info;
}
{
GtkFileFolder *folder;
+ profile_start ("start", (char *) path);
+
folder = gtk_file_system_get_folder (file_system, path, 0, error);
if (!folder)
- return FALSE;
+ {
+ profile_end ("end - is not folder", (char *) path);
+ return FALSE;
+ }
g_object_unref (folder);
+
+ profile_end ("end", (char *) path);
return TRUE;
}
gpointer data;
GtkTreeIter iter;
+ profile_start ("start", is_volume ? "volume" : (char *) path);
+
if (is_volume)
{
data = volume;
else
{
if (!check_is_folder (impl->file_system, path, error))
- return FALSE;
+ {
+ profile_end ("end - is not folder", NULL);
+ return FALSE;
+ }
if (label)
label_copy = g_strdup (label);
GtkFileInfo *info = get_file_info (impl->file_system, path, TRUE, error);
if (!info)
- return FALSE;
+ {
+ profile_end ("end - could not get info", (char *) path);
+ return FALSE;
+ }
label_copy = g_strdup (gtk_file_info_get_display_name (info));
gtk_file_info_free (info);
if (pixbuf)
g_object_unref (pixbuf);
+ profile_end ("end", NULL);
+
return TRUE;
}
GtkFilePath *home_path;
GError *error;
+ profile_start ("start", NULL);
+
home = g_get_home_dir ();
if (home == NULL)
- return;
+ {
+ profile_end ("end - no home directory!?", NULL);
+ return;
+ }
home_path = gtk_file_system_filename_to_path (impl->file_system, home);
error_getting_info_dialog (impl, home_path, error);
gtk_file_path_free (home_path);
+
+ profile_end ("end", NULL);
}
/* Appends the ~/Desktop directory to the shortcuts model */
char *name;
GtkFilePath *path;
+ profile_start ("start", NULL);
+
#ifdef G_OS_WIN32
name = _gtk_file_system_win32_get_desktop ();
#else
const char *home = g_get_home_dir ();
if (home == NULL)
- return;
+ {
+ profile_end ("end - no home directory!?", NULL);
+ return;
+ }
name = g_build_filename (home, "Desktop", NULL);
#endif
*/
gtk_file_path_free (path);
+
+ profile_end ("end", NULL);
}
/* Appends a list of GtkFilePath to the shortcuts model; returns how many were inserted */
int num_inserted;
gchar *label;
+ profile_start ("start", NULL);
+
/* As there is no separator now, we want to start there.
*/
start_row = shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS_SEPARATOR);
g_free (label);
}
+ profile_end ("end", NULL);
+
return num_inserted;
}
int n;
gboolean old_changing_folders;
+ profile_start ("start", NULL);
+
old_changing_folders = impl->changing_folder;
impl->changing_folder = TRUE;
gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (impl->shortcuts_filter_model));
impl->changing_folder = old_changing_folders;
+
+ profile_end ("end", NULL);
}
/* Inserts a separator node in the shortcuts list */
GtkFilePath *combo_selected = NULL;
gboolean is_volume;
gpointer col_data;
+
+ profile_start ("start", NULL);
old_changing_folders = impl->changing_folder;
impl->changing_folder = TRUE;
}
impl->changing_folder = old_changing_folders;
+
+ profile_end ("end", NULL);
}
/* Appends a separator and a row to the shortcuts list for the current folder */
filter_create (GtkFileChooserDefault *impl)
{
impl->filter_combo = gtk_combo_box_new_text ();
+ gtk_combo_box_set_focus_on_click (GTK_COMBO_BOX (impl->filter_combo), FALSE);
+
g_signal_connect (impl->filter_combo, "changed",
G_CALLBACK (filter_combo_changed), impl);
GCallback callback)
{
GtkWidget *button;
- GtkWidget *hbox;
- GtkWidget *widget;
- GtkWidget *align;
-
- button = gtk_button_new ();
- hbox = gtk_hbox_new (FALSE, 2);
- align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
-
- gtk_container_add (GTK_CONTAINER (button), align);
- gtk_container_add (GTK_CONTAINER (align), hbox);
- widget = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_BUTTON);
-
- gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
+ GtkWidget *image;
- widget = gtk_label_new_with_mnemonic (text);
- gtk_label_set_mnemonic_widget (GTK_LABEL (widget), GTK_WIDGET (button));
- gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
+ button = gtk_button_new_with_mnemonic (text);
+ image = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_BUTTON);
+ gtk_button_set_image (GTK_BUTTON (button), image);
gtk_widget_set_sensitive (button, sensitive);
g_signal_connect (button, "clicked", callback, impl);
- gtk_widget_show_all (align);
-
if (show)
gtk_widget_show (button);
volume = col_data;
base_path = gtk_file_system_volume_get_base_path (impl->file_system, volume);
- exists = strcmp (gtk_file_path_get_string (path),
- gtk_file_path_get_string (base_path)) == 0;
+ exists = base_path && strcmp (gtk_file_path_get_string (path),
+ gtk_file_path_get_string (base_path)) == 0;
g_free (base_path);
if (exists)
{
GError *error;
+ g_return_val_if_fail (path != NULL, FALSE);
+
if (shortcut_find_position (impl, path) != -1)
return FALSE;
{
GtkTreeIter iter;
gpointer col_data;
- gboolean is_volume;
GtkFilePath *path;
gboolean removable;
GError *error;
gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter,
SHORTCUTS_COL_DATA, &col_data,
- SHORTCUTS_COL_IS_VOLUME, &is_volume,
SHORTCUTS_COL_REMOVABLE, &removable,
-1);
g_assert (col_data != NULL);
- g_assert (!is_volume);
if (!removable)
return;
gpointer data)
{
GtkFileChooserDefault *impl;
+ int modifiers;
impl = (GtkFileChooserDefault *) data;
+
+ modifiers = gtk_accelerator_get_default_mod_mask ();
if (event->keyval == GDK_slash &&
- ! (event->state & (~GDK_SHIFT_MASK & gtk_accelerator_get_default_mod_mask ())))
+ ! (event->state & (~GDK_SHIFT_MASK & modifiers)))
{
location_popup_handler (impl, "/");
return TRUE;
|| event->keyval == GDK_ISO_Enter
|| event->keyval == GDK_KP_Enter
|| event->keyval == GDK_space)
+ && ((event->state && modifiers) == 0)
&& !(impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER))
{
NULL);
}
+/* Shows an error dialog about not being able to select a dragged file */
+static void
+error_selecting_dragged_file_dialog (GtkFileChooserDefault *impl,
+ const GtkFilePath *path,
+ GError *error)
+{
+ error_dialog (impl,
+ _("Could not select file"),
+ path, error);
+}
+
+static void
+file_list_drag_data_received_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time_,
+ gpointer data)
+{
+ GtkFileChooserDefault *impl;
+ GtkFileChooser *chooser;
+ gchar **uris;
+ char *uri;
+ GtkFilePath *path;
+ GError *error = NULL;
+ gint i;
+
+ impl = GTK_FILE_CHOOSER_DEFAULT (data);
+ chooser = GTK_FILE_CHOOSER (data);
+
+ /* Parse the text/uri-list string, navigate to the first one */
+ uris = g_uri_list_extract_uris (selection_data->data);
+ if (uris[0])
+ {
+ uri = uris[0];
+ path = gtk_file_system_uri_to_path (impl->file_system, uri);
+
+ if (path)
+ {
+ if ((impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
+ impl->action == GTK_FILE_CHOOSER_ACTION_SAVE) &&
+ uris[1] == 0 &&
+ check_is_folder (impl->file_system, path, NULL))
+ change_folder_and_display_error (impl, path);
+ else
+ {
+ gtk_file_chooser_default_unselect_all (chooser);
+ gtk_file_chooser_default_select_path (chooser, path, &error);
+ if (error)
+ error_selecting_dragged_file_dialog (impl, path, error);
+ else
+ browse_files_center_selected_row (impl);
+ }
+
+ gtk_file_path_free (path);
+ }
+ else
+ {
+ g_set_error (&error,
+ GTK_FILE_CHOOSER_ERROR,
+ GTK_FILE_CHOOSER_ERROR_BAD_FILENAME,
+ _("Could not select file '%s' "
+ "because it is an invalid path name."),
+ uri);
+ error_selecting_dragged_file_dialog (impl, NULL, error);
+ }
+
+
+ if (impl->select_multiple)
+ {
+ for (i = 1; uris[i]; i++)
+ {
+ uri = uris[i];
+ path = gtk_file_system_uri_to_path (impl->file_system, uri);
+
+ if (path)
+ {
+ gtk_file_chooser_default_select_path (chooser, path, &error);
+ if (error)
+ error_selecting_dragged_file_dialog (impl, path, error);
+
+ gtk_file_path_free (path);
+ }
+ }
+ }
+ }
+
+ g_strfreev (uris);
+
+ g_signal_stop_emission_by_name (widget, "drag-data-received");
+}
+
+/* Don't do anything with the drag_drop signal */
+static gboolean
+file_list_drag_drop_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time_,
+ GtkFileChooserDefault *impl)
+{
+ g_signal_stop_emission_by_name (widget, "drag-drop");
+ return TRUE;
+}
+
+/* Disable the normal tree drag motion handler, it makes it look like you're
+ dropping the dragged item onto a tree item */
+static gboolean
+file_list_drag_motion_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time_,
+ GtkFileChooserDefault *impl)
+{
+ g_signal_stop_emission_by_name (widget, "drag-motion");
+ return TRUE;
+}
+
/* Constructs the popup menu for the file list if needed */
static void
file_list_build_popup_menu (GtkFileChooserDefault *impl)
gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (impl->browse_files_tree_view), TRUE);
gtk_container_add (GTK_CONTAINER (swin), impl->browse_files_tree_view);
+
+ gtk_drag_dest_set (impl->browse_files_tree_view,
+ GTK_DEST_DEFAULT_ALL,
+ file_list_dest_targets,
+ num_file_list_dest_targets,
+ GDK_ACTION_COPY | GDK_ACTION_MOVE);
+
g_signal_connect (impl->browse_files_tree_view, "row-activated",
G_CALLBACK (list_row_activated), impl);
g_signal_connect (impl->browse_files_tree_view, "key-press-event",
g_signal_connect (impl->browse_files_tree_view, "button-press-event",
G_CALLBACK (list_button_press_event_cb), impl);
+ g_signal_connect (impl->browse_files_tree_view, "drag-data-received",
+ G_CALLBACK (file_list_drag_data_received_cb), impl);
+ g_signal_connect (impl->browse_files_tree_view, "drag-drop",
+ G_CALLBACK (file_list_drag_drop_cb), impl);
+ g_signal_connect (impl->browse_files_tree_view, "drag-motion",
+ G_CALLBACK (file_list_drag_motion_cb), impl);
+
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
gtk_tree_selection_set_select_function (selection,
list_select_func,
set_file_system_backend (GtkFileChooserDefault *impl,
const char *backend)
{
+ profile_start ("start for backend", backend ? backend : "default");
+
if (impl->file_system)
{
g_signal_handler_disconnect (impl->file_system, impl->volumes_changed_id);
G_CALLBACK (bookmarks_changed_cb),
impl);
}
+
+ profile_end ("end", NULL);
}
/* This function is basically a do_all function.
{
gtk_file_chooser_default_unselect_all (GTK_FILE_CHOOSER (impl));
- if (action == GTK_FILE_CHOOSER_ACTION_SAVE && impl->select_multiple)
+ if ((action == GTK_FILE_CHOOSER_ACTION_SAVE || action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
+ && impl->select_multiple)
{
- g_warning ("Multiple selection mode is not allowed in Save mode");
+ g_warning ("Tried to change the file chooser action to SAVE or CREATE_FOLDER, but "
+ "this is not allowed in multiple selection mode. Resetting the file chooser "
+ "to single selection mode.");
set_select_multiple (impl, FALSE, TRUE);
}
impl->action = action;
action);
}
break;
+
case GTK_FILE_CHOOSER_PROP_FILE_SYSTEM_BACKEND:
set_file_system_backend (impl, g_value_get_string (value));
break;
+
case GTK_FILE_CHOOSER_PROP_FILTER:
set_current_filter (impl, g_value_get_object (value));
break;
+
case GTK_FILE_CHOOSER_PROP_LOCAL_ONLY:
set_local_only (impl, g_value_get_boolean (value));
break;
+
case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET:
set_preview_widget (impl, g_value_get_object (value));
break;
+
case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET_ACTIVE:
impl->preview_widget_active = g_value_get_boolean (value);
update_preview_widget_visibility (impl);
break;
+
case GTK_FILE_CHOOSER_PROP_USE_PREVIEW_LABEL:
impl->use_preview_label = g_value_get_boolean (value);
update_preview_widget_visibility (impl);
break;
+
case GTK_FILE_CHOOSER_PROP_EXTRA_WIDGET:
set_extra_widget (impl, g_value_get_object (value));
break;
+
case GTK_FILE_CHOOSER_PROP_SELECT_MULTIPLE:
{
gboolean select_multiple = g_value_get_boolean (value);
- if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE && select_multiple)
+ if ((impl->action == GTK_FILE_CHOOSER_ACTION_SAVE || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
+ && select_multiple)
{
- g_warning ("Multiple selection mode is not allowed in Save mode");
+ g_warning ("Tried to set the file chooser to multiple selection mode, but this is "
+ "not allowed in SAVE or CREATE_FOLDER modes. Ignoring the change and "
+ "leaving the file chooser in single selection mode.");
return;
}
set_select_multiple (impl, select_multiple, FALSE);
}
break;
+
case GTK_FILE_CHOOSER_PROP_SHOW_HIDDEN:
{
gboolean show_hidden = g_value_get_boolean (value);
}
}
break;
+
+ case GTK_FILE_CHOOSER_PROP_DO_OVERWRITE_CONFIRMATION:
+ {
+ gboolean do_overwrite_confirmation = g_value_get_boolean (value);
+ impl->do_overwrite_confirmation = do_overwrite_confirmation;
+ }
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
case GTK_FILE_CHOOSER_PROP_ACTION:
g_value_set_enum (value, impl->action);
break;
+
case GTK_FILE_CHOOSER_PROP_FILTER:
g_value_set_object (value, impl->current_filter);
break;
+
case GTK_FILE_CHOOSER_PROP_LOCAL_ONLY:
g_value_set_boolean (value, impl->local_only);
break;
+
case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET:
g_value_set_object (value, impl->preview_widget);
break;
+
case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET_ACTIVE:
g_value_set_boolean (value, impl->preview_widget_active);
break;
+
case GTK_FILE_CHOOSER_PROP_USE_PREVIEW_LABEL:
g_value_set_boolean (value, impl->use_preview_label);
break;
+
case GTK_FILE_CHOOSER_PROP_EXTRA_WIDGET:
g_value_set_object (value, impl->extra_widget);
break;
+
case GTK_FILE_CHOOSER_PROP_SELECT_MULTIPLE:
g_value_set_boolean (value, impl->select_multiple);
break;
+
case GTK_FILE_CHOOSER_PROP_SHOW_HIDDEN:
g_value_set_boolean (value, impl->show_hidden);
break;
+
+ case GTK_FILE_CHOOSER_PROP_DO_OVERWRITE_CONFIRMATION:
+ g_value_set_boolean (value, impl->do_overwrite_confirmation);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
{
GtkFileChooserDefault *impl;
+ profile_start ("start", NULL);
+
impl = GTK_FILE_CHOOSER_DEFAULT (widget);
if (GTK_WIDGET_CLASS (parent_class)->style_set)
change_icon_theme (impl);
g_signal_emit_by_name (widget, "default-size-changed");
+
+ profile_end ("end", NULL);
}
static void
{
GtkFileChooserDefault *impl;
+ profile_start ("start", NULL);
+
impl = GTK_FILE_CHOOSER_DEFAULT (widget);
GTK_WIDGET_CLASS (parent_class)->map (widget);
}
bookmarks_changed_cb (impl->file_system, impl);
+
+ profile_end ("end", NULL);
}
static gboolean
{
GtkFileChooserDefault *impl;
+ profile_start ("start", NULL);
+
GDK_THREADS_ENTER ();
impl = GTK_FILE_CHOOSER_DEFAULT (data);
GDK_THREADS_LEAVE ();
+ profile_end ("end", NULL);
+
return FALSE;
}
gboolean have_hidden;
gboolean have_filtered;
+ profile_start ("start", NULL);
+
if (!only_one_path && !paths)
- return TRUE;
+ {
+ profile_end ("end", NULL);
+ return TRUE;
+ }
folder = gtk_file_system_get_folder (impl->file_system, parent_path, GTK_FILE_INFO_IS_HIDDEN, error);
if (!folder)
- return FALSE;
+ {
+ profile_end ("end", NULL);
+ return FALSE;
+ }
success = FALSE;
have_hidden = FALSE;
g_object_unref (folder);
if (!success)
- return FALSE;
+ {
+ profile_end ("end", NULL);
+ return FALSE;
+ }
if (have_hidden)
g_object_set (impl, "show-hidden", TRUE, NULL);
}
}
+ profile_end ("end", NULL);
return TRUE;
}
browse_files_model_finished_loading_cb (GtkFileSystemModel *model,
GtkFileChooserDefault *impl)
{
+ profile_start ("start", NULL);
+
if (impl->load_state == LOAD_PRELOAD)
{
load_remove_timer (impl);
/* We can't g_assert_not_reached(), as something other than us may have
* initiated a folder reload. See #165556.
*/
+ profile_end ("end", NULL);
return;
}
pending_select_paths_process (impl);
set_busy_cursor (impl, FALSE);
+
+ profile_end ("end", NULL);
}
/* Gets rid of the old list model and creates a new one for the current folder */
{
g_assert (impl->current_folder != NULL);
+ profile_start ("start", NULL);
+
load_remove_timer (impl); /* This changes the state to LOAD_EMPTY */
if (impl->browse_files_model)
if (!impl->browse_files_model)
{
set_busy_cursor (impl, FALSE);
+ profile_end ("end", NULL);
return FALSE;
}
install_list_model_filter (impl);
+ profile_end ("end", NULL);
+
return TRUE;
}
const GtkFileInfo *info;
GtkTreeIter iter;
GtkTreeIter child_iter;
+ gboolean change_entry;
- if (impl->action != GTK_FILE_CHOOSER_ACTION_SAVE)
+ if (!(impl->action == GTK_FILE_CHOOSER_ACTION_SAVE || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER))
return;
g_assert (!impl->select_multiple);
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
if (!gtk_tree_selection_get_selected (selection, NULL, &iter))
- return;
+ {
+ _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->save_file_name_entry), "");
+ return;
+ }
gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model,
&child_iter,
info = _gtk_file_system_model_get_info (impl->browse_files_model, &child_iter);
- if (!gtk_file_info_get_is_folder (info))
+ if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+ change_entry = !gtk_file_info_get_is_folder (info); /* We don't want the name to change when clicking on a folder... */
+ else
+ change_entry = TRUE; /* ... unless we are in CREATE_FOLDER mode */
+
+ if (change_entry)
_gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->save_file_name_entry),
gtk_file_info_get_display_name (info));
}
gtk_file_chooser_default_set_current_folder (GtkFileChooser *chooser,
const GtkFilePath *path,
GError **error)
+{
+ return gtk_file_chooser_default_update_current_folder (chooser, path, FALSE, error);
+}
+
+static gboolean
+gtk_file_chooser_default_update_current_folder (GtkFileChooser *chooser,
+ const GtkFilePath *path,
+ gboolean keep_trail,
+ GError **error)
{
GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
gboolean result;
+ profile_start ("start", (char *) path);
+
g_assert (path != NULL);
if (impl->local_only &&
GTK_FILE_CHOOSER_ERROR_BAD_FILENAME,
_("Cannot change to folder because it is not local"));
+ profile_end ("end - not local", (char *) path);
return FALSE;
}
/* Test validity of path here. */
if (!check_is_folder (impl->file_system, path, error))
- return FALSE;
+ {
+ profile_end ("end - not a folder", (char *) path);
+ return FALSE;
+ }
- if (!_gtk_path_bar_set_path (GTK_PATH_BAR (impl->browse_path_bar), path, error))
- return FALSE;
+ if (!_gtk_path_bar_set_path (GTK_PATH_BAR (impl->browse_path_bar), path, keep_trail, error))
+ {
+ profile_end ("end - could not set path bar", (char *) path);
+ return FALSE;
+ }
if (impl->current_folder != path)
{
g_signal_emit_by_name (impl, "selection-changed", 0);
+ profile_end ("end", NULL);
return result;
}
g_return_if_fail (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
|| impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER);
+ pending_select_paths_free (impl);
_gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->save_file_name_entry), name);
}
GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
gtk_tree_selection_unselect_all (selection);
+ pending_select_paths_free (impl);
}
-/* Checks whether the filename entry for the Save modes contains a valid filename */
-static GtkFilePath *
+/* Checks whether the filename entry for the Save modes contains a well-formed filename.
+ *
+ * is_well_formed_ret - whether what the user typed passes gkt_file_system_make_path()
+ *
+ * is_empty_ret - whether the file entry is totally empty
+ *
+ * is_file_part_empty_ret - whether the file part is empty (will be if user types "foobar/", and
+ * the path will be "$cwd/foobar")
+ */
+static void
check_save_entry (GtkFileChooserDefault *impl,
- gboolean *is_valid,
- gboolean *is_empty)
+ GtkFilePath **path_ret,
+ gboolean *is_well_formed_ret,
+ gboolean *is_empty_ret,
+ gboolean *is_file_part_empty_ret)
{
GtkFileChooserEntry *chooser_entry;
const GtkFilePath *current_folder;
chooser_entry = GTK_FILE_CHOOSER_ENTRY (impl->save_file_name_entry);
+ if (strlen (gtk_entry_get_text (GTK_ENTRY (chooser_entry))) == 0)
+ {
+ *path_ret = NULL;
+ *is_well_formed_ret = TRUE;
+ *is_empty_ret = TRUE;
+ *is_file_part_empty_ret = TRUE;
+
+ return;
+ }
+
+ *is_empty_ret = FALSE;
+
current_folder = _gtk_file_chooser_entry_get_current_folder (chooser_entry);
file_part = _gtk_file_chooser_entry_get_file_part (chooser_entry);
if (!file_part || file_part[0] == '\0')
{
- *is_valid = FALSE;
- *is_empty = TRUE;
- return NULL;
+ *path_ret = gtk_file_path_copy (current_folder);
+ *is_well_formed_ret = TRUE;
+ *is_file_part_empty_ret = TRUE;
+
+ return;
}
- *is_empty = FALSE;
+ *is_file_part_empty_ret = FALSE;
error = NULL;
path = gtk_file_system_make_path (impl->file_system, current_folder, file_part, &error);
if (!path)
{
error_building_filename_dialog (impl, current_folder, file_part, error);
- *is_valid = FALSE;
- return NULL;
+ *path_ret = NULL;
+ *is_well_formed_ret = FALSE;
+
+ return;
}
- *is_valid = TRUE;
- return path;
+ *path_ret = path;
+ *is_well_formed_ret = TRUE;
}
struct get_paths_closure {
if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
|| impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
{
- gboolean is_valid, is_empty;
+ gboolean is_well_formed, is_empty, is_file_part_empty;
- info.path_from_entry = check_save_entry (impl, &is_valid, &is_empty);
- if (!is_valid && !is_empty)
+ check_save_entry (impl, &info.path_from_entry, &is_well_formed, &is_empty, &is_file_part_empty);
+
+ if (!is_well_formed)
return NULL;
+
+ if (!is_empty)
+ {
+ if (is_file_part_empty && impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+ {
+ gtk_file_path_free (info.path_from_entry);
+ return NULL;
+ }
+ }
}
if (!info.path_from_entry || impl->select_multiple)
change_folder_and_display_error (impl, closure.path);
}
+/* Gets the GtkFileInfo for the selected row in the file list; assumes single
+ * selection mode.
+ */
+static const GtkFileInfo *
+get_selected_file_info_from_file_list (GtkFileChooserDefault *impl,
+ gboolean *had_selection)
+{
+ GtkTreeSelection *selection;
+ GtkTreeIter iter, child_iter;
+ const GtkFileInfo *info;
+
+ g_assert (!impl->select_multiple);
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
+ if (!gtk_tree_selection_get_selected (selection, NULL, &iter))
+ {
+ *had_selection = FALSE;
+ return NULL;
+ }
+
+ *had_selection = TRUE;
+
+ gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model,
+ &child_iter,
+ &iter);
+
+ info = _gtk_file_system_model_get_info (impl->browse_files_model, &child_iter);
+ return info;
+}
+
+/* Gets the display name of the selected file in the file list; assumes single
+ * selection mode and that something is selected.
+ */
+static const gchar *
+get_display_name_from_file_list (GtkFileChooserDefault *impl)
+{
+ const GtkFileInfo *info;
+ gboolean had_selection;
+
+ info = get_selected_file_info_from_file_list (impl, &had_selection);
+ g_assert (had_selection);
+ g_assert (info != NULL);
+
+ return gtk_file_info_get_display_name (info);
+}
+
+static void
+add_custom_button_to_dialog (GtkDialog *dialog,
+ const gchar *mnemonic_label,
+ const gchar *stock_id,
+ gint response_id)
+{
+ GtkWidget *button;
+
+ button = gtk_button_new_with_mnemonic (mnemonic_label);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_button_set_image (GTK_BUTTON (button),
+ gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_BUTTON));
+ gtk_widget_show (button);
+
+ gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button, response_id);
+}
+
+/* Presents an overwrite confirmation dialog; returns whether we should accept
+ * the filename.
+ */
+static gboolean
+confirm_dialog_should_accept_filename (GtkFileChooserDefault *impl,
+ const gchar *file_part,
+ const gchar *folder_display_name)
+{
+ GtkWindow *toplevel;
+ GtkWidget *dialog;
+ int response;
+
+ toplevel = get_toplevel (GTK_WIDGET (impl));
+
+ dialog = gtk_message_dialog_new (toplevel,
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_NONE,
+ _("A file named \"%s\" already exists. Do you want to replace it?"),
+ file_part);
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ _("The file already exists in \"%s\". Replacing it will "
+ "overwrite its contents."),
+ folder_display_name);
+
+ gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+ add_custom_button_to_dialog (GTK_DIALOG (dialog), _("_Replace"), GTK_STOCK_SAVE_AS, GTK_RESPONSE_ACCEPT);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
+
+ if (toplevel->group)
+ gtk_window_group_add_window (toplevel->group, GTK_WINDOW (dialog));
+
+ response = gtk_dialog_run (GTK_DIALOG (dialog));
+
+ gtk_widget_destroy (dialog);
+
+ return (response == GTK_RESPONSE_ACCEPT);
+}
+
+static char *
+get_display_name_for_folder (GtkFileChooserDefault *impl,
+ const GtkFilePath *path)
+{
+ char *display_name;
+ GtkFilePath *parent_path;
+ GtkFileFolder *parent_folder;
+ GtkFileInfo *info;
+
+ display_name = NULL;
+ parent_path = NULL;
+ parent_folder = NULL;
+ info = NULL;
+
+ if (!gtk_file_system_get_parent (impl->file_system, path, &parent_path, NULL))
+ goto out;
+
+ parent_folder = gtk_file_system_get_folder (impl->file_system,
+ parent_path ? parent_path : path,
+ GTK_FILE_INFO_DISPLAY_NAME,
+ NULL);
+ if (!parent_folder)
+ goto out;
+
+ info = gtk_file_folder_get_info (parent_folder, parent_path ? path : NULL, NULL);
+ if (!info)
+ goto out;
+
+ display_name = g_strdup (gtk_file_info_get_display_name (info));
+
+ out:
+
+ if (parent_path)
+ gtk_file_path_free (parent_path);
+
+ if (parent_folder)
+ g_object_unref (parent_folder);
+
+ if (info)
+ gtk_file_info_free (info);
+
+ return display_name;
+}
+
+/* Does overwrite confirmation if appropriate, and returns whether the dialog
+ * should respond. Can get the file part from the file list or the save entry.
+ */
+static gboolean
+should_respond_after_confirm_overwrite (GtkFileChooserDefault *impl,
+ const gchar *file_part,
+ const GtkFilePath *parent_path)
+{
+ GtkFileChooserConfirmation conf;
+
+ if (!impl->do_overwrite_confirmation)
+ return TRUE;
+
+ conf = GTK_FILE_CHOOSER_CONFIRMATION_CONFIRM;
+
+ g_signal_emit_by_name (impl, "confirm-overwrite", &conf);
+
+ switch (conf)
+ {
+ case GTK_FILE_CHOOSER_CONFIRMATION_CONFIRM:
+ {
+ char *parent_display_name;
+ gboolean retval;
+
+ g_assert (file_part != NULL);
+
+ parent_display_name = get_display_name_for_folder (impl, parent_path);
+ if (!parent_display_name)
+ return TRUE; /* Huh? Did the folder disappear? Let the caller deal with it */
+
+ retval = confirm_dialog_should_accept_filename (impl, file_part, parent_display_name);
+ g_free (parent_display_name);
+ return retval;
+ }
+
+ case GTK_FILE_CHOOSER_CONFIRMATION_ACCEPT_FILENAME:
+ return TRUE;
+
+ case GTK_FILE_CHOOSER_CONFIRMATION_SELECT_AGAIN:
+ return FALSE;
+
+ default:
+ g_assert_not_reached ();
+ return FALSE;
+ }
+}
+
/* Implementation for GtkFileChooserEmbed::should_respond() */
static gboolean
gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
if (current_focus == impl->browse_files_tree_view)
{
+ /* The following array encodes what we do based on the impl->action and the
+ * number of files selected.
+ */
+ typedef enum {
+ NOOP, /* Do nothing (don't respond) */
+ RESPOND, /* Respond immediately */
+ RESPOND_OR_SWITCH, /* Respond immediately if the selected item is a file; switch to it if it is a folder */
+ ALL_FILES, /* Respond only if everything selected is a file */
+ ALL_FOLDERS, /* Respond only if everything selected is a folder */
+ SAVE_ENTRY, /* Go to the code for handling the save entry */
+ NOT_REACHED /* Sanity check */
+ } ActionToTake;
+ static const ActionToTake what_to_do[4][3] = {
+ /* 0 selected 1 selected many selected */
+ /* ACTION_OPEN */ { NOOP, RESPOND_OR_SWITCH, ALL_FILES },
+ /* ACTION_SAVE */ { SAVE_ENTRY, RESPOND_OR_SWITCH, NOT_REACHED },
+ /* ACTION_SELECT_FOLDER */ { RESPOND, ALL_FOLDERS, ALL_FOLDERS },
+ /* ACTION_CREATE_FOLDER */ { SAVE_ENTRY, ALL_FOLDERS, NOT_REACHED }
+ };
+
int num_selected;
gboolean all_files, all_folders;
+ int k;
+ ActionToTake action;
file_list:
+ g_assert (impl->action >= GTK_FILE_CHOOSER_ACTION_OPEN && impl->action <= GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER);
+
selection_check (impl, &num_selected, &all_files, &all_folders);
- if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
+ if (num_selected > 2)
+ k = 2;
+ else
+ k = num_selected;
+
+ action = what_to_do [impl->action] [k];
+
+ switch (action)
{
- if (num_selected != 1)
- return TRUE; /* zero means current folder; more than one means use the whole selection */
- else if (current_focus != impl->browse_files_tree_view)
+ case NOOP:
+ return FALSE;
+
+ case RESPOND:
+ return TRUE;
+
+ case RESPOND_OR_SWITCH:
+ g_assert (num_selected == 1);
+
+ if (all_folders)
{
- /* a single folder is selected and a button was clicked */
- switch_to_selected_folder (impl);
- return TRUE;
+ switch_to_selected_folder (impl);
+ return FALSE;
}
- }
-
- if (num_selected == 0)
- {
- if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
- || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
- goto save_entry; /* it makes sense to use the typed name */
+ else if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+ return should_respond_after_confirm_overwrite (impl,
+ get_display_name_from_file_list (impl),
+ impl->current_folder);
else
- return FALSE;
- }
+ return TRUE;
- if (num_selected == 1 && all_folders)
- {
- switch_to_selected_folder (impl);
- return FALSE;
+ case ALL_FILES:
+ return all_files;
+
+ case ALL_FOLDERS:
+ return all_folders;
+
+ case SAVE_ENTRY:
+ goto save_entry;
+
+ default:
+ g_assert_not_reached ();
}
- else
- return all_files;
}
else if (current_focus == impl->save_file_name_entry)
{
GtkFilePath *path;
- gboolean is_valid, is_empty;
+ gboolean is_well_formed, is_empty, is_file_part_empty;
gboolean is_folder;
gboolean retval;
- GtkFileChooserEntry *entry;
+ GtkFileChooserEntry *entry;
+ GError *error;
save_entry:
|| impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER);
entry = GTK_FILE_CHOOSER_ENTRY (impl->save_file_name_entry);
- path = check_save_entry (impl, &is_valid, &is_empty);
+ check_save_entry (impl, &path, &is_well_formed, &is_empty, &is_file_part_empty);
- if (!is_empty && !is_valid)
+ if (is_empty || !is_well_formed)
return FALSE;
- if (is_empty)
- path = gtk_file_path_copy (_gtk_file_chooser_entry_get_current_folder (entry));
-
- is_folder = check_is_folder (impl->file_system, path, NULL);
+ g_assert (path != NULL);
+
+ error = NULL;
+ is_folder = check_is_folder (impl->file_system, path, &error);
if (is_folder)
{
- _gtk_file_chooser_entry_set_file_part (entry, "");
- change_folder_and_display_error (impl, path);
- retval = FALSE;
+ if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+ {
+ _gtk_file_chooser_entry_set_file_part (entry, "");
+ change_folder_and_display_error (impl, path);
+ retval = FALSE;
+ }
+ else /* GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER */
+ {
+ /* The folder already exists, so we do not need to create it.
+ * Just respond to terminate the dialog.
+ */
+ retval = TRUE;
+ }
}
else
{
- /* check that everything up to the last component exists */
- gtk_file_path_free (path);
- path = gtk_file_path_copy (_gtk_file_chooser_entry_get_current_folder (entry));
- is_folder = check_is_folder (impl->file_system, path, NULL);
- if (!is_folder)
+ gboolean file_exists_and_is_not_folder;
+
+ file_exists_and_is_not_folder = g_error_matches (error, GTK_FILE_SYSTEM_ERROR, GTK_FILE_SYSTEM_ERROR_NOT_FOLDER);
+
+ if (impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER && file_exists_and_is_not_folder)
{
- change_folder_and_display_error (impl, path);
+ /* Oops, the user typed the name of an existing path which is not a folder */
+ error_creating_folder_over_existing_file_dialog (impl, path, error);
+ error = NULL; /* as it will be freed below for the general case */
retval = FALSE;
}
else
- retval = TRUE;
+ {
+ GtkFilePath *parent_path;
+ gboolean parent_is_folder;
+
+ /* check that everything up to the last component exists */
+
+ parent_path = gtk_file_path_copy (_gtk_file_chooser_entry_get_current_folder (entry));
+ parent_is_folder = check_is_folder (impl->file_system, parent_path, NULL);
+ if (parent_is_folder)
+ {
+ if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+ {
+ if (file_exists_and_is_not_folder)
+ {
+ const char *file_part;
+
+ file_part = _gtk_file_chooser_entry_get_file_part (GTK_FILE_CHOOSER_ENTRY (impl->save_file_name_entry));
+ retval = should_respond_after_confirm_overwrite (impl, file_part, parent_path);
+ }
+ else
+ retval = TRUE;
+ }
+ else /* GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER */
+ {
+ GError *create_error;
+
+ create_error = NULL;
+ if (gtk_file_system_create_folder (impl->file_system, path, &create_error))
+ retval = TRUE;
+ else
+ {
+ error_creating_folder_dialog (impl, path, create_error);
+ retval = FALSE;
+ }
+ }
+ }
+ else
+ {
+ /* This will display an error, which is what we want */
+ change_folder_and_display_error (impl, parent_path);
+ retval = FALSE;
+ }
+
+ gtk_file_path_free (parent_path);
+ }
+
+ if (error != NULL)
+ g_error_free (error);
}
gtk_file_path_free (path);
/* See if we are in the new folder editable row for Save mode */
if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
{
- GtkTreeSelection *selection;
- GtkTreeIter iter, child_iter;
const GtkFileInfo *info;
+ gboolean had_selection;
- g_assert (!impl->select_multiple);
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
- if (!gtk_tree_selection_get_selected (selection, NULL, &iter))
- return;
+ info = get_selected_file_info_from_file_list (impl, &had_selection);
+ if (!had_selection)
+ goto out; /* normal processing */
- gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model,
- &child_iter,
- &iter);
-
- info = _gtk_file_system_model_get_info (impl->browse_files_model, &child_iter);
if (!info)
return; /* We are on the editable row for New Folder */
}
+ out:
+
update_chooser_entry (impl);
check_preview_change (impl);
bookmarks_check_add_sensitivity (impl);
GdkPixbuf *pixbuf;
const GtkFileInfo *info;
gboolean sensitive = TRUE;
+
+ profile_start ("start", NULL);
info = get_list_file_info (impl, iter);
if (pixbuf)
g_object_unref (pixbuf);
+
+ profile_end ("end", NULL);
}
static void
}
time_mtime = gtk_file_info_get_modification_time (info);
- g_date_set_time (&mtime, (GTime) time_mtime);
- time_now = (GTime ) time (NULL);
- g_date_set_time (&now, (GTime) time_now);
-
- days_diff = g_date_get_julian (&now) - g_date_get_julian (&mtime);
-
- if (days_diff == 0)
- strcpy (buf, _("Today"));
- else if (days_diff == 1)
- strcpy (buf, _("Yesterday"));
+ if (time_mtime == 0)
+ strcpy (buf, _("Unknown"));
else
{
- char *format;
+ g_date_set_time (&mtime, (GTime) time_mtime);
+
+ time_now = (GTime ) time (NULL);
+ g_date_set_time (&now, (GTime) time_now);
- if (days_diff > 1 && days_diff < 7)
- format = "%A"; /* Days from last week */
+ days_diff = g_date_get_julian (&now) - g_date_get_julian (&mtime);
+
+ if (days_diff == 0)
+ strcpy (buf, _("Today"));
+ else if (days_diff == 1)
+ strcpy (buf, _("Yesterday"));
else
- format = "%x"; /* Any other date */
+ {
+ char *format;
+
+ if (days_diff > 1 && days_diff < 7)
+ format = "%A"; /* Days from last week */
+ else
+ format = "%x"; /* Any other date */
- if (g_date_strftime (buf, sizeof (buf), format, &mtime) == 0)
- strcpy (buf, _("Unknown"));
+ if (g_date_strftime (buf, sizeof (buf), format, &mtime) == 0)
+ strcpy (buf, _("Unknown"));
+ }
}
if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
accept_stock, GTK_RESPONSE_ACCEPT,
NULL);
+ if (toplevel->group)
+ gtk_window_group_add_window (toplevel->group, GTK_WINDOW (dialog));
+
gtk_window_set_default_size (GTK_WINDOW (dialog), 300, -1);
gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 2);