Commit 40c79aec authored by Christian Neumair's avatar Christian Neumair Committed by Christian Neumair

No more overlapping desktop icons.

2008-08-24  Christian Neumair  <cneumair@gnome.org>

	* libnautilus-private/nautilus-directory.c
	(nautilus_directory_schedule_position_set):
	* libnautilus-private/nautilus-file.c (get_time_from_time_string),
	(nautilus_file_get_time_metadata),
	(nautilus_file_set_time_metadata):
	* libnautilus-private/nautilus-file.h:
	* libnautilus-private/nautilus-icon-container.c
	(lay_down_icons_vertical_desktop),
	(nautilus_icon_container_class_init),
	(nautilus_icon_container_instance_init),
	(nautilus_icon_container_clear), (finish_adding_new_icons),
	(is_old_or_unknown_icon_data), (nautilus_icon_container_add),
	(nautilus_icon_container_begin_loading),
	(store_layout_timestamps_now),
	(nautilus_icon_container_end_loading),
	(nautilus_icon_container_get_store_layout_timestamps),
	(nautilus_icon_container_set_store_layout_timestamps):
	* libnautilus-private/nautilus-icon-container.h:
	* libnautilus-private/nautilus-icon-dnd.c (handle_local_move):
	* libnautilus-private/nautilus-icon-private.h:
	* libnautilus-private/nautilus-metadata.h:
	* src/file-manager/fm-desktop-icon-view.c
	(fm_desktop_icon_view_init):
	* src/file-manager/fm-directory-view.c (done_loading),
	(display_pending_files), (fm_directory_view_end_loading),
	(fm_directory_view_stop), (fm_directory_view_class_init):
	* src/file-manager/fm-directory-view.h:
	* src/file-manager/fm-icon-view.c (fm_icon_view_add_file),
	(fm_icon_view_begin_loading), (fm_icon_view_end_loading),
	(fm_icon_view_screen_changed), (get_stored_layout_timestamp),
	(store_layout_timestamp), (create_icon_container):
	No more overlapping desktop icons.

	Implement a layout timestamp concept where each file on the desktop
	and the desktop directory itself is timestamped when a full layout
	happened. Iff files were not part of the last layout (or added more
	recently, through DND), they are treated as being “semi-positioned“
	(cf. 2005-11-07).
	This means that they may be freely shifted around, starting from their
	last position, until they don't overlap and fully laid out items.
	Should inter alia fix #330298.

svn path=/trunk/; revision=14519
parent abc9377f
2008-08-24 Christian Neumair <cneumair@gnome.org>
* libnautilus-private/nautilus-directory.c
(nautilus_directory_schedule_position_set):
* libnautilus-private/nautilus-file.c (get_time_from_time_string),
(nautilus_file_get_time_metadata),
(nautilus_file_set_time_metadata):
* libnautilus-private/nautilus-file.h:
* libnautilus-private/nautilus-icon-container.c
(lay_down_icons_vertical_desktop),
(nautilus_icon_container_class_init),
(nautilus_icon_container_instance_init),
(nautilus_icon_container_clear), (finish_adding_new_icons),
(is_old_or_unknown_icon_data), (nautilus_icon_container_add),
(nautilus_icon_container_begin_loading),
(store_layout_timestamps_now),
(nautilus_icon_container_end_loading),
(nautilus_icon_container_get_store_layout_timestamps),
(nautilus_icon_container_set_store_layout_timestamps):
* libnautilus-private/nautilus-icon-container.h:
* libnautilus-private/nautilus-icon-dnd.c (handle_local_move):
* libnautilus-private/nautilus-icon-private.h:
* libnautilus-private/nautilus-metadata.h:
* src/file-manager/fm-desktop-icon-view.c
(fm_desktop_icon_view_init):
* src/file-manager/fm-directory-view.c (done_loading),
(display_pending_files), (fm_directory_view_end_loading),
(fm_directory_view_stop), (fm_directory_view_class_init):
* src/file-manager/fm-directory-view.h:
* src/file-manager/fm-icon-view.c (fm_icon_view_add_file),
(fm_icon_view_begin_loading), (fm_icon_view_end_loading),
(fm_icon_view_screen_changed), (get_stored_layout_timestamp),
(store_layout_timestamp), (create_icon_container):
No more overlapping desktop icons.
Implement a layout timestamp concept where each file on the desktop
and the desktop directory itself is timestamped when a full layout
happened. Iff files were not part of the last layout (or added more
recently, through DND), they are treated as being “semi-positioned“
(cf. 2005-11-07).
This means that they may be freely shifted around, starting from their
last position, until they don't overlap and fully laid out items.
Should inter alia fix #330298.
2008-08-24 Christian Neumair <cneumair@gnome.org>
* libnautilus-private/nautilus-icon-container.c
......
......@@ -1591,6 +1591,9 @@ nautilus_directory_schedule_position_set (GList *position_setting_list)
const NautilusFileChangesQueuePosition *item;
NautilusFile *file;
char str[64];
time_t now;
time (&now);
for (p = position_setting_list; p != NULL; p = p->next) {
item = (NautilusFileChangesQueuePosition *) p->data;
......@@ -1608,6 +1611,18 @@ nautilus_directory_schedule_position_set (GList *position_setting_list)
NULL,
str);
if (item->set) {
nautilus_file_set_time_metadata
(file,
NAUTILUS_METADATA_KEY_ICON_POSITION_TIMESTAMP,
now);
} else {
nautilus_file_set_time_metadata
(file,
NAUTILUS_METADATA_KEY_ICON_POSITION_TIMESTAMP,
UNDEFINED_TIME);
}
if (item->set) {
g_snprintf (str, sizeof (str), "%d", item->screen);
} else {
......
......@@ -2976,6 +2976,62 @@ nautilus_file_get_integer_metadata (NautilusFile *file,
default_metadata);
}
static gboolean
get_time_from_time_string (const char *time_string,
time_t *time)
{
long scanned_time;
char c;
g_assert (time != NULL);
/* Only accept string if it has one integer with nothing
* afterwards.
*/
if (time_string == NULL ||
sscanf (time_string, "%ld%c", &scanned_time, &c) != 1) {
return FALSE;
}
*time = (time_t) scanned_time;
return TRUE;
}
time_t
nautilus_file_get_time_metadata (NautilusFile *file,
const char *key)
{
time_t time;
char *time_string;
time_string = nautilus_file_get_metadata (file, key, NULL);
if (!get_time_from_time_string (time_string, &time)) {
time = UNDEFINED_TIME;
}
g_free (time_string);
return time;
}
void
nautilus_file_set_time_metadata (NautilusFile *file,
const char *key,
time_t time)
{
char time_str[21];
char *metadata;
if (time != UNDEFINED_TIME) {
/* 2^64 turns out to be 20 characters */
snprintf (time_str, 20, "%ld", time);
time_str[20] = '\0';
metadata = time_str;
} else {
metadata = NULL;
}
nautilus_file_set_metadata (file, key, NULL, metadata);
}
void
nautilus_file_set_boolean_metadata (NautilusFile *file,
......
......@@ -330,6 +330,14 @@ void nautilus_file_set_integer_metadata (Nautilu
int default_metadata,
int metadata);
#define UNDEFINED_TIME ((time_t) (-1))
time_t nautilus_file_get_time_metadata (NautilusFile *file,
const char *key);
void nautilus_file_set_time_metadata (NautilusFile *file,
const char *key,
time_t time);
/* Attributes for file objects as user-displayable strings. */
char * nautilus_file_get_string_attribute (NautilusFile *file,
......
......@@ -152,6 +152,9 @@
/* Copied from NautilusIconContainer */
#define NAUTILUS_ICON_CONTAINER_SEARCH_DIALOG_TIMEOUT 5000
/* Copied from NautilusFile */
#define UNDEFINED_TIME ((time_t) (-1))
enum {
ACTION_ACTIVATE,
ACTION_MENU,
......@@ -216,6 +219,8 @@ static double get_mirror_x_position (NautilusIconContai
NautilusIcon *icon,
double x);
static void store_layout_timestamps_now (NautilusIconContainer *container);
static gpointer accessible_parent_class;
static GQuark accessible_private_data_quark = 0;
......@@ -251,6 +256,8 @@ enum {
GET_ICON_DROP_TARGET_URI,
GET_STORED_ICON_POSITION,
ICON_POSITION_CHANGED,
GET_STORED_LAYOUT_TIMESTAMP,
STORE_LAYOUT_TIMESTAMP,
ICON_TEXT_CHANGED,
ICON_STRETCH_STARTED,
ICON_STRETCH_ENDED,
......@@ -1925,7 +1932,6 @@ lay_down_icons_vertical_desktop (NautilusIconContainer *container, GList *icons)
/* Start the icon in the first column */
x = DESKTOP_PAD_HORIZONTAL + (SNAP_SIZE_X / 2) - ((icon_rect.x1 - icon_rect.x0) / 2);
y = DESKTOP_PAD_VERTICAL + SNAP_SIZE_Y - (icon_rect.y1 - icon_rect.y0);
g_message ("got rect y: %f", icon_rect.y1 - icon_rect.y0);
find_empty_location (container,
grid,
......@@ -5523,6 +5529,28 @@ nautilus_icon_container_class_init (NautilusIconContainerClass *class)
G_TYPE_BOOLEAN, 2,
G_TYPE_POINTER,
G_TYPE_POINTER);
signals[GET_STORED_LAYOUT_TIMESTAMP]
= g_signal_new ("get_stored_layout_timestamp",
G_TYPE_FROM_CLASS (class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (NautilusIconContainerClass,
get_stored_layout_timestamp),
NULL, NULL,
eel_marshal_BOOLEAN__POINTER_POINTER,
G_TYPE_BOOLEAN, 2,
G_TYPE_POINTER,
G_TYPE_POINTER);
signals[STORE_LAYOUT_TIMESTAMP]
= g_signal_new ("store_layout_timestamp",
G_TYPE_FROM_CLASS (class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (NautilusIconContainerClass,
store_layout_timestamp),
NULL, NULL,
eel_marshal_BOOLEAN__POINTER_POINTER,
G_TYPE_BOOLEAN, 2,
G_TYPE_POINTER,
G_TYPE_POINTER);
signals[LAYOUT_CHANGED]
= g_signal_new ("layout_changed",
G_TYPE_FROM_CLASS (class),
......@@ -5877,6 +5905,7 @@ nautilus_icon_container_instance_init (NautilusIconContainer *container)
details = g_new0 (NautilusIconContainerDetails, 1);
details->icon_set = g_hash_table_new (g_direct_hash, g_direct_equal);
details->layout_timestamp = UNDEFINED_TIME;
details->zoom_level = NAUTILUS_ZOOM_LEVEL_STANDARD;
......@@ -6113,6 +6142,8 @@ nautilus_icon_container_clear (NautilusIconContainer *container)
g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container));
details = container->details;
details->layout_timestamp = UNDEFINED_TIME;
details->store_layout_timestamps_when_finishing_new_icons = FALSE;
if (details->icons == NULL) {
return;
......@@ -6747,13 +6778,12 @@ finish_adding_new_icons (NautilusIconContainer *container)
no_position_icons = semi_position_icons = NULL;
for (p = new_icons; p != NULL; p = p->next) {
icon = p->data;
if (assign_icon_position (container, icon)) {
if (!container->details->auto_layout && icon->has_lazy_position) {
semi_position_icons = g_list_prepend (semi_position_icons, icon);
}
} else {
no_position_icons = g_list_prepend (no_position_icons, icon);
}
if (icon->has_lazy_position) {
assign_icon_position (container, icon);
semi_position_icons = g_list_prepend (semi_position_icons, icon);
} else if (!assign_icon_position (container, icon)) {
no_position_icons = g_list_prepend (no_position_icons, icon);
}
finish_adding_icon (container, icon);
}
......@@ -6780,6 +6810,7 @@ finish_adding_new_icons (NautilusIconContainer *container)
for (p = semi_position_icons; p != NULL; p = p->next) {
NautilusIcon *icon;
NautilusIconPosition position;
int x, y;
icon = p->data;
......@@ -6791,7 +6822,12 @@ finish_adding_new_icons (NautilusIconContainer *container)
icon_set_position (icon, x, y);
position.x = icon->x;
position.y = icon->y;
position.scale = icon->scale;
placement_grid_mark_icon (grid, icon);
g_signal_emit (container, signals[ICON_POSITION_CHANGED], 0,
icon->data, &position);
/* ensure that next time we run this code, the formerly semi-positioned
* icons are treated as being positioned. */
......@@ -6808,28 +6844,50 @@ finish_adding_new_icons (NautilusIconContainer *container)
g_assert (!container->details->auto_layout);
sort_icons (container, &no_position_icons);
get_all_icon_bounds (container, NULL, NULL, NULL, &bottom, BOUNDS_USAGE_FOR_LAYOUT);
lay_down_icons (container, no_position_icons, bottom + ICON_PAD_BOTTOM);
if (nautilus_icon_container_get_is_desktop (container)) {
lay_down_icons (container, no_position_icons, CONTAINER_PAD_TOP);
} else {
get_all_icon_bounds (container, NULL, NULL, NULL, &bottom, BOUNDS_USAGE_FOR_LAYOUT);
lay_down_icons (container, no_position_icons, bottom + ICON_PAD_BOTTOM);
}
g_list_free (no_position_icons);
}
if (container->details->store_layout_timestamps_when_finishing_new_icons) {
store_layout_timestamps_now (container);
container->details->store_layout_timestamps_when_finishing_new_icons = FALSE;
}
}
static gboolean
is_old_or_unknown_icon_data (NautilusIconContainer *container,
NautilusIconData *data)
{
time_t timestamp;
gboolean success;
if (container->details->layout_timestamp == UNDEFINED_TIME) {
/* don't know */
return FALSE;
}
g_signal_emit (container,
signals[GET_STORED_LAYOUT_TIMESTAMP], 0,
data, &timestamp, &success);
return (!success || timestamp < container->details->layout_timestamp);
}
/**
* nautilus_icon_container_add:
* @container: A NautilusIconContainer
* @data: Icon data.
* @has_lazy_position: Whether the saved icon position should only be used
* if the previous icon position is free. If the position
* is occupied, another position near the last one will
* be used.
*
* Add icon to represent @data to container.
* Returns FALSE if there was already such an icon.
**/
gboolean
nautilus_icon_container_add (NautilusIconContainer *container,
NautilusIconData *data,
gboolean has_lazy_position)
NautilusIconData *data)
{
NautilusIconContainerDetails *details;
NautilusIcon *icon;
......@@ -6849,7 +6907,12 @@ nautilus_icon_container_add (NautilusIconContainer *container,
icon->data = data;
icon->x = ICON_UNPOSITIONED_VALUE;
icon->y = ICON_UNPOSITIONED_VALUE;
icon->has_lazy_position = has_lazy_position;
/* Whether the saved icon position should only be used
* if the previous icon position is free. If the position
* is occupied, another position near the last one will
*/
icon->has_lazy_position = is_old_or_unknown_icon_data (container, data);
icon->scale = 1.0;
icon->item = NAUTILUS_ICON_CANVAS_ITEM
(eel_canvas_item_new (EEL_CANVAS_GROUP (EEL_CANVAS (container)->root),
......@@ -9151,5 +9214,68 @@ nautilus_icon_container_get_max_layout_lines (NautilusIconContainer *container)
return limit;
}
void
nautilus_icon_container_begin_loading (NautilusIconContainer *container)
{
gboolean dummy;
if (nautilus_icon_container_get_store_layout_timestamps (container)) {
container->details->layout_timestamp = UNDEFINED_TIME;
g_signal_emit (container,
signals[GET_STORED_LAYOUT_TIMESTAMP], 0,
NULL, &container->details->layout_timestamp, &dummy);
}
}
static void
store_layout_timestamps_now (NautilusIconContainer *container)
{
NautilusIcon *icon;
GList *p;
gboolean dummy;
container->details->layout_timestamp = time (NULL);
g_signal_emit (container,
signals[STORE_LAYOUT_TIMESTAMP], 0,
NULL, &container->details->layout_timestamp, &dummy);
for (p = container->details->icons; p != NULL; p = p->next) {
icon = p->data;
g_signal_emit (container,
signals[STORE_LAYOUT_TIMESTAMP], 0,
icon->data, &container->details->layout_timestamp, &dummy);
}
}
void
nautilus_icon_container_end_loading (NautilusIconContainer *container,
gboolean all_icons_added)
{
if (all_icons_added &&
nautilus_icon_container_get_store_layout_timestamps (container)) {
if (container->details->new_icons == NULL) {
store_layout_timestamps_now (container);
} else {
container->details->store_layout_timestamps_when_finishing_new_icons = TRUE;
}
}
}
gboolean
nautilus_icon_container_get_store_layout_timestamps (NautilusIconContainer *container)
{
return container->details->store_layout_timestamps;
}
void
nautilus_icon_container_set_store_layout_timestamps (NautilusIconContainer *container,
gboolean store_layout_timestamps)
{
container->details->store_layout_timestamps = store_layout_timestamps;
}
#endif /* ! NAUTILUS_OMIT_SELF_CHECK */
......@@ -176,6 +176,24 @@ typedef struct {
char * (* get_icon_drop_target_uri) (NautilusIconContainer *container,
NautilusIconData *data);
/* If icon data is NULL, the layout timestamp of the container should be retrieved.
* That is the time when the container displayed a fully loaded directory with
* all icon positions assigned.
*
* If icon data is not NULL, the position timestamp of the icon should be retrieved.
* That is the time when the file (i.e. icon data payload) was last displayed in a
* fully loaded directory with all icon positions assigned.
*/
gboolean (* get_stored_layout_timestamp) (NautilusIconContainer *container,
NautilusIconData *data,
time_t *time);
/* If icon data is NULL, the layout timestamp of the container should be stored.
* If icon data is not NULL, the position timestamp of the container should be stored.
*/
gboolean (* store_layout_timestamp) (NautilusIconContainer *container,
NautilusIconData *data,
const time_t *time);
/* Notifications for the whole container. */
void (* band_select_started) (NautilusIconContainer *container);
void (* band_select_ended) (NautilusIconContainer *container);
......@@ -214,8 +232,7 @@ GtkWidget * nautilus_icon_container_new (void);
/* adding, removing, and managing icons */
void nautilus_icon_container_clear (NautilusIconContainer *view);
gboolean nautilus_icon_container_add (NautilusIconContainer *view,
NautilusIconData *data,
gboolean has_lazy_position);
NautilusIconData *data);
void nautilus_icon_container_layout_now (NautilusIconContainer *container);
gboolean nautilus_icon_container_remove (NautilusIconContainer *view,
NautilusIconData *data);
......@@ -232,9 +249,11 @@ NautilusIconData *nautilus_icon_container_get_first_visible_icon (Nautilu
void nautilus_icon_container_scroll_to_icon (NautilusIconContainer *container,
NautilusIconData *data);
void nautilus_icon_container_begin_loading (NautilusIconContainer *container);
void nautilus_icon_container_end_loading (NautilusIconContainer *container,
gboolean all_icons_added);
/* control the layout */
void nautilus_icon_container_set_is_reloading (NautilusIconContainer *container,
gboolean is_reloading);
gboolean nautilus_icon_container_is_auto_layout (NautilusIconContainer *container);
void nautilus_icon_container_set_auto_layout (NautilusIconContainer *container,
gboolean auto_layout);
......@@ -313,6 +332,10 @@ void nautilus_icon_container_set_all_columns_same_width (NautilusIconContaine
gboolean nautilus_icon_container_is_layout_rtl (NautilusIconContainer *container);
gboolean nautilus_icon_container_is_layout_vertical (NautilusIconContainer *container);
gboolean nautilus_icon_container_get_store_layout_timestamps (NautilusIconContainer *container);
void nautilus_icon_container_set_store_layout_timestamps (NautilusIconContainer *container,
gboolean store_layout);
void nautilus_icon_container_widget_to_file_operation_position (NautilusIconContainer *container,
GdkPoint *position);
......
......@@ -925,6 +925,7 @@ handle_local_move (NautilusIconContainer *container,
NautilusFile *file;
char screen_string[32];
GdkScreen *screen;
time_t now;
if (container->details->auto_layout) {
if (!confirm_switch_to_manual_layout (container)) {
......@@ -933,6 +934,7 @@ handle_local_move (NautilusIconContainer *container,
nautilus_icon_container_freeze_icon_positions (container);
}
time (&now);
/* Move and select the icons. */
moved_icons = NULL;
......@@ -955,10 +957,10 @@ handle_local_move (NautilusIconContainer *container,
nautilus_file_set_metadata (file,
NAUTILUS_METADATA_KEY_SCREEN,
NULL, screen_string);
nautilus_file_set_time_metadata (file,
NAUTILUS_METADATA_KEY_ICON_POSITION_TIMESTAMP, now);
nautilus_icon_container_add (container,
NAUTILUS_ICON_CONTAINER_ICON_DATA (file),
FALSE);
nautilus_icon_container_add (container, NAUTILUS_ICON_CONTAINER_ICON_DATA (file));
icon = nautilus_icon_container_get_icon_by_uri
(container, item->uri);
......
......@@ -273,7 +273,11 @@ struct NautilusIconContainerDetails {
guint a11y_item_action_idle_handler;
GQueue* a11y_item_action_queue;
eel_boolean_bit is_reloading : 1;
eel_boolean_bit is_loading : 1;
eel_boolean_bit store_layout_timestamps : 1;
eel_boolean_bit store_layout_timestamps_when_finishing_new_icons : 1;
time_t layout_timestamp;
/* interactive search */
gboolean disable_popdown;
......
......@@ -44,6 +44,7 @@
#define NAUTILUS_METADATA_KEY_ICON_VIEW_SORT_BY "icon_view_sort_by"
#define NAUTILUS_METADATA_KEY_ICON_VIEW_SORT_REVERSED "icon_view_sort_reversed"
#define NAUTILUS_METADATA_KEY_ICON_VIEW_KEEP_ALIGNED "icon_view_keep_aligned"
#define NAUTILUS_METADATA_KEY_ICON_VIEW_LAYOUT_TIMESTAMP "icon_view_layout_timestamp"
#define NAUTILUS_METADATA_KEY_LIST_VIEW_ZOOM_LEVEL "list_view_zoom_level"
#define NAUTILUS_METADATA_KEY_LIST_VIEW_SORT_COLUMN "list_view_sort_column"
......@@ -69,6 +70,7 @@
#define NAUTILUS_METADATA_KEY_ANNOTATION "annotation"
#define NAUTILUS_METADATA_KEY_ICON_POSITION "icon_position"
#define NAUTILUS_METADATA_KEY_ICON_POSITION_TIMESTAMP "icon_position_timestamp"
#define NAUTILUS_METADATA_KEY_ICON_SCALE "icon_scale"
#define NAUTILUS_METADATA_KEY_CUSTOM_ICON "custom_icon"
#define NAUTILUS_METADATA_KEY_SCREEN "screen"
......
......@@ -546,6 +546,7 @@ fm_desktop_icon_view_init (FMDesktopIconView *desktop_icon_view)
nautilus_icon_container_set_is_fixed_size (icon_container, TRUE);
nautilus_icon_container_set_is_desktop (icon_container, TRUE);
nautilus_icon_container_set_store_layout_timestamps (icon_container, TRUE);
/* Set allocation to be at 0, 0 */
allocation = &GTK_WIDGET (icon_container)->allocation;
......
......@@ -2343,7 +2343,8 @@ reveal_selection_idle_callback (gpointer data)
}
static void
done_loading (FMDirectoryView *view)
done_loading (FMDirectoryView *view,
gboolean all_files_seen)
{
GList *locations_selected, *selection;
......@@ -2393,7 +2394,7 @@ done_loading (FMDirectoryView *view)
fm_directory_view_display_selection_info (view);
}
fm_directory_view_end_loading (view);
fm_directory_view_end_loading (view, all_files_seen);
view->details->loading = FALSE;
}
......@@ -2807,7 +2808,7 @@ display_pending_files (FMDirectoryView *view)
if (view->details->model != NULL
&& nautilus_directory_are_all_files_seen (view->details->model)
&& g_hash_table_size (view->details->non_ready_files) == 0) {
done_loading (view);
done_loading (view, TRUE);
}
}
......@@ -3269,11 +3270,12 @@ fm_directory_view_begin_loading (FMDirectoryView *view)
*
**/
void
fm_directory_view_end_loading (FMDirectoryView *view)
fm_directory_view_end_loading (FMDirectoryView *view,
gboolean all_files_seen)
{
g_return_if_fail (FM_IS_DIRECTORY_VIEW (view));
g_signal_emit (view, signals[END_LOADING], 0);
g_signal_emit (view, signals[END_LOADING], 0, all_files_seen);
}
/**
......@@ -8791,7 +8793,7 @@ fm_directory_view_stop (FMDirectoryView *view)
if (view->details->model != NULL) {
nautilus_directory_file_monitor_remove (view->details->model, view);
}
done_loading (view);
done_loading (view, FALSE);
}
gboolean
......@@ -9689,8 +9691,8 @@ fm_directory_view_class_init (FMDirectoryViewClass *klass)
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (FMDirectoryViewClass, end_loading),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
g_cclosure_marshal_VOID__BOOLEAN,
G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
signals[FILE_CHANGED] =
g_signal_new ("file_changed",
G_TYPE_FROM_CLASS (klass),
......
......@@ -108,8 +108,16 @@ struct FMDirectoryViewClass {
* of a directory are added to the view. It can be replaced by a
* subclass to do any necessary clean-up. The default implementation
* does nothing.
*
* If all_files_seen is true, the handler may assume that
* no load error ocurred, and all files of the underlying
* directory were loaded.
*
* Otherwise, end_loading was emitted due to cancellation,
* which usually means that not all files are available.
*/
void (* end_loading) (FMDirectoryView *view);
void (* end_loading) (FMDirectoryView *view,
gboolean all_files_seen);
/* The 'load_error' signal is emitted when the directory model
* reports an error in the process of monitoring the directory's
......@@ -382,7 +390,8 @@ gboolean fm_directory_view_get_active (FMDirect
*/
void fm_directory_view_clear (FMDirectoryView *view);
void fm_directory_view_begin_loading (FMDirectoryView *view);
void fm_directory_view_end_loading (FMDirectoryView *view);
void fm_directory_view_end_loading (FMDirectoryView *view,
gboolean all_files_seen);
gboolean fm_directory_view_get_loading (FMDirectoryView *view);
......
......@@ -269,6 +269,7 @@ get_stored_icon_position_callback (NautilusIconContainer *container,
return position_good;
}
static gboolean
set_sort_criterion (FMIconView *icon_view, const SortCriterion *sort)
{
......@@ -495,28 +496,6 @@ fm_icon_view_remove_file (FMDirectoryView *view, NautilusFile *file, NautilusDir
}
}
static gboolean
file_has_lazy_position (FMDirectoryView *view,
NautilusFile *file)
{
gboolean lazy_position;
/* For volumes (i.e. cdrom icon) we use lazy positioning so that when
* an old cdrom gets re-mounted in a place that now has another
* icon we don't overlap that one. We don't do this in general though,
* as it can cause icons moving around.
*/
lazy_position = nautilus_file_can_unmount (file);
if (lazy_position && fm_directory_view_get_loading (view)) {
/* if volumes are loaded during directory load, don't mark them
* as lazy. This is wrong for files that were mounted during user
* log-off, but it is right for files that were mounted during login. */
lazy_position = FALSE;
}
return lazy_position;
}
static void
fm_icon_view_add_file (FMDirectoryView *view, NautilusFile *file, NautilusDirectory *directory)
{
......@@ -539,8 +518,7 @@ fm_icon_view_add_file (FMDirectoryView *view, NautilusFile *file, NautilusDirect
}
if (nautilus_icon_container_add (icon_container,
NAUTILUS_ICON_CONTAINER_ICON_DATA (file),
file_has_lazy_position (view, file))) {
NAUTILUS_ICON_CONTAINER_ICON_DATA (file))) {
nautilus_file_ref (file);
}
}
......@@ -1128,6 +1106,8 @@ fm_icon_view_begin_loading (FMDirectoryView *view)
file = fm_directory_view_get_directory_as_file (view);
icon_container = GTK_WIDGET (get_icon_container (icon_view));
nautilus_icon_container_begin_loading (NAUTILUS_ICON_CONTAINER (icon_container));
nautilus_icon_container_set_allow_moves (NAUTILUS_ICON_CONTAINER (icon_container),
fm_directory_view_get_allow_moves (view));
......@@ -1206,11 +1186,16 @@ fm_icon_view_begin_loading (FMDirectoryView *view)
}
static void
fm_icon_view_end_loading (FMDirectoryView *view)
fm_icon_view_end_loading (FMDirectoryView *view,
gboolean all_files_seen)
{
FMIconView *icon_view;
GtkWidget *icon_container;
icon_view = FM_ICON_VIEW (view);
icon_container = GTK_WIDGET (get_icon_container (icon_view));
nautilus_icon_container_end_loading (NAUTILUS_ICON_CONTAINER (icon_container), all_files_seen);
}
static NautilusZoomLevel
......@@ -2180,8 +2165,7 @@ fm_icon_view_screen_changed (GtkWidget *widget,
fm_icon_view_remove_file (view, file, directory);
} else {
if (nautilus_icon_container_add (icon_container,
NAUTILUS_ICON_CONTAINER_ICON_DATA (file),
file_has_lazy_position (view, file))) {
NAUTILUS_ICON_CONTAINER_ICON_DATA (file))) {
nautilus_file_ref (file);
}
}
......@@ -2573,6 +2557,62 @@ fm_icon_view_update_click_mode (FMIconView *icon_view)
click_mode == NAUTILUS_CLICK_POLICY_SINGLE);
}
static gboolean
get_stored_layout_timestamp (NautilusIconContainer *container,
NautilusIconData *icon_data,
time_t *timestamp,
FMIconView *view)
{
NautilusFile *file;
NautilusDirectory *directory;
if (icon_data == NULL) {