/* fm-canvas-view.c - implementation of canvas view of directory.
*
* Copyright (C) 2000, 2001 Eazel, Inc.
*
* The Gnome Library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* The Gnome Library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with the Gnome Library; see the file COPYING.LIB. If not,
* see .
*
* Authors: John Sullivan
*/
#include
#include "nautilus-canvas-view.h"
#include "nautilus-canvas-view-container.h"
#include "nautilus-error-reporting.h"
#include "nautilus-files-view-dnd.h"
#include "nautilus-toolbar.h"
#include "nautilus-view.h"
#include
#include
#include
#include
#include
#include
#include "nautilus-directory.h"
#include "nautilus-dnd.h"
#include "nautilus-file-utilities.h"
#include "nautilus-ui-utilities.h"
#include "nautilus-global-preferences.h"
#include "nautilus-canvas-container.h"
#include "nautilus-canvas-dnd.h"
#include "nautilus-metadata.h"
#include "nautilus-clipboard.h"
#define DEBUG_FLAG NAUTILUS_DEBUG_CANVAS_VIEW
#include "nautilus-debug.h"
#include
#include
#include
#include
#include
#include
typedef gboolean (*SortCriterionMatchFunc) (NautilusFile *file);
typedef struct
{
const NautilusFileSortType sort_type;
const char *metadata_text;
const char *action_target_name;
const gboolean reverse_order;
SortCriterionMatchFunc match_func;
} SortCriterion;
typedef enum
{
MENU_ITEM_TYPE_STANDARD,
MENU_ITEM_TYPE_CHECK,
MENU_ITEM_TYPE_RADIO,
MENU_ITEM_TYPE_TREE
} MenuItemType;
struct _NautilusCanvasView
{
NautilusFilesView parent_instance;
GList *icons_not_positioned;
guint react_to_canvas_change_idle_id;
const SortCriterion *sort;
GtkWidget *canvas_container;
/* FIXME: Needed for async operations. Suposedly we would use cancellable and gtask,
* sadly gtkclipboard doesn't support that.
* We follow this pattern for checking validity of the object in the views.
* Ideally we would connect to a weak reference and do a cancellable.
*/
gboolean destroyed;
};
/* Note that the first item in this list is the default sort,
* and that the items show up in the menu in the order they
* appear in this list.
*/
static const SortCriterion sort_criteria[] =
{
{
NAUTILUS_FILE_SORT_BY_DISPLAY_NAME,
"name",
"name",
FALSE
},
{
NAUTILUS_FILE_SORT_BY_DISPLAY_NAME,
"name",
"name-desc",
TRUE
},
{
NAUTILUS_FILE_SORT_BY_SIZE,
"size",
"size",
TRUE
},
{
NAUTILUS_FILE_SORT_BY_TYPE,
"type",
"type",
FALSE
},
{
NAUTILUS_FILE_SORT_BY_MTIME,
"modification date",
"modification-date",
FALSE
},
{
NAUTILUS_FILE_SORT_BY_MTIME,
"modification date",
"modification-date-desc",
TRUE
},
{
NAUTILUS_FILE_SORT_BY_ATIME,
"access date",
"access-date",
FALSE
},
{
NAUTILUS_FILE_SORT_BY_ATIME,
"access date",
"access-date-desc",
TRUE
},
{
NAUTILUS_FILE_SORT_BY_BTIME,
"creation date",
"creation-date",
FALSE
},
{
NAUTILUS_FILE_SORT_BY_BTIME,
"creation date",
"creation-date-desc",
TRUE
},
{
NAUTILUS_FILE_SORT_BY_TRASHED_TIME,
"trashed",
"trash-time",
TRUE,
nautilus_file_is_in_trash
},
{
NAUTILUS_FILE_SORT_BY_SEARCH_RELEVANCE,
NULL,
"search-relevance",
TRUE,
nautilus_file_is_in_search
},
{
NAUTILUS_FILE_SORT_BY_RECENCY,
NULL,
"recency",
TRUE,
nautilus_file_is_in_recent
}
};
G_DEFINE_TYPE (NautilusCanvasView, nautilus_canvas_view, NAUTILUS_TYPE_FILES_VIEW);
static void nautilus_canvas_view_set_directory_sort_by (NautilusCanvasView *canvas_view,
NautilusFile *file,
const SortCriterion *sort);
static void nautilus_canvas_view_update_click_mode (NautilusCanvasView *canvas_view);
static void nautilus_canvas_view_reveal_selection (NautilusFilesView *view);
static const SortCriterion *get_sort_criterion_by_metadata_text (const char *metadata_text,
gboolean reversed);
static const SortCriterion *get_sort_criterion_by_sort_type (NautilusFileSortType sort_type,
gboolean reversed);
static const SortCriterion *get_default_sort_order (NautilusFile *file);
static void nautilus_canvas_view_clear (NautilusFilesView *view);
static void on_clipboard_owner_changed (GtkClipboard *clipboard,
GdkEvent *event,
gpointer user_data);
static void
nautilus_canvas_view_destroy (GtkWidget *object)
{
NautilusCanvasView *canvas_view;
GtkClipboard *clipboard;
canvas_view = NAUTILUS_CANVAS_VIEW (object);
nautilus_canvas_view_clear (NAUTILUS_FILES_VIEW (object));
if (canvas_view->react_to_canvas_change_idle_id != 0)
{
g_source_remove (canvas_view->react_to_canvas_change_idle_id);
canvas_view->react_to_canvas_change_idle_id = 0;
}
clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
g_signal_handlers_disconnect_by_func (clipboard,
on_clipboard_owner_changed,
canvas_view);
if (canvas_view->icons_not_positioned)
{
nautilus_file_list_free (canvas_view->icons_not_positioned);
canvas_view->icons_not_positioned = NULL;
}
GTK_WIDGET_CLASS (nautilus_canvas_view_parent_class)->destroy (object);
}
static NautilusCanvasContainer *
get_canvas_container (NautilusCanvasView *canvas_view)
{
return NAUTILUS_CANVAS_CONTAINER (canvas_view->canvas_container);
}
NautilusCanvasContainer *
nautilus_canvas_view_get_canvas_container (NautilusCanvasView *canvas_view)
{
return get_canvas_container (canvas_view);
}
static void
update_sort_criterion (NautilusCanvasView *canvas_view,
const SortCriterion *sort,
gboolean set_metadata)
{
NautilusFile *file;
const SortCriterion *overrided_sort_criterion;
file = nautilus_files_view_get_directory_as_file (NAUTILUS_FILES_VIEW (canvas_view));
/* Make sure we use the default one and not one that the user used previously
* of the change to not allow sorting on search and recent, or the
* case that the user or some app modified directly the metadata */
if (nautilus_file_is_in_search (file) || nautilus_file_is_in_recent (file))
{
overrided_sort_criterion = get_default_sort_order (file);
}
else if (sort != NULL && canvas_view->sort != sort)
{
overrided_sort_criterion = sort;
if (set_metadata)
{
/* Store the new sort setting. */
nautilus_canvas_view_set_directory_sort_by (canvas_view,
file,
sort);
}
}
else
{
return;
}
canvas_view->sort = overrided_sort_criterion;
}
static void
list_covers (NautilusCanvasIconData *data,
gpointer callback_data)
{
GSList **file_list;
file_list = callback_data;
*file_list = g_slist_prepend (*file_list, data);
}
static void
unref_cover (NautilusCanvasIconData *data,
gpointer callback_data)
{
nautilus_file_unref (NAUTILUS_FILE (data));
}
static void
nautilus_canvas_view_clear (NautilusFilesView *view)
{
NautilusCanvasContainer *canvas_container;
GSList *file_list;
g_return_if_fail (NAUTILUS_IS_CANVAS_VIEW (view));
canvas_container = get_canvas_container (NAUTILUS_CANVAS_VIEW (view));
if (!canvas_container)
{
return;
}
/* Clear away the existing icons. */
file_list = NULL;
nautilus_canvas_container_for_each (canvas_container, list_covers, &file_list);
nautilus_canvas_container_clear (canvas_container);
g_slist_foreach (file_list, (GFunc) unref_cover, NULL);
g_slist_free (file_list);
}
static void
nautilus_canvas_view_remove_file (NautilusFilesView *view,
NautilusFile *file,
NautilusDirectory *directory)
{
NautilusCanvasView *canvas_view;
/* This used to assert that 'directory == nautilus_files_view_get_model (view)', but that
* resulted in a lot of crash reports (bug #352592). I don't see how that trace happens.
* It seems that somehow we get a files_changed event sent to the view from a directory
* that isn't the model, but the code disables the monitor and signal callback handlers when
* changing directories. Maybe we can get some more information when this happens.
* Further discussion in bug #368178.
*/
if (directory != nautilus_files_view_get_model (view))
{
char *file_uri, *dir_uri, *model_uri;
file_uri = nautilus_file_get_uri (file);
dir_uri = nautilus_directory_get_uri (directory);
model_uri = nautilus_directory_get_uri (nautilus_files_view_get_model (view));
g_warning ("nautilus_canvas_view_remove_file() - directory not canvas view model, shouldn't happen.\n"
"file: %p:%s, dir: %p:%s, model: %p:%s, view loading: %d\n"
"If you see this, please add this info to http://bugzilla.gnome.org/show_bug.cgi?id=368178",
file, file_uri, directory, dir_uri, nautilus_files_view_get_model (view), model_uri, nautilus_files_view_get_loading (view));
g_free (file_uri);
g_free (dir_uri);
g_free (model_uri);
}
canvas_view = NAUTILUS_CANVAS_VIEW (view);
if (nautilus_canvas_container_remove (get_canvas_container (canvas_view),
NAUTILUS_CANVAS_ICON_DATA (file)))
{
nautilus_file_unref (file);
}
}
static void
nautilus_canvas_view_add_files (NautilusFilesView *view,
GList *files)
{
NautilusCanvasView *canvas_view;
NautilusCanvasContainer *canvas_container;
GList *l;
canvas_view = NAUTILUS_CANVAS_VIEW (view);
canvas_container = get_canvas_container (canvas_view);
for (l = files; l != NULL; l = l->next)
{
if (nautilus_canvas_container_add (canvas_container,
NAUTILUS_CANVAS_ICON_DATA (l->data)))
{
nautilus_file_ref (NAUTILUS_FILE (l->data));
}
}
}
static void
nautilus_canvas_view_file_changed (NautilusFilesView *view,
NautilusFile *file,
NautilusDirectory *directory)
{
NautilusCanvasView *canvas_view;
g_assert (directory == nautilus_files_view_get_model (view));
g_return_if_fail (view != NULL);
canvas_view = NAUTILUS_CANVAS_VIEW (view);
nautilus_canvas_container_request_update
(get_canvas_container (canvas_view),
NAUTILUS_CANVAS_ICON_DATA (file));
}
static const SortCriterion *
nautilus_canvas_view_get_directory_sort_by (NautilusCanvasView *canvas_view,
NautilusFile *file)
{
const SortCriterion *default_sort;
g_autofree char *sort_by = NULL;
gboolean reversed;
default_sort = get_default_sort_order (file);
g_return_val_if_fail (default_sort != NULL, NULL);
sort_by = nautilus_file_get_metadata (file,
NAUTILUS_METADATA_KEY_ICON_VIEW_SORT_BY,
default_sort->metadata_text);
reversed = nautilus_file_get_boolean_metadata (file,
NAUTILUS_METADATA_KEY_ICON_VIEW_SORT_REVERSED,
default_sort->reverse_order);
return get_sort_criterion_by_metadata_text (sort_by, reversed);
}
static const SortCriterion *
get_default_sort_order (NautilusFile *file)
{
NautilusFileSortType sort_type;
gboolean reversed;
sort_type = nautilus_file_get_default_sort_type (file, &reversed);
return get_sort_criterion_by_sort_type (sort_type, reversed);
}
static void
nautilus_canvas_view_set_directory_sort_by (NautilusCanvasView *canvas_view,
NautilusFile *file,
const SortCriterion *sort)
{
const SortCriterion *default_sort_criterion;
default_sort_criterion = get_default_sort_order (file);
g_return_if_fail (default_sort_criterion != NULL);
nautilus_file_set_metadata
(file, NAUTILUS_METADATA_KEY_ICON_VIEW_SORT_BY,
default_sort_criterion->metadata_text,
sort->metadata_text);
nautilus_file_set_boolean_metadata (file,
NAUTILUS_METADATA_KEY_ICON_VIEW_SORT_REVERSED,
default_sort_criterion->reverse_order,
sort->reverse_order);
}
static const SortCriterion *
get_sort_criterion_by_metadata_text (const char *metadata_text,
gboolean reversed)
{
guint i;
/* Figure out what the new sort setting should be. */
for (i = 0; i < G_N_ELEMENTS (sort_criteria); i++)
{
if (g_strcmp0 (sort_criteria[i].metadata_text, metadata_text) == 0
&& reversed == sort_criteria[i].reverse_order)
{
return &sort_criteria[i];
}
}
return &sort_criteria[0];
}
static const SortCriterion *
get_sort_criterion_by_action_target_name (const char *action_target_name)
{
guint i;
/* Figure out what the new sort setting should be. */
for (i = 0; i < G_N_ELEMENTS (sort_criteria); i++)
{
if (g_strcmp0 (sort_criteria[i].action_target_name, action_target_name) == 0)
{
return &sort_criteria[i];
}
}
return NULL;
}
static const SortCriterion *
get_sort_criterion_by_sort_type (NautilusFileSortType sort_type,
gboolean reversed)
{
guint i;
/* Figure out what the new sort setting should be. */
for (i = 0; i < G_N_ELEMENTS (sort_criteria); i++)
{
if (sort_type == sort_criteria[i].sort_type
&& reversed == sort_criteria[i].reverse_order)
{
return &sort_criteria[i];
}
}
return &sort_criteria[0];
}
static NautilusCanvasZoomLevel
get_default_zoom_level (NautilusCanvasView *canvas_view)
{
NautilusCanvasZoomLevel default_zoom_level;
default_zoom_level = g_settings_get_enum (nautilus_icon_view_preferences,
NAUTILUS_PREFERENCES_ICON_VIEW_DEFAULT_ZOOM_LEVEL);
return CLAMP (default_zoom_level, NAUTILUS_CANVAS_ZOOM_LEVEL_SMALL, NAUTILUS_CANVAS_ZOOM_LEVEL_LARGER);
}
static void
nautilus_canvas_view_begin_loading (NautilusFilesView *view)
{
NautilusCanvasView *canvas_view;
NautilusFile *file;
char *uri;
const SortCriterion *sort;
g_return_if_fail (NAUTILUS_IS_CANVAS_VIEW (view));
canvas_view = NAUTILUS_CANVAS_VIEW (view);
file = nautilus_files_view_get_directory_as_file (view);
uri = nautilus_file_get_uri (file);
g_free (uri);
/* Set the sort mode.
* It's OK not to resort the icons because the
* container doesn't have any icons at this point.
*/
sort = nautilus_canvas_view_get_directory_sort_by (canvas_view, file);
update_sort_criterion (canvas_view, sort, FALSE);
/* We could have changed to the trash directory or to searching, and then
* we need to update the menus */
nautilus_files_view_update_context_menus (view);
nautilus_files_view_update_toolbar_menus (view);
}
static void
on_clipboard_contents_received (GtkClipboard *clipboard,
GtkSelectionData *selection_data,
gpointer user_data)
{
NautilusCanvasView *canvas_view;
canvas_view = NAUTILUS_CANVAS_VIEW (user_data);
if (canvas_view->destroyed)
{
/* We've been destroyed since call */
g_object_unref (canvas_view);
return;
}
if (nautilus_clipboard_is_cut_from_selection_data (selection_data))
{
GList *uris;
GList *files;
uris = nautilus_clipboard_get_uri_list_from_selection_data (selection_data);
files = nautilus_file_list_from_uri_list (uris);
nautilus_canvas_container_set_highlighted_for_clipboard (get_canvas_container (canvas_view),
files);
nautilus_file_list_free (files);
g_list_free_full (uris, g_free);
}
else
{
nautilus_canvas_container_set_highlighted_for_clipboard (get_canvas_container (canvas_view),
NULL);
}
g_object_unref (canvas_view);
}
static void
update_clipboard_status (NautilusCanvasView *view)
{
g_object_ref (view); /* Need to keep the object alive until we get the reply */
gtk_clipboard_request_contents (nautilus_clipboard_get (GTK_WIDGET (view)),
nautilus_clipboard_get_atom (),
on_clipboard_contents_received,
view);
}
static void
on_clipboard_owner_changed (GtkClipboard *clipboard,
GdkEvent *event,
gpointer user_data)
{
update_clipboard_status (NAUTILUS_CANVAS_VIEW (user_data));
}
static void
nautilus_canvas_view_end_loading (NautilusFilesView *view,
gboolean all_files_seen)
{
NautilusCanvasView *canvas_view;
canvas_view = NAUTILUS_CANVAS_VIEW (view);
update_clipboard_status (canvas_view);
}
static NautilusCanvasZoomLevel
nautilus_canvas_view_get_zoom_level (NautilusFilesView *view)
{
g_return_val_if_fail (NAUTILUS_IS_CANVAS_VIEW (view), NAUTILUS_CANVAS_ZOOM_LEVEL_LARGE);
return nautilus_canvas_container_get_zoom_level (get_canvas_container (NAUTILUS_CANVAS_VIEW (view)));
}
static void
nautilus_canvas_view_zoom_to_level (NautilusFilesView *view,
gint new_level)
{
NautilusCanvasView *canvas_view;
NautilusCanvasContainer *canvas_container;
g_return_if_fail (NAUTILUS_IS_CANVAS_VIEW (view));
g_return_if_fail (new_level >= NAUTILUS_CANVAS_ZOOM_LEVEL_SMALL &&
new_level <= NAUTILUS_CANVAS_ZOOM_LEVEL_LARGER);
canvas_view = NAUTILUS_CANVAS_VIEW (view);
canvas_container = get_canvas_container (canvas_view);
if (nautilus_canvas_container_get_zoom_level (canvas_container) == new_level)
{
return;
}
nautilus_canvas_container_set_zoom_level (canvas_container, new_level);
g_action_group_change_action_state (nautilus_files_view_get_action_group (view),
"zoom-to-level", g_variant_new_int32 (new_level));
nautilus_files_view_update_toolbar_menus (view);
}
static void
nautilus_canvas_view_bump_zoom_level (NautilusFilesView *view,
int zoom_increment)
{
NautilusCanvasZoomLevel new_level;
g_return_if_fail (NAUTILUS_IS_CANVAS_VIEW (view));
if (!nautilus_files_view_supports_zooming (view))
{
return;
}
new_level = nautilus_canvas_view_get_zoom_level (view) + zoom_increment;
if (new_level >= NAUTILUS_CANVAS_ZOOM_LEVEL_SMALL &&
new_level <= NAUTILUS_CANVAS_ZOOM_LEVEL_LARGER)
{
nautilus_canvas_view_zoom_to_level (view, new_level);
}
}
static void
nautilus_canvas_view_restore_standard_zoom_level (NautilusFilesView *view)
{
nautilus_canvas_view_zoom_to_level (view, NAUTILUS_CANVAS_ZOOM_LEVEL_LARGE);
}
static gboolean
nautilus_canvas_view_can_zoom_in (NautilusFilesView *view)
{
g_return_val_if_fail (NAUTILUS_IS_CANVAS_VIEW (view), FALSE);
return nautilus_canvas_view_get_zoom_level (view)
< NAUTILUS_CANVAS_ZOOM_LEVEL_LARGER;
}
static gboolean
nautilus_canvas_view_can_zoom_out (NautilusFilesView *view)
{
g_return_val_if_fail (NAUTILUS_IS_CANVAS_VIEW (view), FALSE);
return nautilus_canvas_view_get_zoom_level (view)
> NAUTILUS_CANVAS_ZOOM_LEVEL_SMALL;
}
static gfloat
nautilus_canvas_view_get_zoom_level_percentage (NautilusFilesView *view)
{
guint icon_size;
NautilusCanvasZoomLevel zoom_level;
zoom_level = nautilus_canvas_view_get_zoom_level (view);
icon_size = nautilus_canvas_container_get_icon_size_for_zoom_level (zoom_level);
return (gfloat) icon_size / NAUTILUS_CANVAS_ICON_SIZE_LARGE;
}
static gboolean
nautilus_canvas_view_is_zoom_level_default (NautilusFilesView *view)
{
guint icon_size;
NautilusCanvasZoomLevel zoom_level;
zoom_level = nautilus_canvas_view_get_zoom_level (view);
icon_size = nautilus_canvas_container_get_icon_size_for_zoom_level (zoom_level);
return icon_size == NAUTILUS_CANVAS_ICON_SIZE_LARGE;
}
static gboolean
nautilus_canvas_view_is_empty (NautilusFilesView *view)
{
g_assert (NAUTILUS_IS_CANVAS_VIEW (view));
return nautilus_canvas_container_is_empty
(get_canvas_container (NAUTILUS_CANVAS_VIEW (view)));
}
static GList *
nautilus_canvas_view_get_selection (NautilusFilesView *view)
{
GList *list;
g_return_val_if_fail (NAUTILUS_IS_CANVAS_VIEW (view), NULL);
list = nautilus_canvas_container_get_selection
(get_canvas_container (NAUTILUS_CANVAS_VIEW (view)));
nautilus_file_list_ref (list);
return list;
}
static void
action_sort_order_changed (GSimpleAction *action,
GVariant *value,
gpointer user_data)
{
const gchar *target_name;
const SortCriterion *sort_criterion;
g_assert (NAUTILUS_IS_CANVAS_VIEW (user_data));
target_name = g_variant_get_string (value, NULL);
sort_criterion = get_sort_criterion_by_action_target_name (target_name);
g_assert (sort_criterion != NULL);
update_sort_criterion (user_data, sort_criterion, TRUE);
nautilus_canvas_container_sort (get_canvas_container (user_data));
nautilus_canvas_view_reveal_selection (NAUTILUS_FILES_VIEW (user_data));
g_simple_action_set_state (action, value);
}
static void
action_zoom_to_level (GSimpleAction *action,
GVariant *state,
gpointer user_data)
{
NautilusFilesView *view;
NautilusCanvasZoomLevel zoom_level;
g_assert (NAUTILUS_IS_FILES_VIEW (user_data));
view = NAUTILUS_FILES_VIEW (user_data);
zoom_level = g_variant_get_int32 (state);
nautilus_canvas_view_zoom_to_level (view, zoom_level);
g_simple_action_set_state (G_SIMPLE_ACTION (action), state);
if (g_settings_get_enum (nautilus_icon_view_preferences,
NAUTILUS_PREFERENCES_ICON_VIEW_DEFAULT_ZOOM_LEVEL) != zoom_level)
{
g_settings_set_enum (nautilus_icon_view_preferences,
NAUTILUS_PREFERENCES_ICON_VIEW_DEFAULT_ZOOM_LEVEL,
zoom_level);
}
}
const GActionEntry canvas_view_entries[] =
{
{ "sort", NULL, "s", "'name'", action_sort_order_changed },
{ "zoom-to-level", NULL, NULL, "1", action_zoom_to_level }
};
static void
update_sort_action_state_hint (NautilusCanvasView *canvas_view)
{
NautilusFile *file;
GVariantBuilder builder;
GActionGroup *action_group;
GAction *action;
GVariant *state_hint;
gint idx;
file = nautilus_files_view_get_directory_as_file (NAUTILUS_FILES_VIEW (canvas_view));
g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
for (idx = 0; idx < G_N_ELEMENTS (sort_criteria); idx++)
{
if (sort_criteria[idx].match_func == NULL ||
(file != NULL && sort_criteria[idx].match_func (file)))
{
g_variant_builder_add (&builder, "s", sort_criteria[idx].action_target_name);
}
}
state_hint = g_variant_builder_end (&builder);
action_group = nautilus_files_view_get_action_group (NAUTILUS_FILES_VIEW (canvas_view));
action = g_action_map_lookup_action (G_ACTION_MAP (action_group), "sort");
g_simple_action_set_state_hint (G_SIMPLE_ACTION (action), state_hint);
g_variant_unref (state_hint);
}
static gboolean
showing_recent_directory (NautilusFilesView *view)
{
NautilusFile *file;
file = nautilus_files_view_get_directory_as_file (view);
if (file != NULL)
{
return nautilus_file_is_in_recent (file);
}
return FALSE;
}
static gboolean
showing_search_directory (NautilusFilesView *view)
{
NautilusFile *file;
file = nautilus_files_view_get_directory_as_file (view);
if (file != NULL)
{
return nautilus_file_is_in_search (file);
}
return FALSE;
}
static void
nautilus_canvas_view_update_actions_state (NautilusFilesView *view)
{
GActionGroup *view_action_group;
GVariant *sort_state;
GAction *action;
NautilusCanvasView *canvas_view;
canvas_view = NAUTILUS_CANVAS_VIEW (view);
NAUTILUS_FILES_VIEW_CLASS (nautilus_canvas_view_parent_class)->update_actions_state (view);
view_action_group = nautilus_files_view_get_action_group (view);
/* When we change the sort action state, even using the same value, it triggers
* the sort action changed handler, which reveals the selection, since we expect
* the selection to be visible when the user changes the sort order. But we may
* need to update the actions state for others reason than an actual sort change,
* so we need to prevent to trigger the sort action changed handler for those cases.
* To achieve this, check if the action state value actually changed before setting
* it
*/
sort_state = g_action_group_get_action_state (view_action_group, "sort");
if (g_strcmp0 (g_variant_get_string (sort_state, NULL),
canvas_view->sort->action_target_name) != 0)
{
g_action_group_change_action_state (view_action_group,
"sort",
g_variant_new_string (canvas_view->sort->action_target_name));
}
action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), "sort");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
!showing_recent_directory (view) &&
!showing_search_directory (view));
update_sort_action_state_hint (canvas_view);
g_variant_unref (sort_state);
}
static void
nautilus_canvas_view_select_all (NautilusFilesView *view)
{
NautilusCanvasContainer *canvas_container;
g_return_if_fail (NAUTILUS_IS_CANVAS_VIEW (view));
canvas_container = get_canvas_container (NAUTILUS_CANVAS_VIEW (view));
nautilus_canvas_container_select_all (canvas_container);
}
static void
nautilus_canvas_view_select_first (NautilusFilesView *view)
{
NautilusCanvasContainer *canvas_container;
g_return_if_fail (NAUTILUS_IS_CANVAS_VIEW (view));
canvas_container = get_canvas_container (NAUTILUS_CANVAS_VIEW (view));
nautilus_canvas_container_select_first (canvas_container);
}
static void
nautilus_canvas_view_reveal_selection (NautilusFilesView *view)
{
g_autolist (NautilusFile) selection = NULL;
g_return_if_fail (NAUTILUS_IS_CANVAS_VIEW (view));
selection = nautilus_view_get_selection (NAUTILUS_VIEW (view));
/* Make sure at least one of the selected items is scrolled into view */
if (selection != NULL)
{
/* Update the icon ordering to reveal the rigth selection */
nautilus_canvas_container_layout_now (get_canvas_container (NAUTILUS_CANVAS_VIEW (view)));
nautilus_canvas_container_reveal
(get_canvas_container (NAUTILUS_CANVAS_VIEW (view)),
selection->data);
}
}
static GdkRectangle *
get_rectangle_for_data (NautilusFilesView *view,
NautilusCanvasIconData *data)
{
NautilusCanvasContainer *container;
GdkRectangle *rectangle;
container = get_canvas_container (NAUTILUS_CANVAS_VIEW (view));
rectangle = nautilus_canvas_container_get_icon_bounding_box (container, data);
if (rectangle != NULL)
{
GtkWidget *context_widget;
GtkAdjustment *vadjustment;
GtkAdjustment *hadjustment;
context_widget = nautilus_files_view_get_content_widget (view);
vadjustment = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (context_widget));
hadjustment = gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (context_widget));
rectangle->x -= gtk_adjustment_get_value (hadjustment);
rectangle->y -= gtk_adjustment_get_value (vadjustment);
}
return rectangle;
}
static GdkRectangle *
nautilus_canvas_view_compute_rename_popover_pointing_to (NautilusFilesView *view)
{
g_autolist (NautilusFile) selection = NULL;
NautilusCanvasIconData *data;
g_return_val_if_fail (NAUTILUS_IS_CANVAS_VIEW (view), NULL);
selection = nautilus_view_get_selection (NAUTILUS_VIEW (view));
g_return_val_if_fail (selection != NULL, NULL);
/* We only allow renaming one item at once */
data = NAUTILUS_CANVAS_ICON_DATA (selection->data);
return get_rectangle_for_data (view, data);
}
static GdkRectangle *
nautilus_canvas_view_reveal_for_selection_context_menu (NautilusFilesView *view)
{
g_autolist (NautilusFile) selection = NULL;
NautilusCanvasContainer *container;
NautilusCanvasIconData *data;
g_return_val_if_fail (NAUTILUS_IS_CANVAS_VIEW (view), NULL);
selection = nautilus_view_get_selection (NAUTILUS_VIEW (view));
g_return_val_if_fail (selection != NULL, NULL);
container = get_canvas_container (NAUTILUS_CANVAS_VIEW (view));
/* Update the icon ordering to reveal the rigth selection */
nautilus_canvas_container_layout_now (container);
/* Get the data of the focused item, if selected. Otherwise, get the
* data of the last selected item.*/
data = nautilus_canvas_container_get_focused_icon (container);
if (data == NULL || g_list_find (selection, NAUTILUS_FILE (data)) == NULL)
{
selection = g_list_last (selection);
data = NAUTILUS_CANVAS_ICON_DATA (selection->data);
}
nautilus_canvas_container_reveal (container, data);
return get_rectangle_for_data (view, data);
}
static void
nautilus_canvas_view_set_selection (NautilusFilesView *view,
GList *selection)
{
g_return_if_fail (NAUTILUS_IS_CANVAS_VIEW (view));
nautilus_canvas_container_set_selection
(get_canvas_container (NAUTILUS_CANVAS_VIEW (view)), selection);
}
static void
nautilus_canvas_view_invert_selection (NautilusFilesView *view)
{
g_return_if_fail (NAUTILUS_IS_CANVAS_VIEW (view));
nautilus_canvas_container_invert_selection
(get_canvas_container (NAUTILUS_CANVAS_VIEW (view)));
}
static void
nautilus_canvas_view_widget_to_file_operation_position (NautilusFilesView *view,
GdkPoint *position)
{
g_assert (NAUTILUS_IS_CANVAS_VIEW (view));
nautilus_canvas_container_widget_to_file_operation_position
(get_canvas_container (NAUTILUS_CANVAS_VIEW (view)), position);
}
static void
canvas_container_activate_callback (NautilusCanvasContainer *container,
GList *file_list,
NautilusCanvasView *canvas_view)
{
g_assert (NAUTILUS_IS_CANVAS_VIEW (canvas_view));
g_assert (container == get_canvas_container (canvas_view));
nautilus_files_view_activate_files (NAUTILUS_FILES_VIEW (canvas_view),
file_list,
0, TRUE);
}
static void
canvas_container_activate_previewer_callback (NautilusCanvasContainer *container,
GList *file_list,
GArray *locations,
NautilusCanvasView *canvas_view)
{
g_assert (NAUTILUS_IS_CANVAS_VIEW (canvas_view));
g_assert (container == get_canvas_container (canvas_view));
nautilus_files_view_preview_files (NAUTILUS_FILES_VIEW (canvas_view),
file_list, locations);
}
/* this is called in one of these cases:
* - we activate with enter holding shift
* - we activate with space holding shift
* - we double click an canvas holding shift
* - we middle click an canvas
*
* If we don't open in new windows by default, the behavior should be
* - middle click, shift + activate -> open in new tab
* - shift + double click -> open in new window
*
* If we open in new windows by default, the behaviour should be
* - middle click, or shift + activate, or shift + double-click -> close parent
*/
static void
canvas_container_activate_alternate_callback (NautilusCanvasContainer *container,
GList *file_list,
NautilusCanvasView *canvas_view)
{
GdkEvent *event;
GdkEventButton *button_event;
GdkEventKey *key_event;
gboolean open_in_tab, open_in_window;
NautilusWindowOpenFlags flags;
g_assert (NAUTILUS_IS_CANVAS_VIEW (canvas_view));
g_assert (container == get_canvas_container (canvas_view));
flags = 0;
event = gtk_get_current_event ();
open_in_tab = FALSE;
open_in_window = FALSE;
if (event->type == GDK_BUTTON_PRESS ||
event->type == GDK_BUTTON_RELEASE ||
event->type == GDK_2BUTTON_PRESS ||
event->type == GDK_3BUTTON_PRESS)
{
button_event = (GdkEventButton *) event;
open_in_window = ((button_event->state & GDK_SHIFT_MASK) != 0);
open_in_tab = !open_in_window;
}
else if (event->type == GDK_KEY_PRESS ||
event->type == GDK_KEY_RELEASE)
{
key_event = (GdkEventKey *) event;
open_in_tab = ((key_event->state & GDK_SHIFT_MASK) != 0);
}
if (open_in_tab)
{
flags |= NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB;
flags |= NAUTILUS_WINDOW_OPEN_FLAG_DONT_MAKE_ACTIVE;
}
if (open_in_window)
{
flags |= NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW;
}
DEBUG ("Activate alternate, open in tab %d, new window %d\n",
open_in_tab, open_in_window);
nautilus_files_view_activate_files (NAUTILUS_FILES_VIEW (canvas_view),
file_list,
flags,
TRUE);
}
static void
band_select_started_callback (NautilusCanvasContainer *container,
NautilusCanvasView *canvas_view)
{
g_assert (NAUTILUS_IS_CANVAS_VIEW (canvas_view));
g_assert (container == get_canvas_container (canvas_view));
nautilus_files_view_start_batching_selection_changes (NAUTILUS_FILES_VIEW (canvas_view));
}
static void
band_select_ended_callback (NautilusCanvasContainer *container,
NautilusCanvasView *canvas_view)
{
g_assert (NAUTILUS_IS_CANVAS_VIEW (canvas_view));
g_assert (container == get_canvas_container (canvas_view));
nautilus_files_view_stop_batching_selection_changes (NAUTILUS_FILES_VIEW (canvas_view));
}
int
nautilus_canvas_view_compare_files (NautilusCanvasView *canvas_view,
NautilusFile *a,
NautilusFile *b)
{
return nautilus_file_compare_for_sort
(a, b, canvas_view->sort->sort_type,
/* Use type-unsafe cast for performance */
nautilus_files_view_should_sort_directories_first ((NautilusFilesView *) canvas_view),
canvas_view->sort->reverse_order);
}
static int
compare_files (NautilusFilesView *canvas_view,
NautilusFile *a,
NautilusFile *b)
{
return nautilus_canvas_view_compare_files ((NautilusCanvasView *) canvas_view, a, b);
}
static void
selection_changed_callback (NautilusCanvasContainer *container,
NautilusCanvasView *canvas_view)
{
g_assert (NAUTILUS_IS_CANVAS_VIEW (canvas_view));
g_assert (container == get_canvas_container (canvas_view));
nautilus_files_view_notify_selection_changed (NAUTILUS_FILES_VIEW (canvas_view));
}
static void
canvas_container_context_click_selection_callback (NautilusCanvasContainer *container,
const GdkEvent *event,
NautilusCanvasView *canvas_view)
{
g_assert (NAUTILUS_IS_CANVAS_CONTAINER (container));
g_assert (NAUTILUS_IS_CANVAS_VIEW (canvas_view));
nautilus_files_view_pop_up_selection_context_menu (NAUTILUS_FILES_VIEW (canvas_view),
event);
}
static void
canvas_container_context_click_background_callback (NautilusCanvasContainer *container,
const GdkEvent *event,
NautilusCanvasView *canvas_view)
{
g_assert (NAUTILUS_IS_CANVAS_CONTAINER (container));
g_assert (NAUTILUS_IS_CANVAS_VIEW (canvas_view));
nautilus_files_view_pop_up_background_context_menu (NAUTILUS_FILES_VIEW (canvas_view),
event);
}
static char *
get_icon_uri_callback (NautilusCanvasContainer *container,
NautilusFile *file,
NautilusCanvasView *canvas_view)
{
g_assert (NAUTILUS_IS_CANVAS_CONTAINER (container));
g_assert (NAUTILUS_IS_FILE (file));
g_assert (NAUTILUS_IS_CANVAS_VIEW (canvas_view));
return nautilus_file_get_uri (file);
}
static char *
get_icon_activation_uri_callback (NautilusCanvasContainer *container,
NautilusFile *file,
NautilusCanvasView *canvas_view)
{
g_assert (NAUTILUS_IS_CANVAS_CONTAINER (container));
g_assert (NAUTILUS_IS_FILE (file));
g_assert (NAUTILUS_IS_CANVAS_VIEW (canvas_view));
return nautilus_file_get_activation_uri (file);
}
static char *
get_icon_drop_target_uri_callback (NautilusCanvasContainer *container,
NautilusFile *file,
NautilusCanvasView *canvas_view)
{
g_return_val_if_fail (NAUTILUS_IS_CANVAS_CONTAINER (container), NULL);
g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
g_return_val_if_fail (NAUTILUS_IS_CANVAS_VIEW (canvas_view), NULL);
return nautilus_file_get_uri (file);
}
/* Preferences changed callbacks */
static void
nautilus_canvas_view_click_policy_changed (NautilusFilesView *directory_view)
{
g_assert (NAUTILUS_IS_CANVAS_VIEW (directory_view));
nautilus_canvas_view_update_click_mode (NAUTILUS_CANVAS_VIEW (directory_view));
}
static void
image_display_policy_changed_callback (gpointer callback_data)
{
NautilusCanvasView *canvas_view;
canvas_view = NAUTILUS_CANVAS_VIEW (callback_data);
nautilus_canvas_container_request_update_all (get_canvas_container (canvas_view));
}
static void
text_attribute_names_changed_callback (gpointer callback_data)
{
NautilusCanvasView *canvas_view;
canvas_view = NAUTILUS_CANVAS_VIEW (callback_data);
nautilus_canvas_container_request_update_all (get_canvas_container (canvas_view));
}
static void
default_sort_order_changed_callback (gpointer callback_data)
{
NautilusCanvasView *canvas_view;
NautilusFile *file;
const SortCriterion *sort;
NautilusCanvasContainer *canvas_container;
g_return_if_fail (NAUTILUS_IS_CANVAS_VIEW (callback_data));
canvas_view = NAUTILUS_CANVAS_VIEW (callback_data);
file = nautilus_files_view_get_directory_as_file (NAUTILUS_FILES_VIEW (canvas_view));
sort = nautilus_canvas_view_get_directory_sort_by (canvas_view, file);
update_sort_criterion (canvas_view, sort, FALSE);
canvas_container = get_canvas_container (canvas_view);
g_return_if_fail (NAUTILUS_IS_CANVAS_CONTAINER (canvas_container));
nautilus_canvas_container_request_update_all (canvas_container);
}
static void
nautilus_canvas_view_sort_directories_first_changed (NautilusFilesView *directory_view)
{
NautilusCanvasView *canvas_view;
canvas_view = NAUTILUS_CANVAS_VIEW (directory_view);
nautilus_canvas_container_sort (get_canvas_container (canvas_view));
}
static void
nautilus_canvas_view_preview_selection_event (NautilusFilesView *directory_view,
GtkDirectionType direction)
{
NautilusCanvasView *canvas_view;
canvas_view = NAUTILUS_CANVAS_VIEW (directory_view);
nautilus_canvas_container_preview_selection_event (get_canvas_container (canvas_view),
direction);
}
static char *
canvas_view_get_container_uri (NautilusCanvasContainer *container,
NautilusFilesView *view)
{
return nautilus_files_view_get_uri (view);
}
static void
canvas_view_move_copy_items (NautilusCanvasContainer *container,
const GList *item_uris,
const char *target_dir,
int copy_action,
NautilusFilesView *view)
{
nautilus_clipboard_clear_if_colliding_uris (GTK_WIDGET (view),
item_uris);
nautilus_files_view_move_copy_items (view, item_uris, target_dir,
copy_action);
}
static void
nautilus_canvas_view_update_click_mode (NautilusCanvasView *canvas_view)
{
NautilusCanvasContainer *canvas_container;
int click_mode;
canvas_container = get_canvas_container (canvas_view);
g_assert (canvas_container != NULL);
click_mode = g_settings_get_enum (nautilus_preferences, NAUTILUS_PREFERENCES_CLICK_POLICY);
nautilus_canvas_container_set_single_click_mode (canvas_container,
click_mode == NAUTILUS_CLICK_POLICY_SINGLE);
}
static void
canvas_container_longpress_gesture_pressed_callback (GtkGestureLongPress *gesture,
gdouble x,
gdouble y,
gpointer user_data)
{
GdkEventSequence *event_sequence;
const GdkEvent *event;
NautilusCanvasView *view = NAUTILUS_CANVAS_VIEW (user_data);
event_sequence = gtk_gesture_get_last_updated_sequence (GTK_GESTURE (gesture));
event = gtk_gesture_get_last_event (GTK_GESTURE (gesture), event_sequence);
if (nautilus_view_get_selection (NAUTILUS_VIEW (view)))
{
nautilus_files_view_pop_up_selection_context_menu (NAUTILUS_FILES_VIEW (view),
event);
}
else
{
nautilus_files_view_pop_up_background_context_menu (NAUTILUS_FILES_VIEW (view),
event);
}
}
static void
initialize_canvas_container (NautilusCanvasView *canvas_view,
NautilusCanvasContainer *canvas_container)
{
GtkWidget *content_widget;
GtkGesture *longpress_gesture;
content_widget = nautilus_files_view_get_content_widget (NAUTILUS_FILES_VIEW (canvas_view));
canvas_view->canvas_container = GTK_WIDGET (canvas_container);
g_object_add_weak_pointer (G_OBJECT (canvas_container),
(gpointer *) &canvas_view->canvas_container);
longpress_gesture = gtk_gesture_long_press_new (GTK_WIDGET (content_widget));
gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (longpress_gesture),
GTK_PHASE_CAPTURE);
gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (longpress_gesture),
TRUE);
g_signal_connect (longpress_gesture, "pressed",
(GCallback) canvas_container_longpress_gesture_pressed_callback,
canvas_view);
gtk_widget_set_can_focus (GTK_WIDGET (canvas_container), TRUE);
g_signal_connect_object (canvas_container, "activate",
G_CALLBACK (canvas_container_activate_callback), canvas_view, 0);
g_signal_connect_object (canvas_container, "activate-alternate",
G_CALLBACK (canvas_container_activate_alternate_callback), canvas_view, 0);
g_signal_connect_object (canvas_container, "activate-previewer",
G_CALLBACK (canvas_container_activate_previewer_callback), canvas_view, 0);
g_signal_connect_object (canvas_container, "band-select-started",
G_CALLBACK (band_select_started_callback), canvas_view, 0);
g_signal_connect_object (canvas_container, "band-select-ended",
G_CALLBACK (band_select_ended_callback), canvas_view, 0);
g_signal_connect_object (canvas_container, "context-click-selection",
G_CALLBACK (canvas_container_context_click_selection_callback), canvas_view, 0);
g_signal_connect_object (canvas_container, "context-click-background",
G_CALLBACK (canvas_container_context_click_background_callback), canvas_view, 0);
g_signal_connect_object (canvas_container, "selection-changed",
G_CALLBACK (selection_changed_callback), canvas_view, 0);
/* FIXME: many of these should move into fm-canvas-container as virtual methods */
g_signal_connect_object (canvas_container, "get-icon-uri",
G_CALLBACK (get_icon_uri_callback), canvas_view, 0);
g_signal_connect_object (canvas_container, "get-icon-activation-uri",
G_CALLBACK (get_icon_activation_uri_callback), canvas_view, 0);
g_signal_connect_object (canvas_container, "get-icon-drop-target-uri",
G_CALLBACK (get_icon_drop_target_uri_callback), canvas_view, 0);
g_signal_connect_object (canvas_container, "move-copy-items",
G_CALLBACK (canvas_view_move_copy_items), canvas_view, 0);
g_signal_connect_object (canvas_container, "get-container-uri",
G_CALLBACK (canvas_view_get_container_uri), canvas_view, 0);
gtk_container_add (GTK_CONTAINER (content_widget),
GTK_WIDGET (canvas_container));
nautilus_canvas_view_update_click_mode (canvas_view);
nautilus_canvas_container_set_zoom_level (canvas_container,
get_default_zoom_level (canvas_view));
gtk_widget_show (GTK_WIDGET (canvas_container));
}
static void
canvas_view_handle_uri_list (NautilusCanvasContainer *container,
const char *item_uris,
const char *target_uri,
GdkDragAction action,
NautilusCanvasView *view)
{
nautilus_files_view_handle_uri_list_drop (NAUTILUS_FILES_VIEW (view),
item_uris, target_uri, action);
}
/* Handles an URL received from Mozilla */
static void
canvas_view_handle_netscape_url (NautilusCanvasContainer *container,
const char *encoded_url,
const char *target_uri,
GdkDragAction action,
NautilusCanvasView *view)
{
nautilus_files_view_handle_netscape_url_drop (NAUTILUS_FILES_VIEW (view),
encoded_url, target_uri, action);
}
static void
canvas_view_handle_text (NautilusCanvasContainer *container,
const char *text,
const char *target_uri,
GdkDragAction action,
NautilusCanvasView *view)
{
nautilus_files_view_handle_text_drop (NAUTILUS_FILES_VIEW (view),
text, target_uri, action);
}
static void
canvas_view_handle_raw (NautilusCanvasContainer *container,
const char *raw_data,
int length,
const char *target_uri,
const char *direct_save_uri,
GdkDragAction action,
NautilusCanvasView *view)
{
nautilus_files_view_handle_raw_drop (NAUTILUS_FILES_VIEW (view),
raw_data, length, target_uri, direct_save_uri, action);
}
static void
canvas_view_handle_hover (NautilusCanvasContainer *container,
const char *target_uri,
NautilusCanvasView *view)
{
nautilus_files_view_handle_hover (NAUTILUS_FILES_VIEW (view), target_uri);
}
static char *
canvas_view_get_first_visible_file (NautilusFilesView *view)
{
NautilusFile *file;
NautilusCanvasView *canvas_view;
canvas_view = NAUTILUS_CANVAS_VIEW (view);
file = NAUTILUS_FILE (nautilus_canvas_container_get_first_visible_icon (get_canvas_container (canvas_view)));
if (file)
{
return nautilus_file_get_uri (file);
}
return NULL;
}
static void
canvas_view_scroll_to_file (NautilusFilesView *view,
const char *uri)
{
NautilusFile *file;
NautilusCanvasView *canvas_view;
canvas_view = NAUTILUS_CANVAS_VIEW (view);
if (uri != NULL)
{
/* Only if existing, since we don't want to add the file to
* the directory if it has been removed since then */
file = nautilus_file_get_existing_by_uri (uri);
if (file != NULL)
{
nautilus_canvas_container_scroll_to_canvas (get_canvas_container (canvas_view),
NAUTILUS_CANVAS_ICON_DATA (file));
nautilus_file_unref (file);
}
}
}
static guint
nautilus_canvas_view_get_id (NautilusFilesView *view)
{
return NAUTILUS_VIEW_GRID_ID;
}
static void
nautilus_canvas_view_dispose (GObject *object)
{
NautilusCanvasView *canvas_view;
canvas_view = NAUTILUS_CANVAS_VIEW (object);
canvas_view->destroyed = TRUE;
g_signal_handlers_disconnect_by_func (nautilus_preferences,
default_sort_order_changed_callback,
canvas_view);
g_signal_handlers_disconnect_by_func (nautilus_preferences,
image_display_policy_changed_callback,
canvas_view);
g_signal_handlers_disconnect_by_func (nautilus_icon_view_preferences,
text_attribute_names_changed_callback,
canvas_view);
G_OBJECT_CLASS (nautilus_canvas_view_parent_class)->dispose (object);
}
static void
nautilus_canvas_view_class_init (NautilusCanvasViewClass *klass)
{
NautilusFilesViewClass *nautilus_files_view_class;
GObjectClass *oclass;
nautilus_files_view_class = NAUTILUS_FILES_VIEW_CLASS (klass);
oclass = G_OBJECT_CLASS (klass);
oclass->dispose = nautilus_canvas_view_dispose;
GTK_WIDGET_CLASS (klass)->destroy = nautilus_canvas_view_destroy;
nautilus_files_view_class->add_files = nautilus_canvas_view_add_files;
nautilus_files_view_class->begin_loading = nautilus_canvas_view_begin_loading;
nautilus_files_view_class->bump_zoom_level = nautilus_canvas_view_bump_zoom_level;
nautilus_files_view_class->can_zoom_in = nautilus_canvas_view_can_zoom_in;
nautilus_files_view_class->can_zoom_out = nautilus_canvas_view_can_zoom_out;
nautilus_files_view_class->get_zoom_level_percentage = nautilus_canvas_view_get_zoom_level_percentage;
nautilus_files_view_class->is_zoom_level_default = nautilus_canvas_view_is_zoom_level_default;
nautilus_files_view_class->clear = nautilus_canvas_view_clear;
nautilus_files_view_class->end_loading = nautilus_canvas_view_end_loading;
nautilus_files_view_class->file_changed = nautilus_canvas_view_file_changed;
nautilus_files_view_class->compute_rename_popover_pointing_to = nautilus_canvas_view_compute_rename_popover_pointing_to;
nautilus_files_view_class->get_selection = nautilus_canvas_view_get_selection;
nautilus_files_view_class->get_selection_for_file_transfer = nautilus_canvas_view_get_selection;
nautilus_files_view_class->is_empty = nautilus_canvas_view_is_empty;
nautilus_files_view_class->remove_file = nautilus_canvas_view_remove_file;
nautilus_files_view_class->restore_standard_zoom_level = nautilus_canvas_view_restore_standard_zoom_level;
nautilus_files_view_class->reveal_selection = nautilus_canvas_view_reveal_selection;
nautilus_files_view_class->select_all = nautilus_canvas_view_select_all;
nautilus_files_view_class->select_first = nautilus_canvas_view_select_first;
nautilus_files_view_class->set_selection = nautilus_canvas_view_set_selection;
nautilus_files_view_class->invert_selection = nautilus_canvas_view_invert_selection;
nautilus_files_view_class->compare_files = compare_files;
nautilus_files_view_class->click_policy_changed = nautilus_canvas_view_click_policy_changed;
nautilus_files_view_class->update_actions_state = nautilus_canvas_view_update_actions_state;
nautilus_files_view_class->sort_directories_first_changed = nautilus_canvas_view_sort_directories_first_changed;
nautilus_files_view_class->widget_to_file_operation_position = nautilus_canvas_view_widget_to_file_operation_position;
nautilus_files_view_class->get_view_id = nautilus_canvas_view_get_id;
nautilus_files_view_class->get_first_visible_file = canvas_view_get_first_visible_file;
nautilus_files_view_class->scroll_to_file = canvas_view_scroll_to_file;
nautilus_files_view_class->reveal_for_selection_context_menu = nautilus_canvas_view_reveal_for_selection_context_menu;
nautilus_files_view_class->preview_selection_event = nautilus_canvas_view_preview_selection_event;
}
static void
nautilus_canvas_view_init (NautilusCanvasView *canvas_view)
{
NautilusCanvasContainer *canvas_container;
GActionGroup *view_action_group;
GtkClipboard *clipboard;
canvas_view->sort = &sort_criteria[0];
canvas_view->destroyed = FALSE;
canvas_container = nautilus_canvas_view_container_new (canvas_view);
initialize_canvas_container (canvas_view, canvas_container);
g_signal_connect_swapped (nautilus_preferences,
"changed::" NAUTILUS_PREFERENCES_DEFAULT_SORT_ORDER,
G_CALLBACK (default_sort_order_changed_callback),
canvas_view);
g_signal_connect_swapped (nautilus_preferences,
"changed::" NAUTILUS_PREFERENCES_DEFAULT_SORT_IN_REVERSE_ORDER,
G_CALLBACK (default_sort_order_changed_callback),
canvas_view);
g_signal_connect_swapped (nautilus_preferences,
"changed::" NAUTILUS_PREFERENCES_SHOW_FILE_THUMBNAILS,
G_CALLBACK (image_display_policy_changed_callback),
canvas_view);
g_signal_connect_swapped (nautilus_icon_view_preferences,
"changed::" NAUTILUS_PREFERENCES_ICON_VIEW_CAPTIONS,
G_CALLBACK (text_attribute_names_changed_callback),
canvas_view);
g_signal_connect_object (canvas_container, "handle-uri-list",
G_CALLBACK (canvas_view_handle_uri_list), canvas_view, 0);
g_signal_connect_object (canvas_container, "handle-netscape-url",
G_CALLBACK (canvas_view_handle_netscape_url), canvas_view, 0);
g_signal_connect_object (canvas_container, "handle-text",
G_CALLBACK (canvas_view_handle_text), canvas_view, 0);
g_signal_connect_object (canvas_container, "handle-raw",
G_CALLBACK (canvas_view_handle_raw), canvas_view, 0);
g_signal_connect_object (canvas_container, "handle-hover",
G_CALLBACK (canvas_view_handle_hover), canvas_view, 0);
/* React to clipboard changes */
clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
g_signal_connect (clipboard, "owner-change",
G_CALLBACK (on_clipboard_owner_changed), canvas_view);
view_action_group = nautilus_files_view_get_action_group (NAUTILUS_FILES_VIEW (canvas_view));
g_action_map_add_action_entries (G_ACTION_MAP (view_action_group),
canvas_view_entries,
G_N_ELEMENTS (canvas_view_entries),
canvas_view);
/* Keep the action synced with the actual value, so the toolbar can poll it */
g_action_group_change_action_state (nautilus_files_view_get_action_group (NAUTILUS_FILES_VIEW (canvas_view)),
"zoom-to-level", g_variant_new_int32 (get_default_zoom_level (canvas_view)));
}
NautilusFilesView *
nautilus_canvas_view_new (NautilusWindowSlot *slot)
{
return g_object_new (NAUTILUS_TYPE_CANVAS_VIEW,
"window-slot", slot,
NULL);
}