GitLab repository storage has been migrated to hashed layout. Please contact Infrastructure team if you notice any issues with repositories or hooks.

nautilus-view.c 281 KB
Newer Older
1
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
Darin Adler's avatar
Darin Adler committed
2

3
/* nautilus-view.c
Ettore Perazzoli's avatar
Ettore Perazzoli committed
4
 *
5
 * Copyright (C) 1999, 2000  Free Software Foundation
6
 * Copyright (C) 2000, 2001  Eazel, Inc.
Ettore Perazzoli's avatar
Ettore Perazzoli committed
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program 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
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 *
23 24
 * Authors: Ettore Perazzoli,
 *          John Sullivan <sullivan@eazel.com>,
25
 *          Darin Adler <darin@bentspoon.com>,
26 27
 *          Pavel Cisler <pavel@eazel.com>,
 *          David Emory Watson <dwatson@cs.ucr.edu>
Ettore Perazzoli's avatar
Ettore Perazzoli committed
28 29
 */

30
#include <config.h>
31

32 33
#include "nautilus-view.h"

34
#include "gedit-overlay.h"
35 36 37
#include "nautilus-actions.h"
#include "nautilus-desktop-icon-view.h"
#include "nautilus-error-reporting.h"
38
#include "nautilus-floating-bar.h"
39
#include "nautilus-list-view.h"
40
#include "nautilus-mime-actions.h"
41
#include "nautilus-properties-window.h"
42
#include "nautilus-src-marshal.h"
43 44 45 46 47 48 49

#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include <glib/gstdio.h>
#include <gio/gio.h>
#include <math.h>
Alexander Larsson's avatar
Alexander Larsson committed
50

Ramiro Estrugo's avatar
Ramiro Estrugo committed
51 52 53 54 55 56 57
#include <eel/eel-glib-extensions.h>
#include <eel/eel-gnome-extensions.h>
#include <eel/eel-gtk-extensions.h>
#include <eel/eel-gtk-macros.h>
#include <eel/eel-stock-dialogs.h>
#include <eel/eel-string.h>
#include <eel/eel-vfs-extensions.h>
58

59
#include <libnautilus-extension/nautilus-menu-provider.h>
60
#include <libnautilus-private/nautilus-clipboard.h>
61
#include <libnautilus-private/nautilus-clipboard-monitor.h>
Alexander Larsson's avatar
Alexander Larsson committed
62 63
#include <libnautilus-private/nautilus-desktop-icon-file.h>
#include <libnautilus-private/nautilus-desktop-directory.h>
64
#include <libnautilus-private/nautilus-search-directory.h>
65
#include <libnautilus-private/nautilus-directory.h>
66
#include <libnautilus-private/nautilus-dnd.h>
67
#include <libnautilus-private/nautilus-file-attributes.h>
68
#include <libnautilus-private/nautilus-file-changes-queue.h>
69 70 71
#include <libnautilus-private/nautilus-file-dnd.h>
#include <libnautilus-private/nautilus-file-operations.h>
#include <libnautilus-private/nautilus-file-utilities.h>
72
#include <libnautilus-private/nautilus-file-private.h>
73 74 75
#include <libnautilus-private/nautilus-global-preferences.h>
#include <libnautilus-private/nautilus-link.h>
#include <libnautilus-private/nautilus-metadata.h>
76
#include <libnautilus-private/nautilus-recent.h>
77
#include <libnautilus-private/nautilus-module.h>
78 79
#include <libnautilus-private/nautilus-program-choosing.h>
#include <libnautilus-private/nautilus-trash-monitor.h>
Alexander Larsson's avatar
Alexander Larsson committed
80
#include <libnautilus-private/nautilus-ui-utilities.h>
Alexander Larsson's avatar
Alexander Larsson committed
81
#include <libnautilus-private/nautilus-signaller.h>
Luca Ferretti's avatar
Luca Ferretti committed
82
#include <libnautilus-private/nautilus-icon-names.h>
83

84 85 86
#define DEBUG_FLAG NAUTILUS_DEBUG_DIRECTORY_VIEW
#include <libnautilus-private/nautilus-debug.h>

87 88 89 90 91 92 93 94 95 96 97
/* Minimum starting update inverval */
#define UPDATE_INTERVAL_MIN 100
/* Maximum update interval */
#define UPDATE_INTERVAL_MAX 2000
/* Amount of miliseconds the update interval is increased */
#define UPDATE_INTERVAL_INC 250
/* Interval at which the update interval is increased */
#define UPDATE_INTERVAL_TIMEOUT_INTERVAL 250
/* Milliseconds that have to pass without a change to reset the update interval */
#define UPDATE_INTERVAL_RESET 1000

98
#define SILENT_WINDOW_OPEN_LIMIT 5
99

100 101 102
#define DUPLICATE_HORIZONTAL_ICON_OFFSET 70
#define DUPLICATE_VERTICAL_ICON_OFFSET   30

103 104
#define MAX_QUEUED_UPDATES 500

105 106 107 108 109 110
#define NAUTILUS_VIEW_MENU_PATH_APPLICATIONS_SUBMENU_PLACEHOLDER  "/MenuBar/File/Open Placeholder/Open With/Applications Placeholder"
#define NAUTILUS_VIEW_MENU_PATH_APPLICATIONS_PLACEHOLDER    	  "/MenuBar/File/Open Placeholder/Applications Placeholder"
#define NAUTILUS_VIEW_MENU_PATH_SCRIPTS_PLACEHOLDER               "/MenuBar/File/Open Placeholder/Scripts/Scripts Placeholder"
#define NAUTILUS_VIEW_MENU_PATH_EXTENSION_ACTIONS_PLACEHOLDER     "/MenuBar/Edit/Extension Actions"
#define NAUTILUS_VIEW_MENU_PATH_NEW_DOCUMENTS_PLACEHOLDER  	  "/MenuBar/File/New Items Placeholder/New Documents/New Documents Placeholder"
#define NAUTILUS_VIEW_MENU_PATH_OPEN				  "/MenuBar/File/Open Placeholder/Open"
111

112 113 114 115 116 117
#define NAUTILUS_VIEW_POPUP_PATH_SELECTION			  "/selection"
#define NAUTILUS_VIEW_POPUP_PATH_APPLICATIONS_SUBMENU_PLACEHOLDER "/selection/Open Placeholder/Open With/Applications Placeholder"
#define NAUTILUS_VIEW_POPUP_PATH_APPLICATIONS_PLACEHOLDER    	  "/selection/Open Placeholder/Applications Placeholder"
#define NAUTILUS_VIEW_POPUP_PATH_SCRIPTS_PLACEHOLDER    	  "/selection/Open Placeholder/Scripts/Scripts Placeholder"
#define NAUTILUS_VIEW_POPUP_PATH_EXTENSION_ACTIONS		  "/selection/Extension Actions"
#define NAUTILUS_VIEW_POPUP_PATH_OPEN				  "/selection/Open Placeholder/Open"
Alexander Larsson's avatar
Alexander Larsson committed
118

119 120 121
#define NAUTILUS_VIEW_POPUP_PATH_BACKGROUND			  "/background"
#define NAUTILUS_VIEW_POPUP_PATH_BACKGROUND_SCRIPTS_PLACEHOLDER	  "/background/Before Zoom Items/New Object Items/Scripts/Scripts Placeholder"
#define NAUTILUS_VIEW_POPUP_PATH_BACKGROUND_NEW_DOCUMENTS_PLACEHOLDER "/background/Before Zoom Items/New Object Items/New Documents/New Documents Placeholder"
122

123
#define NAUTILUS_VIEW_POPUP_PATH_LOCATION			  "/location"
124

125
#define MAX_MENU_LEVELS 5
126
#define TEMPLATE_LIMIT 30
127

Pavel Cisler's avatar
Pavel Cisler committed
128
enum {
129
	ADD_FILE,
130
	BEGIN_FILE_CHANGES,
131
	BEGIN_LOADING,
132
	CLEAR,
133 134
	END_FILE_CHANGES,
	END_LOADING,
135
	FILE_CHANGED,
136
	LOAD_ERROR,
Pavel Cisler's avatar
Pavel Cisler committed
137
	MOVE_COPY_ITEMS,
138
	REMOVE_FILE,
139
	ZOOM_LEVEL_CHANGED,
140
	SELECTION_CHANGED,
Alexander Larsson's avatar
Alexander Larsson committed
141 142
	TRASH,
	DELETE,
143 144 145
	LAST_SIGNAL
};

146 147 148
enum {
	PROP_0,
	PROP_WINDOW_SLOT
Alexander Larsson's avatar
Alexander Larsson committed
149 150 151
};


152
static guint signals[LAST_SIGNAL];
Ettore Perazzoli's avatar
Ettore Perazzoli committed
153

154 155
static GdkAtom copied_files_atom;

156 157 158
static char *scripts_directory_uri;
static int scripts_directory_uri_length;

159
struct NautilusViewDetails
Ettore Perazzoli's avatar
Ettore Perazzoli committed
160
{
161 162
	NautilusWindow *window;
	NautilusWindowSlot *slot;
163
	NautilusDirectory *model;
Darin Adler's avatar
Darin Adler committed
164
	NautilusFile *directory_as_file;
165 166
	NautilusFile *location_popup_directory_as_file;
	GdkEventButton *location_popup_event;
Alexander Larsson's avatar
Alexander Larsson committed
167 168
	GtkActionGroup *dir_action_group;
	guint dir_merge_id;
169 170
	GtkWidget *overlay;
	GtkWidget *floating_bar;
171

172
	GList *scripts_directory_list;
Alexander Larsson's avatar
Alexander Larsson committed
173 174 175
	GtkActionGroup *scripts_action_group;
	guint scripts_merge_id;
	
176
	GList *templates_directory_list;
Alexander Larsson's avatar
Alexander Larsson committed
177 178
	GtkActionGroup *templates_action_group;
	guint templates_merge_id;
179

Alexander Larsson's avatar
Alexander Larsson committed
180 181 182
	GtkActionGroup *extensions_menu_action_group;
	guint extensions_menu_merge_id;
	
183
	guint display_selection_idle_id;
184
	guint update_menus_timeout_id;
185
	guint update_status_idle_id;
186 187
	guint reveal_selection_idle_id;

188 189 190 191 192
	guint display_pending_source_id;
	guint changes_timeout_id;

	guint update_interval;
 	guint64 last_queued;
193
	
194 195
	guint files_added_handler_id;
	guint files_changed_handler_id;
196
	guint load_error_handler_id;
197
	guint done_loading_handler_id;
198
	guint file_changed_handler_id;
199

200 201
	guint delayed_rename_file_id;

202 203 204 205 206 207 208 209
	GList *new_added_files;
	GList *new_changed_files;

	GHashTable *non_ready_files;

	GList *old_added_files;
	GList *old_changed_files;

210
	GList *pending_selection;
211

212 213 214
	/* whether we are in the active slot */
	gboolean active;

215
	/* loading indicates whether this view has begun loading a directory.
216
	 * This flag should need not be set inside subclasses. NautilusView automatically
217 218 219
	 * sets 'loading' to TRUE before it begins loading a directory's contents and to FALSE
	 * after it finishes loading the directory and its view.
	 */
220
	gboolean loading;
221
	gboolean menu_states_untrustworthy;
222
	gboolean scripts_invalid;
223
	gboolean templates_invalid;
224
	gboolean reported_load_error;
225

226 227 228 229 230 231 232 233
	/* flag to indicate that no file updates should be dispatched to subclasses.
	 * This is a workaround for bug #87701 that prevents the list view from
	 * losing focus when the underlying GtkTreeView is updated.
	 */
	gboolean updates_frozen;
	guint	 updates_queued;
	gboolean needs_reload;

234 235
	gboolean sort_directories_first;

236
	gboolean show_foreign_files;
237
	gboolean show_hidden_files;
238
	gboolean ignore_hidden_file_preferences;
239 240 241

	gboolean batching_selection_level;
	gboolean selection_changed_while_batched;
242

243 244
	gboolean selection_was_removed;

245 246 247
	gboolean metadata_for_directory_as_file_pending;
	gboolean metadata_for_files_in_directory_pending;

248 249 250
	gboolean selection_change_is_due_to_shell;
	gboolean send_selection_change_to_shell;

Alexander Larsson's avatar
Alexander Larsson committed
251 252
	GtkActionGroup *open_with_action_group;
	guint open_with_merge_id;
Alexander Larsson's avatar
Alexander Larsson committed
253 254

	GList *subdirectory_list;
255 256

	GdkPoint context_menu_position;
257
};
Ettore Perazzoli's avatar
Ettore Perazzoli committed
258

259 260 261 262 263
typedef struct {
	NautilusFile *file;
	NautilusDirectory *directory;
} FileAndDirectory;

264
/* forward declarations */
265

266
static gboolean display_selection_info_idle_callback           (gpointer              data);
267 268 269 270 271 272
static void     nautilus_view_duplicate_selection              (NautilusView      *view,
							        GList                *files,
							        GArray               *item_locations);
static void     nautilus_view_create_links_for_files           (NautilusView      *view,
							        GList                *files,
							        GArray               *item_locations);
Alexander Larsson's avatar
Alexander Larsson committed
273 274
static void     trash_or_delete_files                          (GtkWindow            *parent_window,
								const GList          *files,
275
								gboolean              delete_if_all_already_in_trash,
276 277
								NautilusView      *view);
static void     load_directory                                 (NautilusView      *view,
278
								NautilusDirectory    *directory);
279 280 281
static void     nautilus_view_merge_menus                      (NautilusView      *view);
static void     nautilus_view_unmerge_menus                    (NautilusView      *view);
static void     nautilus_view_init_show_hidden_files           (NautilusView      *view);
282
static void     clipboard_changed_callback                     (NautilusClipboardMonitor *monitor,
283
								NautilusView      *view);
284 285
static void     open_one_in_new_window                         (gpointer              data,
								gpointer              callback_data);
286 287
static void     open_one_in_folder_window                      (gpointer              data,
								gpointer              callback_data);
288
static void     schedule_update_menus                          (NautilusView      *view);
289
static void     schedule_update_menus_callback                 (gpointer              callback_data);
290 291 292 293 294 295 296
static void     remove_update_menus_timeout_callback           (NautilusView      *view);
static void     schedule_update_status                          (NautilusView      *view);
static void     remove_update_status_idle_callback             (NautilusView *view); 
static void     reset_update_interval                          (NautilusView      *view);
static void     schedule_idle_display_of_pending_files         (NautilusView      *view);
static void     unschedule_display_of_pending_files            (NautilusView      *view);
static void     disconnect_model_handlers                      (NautilusView      *view);
297 298 299 300 301
static void     metadata_for_directory_as_file_ready_callback  (NautilusFile         *file,
								gpointer              callback_data);
static void     metadata_for_files_in_directory_ready_callback (NautilusDirectory    *directory,
								GList                *files,
								gpointer              callback_data);
302 303 304 305 306
static void     nautilus_view_trash_state_changed_callback     (NautilusTrashMonitor *trash,
							        gboolean              state,
							        gpointer              callback_data);
static void     nautilus_view_select_file                      (NautilusView      *view,
							        NautilusFile         *file);
Alexander Larsson's avatar
Alexander Larsson committed
307

308 309
static void     update_templates_directory                     (NautilusView *view);
static void     user_dirs_changed                              (NautilusView *view);
310

311 312
static gboolean file_list_all_are_folders                      (GList *file_list);

313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334
static void unschedule_pop_up_location_context_menu (NautilusView *view);

G_DEFINE_TYPE (NautilusView, nautilus_view, GTK_TYPE_SCROLLED_WINDOW);
#define parent_class nautilus_view_parent_class

EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (nautilus_view, add_file)
EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (nautilus_view, bump_zoom_level)
EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (nautilus_view, can_zoom_in)
EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (nautilus_view, can_zoom_out)
EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (nautilus_view, clear)
EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (nautilus_view, file_changed)
EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (nautilus_view, get_selection)
EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (nautilus_view, get_selection_for_file_transfer)
EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (nautilus_view, get_item_count)
EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (nautilus_view, is_empty)
EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (nautilus_view, reset_to_defaults)
EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (nautilus_view, restore_default_zoom_level)
EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (nautilus_view, select_all)
EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (nautilus_view, set_selection)
EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (nautilus_view, zoom_to_level)
EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (nautilus_view, get_zoom_level)
EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (nautilus_view, invert_selection)
335

336
/* virtual methods (public and non-public) */
337

338
/**
339
 * nautilus_view_merge_menus:
340 341
 * 
 * Add this view's menus to the window's menu bar.
342
 * @view: NautilusView in question.
343 344
 */
static void
345
nautilus_view_merge_menus (NautilusView *view)
346
{
347
	g_return_if_fail (NAUTILUS_IS_VIEW (view));
348

349
	EEL_CALL_METHOD
350
		(NAUTILUS_VIEW_CLASS, view,
351 352
		 merge_menus, (view));
}
353

354
static void
355
nautilus_view_unmerge_menus (NautilusView *view)
Alexander Larsson's avatar
Alexander Larsson committed
356
{
357
	g_return_if_fail (NAUTILUS_IS_VIEW (view));
Alexander Larsson's avatar
Alexander Larsson committed
358

359
	EEL_CALL_METHOD
360
		(NAUTILUS_VIEW_CLASS, view,
361 362
		 unmerge_menus, (view));
}
Alexander Larsson's avatar
Alexander Larsson committed
363

364
/**
365
 * nautilus_view_select_all:
366 367 368 369 370
 *
 * select all the items in the view
 * 
 **/
static void
371
nautilus_view_select_all (NautilusView *view)
372
{
373
	g_return_if_fail (NAUTILUS_IS_VIEW (view));
Alexander Larsson's avatar
Alexander Larsson committed
374

375
	EEL_CALL_METHOD
376
		(NAUTILUS_VIEW_CLASS, view,
377
		 select_all, (view));
Alexander Larsson's avatar
Alexander Larsson committed
378 379 380
}

static void
381
nautilus_view_call_set_selection (NautilusView *view, GList *selection)
Alexander Larsson's avatar
Alexander Larsson committed
382
{
383
	g_return_if_fail (NAUTILUS_IS_VIEW (view));
384

385
	EEL_CALL_METHOD
386
		(NAUTILUS_VIEW_CLASS, view,
387 388
		 set_selection, (view, selection));
}
389 390

static GList *
391
nautilus_view_get_selection_for_file_transfer (NautilusView *view)
392
{
393
	g_return_val_if_fail (NAUTILUS_IS_VIEW (view), NULL);
394

395
	return EEL_CALL_METHOD_WITH_RETURN_VALUE
396
		(NAUTILUS_VIEW_CLASS, view,
397
		 get_selection_for_file_transfer, (view));
398 399
}

400
/**
401
 * nautilus_view_get_selected_icon_locations:
402 403 404 405 406 407
 *
 * return an array of locations of selected icons if available
 * Return value: GArray of GdkPoints
 * 
 **/
static GArray *
408
nautilus_view_get_selected_icon_locations (NautilusView *view)
409
{
410
	g_return_val_if_fail (NAUTILUS_IS_VIEW (view), NULL);
411

412
	return EEL_CALL_METHOD_WITH_RETURN_VALUE
413
		(NAUTILUS_VIEW_CLASS, view,
414
		 get_selected_icon_locations, (view));
415 416 417
}

static void
418
nautilus_view_invert_selection (NautilusView *view)
419
{
420
	g_return_if_fail (NAUTILUS_IS_VIEW (view));
421 422

	EEL_CALL_METHOD
423
		(NAUTILUS_VIEW_CLASS, view,
424
		 invert_selection, (view));
425 426
}

427
/**
428
 * nautilus_view_reveal_selection:
429 430 431 432
 *
 * Scroll as necessary to reveal the selected items.
 **/
static void
433
nautilus_view_reveal_selection (NautilusView *view)
434
{
435
	g_return_if_fail (NAUTILUS_IS_VIEW (view));
436 437

	EEL_CALL_METHOD
438
		(NAUTILUS_VIEW_CLASS, view,
439 440
		 reveal_selection, (view));
}
441

442
/**
443
 * nautilus_view_reset_to_defaults:
444 445 446 447
 *
 * set sorting order, zoom level, etc. to match defaults
 * 
 **/
448
static void
449
nautilus_view_reset_to_defaults (NautilusView *view)
450
{
451
	NautilusWindowShowHiddenFilesMode mode;
452

453
	g_return_if_fail (NAUTILUS_IS_VIEW (view));
454 455
	
	EEL_CALL_METHOD
456
		(NAUTILUS_VIEW_CLASS, view,
457 458 459 460
		 reset_to_defaults, (view));
	mode = nautilus_window_get_hidden_files_mode (view->details->window);
	if (mode != NAUTILUS_WINDOW_SHOW_HIDDEN_FILES_DEFAULT) {
		nautilus_window_set_hidden_files_mode (view->details->window,
461
						       NAUTILUS_WINDOW_SHOW_HIDDEN_FILES_DEFAULT);
462 463 464 465
	}
}

static gboolean
466
nautilus_view_using_manual_layout (NautilusView  *view)
467
{
468
	g_return_val_if_fail (NAUTILUS_IS_VIEW (view), FALSE);
469

470
	return EEL_CALL_METHOD_WITH_RETURN_VALUE
471
		(NAUTILUS_VIEW_CLASS, view,
472
		 using_manual_layout, (view));
473 474 475
}

static guint
476
nautilus_view_get_item_count (NautilusView *view)
477
{
478
	g_return_val_if_fail (NAUTILUS_IS_VIEW (view), 0);
479

480
	return EEL_CALL_METHOD_WITH_RETURN_VALUE
481
		(NAUTILUS_VIEW_CLASS, view,
482
		 get_item_count, (view));
483 484
}

485
/**
486
 * nautilus_view_can_rename_file
487 488 489 490 491 492 493 494
 *
 * Determine whether a file can be renamed.
 * @file: A NautilusFile
 * 
 * Return value: TRUE if @file can be renamed, FALSE otherwise.
 * 
 **/
static gboolean
495
nautilus_view_can_rename_file (NautilusView *view, NautilusFile *file)
496 497
{
	return EEL_CALL_METHOD_WITH_RETURN_VALUE
498
		(NAUTILUS_VIEW_CLASS, view,
499 500
		 can_rename_file, (view, file));
}
501

502
static gboolean
503
nautilus_view_is_read_only (NautilusView *view)
504
{
505
	g_return_val_if_fail (NAUTILUS_IS_VIEW (view), FALSE);
506

507
	return EEL_CALL_METHOD_WITH_RETURN_VALUE
508
		(NAUTILUS_VIEW_CLASS, view,
509 510
		 is_read_only, (view));
}
511

512
static gboolean
513
showing_trash_directory (NautilusView *view)
514 515 516
{
	NautilusFile *file;

517
	file = nautilus_view_get_directory_as_file (view);
518 519 520 521 522 523
	if (file != NULL) {
		return nautilus_file_is_in_trash (file);
	}
	return FALSE;
}

524
static gboolean
525
nautilus_view_supports_creating_files (NautilusView *view)
526
{
527
	g_return_val_if_fail (NAUTILUS_IS_VIEW (view), FALSE);
528

529
	return !nautilus_view_is_read_only (view) && !showing_trash_directory (view);
530 531
}

532
static gboolean
533
nautilus_view_is_empty (NautilusView *view)
534
{
535
	g_return_val_if_fail (NAUTILUS_IS_VIEW (view), FALSE);
536

537
	return EEL_CALL_METHOD_WITH_RETURN_VALUE
538
		(NAUTILUS_VIEW_CLASS, view,
539
		 is_empty, (view));
540 541
}

542 543 544 545 546 547 548 549 550
/**
 * nautilus_view_bump_zoom_level:
 *
 * bump the current zoom level by invoking the relevant subclass through the slot
 * 
 **/
void
nautilus_view_bump_zoom_level (NautilusView *view,
			       int zoom_increment)
551
{
552
	g_return_if_fail (NAUTILUS_IS_VIEW (view));
553

554 555 556
	if (!nautilus_view_supports_zooming (view)) {
		return;
	}
Alexander Larsson's avatar
Alexander Larsson committed
557

558
	EEL_CALL_METHOD
559
		(NAUTILUS_VIEW_CLASS, view,
560
		 bump_zoom_level, (view, zoom_increment));
Alexander Larsson's avatar
Alexander Larsson committed
561 562
}

563 564 565 566 567 568 569 570 571
/**
 * nautilus_view_zoom_to_level:
 *
 * Set the current zoom level by invoking the relevant subclass through the slot
 * 
 **/
void
nautilus_view_zoom_to_level (NautilusView *view,
			     NautilusZoomLevel zoom_level)
572
{
573
	g_return_if_fail (NAUTILUS_IS_VIEW (view));
574

575 576 577 578 579
	if (!nautilus_view_supports_zooming (view)) {
		return;
	}

	EEL_CALL_METHOD
580
		(NAUTILUS_VIEW_CLASS, view,
581
		 zoom_to_level, (view, zoom_level));
582
}
Alexander Larsson's avatar
Alexander Larsson committed
583

584
NautilusZoomLevel
585
nautilus_view_get_zoom_level (NautilusView *view)
586
{
587
	g_return_val_if_fail (NAUTILUS_IS_VIEW (view), NAUTILUS_ZOOM_LEVEL_STANDARD);
588

589 590
	if (!nautilus_view_supports_zooming (view)) {
		return NAUTILUS_ZOOM_LEVEL_STANDARD;
591 592
	}

593
	return EEL_CALL_METHOD_WITH_RETURN_VALUE
594
		(NAUTILUS_VIEW_CLASS, view,
595
		 get_zoom_level, (view));
596 597
}

598 599 600 601
/**
 * nautilus_view_can_zoom_in:
 *
 * Determine whether the view can be zoomed any closer.
602
 * @view: The zoomable NautilusView.
603 604 605 606 607 608
 * 
 * Return value: TRUE if @view can be zoomed any closer, FALSE otherwise.
 * 
 **/
gboolean
nautilus_view_can_zoom_in (NautilusView *view)
609
{
610
	g_return_val_if_fail (NAUTILUS_IS_VIEW (view), FALSE);
611

612 613
	if (!nautilus_view_supports_zooming (view)) {
		return FALSE;
614
	}
615

616
	return EEL_CALL_METHOD_WITH_RETURN_VALUE
617
		(NAUTILUS_VIEW_CLASS, view,
618
		 can_zoom_in, (view));
619 620
}

621 622 623 624
/**
 * nautilus_view_can_zoom_out:
 *
 * Determine whether the view can be zoomed any further away.
625
 * @view: The zoomable NautilusView.
626 627 628 629 630 631
 * 
 * Return value: TRUE if @view can be zoomed any further away, FALSE otherwise.
 * 
 **/
gboolean
nautilus_view_can_zoom_out (NautilusView *view)
632
{
633
	g_return_val_if_fail (NAUTILUS_IS_VIEW (view), FALSE);
634

635 636
	if (!nautilus_view_supports_zooming (view)) {
		return FALSE;
637 638
	}

639
	return EEL_CALL_METHOD_WITH_RETURN_VALUE
640
		(NAUTILUS_VIEW_CLASS, view,
641
		 can_zoom_out, (view));
642 643
}

644
gboolean
645
nautilus_view_supports_zooming (NautilusView *view)
646
{
647
	g_return_val_if_fail (NAUTILUS_IS_VIEW (view), FALSE);
648

649
	return EEL_CALL_METHOD_WITH_RETURN_VALUE
650
		(NAUTILUS_VIEW_CLASS, view,
651
		 supports_zooming, (view));
652 653
}

654 655 656 657 658 659 660 661
/**
 * nautilus_view_restore_default_zoom_level:
 *
 * restore to the default zoom level by invoking the relevant subclass through the slot
 * 
 **/
void
nautilus_view_restore_default_zoom_level (NautilusView *view)
Alexander Larsson's avatar
Alexander Larsson committed
662
{
663
	g_return_if_fail (NAUTILUS_IS_VIEW (view));
664 665 666

	if (!nautilus_view_supports_zooming (view)) {
		return;
Alexander Larsson's avatar
Alexander Larsson committed
667
	}
668 669

	EEL_CALL_METHOD
670
		(NAUTILUS_VIEW_CLASS, view,
671
		 restore_default_zoom_level, (view));
Alexander Larsson's avatar
Alexander Larsson committed
672 673
}

674 675
const char *
nautilus_view_get_view_id (NautilusView *view)
Alexander Larsson's avatar
Alexander Larsson committed
676
{
677
	return EEL_CALL_METHOD_WITH_RETURN_VALUE
678
		(NAUTILUS_VIEW_CLASS, view,
679 680
		 get_view_id, (view));
}
Alexander Larsson's avatar
Alexander Larsson committed
681

682 683 684 685
char *
nautilus_view_get_first_visible_file (NautilusView *view)
{
	return EEL_CALL_METHOD_WITH_RETURN_VALUE
686
		(NAUTILUS_VIEW_CLASS, view,
687
		 get_first_visible_file, (view));
Alexander Larsson's avatar
Alexander Larsson committed
688 689 690
}

void
691 692
nautilus_view_scroll_to_file (NautilusView *view,
			      const char *uri)
Alexander Larsson's avatar
Alexander Larsson committed
693
{
694
	EEL_CALL_METHOD
695
		(NAUTILUS_VIEW_CLASS, view,
696 697
		 scroll_to_file, (view, uri));
}
Alexander Larsson's avatar
Alexander Larsson committed
698

699
char **
700
nautilus_view_get_emblem_names_to_exclude (NautilusView *view)
701
{
702 703 704
	char **excludes;
	int i;
	
705
	g_assert (NAUTILUS_IS_VIEW (view));
Alexander Larsson's avatar
Alexander Larsson committed
706

707 708 709 710 711 712 713 714 715 716 717 718
	excludes = g_new (char *, 3);
	
	i = 0;
	excludes[i++] = g_strdup (NAUTILUS_FILE_EMBLEM_NAME_TRASH);

	if (!nautilus_file_can_write (view->details->directory_as_file)) {
		excludes[i++] = g_strdup (NAUTILUS_FILE_EMBLEM_NAME_CANT_WRITE);
	}

	excludes[i++] = NULL;

	return excludes;
Alexander Larsson's avatar
Alexander Larsson committed
719 720
}

721
void
722
nautilus_view_set_is_active (NautilusView *view,
723
			     gboolean is_active)
724
{
725
	g_return_if_fail (NAUTILUS_IS_VIEW (view));
726

727
	EEL_CALL_METHOD (NAUTILUS_VIEW_CLASS, view,
728
			 set_is_active, (view, is_active));
729 730
}

731
/**
732
 * nautilus_view_get_selection:
733 734 735 736 737
 *
 * Get a list of NautilusFile pointers that represents the
 * currently-selected items in this view. Subclasses must override
 * the signal handler for the 'get_selection' signal. Callers are
 * responsible for g_free-ing the list (but not its data).
738
 * @view: NautilusView whose selected items are of interest.
739 740 741 742 743
 * 
 * Return value: GList of NautilusFile pointers representing the selection.
 * 
 **/
GList *
744
nautilus_view_get_selection (NautilusView *view)
745
{
746
	g_return_val_if_fail (NAUTILUS_IS_VIEW (view), NULL);
747

748
	return EEL_CALL_METHOD_WITH_RETURN_VALUE
749
		(NAUTILUS_VIEW_CLASS, view,
750
		 get_selection, (view));
751 752 753
}


754 755 756 757
/**
 * nautilus_view_update_menus:
 * 
 * Update the sensitivity and wording of dynamic menu items.
758
 * @view: NautilusView in question.
759 760 761
 */
void
nautilus_view_update_menus (NautilusView *view)
762
{
763
	g_return_if_fail (NAUTILUS_IS_VIEW (view));
Alexander Larsson's avatar
Alexander Larsson committed
764

765 766
	if (!view->details->active) {
		return;
767
	}
768 769


770
	EEL_CALL_METHOD
771
		(NAUTILUS_VIEW_CLASS, view,
772
		 update_menus, (view));
773

774 775
	view->details->menu_states_untrustworthy = FALSE;
}
776

777 778 779
typedef struct {
	GAppInfo *application;
	GList *files;
780
	NautilusView *directory_view;
781
} ApplicationLaunchParameters;
782

783 784
typedef struct {
	NautilusFile *file;
785
	NautilusView *directory_view;
786
} ScriptLaunchParameters;
787

788 789
typedef struct {
	NautilusFile *file;
790
	NautilusView *directory_view;
791
} CreateTemplateParameters;
792

793 794 795
static ApplicationLaunchParameters *
application_launch_parameters_new (GAppInfo *application,
			      	   GList *files,
796
			           NautilusView *directory_view)
797
{
798
	ApplicationLaunchParameters *result;
799

800 801 802
	result = g_new0 (ApplicationLaunchParameters, 1);
	result->application = g_object_ref (application);
	result->files = nautilus_file_list_copy (files);
Alexander Larsson's avatar
Alexander Larsson committed
803

804 805 806
	if (directory_view != NULL) {
		g_object_ref (directory_view);
		result->directory_view = directory_view;
807 808
	}

809
	return result;
810 811
}

812
static void
813
application_launch_parameters_free (ApplicationLaunchParameters *parameters)
814
{
815 816
	g_object_unref (parameters->application);
	nautilus_file_list_free (parameters->files);
817

818 819
	if (parameters->directory_view != NULL) {
		g_object_unref (parameters->directory_view);
820 821
	}

822 823
	g_free (parameters);
}			      
824

825 826
static GList *
file_and_directory_list_to_files (GList *fad_list)
827
{
828 829
	GList *res, *l;
	FileAndDirectory *fad;
830

831 832 833 834 835 836 837
	res = NULL;
	for (l = fad_list; l != NULL; l = l->next) {
		fad = l->data;
		res = g_list_prepend (res, nautilus_file_ref (fad->file));
	}
	return g_list_reverse (res);
}
838 839


840 841 842 843 844
static GList *
file_and_directory_list_from_files (NautilusDirectory *directory, GList *files)
{
	GList *res, *l;
	FileAndDirectory *fad;
845

846 847 848 849 850 851 852 853
	res = NULL;
	for (l = files; l != NULL; l = l->next) {
		fad = g_new0 (FileAndDirectory, 1);
		fad->directory = nautilus_directory_ref (directory);
		fad->file = nautilus_file_ref (l->data);
		res = g_list_prepend (res, fad);
	}
	return g_list_reverse (res);
854 855 856
}

static void
857
file_and_directory_free (FileAndDirectory *fad)
858
{
859 860 861 862
	nautilus_directory_unref (fad->directory);
	nautilus_file_unref (fad->file);
	g_free (fad);
}
863 864


865 866 867 868
static void
file_and_directory_list_free (GList *list)
{
	GList *l;
869

870 871
	for (l = list; l != NULL; l = l->next) {
		file_and_directory_free (l->data);
872
	}
873

874
	g_list_free (list);
875 876
}

877 878 879
static gboolean
file_and_directory_equal (gconstpointer  v1,
			  gconstpointer  v2)
880
{
881 882 883
	const FileAndDirectory *fad1, *fad2;
	fad1 = v1;
	fad2 = v2;
884

885 886
	return (fad1->file == fad2->file &&
		fad1->directory == fad2->directory);
887 888
}

889 890
static guint
file_and_directory_hash  (gconstpointer  v)
891
{
892
	const FileAndDirectory *fad;
893

894 895
	fad = v;
	return GPOINTER_TO_UINT (fad->file) ^ GPOINTER_TO_UINT (fad->directory);
896 897
}

898

Alexander Larsson's avatar
Alexander Larsson committed
899

900 901 902

static ScriptLaunchParameters *
script_launch_parameters_new (NautilusFile *file,
903
			      NautilusView *directory_view)
904
{
905 906 907 908 909 910 911 912 913
	ScriptLaunchParameters *result;

	result = g_new0 (ScriptLaunchParameters, 1);
	g_object_ref (directory_view);
	result->directory_view = directory_view;
	nautilus_file_ref (file);
	result->file = file;

	return result;
914 915
}

916
static void
917
script_launch_parameters_free (ScriptLaunchParameters *parameters)
918
{
919 920 921 922
	g_object_unref (parameters->directory_view);
	nautilus_file_unref (parameters->file);
	g_free (parameters);
}			      
923

924 925
static CreateTemplateParameters *
create_template_parameters_new (NautilusFile *file,