nautilus-3.6.3/src/nautilus-list-view.c

Location Tool Test ID Function Issue
nautilus-list-view.c:1918:4 clang-analyzer Value stored to 'file' is never read
   1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
   2 
   3 /* fm-list-view.c - implementation of list view of directory.
   4 
   5    Copyright (C) 2000 Eazel, Inc.
   6    Copyright (C) 2001, 2002 Anders Carlsson <andersca@gnu.org>
   7    
   8    The Gnome Library is free software; you can redistribute it and/or
   9    modify it under the terms of the GNU Library General Public License as
  10    published by the Free Software Foundation; either version 2 of the
  11    License, or (at your option) any later version.
  12 
  13    The Gnome Library is distributed in the hope that it will be useful,
  14    but WITHOUT ANY WARRANTY; without even the implied warranty of
  15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16    Library General Public License for more details.
  17 
  18    You should have received a copy of the GNU Library General Public
  19    License along with the Gnome Library; see the file COPYING.LIB.  If not,
  20    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  21    Boston, MA 02111-1307, USA.
  22 
  23    Authors: John Sullivan <sullivan@eazel.com>
  24             Anders Carlsson <andersca@gnu.org>
  25 	    David Emory Watson <dwatson@cs.ucr.edu>
  26 */
  27 
  28 #include <config.h>
  29 #include "nautilus-list-view.h"
  30 
  31 #include "nautilus-list-model.h"
  32 #include "nautilus-error-reporting.h"
  33 #include "nautilus-view-dnd.h"
  34 #include "nautilus-view-factory.h"
  35 
  36 #include <string.h>
  37 #include <eel/eel-vfs-extensions.h>
  38 #include <eel/eel-gdk-extensions.h>
  39 #include <eel/eel-glib-extensions.h>
  40 #include <gdk/gdk.h>
  41 #include <gdk/gdkkeysyms.h>
  42 #include <gtk/gtk.h>
  43 #include <libegg/eggtreemultidnd.h>
  44 #include <glib/gi18n.h>
  45 #include <glib-object.h>
  46 #include <libnautilus-extension/nautilus-column-provider.h>
  47 #include <libnautilus-private/nautilus-clipboard-monitor.h>
  48 #include <libnautilus-private/nautilus-column-chooser.h>
  49 #include <libnautilus-private/nautilus-column-utilities.h>
  50 #include <libnautilus-private/nautilus-dnd.h>
  51 #include <libnautilus-private/nautilus-file-dnd.h>
  52 #include <libnautilus-private/nautilus-file-utilities.h>
  53 #include <libnautilus-private/nautilus-ui-utilities.h>
  54 #include <libnautilus-private/nautilus-global-preferences.h>
  55 #include <libnautilus-private/nautilus-metadata.h>
  56 #include <libnautilus-private/nautilus-module.h>
  57 #include <libnautilus-private/nautilus-tree-view-drag-dest.h>
  58 #include <libnautilus-private/nautilus-clipboard.h>
  59 
  60 #define DEBUG_FLAG NAUTILUS_DEBUG_LIST_VIEW
  61 #include <libnautilus-private/nautilus-debug.h>
  62 
  63 struct NautilusListViewDetails {
  64 	GtkTreeView *tree_view;
  65 	NautilusListModel *model;
  66 	GtkActionGroup *list_action_group;
  67 	guint list_merge_id;
  68 
  69 	GtkTreeViewColumn   *file_name_column;
  70 	int file_name_column_num;
  71 
  72 	GtkCellRendererPixbuf *pixbuf_cell;
  73 	GtkCellRendererText   *file_name_cell;
  74 	GList *cells;
  75 	GtkCellEditable *editable_widget;
  76 
  77 	NautilusZoomLevel zoom_level;
  78 
  79 	NautilusTreeViewDragDest *drag_dest;
  80 
  81 	GtkTreePath *double_click_path[2]; /* Both clicks in a double click need to be on the same row */
  82 
  83 	GtkTreePath *new_selection_path;   /* Path of the new selection after removing a file */
  84 
  85 	GtkTreePath *hover_path;
  86 
  87 	guint drag_button;
  88 	int drag_x;
  89 	int drag_y;
  90 
  91 	gboolean drag_started;
  92 	gboolean row_selected_on_button_down;
  93 	gboolean menus_ready;
  94 	gboolean active;
  95 	
  96 	GHashTable *columns;
  97 	GtkWidget *column_editor;
  98 
  99 	char *original_name;
 100 	
 101 	NautilusFile *renaming_file;
 102 	gboolean rename_done;
 103 	guint renaming_file_activate_timeout;
 104 
 105 	gulong clipboard_handler_id;
 106 
 107 	GQuark last_sort_attr;
 108 };
 109 
 110 struct SelectionForeachData {
 111 	GList *list;
 112 	GtkTreeSelection *selection;
 113 };
 114 
 115 /*
 116  * The row height should be large enough to not clip emblems.
 117  * Computing this would be costly, so we just choose a number
 118  * that works well with the set of emblems we've designed.
 119  */
 120 #define LIST_VIEW_MINIMUM_ROW_HEIGHT	28
 121 
 122 /* Wait for the rename to end when activating a file being renamed */
 123 #define WAIT_FOR_RENAME_ON_ACTIVATE 200
 124 
 125 static GdkCursor *              hand_cursor = NULL;
 126 
 127 static GtkTargetList *          source_target_list = NULL;
 128 
 129 static GList *nautilus_list_view_get_selection                   (NautilusView   *view);
 130 static GList *nautilus_list_view_get_selection_for_file_transfer (NautilusView   *view);
 131 static void   nautilus_list_view_set_zoom_level                  (NautilusListView        *view,
 132 								  NautilusZoomLevel  new_level,
 133 								  gboolean           always_set_level);
 134 static void   nautilus_list_view_scroll_to_file                  (NautilusListView        *view,
 135 								  NautilusFile      *file);
 136 static void   nautilus_list_view_rename_callback                 (NautilusFile      *file,
 137 								  GFile             *result_location,
 138 								  GError            *error,
 139 								  gpointer           callback_data);
 140 
 141 
 142 G_DEFINE_TYPE (NautilusListView, nautilus_list_view, NAUTILUS_TYPE_VIEW);
 143 
 144 static const char * default_trash_visible_columns[] = {
 145 	"name", "size", "type", "trashed_on", "trash_orig_path", NULL
 146 };
 147 
 148 static const char * default_trash_columns_order[] = {
 149 	"name", "size", "type", "trashed_on", "trash_orig_path", NULL
 150 };
 151 
 152 static const gchar*
 153 get_default_sort_order (NautilusFile *file, gboolean *reversed)
 154 {
 155 	NautilusFileSortType default_sort_order;
 156 	gboolean default_sort_reversed;
 157 	const gchar *retval;
 158 	const char *attributes[] = {
 159 		"name", /* is really "manually" which doesn't apply to lists */
 160 		"name",
 161 		"size",
 162 		"type",
 163 		"date_modified",
 164 		"date_accessed",
 165 		"trashed_on",
 166 		NULL
 167 	};
 168 
 169 	retval = nautilus_file_get_default_sort_attribute (file, reversed);
 170 
 171 	if (retval == NULL) {
 172 		default_sort_order = g_settings_get_enum (nautilus_preferences,
 173 							  NAUTILUS_PREFERENCES_DEFAULT_SORT_ORDER);
 174 		default_sort_reversed = g_settings_get_boolean (nautilus_preferences,
 175 								NAUTILUS_PREFERENCES_DEFAULT_SORT_IN_REVERSE_ORDER);
 176 
 177 		retval = attributes[default_sort_order];
 178 		*reversed = default_sort_reversed;
 179 	}
 180 
 181 	return retval;
 182 }
 183 
 184 static void
 185 list_selection_changed_callback (GtkTreeSelection *selection, gpointer user_data)
 186 {
 187 	NautilusView *view;
 188 
 189 	view = NAUTILUS_VIEW (user_data);
 190 
 191 	nautilus_view_notify_selection_changed (view);
 192 }
 193 
 194 /* Move these to eel? */
 195 
 196 static void
 197 tree_selection_foreach_set_boolean (GtkTreeModel *model,
 198 				    GtkTreePath *path,
 199 				    GtkTreeIter *iter,
 200 				    gpointer callback_data)
 201 {
 202 	* (gboolean *) callback_data = TRUE;
 203 }
 204 
 205 static gboolean
 206 tree_selection_not_empty (GtkTreeSelection *selection)
 207 {
 208 	gboolean not_empty;
 209 
 210 	not_empty = FALSE;
 211 	gtk_tree_selection_selected_foreach (selection,
 212 					     tree_selection_foreach_set_boolean,
 213 					     &not_empty);
 214 	return not_empty;
 215 }
 216 
 217 static gboolean
 218 tree_view_has_selection (GtkTreeView *view)
 219 {
 220 	return tree_selection_not_empty (gtk_tree_view_get_selection (view));
 221 }
 222 
 223 static void
 224 preview_selected_items (NautilusListView *view)
 225 {
 226 	GList *file_list;
 227 	
 228 	file_list = nautilus_list_view_get_selection (NAUTILUS_VIEW (view));
 229 
 230 	if (file_list != NULL) {
 231 		nautilus_view_preview_files (NAUTILUS_VIEW (view),
 232 					     file_list, NULL);
 233 		nautilus_file_list_free (file_list);
 234 	}
 235 }
 236 
 237 static void
 238 activate_selected_items (NautilusListView *view)
 239 {
 240 	GList *file_list;
 241 	
 242 	file_list = nautilus_list_view_get_selection (NAUTILUS_VIEW (view));
 243 
 244 	
 245 	if (view->details->renaming_file) {
 246 		/* We're currently renaming a file, wait until the rename is
 247 		   finished, or the activation uri will be wrong */
 248 		if (view->details->renaming_file_activate_timeout == 0) {
 249 			view->details->renaming_file_activate_timeout =
 250 				g_timeout_add (WAIT_FOR_RENAME_ON_ACTIVATE, (GSourceFunc) activate_selected_items, view);
 251 		}
 252 		return;
 253 	}
 254 	
 255 	if (view->details->renaming_file_activate_timeout != 0) {
 256 		g_source_remove (view->details->renaming_file_activate_timeout);
 257 		view->details->renaming_file_activate_timeout = 0;
 258 	}
 259 	
 260 	nautilus_view_activate_files (NAUTILUS_VIEW (view),
 261 				      file_list,
 262 				      0, TRUE);
 263 	nautilus_file_list_free (file_list);
 264 
 265 }
 266 
 267 static void
 268 activate_selected_items_alternate (NautilusListView *view,
 269 				   NautilusFile *file,
 270 				   gboolean open_in_tab)
 271 {
 272 	GList *file_list;
 273 	NautilusWindowOpenFlags flags;
 274 
 275 	flags = 0;
 276 
 277 	if (open_in_tab) {
 278 		flags |= NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB;
 279 	} else {
 280 		flags |= NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW;
 281 	}
 282 
 283 	if (file != NULL) {
 284 		nautilus_file_ref (file);
 285 		file_list = g_list_prepend (NULL, file);
 286 	} else {
 287 		file_list = nautilus_list_view_get_selection (NAUTILUS_VIEW (view));
 288 	}
 289 	nautilus_view_activate_files (NAUTILUS_VIEW (view),
 290 				      file_list,
 291 				      flags,
 292 				      TRUE);
 293 	nautilus_file_list_free (file_list);
 294 
 295 }
 296 
 297 static gboolean
 298 button_event_modifies_selection (GdkEventButton *event)
 299 {
 300 	return (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) != 0;
 301 }
 302 
 303 static int
 304 get_click_policy (void)
 305 {
 306 	return g_settings_get_enum (nautilus_preferences,
 307 				    NAUTILUS_PREFERENCES_CLICK_POLICY);
 308 }
 309 
 310 static void
 311 nautilus_list_view_did_not_drag (NautilusListView *view,
 312 				 GdkEventButton *event)
 313 {
 314 	GtkTreeView *tree_view;
 315 	GtkTreeSelection *selection;
 316 	GtkTreePath *path;
 317 	
 318 	tree_view = view->details->tree_view;
 319 	selection = gtk_tree_view_get_selection (tree_view);
 320 
 321 	if (gtk_tree_view_get_path_at_pos (tree_view, event->x, event->y,
 322 					   &path, NULL, NULL, NULL)) {
 323 		if ((event->button == 1 || event->button == 2)
 324 		    && ((event->state & GDK_CONTROL_MASK) != 0 ||
 325 			(event->state & GDK_SHIFT_MASK) == 0)
 326 		    && view->details->row_selected_on_button_down) {
 327 			if (!button_event_modifies_selection (event)) {
 328 				gtk_tree_selection_unselect_all (selection);
 329 				gtk_tree_selection_select_path (selection, path);
 330 			} else {
 331 				gtk_tree_selection_unselect_path (selection, path);
 332 			}
 333 		}
 334 
 335 		if ((get_click_policy () == NAUTILUS_CLICK_POLICY_SINGLE)
 336 		    && !button_event_modifies_selection(event)) {
 337 			if (event->button == 1) {
 338 				activate_selected_items (view);
 339 			} else if (event->button == 2) {
 340 				activate_selected_items_alternate (view, NULL, TRUE);
 341 			}
 342 		}
 343 		gtk_tree_path_free (path);
 344 	}
 345 	
 346 }
 347 
 348 static void 
 349 drag_data_get_callback (GtkWidget *widget,
 350 			GdkDragContext *context,
 351 			GtkSelectionData *selection_data,
 352 			guint info,
 353 			guint time)
 354 {
 355 	GtkTreeView *tree_view;
 356 	GtkTreeModel *model;
 357 	GList *ref_list;
 358 
 359 	tree_view = GTK_TREE_VIEW (widget);
 360   
 361 	model = gtk_tree_view_get_model (tree_view);
 362   
 363 	if (model == NULL) {
 364 		return;
 365 	}
 366 
 367 	ref_list = g_object_get_data (G_OBJECT (context), "drag-info");
 368 
 369 	if (ref_list == NULL) {
 370 		return;
 371 	}
 372 
 373 	if (EGG_IS_TREE_MULTI_DRAG_SOURCE (model)) {
 374 		egg_tree_multi_drag_source_drag_data_get (EGG_TREE_MULTI_DRAG_SOURCE (model),
 375 							  ref_list,
 376 							  selection_data);
 377 	}
 378 }
 379 
 380 static void
 381 filtered_selection_foreach (GtkTreeModel *model,
 382 			    GtkTreePath *path,
 383 			    GtkTreeIter *iter,
 384 			    gpointer data)
 385 {
 386 	struct SelectionForeachData *selection_data;
 387 	GtkTreeIter parent;
 388 	GtkTreeIter child;
 389 	
 390 	selection_data = data;
 391 
 392 	/* If the parent folder is also selected, don't include this file in the
 393 	 * file operation, since that would copy it to the toplevel target instead
 394 	 * of keeping it as a child of the copied folder
 395 	 */
 396 	child = *iter;
 397 	while (gtk_tree_model_iter_parent (model, &parent, &child)) {
 398 		if (gtk_tree_selection_iter_is_selected (selection_data->selection,
 399 							 &parent)) {
 400 			return;
 401 		}
 402 		child = parent;
 403 	}
 404 	
 405 	selection_data->list = g_list_prepend (selection_data->list, 
 406 					       gtk_tree_row_reference_new (model, path));
 407 }
 408 
 409 static GList *
 410 get_filtered_selection_refs (GtkTreeView *tree_view)
 411 {
 412 	struct SelectionForeachData selection_data;
 413 
 414 	selection_data.list = NULL;
 415 	selection_data.selection = gtk_tree_view_get_selection (tree_view);
 416 	
 417 	gtk_tree_selection_selected_foreach (selection_data.selection, 
 418 					     filtered_selection_foreach, 
 419 					     &selection_data);
 420 	return g_list_reverse (selection_data.list);
 421 }
 422 
 423 static void
 424 ref_list_free (GList *ref_list)
 425 {
 426 	g_list_foreach (ref_list, (GFunc) gtk_tree_row_reference_free, NULL);
 427 	g_list_free (ref_list);
 428 }
 429 
 430 static void
 431 stop_drag_check (NautilusListView *view)
 432 {		
 433 	view->details->drag_button = 0;
 434 }
 435 
 436 static GdkPixbuf *
 437 get_drag_pixbuf (NautilusListView *view)
 438 {
 439 	GtkTreeModel *model;
 440 	GtkTreePath *path;
 441 	GtkTreeIter iter;
 442 	GdkPixbuf *ret;
 443 	GdkRectangle cell_area;
 444 	
 445 	ret = NULL;
 446 	
 447 	if (gtk_tree_view_get_path_at_pos (view->details->tree_view, 
 448 					   view->details->drag_x,
 449 					   view->details->drag_y,
 450 					   &path, NULL, NULL, NULL)) {
 451 		model = gtk_tree_view_get_model (view->details->tree_view);
 452 		gtk_tree_model_get_iter (model, &iter, path);
 453 		gtk_tree_model_get (model, &iter,
 454 				    nautilus_list_model_get_column_id_from_zoom_level (view->details->zoom_level),
 455 				    &ret,
 456 				    -1);
 457 
 458 		gtk_tree_view_get_cell_area (view->details->tree_view,
 459 					     path, 
 460 					     view->details->file_name_column, 
 461 					     &cell_area);
 462 
 463 		gtk_tree_path_free (path);
 464 	}
 465 
 466 	return ret;
 467 }
 468 
 469 static void
 470 drag_begin_callback (GtkWidget *widget,
 471 		     GdkDragContext *context,
 472 		     NautilusListView *view)
 473 {
 474 	GList *ref_list;
 475 	GdkPixbuf *pixbuf;
 476 
 477 	pixbuf = get_drag_pixbuf (view);
 478 	if (pixbuf) {
 479 		gtk_drag_set_icon_pixbuf (context,
 480 					  pixbuf,
 481 					  0, 0);
 482 		g_object_unref (pixbuf);
 483 	} else {
 484 		gtk_drag_set_icon_default (context);
 485 	}
 486 
 487 	stop_drag_check (view);
 488 	view->details->drag_started = TRUE;
 489 	
 490 	ref_list = get_filtered_selection_refs (GTK_TREE_VIEW (widget));
 491 	g_object_set_data_full (G_OBJECT (context),
 492 				"drag-info",
 493 				ref_list,
 494 				(GDestroyNotify)ref_list_free);
 495 }
 496 
 497 static gboolean
 498 motion_notify_callback (GtkWidget *widget,
 499 			GdkEventMotion *event,
 500 			gpointer callback_data)
 501 {
 502 	NautilusListView *view;
 503 	
 504 	view = NAUTILUS_LIST_VIEW (callback_data);
 505 
 506 	if (event->window != gtk_tree_view_get_bin_window (GTK_TREE_VIEW (widget))) {
 507 		return FALSE;
 508 	}
 509 
 510 	if (get_click_policy () == NAUTILUS_CLICK_POLICY_SINGLE) {
 511 		GtkTreePath *old_hover_path;
 512 
 513 		old_hover_path = view->details->hover_path;
 514 		gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (widget),
 515 					       event->x, event->y,
 516 					       &view->details->hover_path,
 517 					       NULL, NULL, NULL);
 518 
 519 		if ((old_hover_path != NULL) != (view->details->hover_path != NULL)) {
 520 			if (view->details->hover_path != NULL) {
 521 				gdk_window_set_cursor (gtk_widget_get_window (widget), hand_cursor);
 522 			} else {
 523 				gdk_window_set_cursor (gtk_widget_get_window (widget), NULL);
 524 			}
 525 		}
 526 
 527 		if (old_hover_path != NULL) {
 528 			gtk_tree_path_free (old_hover_path);
 529 		}
 530 	}
 531 
 532 	if (view->details->drag_button != 0) {
 533 		if (!source_target_list) {
 534 			source_target_list = nautilus_list_model_get_drag_target_list ();
 535 		}
 536 
 537 		if (gtk_drag_check_threshold (widget,
 538 					      view->details->drag_x,
 539 					      view->details->drag_y,
 540 					      event->x, 
 541 					      event->y)) {
 542 			gtk_drag_begin
 543 				(widget,
 544 				 source_target_list,
 545 				 GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK | GDK_ACTION_ASK,
 546 				 view->details->drag_button,
 547 				 (GdkEvent*)event);
 548 		}		      
 549 		return TRUE;
 550 	}
 551 	
 552 	return FALSE;
 553 }
 554 
 555 static gboolean
 556 leave_notify_callback (GtkWidget *widget,
 557 		       GdkEventCrossing *event,
 558 		       gpointer callback_data)
 559 {
 560 	NautilusListView *view;
 561 
 562 	view = NAUTILUS_LIST_VIEW (callback_data);
 563 
 564 	if (get_click_policy () == NAUTILUS_CLICK_POLICY_SINGLE &&
 565 	    view->details->hover_path != NULL) {
 566 		gtk_tree_path_free (view->details->hover_path);
 567 		view->details->hover_path = NULL;
 568 	}
 569 
 570 	return FALSE;
 571 }
 572 
 573 static gboolean
 574 enter_notify_callback (GtkWidget *widget,
 575 		       GdkEventCrossing *event,
 576 		       gpointer callback_data)
 577 {
 578 	NautilusListView *view;
 579 
 580 	view = NAUTILUS_LIST_VIEW (callback_data);
 581 
 582 	if (get_click_policy () == NAUTILUS_CLICK_POLICY_SINGLE) {
 583 		if (view->details->hover_path != NULL) {
 584 			gtk_tree_path_free (view->details->hover_path);
 585 		}
 586 
 587 		gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (widget),
 588 					       event->x, event->y,
 589 					       &view->details->hover_path,
 590 					       NULL, NULL, NULL);
 591 
 592 		if (view->details->hover_path != NULL) {
 593 			gdk_window_set_cursor (gtk_widget_get_window (widget), hand_cursor);
 594 		}
 595 	}
 596 
 597 	return FALSE;
 598 }
 599 
 600 static void
 601 do_popup_menu (GtkWidget *widget, NautilusListView *view, GdkEventButton *event)
 602 {
 603  	if (tree_view_has_selection (GTK_TREE_VIEW (widget))) {
 604 		nautilus_view_pop_up_selection_context_menu (NAUTILUS_VIEW (view), event);
 605 	} else {
 606                 nautilus_view_pop_up_background_context_menu (NAUTILUS_VIEW (view), event);
 607 	}
 608 }
 609 
 610 static void
 611 row_activated_callback (GtkTreeView *treeview, GtkTreePath *path, 
 612 			GtkTreeViewColumn *column, NautilusListView *view)
 613 {
 614 	activate_selected_items (view);
 615 }
 616 
 617 static gboolean
 618 button_press_callback (GtkWidget *widget, GdkEventButton *event, gpointer callback_data)
 619 {
 620 	NautilusListView *view;
 621 	GtkTreeView *tree_view;
 622 	GtkTreePath *path;
 623 	gboolean call_parent;
 624 	GtkTreeSelection *selection;
 625 	GtkWidgetClass *tree_view_class;
 626 	gint64 current_time;
 627 	static gint64 last_click_time = 0;
 628 	static int click_count = 0;
 629 	int double_click_time;
 630 
 631 	view = NAUTILUS_LIST_VIEW (callback_data);
 632 	tree_view = GTK_TREE_VIEW (widget);
 633 	tree_view_class = GTK_WIDGET_GET_CLASS (tree_view);
 634 	selection = gtk_tree_view_get_selection (tree_view);
 635 
 636 	/* Don't handle extra mouse buttons here */
 637 	if (event->button > 5) {
 638 		return FALSE;
 639 	}
 640 
 641 	if (event->window != gtk_tree_view_get_bin_window (tree_view)) {
 642 		return FALSE;
 643 	}
 644 
 645 	nautilus_list_model_set_drag_view
 646 		(NAUTILUS_LIST_MODEL (gtk_tree_view_get_model (tree_view)),
 647 		 tree_view,
 648 		 event->x, event->y);
 649 
 650 	g_object_get (G_OBJECT (gtk_widget_get_settings (widget)),
 651 		      "gtk-double-click-time", &double_click_time,
 652 		      NULL);
 653 
 654 	/* Determine click count */
 655 	current_time = g_get_monotonic_time ();
 656 	if (current_time - last_click_time < double_click_time * 1000) {
 657 		click_count++;
 658 	} else {
 659 		click_count = 0;
 660 	}
 661 
 662 	/* Stash time for next compare */
 663 	last_click_time = current_time;
 664 
 665 	/* Ignore double click if we are in single click mode */
 666 	if (get_click_policy () == NAUTILUS_CLICK_POLICY_SINGLE && click_count >= 2) {
 667 		return TRUE;
 668 	}
 669 
 670 	call_parent = TRUE;
 671 	if (gtk_tree_view_get_path_at_pos (tree_view, event->x, event->y,
 672 					   &path, NULL, NULL, NULL)) {
 673 		/* Keep track of path of last click so double clicks only happen
 674 		 * on the same item */
 675 		if ((event->button == 1 || event->button == 2)  && 
 676 		    event->type == GDK_BUTTON_PRESS) {
 677 			if (view->details->double_click_path[1]) {
 678 				gtk_tree_path_free (view->details->double_click_path[1]);
 679 			}
 680 			view->details->double_click_path[1] = view->details->double_click_path[0];
 681 			view->details->double_click_path[0] = gtk_tree_path_copy (path);
 682 		}
 683 		if (event->type == GDK_2BUTTON_PRESS) {
 684 			/* Double clicking does not trigger a D&D action. */
 685 			view->details->drag_button = 0;
 686 			if (view->details->double_click_path[1] &&
 687 			    gtk_tree_path_compare (view->details->double_click_path[0], view->details->double_click_path[1]) == 0) {
 688 				/* NOTE: Activation can actually destroy the view if we're switching */
 689 				if (!button_event_modifies_selection (event)) {
 690 					if ((event->button == 1 || event->button == 3)) {
 691 						activate_selected_items (view);
 692 					} else if (event->button == 2) {
 693 						activate_selected_items_alternate (view, NULL, TRUE);
 694 					}
 695 				} else if (event->button == 1 &&
 696 					   (event->state & GDK_SHIFT_MASK) != 0) {
 697 					NautilusFile *file;
 698 					file = nautilus_list_model_file_for_path (view->details->model, path);
 699 					if (file != NULL) {
 700 						activate_selected_items_alternate (view, file, TRUE);
 701 						nautilus_file_unref (file);
 702 					}
 703 				}
 704 			} else {
 705 				tree_view_class->button_press_event (widget, event);
 706 			}
 707 		} else {
 708 	
 709 			/* We're going to filter out some situations where
 710 			 * we can't let the default code run because all
 711 			 * but one row would be would be deselected. We don't
 712 			 * want that; we want the right click menu or single
 713 			 * click to apply to everything that's currently selected. */
 714 
 715 			if (event->button == 3 && gtk_tree_selection_path_is_selected (selection, path)) {
 716 				call_parent = FALSE;
 717 			}
 718 
 719 			if ((event->button == 1 || event->button == 2) &&
 720 			    ((event->state & GDK_CONTROL_MASK) != 0 ||
 721 			     (event->state & GDK_SHIFT_MASK) == 0)) {			
 722 				view->details->row_selected_on_button_down = gtk_tree_selection_path_is_selected (selection, path);
 723 				if (view->details->row_selected_on_button_down) {
 724 					call_parent = FALSE;
 725 				} else if ((event->state & GDK_CONTROL_MASK) != 0) {
 726 					GList *selected_rows;
 727 					GList *l;
 728 
 729 					call_parent = FALSE;
 730 					if ((event->state & GDK_SHIFT_MASK) != 0) {
 731 						GtkTreePath *cursor;
 732 						gtk_tree_view_get_cursor (tree_view, &cursor, NULL);
 733 						if (cursor != NULL) {
 734 							gtk_tree_selection_select_range (selection, cursor, path);
 735 						} else {
 736 							gtk_tree_selection_select_path (selection, path);
 737 						}
 738 					} else {
 739 						gtk_tree_selection_select_path (selection, path);
 740 					}
 741 					selected_rows = gtk_tree_selection_get_selected_rows (selection, NULL);
 742 
 743 					/* This unselects everything */
 744 					gtk_tree_view_set_cursor (tree_view, path, NULL, FALSE);
 745 
 746 					/* So select it again */
 747 					l = selected_rows;
 748 					while (l != NULL) {
 749 						GtkTreePath *p = l->data;
 750 						l = l->next;
 751 						gtk_tree_selection_select_path (selection, p);
 752 						gtk_tree_path_free (p);
 753 					}
 754 					g_list_free (selected_rows);
 755 				}
 756 			}
 757 		
 758 			if (call_parent) {
 759 				g_signal_handlers_block_by_func (tree_view,
 760 								 row_activated_callback,
 761 								 view);
 762 
 763 				tree_view_class->button_press_event (widget, event);
 764 
 765 				g_signal_handlers_unblock_by_func (tree_view,
 766 								   row_activated_callback,
 767 								   view);
 768 			} else if (gtk_tree_selection_path_is_selected (selection, path)) {
 769 				gtk_widget_grab_focus (widget);
 770 			}
 771 			
 772 			if ((event->button == 1 || event->button == 2) &&
 773 			    event->type == GDK_BUTTON_PRESS) {
 774 				view->details->drag_started = FALSE;
 775 				view->details->drag_button = event->button;
 776 				view->details->drag_x = event->x;
 777 				view->details->drag_y = event->y;
 778 			}
 779 			
 780 			if (event->button == 3) {
 781 				do_popup_menu (widget, view, event);
 782 			}
 783 		}
 784 
 785 		gtk_tree_path_free (path);
 786 	} else {
 787 		if ((event->button == 1 || event->button == 2)  && 
 788 		    event->type == GDK_BUTTON_PRESS) {
 789 			if (view->details->double_click_path[1]) {
 790 				gtk_tree_path_free (view->details->double_click_path[1]);
 791 			}
 792 			view->details->double_click_path[1] = view->details->double_click_path[0];
 793 			view->details->double_click_path[0] = NULL;
 794 		}
 795 		/* Deselect if people click outside any row. It's OK to
 796 		   let default code run; it won't reselect anything. */
 797 		gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (tree_view));
 798 		tree_view_class->button_press_event (widget, event);
 799 
 800 		if (event->button == 3) {
 801 			do_popup_menu (widget, view, event);
 802 		}
 803 	}
 804 	
 805 	/* We chained to the default handler in this method, so never
 806 	 * let the default handler run */ 
 807 	return TRUE;
 808 }
 809 
 810 static gboolean
 811 button_release_callback (GtkWidget *widget, 
 812 			 GdkEventButton *event, 
 813 			 gpointer callback_data)
 814 {
 815 	NautilusListView *view;
 816 	
 817 	view = NAUTILUS_LIST_VIEW (callback_data);
 818 
 819 	if (event->button == view->details->drag_button) {
 820 		stop_drag_check (view);
 821 		if (!view->details->drag_started) {
 822 			nautilus_list_view_did_not_drag (view, event);
 823 		}
 824 	}
 825 	return FALSE;
 826 }
 827 
 828 static gboolean
 829 popup_menu_callback (GtkWidget *widget, gpointer callback_data)
 830 {
 831  	NautilusListView *view;
 832 
 833 	view = NAUTILUS_LIST_VIEW (callback_data);
 834 
 835 	do_popup_menu (widget, view, NULL);
 836 
 837 	return TRUE;
 838 }
 839 
 840 static void
 841 subdirectory_done_loading_callback (NautilusDirectory *directory, NautilusListView *view)
 842 {
 843 	nautilus_list_model_subdirectory_done_loading (view->details->model, directory);
 844 }
 845 
 846 struct UnloadDelayData {
 847 	NautilusFile *file;
 848 	NautilusDirectory *directory;
 849 	NautilusListView *view;
 850 };
 851 
 852 static void
 853 subdirectory_unloaded_callback (NautilusListModel *model,
 854 				NautilusDirectory *directory,
 855 				gpointer callback_data)
 856 {
 857 	NautilusListView *view;
 858 	
 859 	g_return_if_fail (NAUTILUS_IS_LIST_MODEL (model));
 860 	g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory));
 861 
 862 	view = NAUTILUS_LIST_VIEW(callback_data);
 863 	
 864 	g_signal_handlers_disconnect_by_func (directory,
 865 					      G_CALLBACK (subdirectory_done_loading_callback),
 866 					      view);
 867 	nautilus_view_remove_subdirectory (NAUTILUS_VIEW (view), directory);
 868 }
 869 
 870 static gboolean
 871 key_press_callback (GtkWidget *widget, GdkEventKey *event, gpointer callback_data)
 872 {
 873 	NautilusView *view;
 874 	GdkEventButton button_event = { 0 };
 875 	gboolean handled;
 876 
 877 	view = NAUTILUS_VIEW (callback_data);
 878 	handled = FALSE;
 879 
 880 	switch (event->keyval) {
 881 	case GDK_KEY_F10:
 882 		if (event->state & GDK_CONTROL_MASK) {
 883 			nautilus_view_pop_up_background_context_menu (view, &button_event);
 884 			handled = TRUE;
 885 		}
 886 		break;
 887 	case GDK_KEY_space:
 888 		if (event->state & GDK_CONTROL_MASK) {
 889 			handled = FALSE;
 890 			break;
 891 		}
 892 		if (!gtk_widget_has_focus (GTK_WIDGET (NAUTILUS_LIST_VIEW (view)->details->tree_view))) {
 893 			handled = FALSE;
 894 			break;
 895 		}
 896 		if ((event->state & GDK_SHIFT_MASK) != 0) {
 897 			activate_selected_items_alternate (NAUTILUS_LIST_VIEW (view), NULL, TRUE);
 898 		} else {
 899 			preview_selected_items (NAUTILUS_LIST_VIEW (view));
 900 		}
 901 		handled = TRUE;
 902 		break;
 903 	case GDK_KEY_Return:
 904 	case GDK_KEY_KP_Enter:
 905 		if ((event->state & GDK_SHIFT_MASK) != 0) {
 906 			activate_selected_items_alternate (NAUTILUS_LIST_VIEW (view), NULL, TRUE);
 907 		} else {
 908 			activate_selected_items (NAUTILUS_LIST_VIEW (view));
 909 		}
 910 		handled = TRUE;
 911 		break;
 912 	case GDK_KEY_v:
 913 		/* Eat Control + v to not enable type ahead */
 914 		if ((event->state & GDK_CONTROL_MASK) != 0) {
 915 			handled = TRUE;
 916 		}
 917 		break;
 918 
 919 	default:
 920 		handled = FALSE;
 921 	}
 922 
 923 	return handled;
 924 }
 925 
 926 static void
 927 nautilus_list_view_reveal_selection (NautilusView *view)
 928 {
 929 	GList *selection;
 930 
 931 	g_return_if_fail (NAUTILUS_IS_LIST_VIEW (view));
 932 
 933         selection = nautilus_view_get_selection (view);
 934 
 935 	/* Make sure at least one of the selected items is scrolled into view */
 936 	if (selection != NULL) {
 937 		NautilusListView *list_view;
 938 		NautilusFile *file;
 939 		GtkTreeIter iter;
 940 		GtkTreePath *path;
 941 		
 942 		list_view = NAUTILUS_LIST_VIEW (view);
 943 		file = selection->data;
 944 		if (nautilus_list_model_get_first_iter_for_file (list_view->details->model, file, &iter)) {
 945 			path = gtk_tree_model_get_path (GTK_TREE_MODEL (list_view->details->model), &iter);
 946 
 947 			gtk_tree_view_scroll_to_cell (list_view->details->tree_view, path, NULL, FALSE, 0.0, 0.0);
 948 			
 949 			gtk_tree_path_free (path);
 950 		}
 951 	}
 952 
 953         nautilus_file_list_free (selection);
 954 }
 955 
 956 static gboolean
 957 sort_criterion_changes_due_to_user (GtkTreeView *tree_view)
 958 {
 959 	GList *columns, *p;
 960 	GtkTreeViewColumn *column;
 961 	GSignalInvocationHint *ihint;
 962 	gboolean ret;
 963 
 964 	ret = FALSE;
 965 
 966 	columns = gtk_tree_view_get_columns (tree_view);
 967 	for (p = columns; p != NULL; p = p->next) {
 968 		column = p->data;
 969 		ihint = g_signal_get_invocation_hint (column);
 970 		if (ihint != NULL) {
 971 			ret = TRUE;
 972 			break;
 973 		}
 974 	}
 975 	g_list_free (columns);
 976 
 977 	return ret;
 978 }
 979 
 980 static void
 981 sort_column_changed_callback (GtkTreeSortable *sortable, 
 982 			      NautilusListView *view)
 983 {
 984 	NautilusFile *file;
 985 	gint sort_column_id, default_sort_column_id;
 986 	GtkSortType reversed;
 987 	GQuark sort_attr, default_sort_attr;
 988 	char *reversed_attr, *default_reversed_attr;
 989 	gboolean default_sort_reversed;
 990 
 991 	file = nautilus_view_get_directory_as_file (NAUTILUS_VIEW (view));
 992 
 993 	gtk_tree_sortable_get_sort_column_id (sortable, &sort_column_id, &reversed);
 994 	sort_attr = nautilus_list_model_get_attribute_from_sort_column_id (view->details->model, sort_column_id);
 995 
 996 	default_sort_column_id = nautilus_list_model_get_sort_column_id_from_attribute (view->details->model,
 997 										  g_quark_from_string (get_default_sort_order (file, &default_sort_reversed)));
 998 	default_sort_attr = nautilus_list_model_get_attribute_from_sort_column_id (view->details->model, default_sort_column_id);
 999 	nautilus_file_set_metadata (file, NAUTILUS_METADATA_KEY_LIST_VIEW_SORT_COLUMN,
1000 				    g_quark_to_string (default_sort_attr), g_quark_to_string (sort_attr));
1001 
1002 	default_reversed_attr = (default_sort_reversed ? "true" : "false");
1003 
1004 	if (view->details->last_sort_attr != sort_attr &&
1005 	    sort_criterion_changes_due_to_user (view->details->tree_view)) {
1006 		/* at this point, the sort order is always GTK_SORT_ASCENDING, if the sort column ID
1007 		 * switched. Invert the sort order, if it's the default criterion with a reversed preference,
1008 		 * or if it makes sense for the attribute (i.e. date). */
1009 		if (sort_attr == default_sort_attr) {
1010 			/* use value from preferences */
1011 			reversed = g_settings_get_boolean (nautilus_preferences,
1012 							   NAUTILUS_PREFERENCES_DEFAULT_SORT_IN_REVERSE_ORDER);
1013 		} else {
1014 			reversed = nautilus_file_is_date_sort_attribute_q (sort_attr);
1015 		}
1016 
1017 		if (reversed) {
1018 			g_signal_handlers_block_by_func (sortable, sort_column_changed_callback, view);
1019 			gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (view->details->model),
1020 							      sort_column_id,
1021 							      GTK_SORT_DESCENDING);
1022 			g_signal_handlers_unblock_by_func (sortable, sort_column_changed_callback, view);
1023 		}
1024 	}
1025 
1026 
1027 	reversed_attr = (reversed ? "true" : "false");
1028 	nautilus_file_set_metadata (file, NAUTILUS_METADATA_KEY_LIST_VIEW_SORT_REVERSED,
1029 				    default_reversed_attr, reversed_attr);
1030 
1031 	/* Make sure selected item(s) is visible after sort */
1032 	nautilus_list_view_reveal_selection (NAUTILUS_VIEW (view));
1033 
1034 	view->details->last_sort_attr = sort_attr;
1035 }
1036 
1037 static void
1038 editable_focus_out_cb (GtkWidget *widget,
1039 		       GdkEvent *event,
1040 		       gpointer user_data)
1041 {
1042 	NautilusListView *view = user_data;
1043 
1044 	view->details->editable_widget = NULL;
1045 
1046 	nautilus_view_set_is_renaming (NAUTILUS_VIEW (view), FALSE);
1047 	nautilus_view_unfreeze_updates (NAUTILUS_VIEW (view));
1048 }
1049 
1050 static void
1051 cell_renderer_editing_started_cb (GtkCellRenderer *renderer,
1052 				  GtkCellEditable *editable,
1053 				  const gchar *path_str,
1054 				  NautilusListView *list_view)
1055 {
1056 	GtkEntry *entry;
1057 
1058 	entry = GTK_ENTRY (editable);
1059 	list_view->details->editable_widget = editable;
1060 
1061 	/* Free a previously allocated original_name */
1062 	g_free (list_view->details->original_name);
1063 
1064 	list_view->details->original_name = g_strdup (gtk_entry_get_text (entry));
1065 
1066 	g_signal_connect (entry, "focus-out-event",
1067 			  G_CALLBACK (editable_focus_out_cb), list_view);
1068 
1069 	nautilus_clipboard_set_up_editable
1070 		(GTK_EDITABLE (entry),
1071 		 nautilus_view_get_ui_manager (NAUTILUS_VIEW (list_view)),
1072 		 FALSE);
1073 }
1074 
1075 static void
1076 cell_renderer_editing_canceled (GtkCellRendererText *cell,
1077 				NautilusListView    *view)
1078 {
1079 	view->details->editable_widget = NULL;
1080 
1081 	nautilus_view_set_is_renaming (NAUTILUS_VIEW (view), FALSE);
1082 	nautilus_view_unfreeze_updates (NAUTILUS_VIEW (view));
1083 }
1084 
1085 static void
1086 cell_renderer_edited (GtkCellRendererText *cell,
1087 		      const char          *path_str,
1088 		      const char          *new_text,
1089 		      NautilusListView    *view)
1090 {
1091 	GtkTreePath *path;
1092 	NautilusFile *file;
1093 	GtkTreeIter iter;
1094 
1095 	view->details->editable_widget = NULL;
1096 	nautilus_view_set_is_renaming (NAUTILUS_VIEW (view), FALSE);
1097 
1098 	/* Don't allow a rename with an empty string. Revert to original 
1099 	 * without notifying the user.
1100 	 */
1101 	if (new_text[0] == '\0') {
1102 		g_object_set (G_OBJECT (view->details->file_name_cell),
1103 			      "editable", FALSE,
1104 			      NULL);
1105 		nautilus_view_unfreeze_updates (NAUTILUS_VIEW (view));
1106 		return;
1107 	}
1108 	
1109 	path = gtk_tree_path_new_from_string (path_str);
1110 
1111 	gtk_tree_model_get_iter (GTK_TREE_MODEL (view->details->model),
1112 				 &iter, path);
1113 
1114 	gtk_tree_path_free (path);
1115 	
1116 	gtk_tree_model_get (GTK_TREE_MODEL (view->details->model),
1117 			    &iter,
1118 			    NAUTILUS_LIST_MODEL_FILE_COLUMN, &file,
1119 			    -1);
1120 
1121 	/* Only rename if name actually changed */
1122 	if (strcmp (new_text, view->details->original_name) != 0) {
1123 		view->details->renaming_file = nautilus_file_ref (file);
1124 		view->details->rename_done = FALSE;
1125 		nautilus_rename_file (file, new_text, nautilus_list_view_rename_callback, g_object_ref (view));
1126 		g_free (view->details->original_name);
1127 		view->details->original_name = g_strdup (new_text);
1128 	}
1129 	
1130 	nautilus_file_unref (file);
1131 
1132 	/*We're done editing - make the filename-cells readonly again.*/
1133 	g_object_set (G_OBJECT (view->details->file_name_cell),
1134 		      "editable", FALSE,
1135 		      NULL);
1136 
1137 	nautilus_view_unfreeze_updates (NAUTILUS_VIEW (view));
1138 }
1139 
1140 static char *
1141 get_root_uri_callback (NautilusTreeViewDragDest *dest,
1142 		       gpointer user_data)
1143 {
1144 	NautilusListView *view;
1145 	
1146 	view = NAUTILUS_LIST_VIEW (user_data);
1147 
1148 	return nautilus_view_get_uri (NAUTILUS_VIEW (view));
1149 }
1150 
1151 static NautilusFile *
1152 get_file_for_path_callback (NautilusTreeViewDragDest *dest,
1153 			    GtkTreePath *path,
1154 			    gpointer user_data)
1155 {
1156 	NautilusListView *view;
1157 	
1158 	view = NAUTILUS_LIST_VIEW (user_data);
1159 
1160 	return nautilus_list_model_file_for_path (view->details->model, path);
1161 }
1162 
1163 /* Handles an URL received from Mozilla */
1164 static void
1165 list_view_handle_netscape_url (NautilusTreeViewDragDest *dest, const char *encoded_url,
1166 			       const char *target_uri, GdkDragAction action, int x, int y, NautilusListView *view)
1167 {
1168 	nautilus_view_handle_netscape_url_drop (NAUTILUS_VIEW (view),
1169 						encoded_url, target_uri, action, x, y);
1170 }
1171 
1172 static void
1173 list_view_handle_uri_list (NautilusTreeViewDragDest *dest, const char *item_uris,
1174 			   const char *target_uri,
1175 			   GdkDragAction action, int x, int y, NautilusListView *view)
1176 {
1177 	nautilus_view_handle_uri_list_drop (NAUTILUS_VIEW (view),
1178 					    item_uris, target_uri, action, x, y);
1179 }
1180 
1181 static void
1182 list_view_handle_text (NautilusTreeViewDragDest *dest, const char *text,
1183 		       const char *target_uri,
1184 		       GdkDragAction action, int x, int y, NautilusListView *view)
1185 {
1186 	nautilus_view_handle_text_drop (NAUTILUS_VIEW (view),
1187 					text, target_uri, action, x, y);
1188 }
1189 
1190 static void
1191 list_view_handle_raw (NautilusTreeViewDragDest *dest, const char *raw_data,
1192 		      int length, const char *target_uri, const char *direct_save_uri,
1193 		      GdkDragAction action, int x, int y, NautilusListView *view)
1194 {
1195 	nautilus_view_handle_raw_drop (NAUTILUS_VIEW (view),
1196 				       raw_data, length, target_uri, direct_save_uri,
1197 				       action, x, y);
1198 }
1199 
1200 static void
1201 move_copy_items_callback (NautilusTreeViewDragDest *dest,
1202 			  const GList *item_uris,
1203 			  const char *target_uri,
1204 			  guint action,
1205 			  int x, 
1206 			  int y,
1207 			  gpointer user_data)
1208 
1209 {
1210 	NautilusView *view = user_data;
1211 
1212 	nautilus_clipboard_clear_if_colliding_uris (GTK_WIDGET (view),
1213 						    item_uris,
1214 						    nautilus_view_get_copied_files_atom (view));
1215 	nautilus_view_move_copy_items (view,
1216 				       item_uris,
1217 				       NULL,
1218 				       target_uri,
1219 				       action,
1220 				       x, y);
1221 }
1222 
1223 static void
1224 apply_columns_settings (NautilusListView *list_view,
1225 			char **column_order,
1226 			char **visible_columns)
1227 {
1228 	GList *all_columns;
1229 	NautilusFile *file;
1230 	GList *old_view_columns, *view_columns;
1231 	GHashTable *visible_columns_hash;
1232 	GtkTreeViewColumn *prev_view_column;
1233 	GList *l;
1234 	int i;
1235 
1236 	file = nautilus_view_get_directory_as_file (NAUTILUS_VIEW (list_view));
1237 
1238 	/* prepare ordered list of view columns using column_order and visible_columns */
1239 	view_columns = NULL;
1240 
1241 	all_columns = nautilus_get_columns_for_file (file);
1242 	all_columns = nautilus_sort_columns (all_columns, column_order);
1243 
1244 	/* hash table to lookup if a given column should be visible */
1245 	visible_columns_hash = g_hash_table_new_full (g_str_hash,
1246 						      g_str_equal,
1247 						      (GDestroyNotify) g_free,
1248 						      (GDestroyNotify) g_free);
1249 	/* always show name column */
1250 	g_hash_table_insert (visible_columns_hash, g_strdup ("name"), g_strdup ("name"));
1251 	if (visible_columns != NULL) {
1252 		for (i = 0; visible_columns[i] != NULL; ++i) {
1253 			g_hash_table_insert (visible_columns_hash,
1254 					     g_ascii_strdown (visible_columns[i], -1),
1255 					     g_ascii_strdown (visible_columns[i], -1));
1256 		}
1257 	}
1258 
1259 	for (l = all_columns; l != NULL; l = l->next) {
1260 		char *name;
1261 		char *lowercase;
1262 
1263 		g_object_get (G_OBJECT (l->data), "name", &name, NULL);
1264 		lowercase = g_ascii_strdown (name, -1);
1265 
1266 		if (g_hash_table_lookup (visible_columns_hash, lowercase) != NULL) {
1267 			GtkTreeViewColumn *view_column;
1268 
1269 			view_column = g_hash_table_lookup (list_view->details->columns, name);
1270 			if (view_column != NULL) {
1271 				view_columns = g_list_prepend (view_columns, view_column);
1272 			}
1273 		}
1274 
1275 		g_free (name);
1276 		g_free (lowercase);
1277 	}
1278 
1279 	g_hash_table_destroy (visible_columns_hash);
1280 	nautilus_column_list_free (all_columns);
1281 
1282 	view_columns = g_list_reverse (view_columns);
1283 
1284 	/* remove columns that are not present in the configuration */
1285 	old_view_columns = gtk_tree_view_get_columns (list_view->details->tree_view);
1286 	for (l = old_view_columns; l != NULL; l = l->next) {
1287 		if (g_list_find (view_columns, l->data) == NULL) {
1288 			gtk_tree_view_remove_column (list_view->details->tree_view, l->data);
1289 		}
1290 	}
1291 	g_list_free (old_view_columns);
1292 
1293 	/* append new columns from the configuration */
1294 	old_view_columns = gtk_tree_view_get_columns (list_view->details->tree_view);
1295 	for (l = view_columns; l != NULL; l = l->next) {
1296 		if (g_list_find (old_view_columns, l->data) == NULL) {
1297 			gtk_tree_view_append_column (list_view->details->tree_view, l->data);
1298 		}
1299 	}
1300 	g_list_free (old_view_columns);
1301 
1302 	/* place columns in the correct order */
1303 	prev_view_column = NULL;
1304 	for (l = view_columns; l != NULL; l = l->next) {
1305 		gtk_tree_view_move_column_after (list_view->details->tree_view, l->data, prev_view_column);
1306 		prev_view_column = l->data;
1307 	}
1308 	g_list_free (view_columns);
1309 }
1310 
1311 static void
1312 filename_cell_data_func (GtkTreeViewColumn *column,
1313 			 GtkCellRenderer   *renderer,
1314 			 GtkTreeModel      *model,
1315 			 GtkTreeIter       *iter,
1316 			 NautilusListView        *view)
1317 {
1318 	char *text;
1319 	GtkTreePath *path;
1320 	PangoUnderline underline;
1321 
1322 	gtk_tree_model_get (model, iter,
1323 			    view->details->file_name_column_num, &text,
1324 			    -1);
1325 
1326 	if (get_click_policy () == NAUTILUS_CLICK_POLICY_SINGLE) {
1327 		path = gtk_tree_model_get_path (model, iter);
1328 
1329 		if (view->details->hover_path == NULL ||
1330 		    gtk_tree_path_compare (path, view->details->hover_path)) {
1331 			underline = PANGO_UNDERLINE_NONE;
1332 		} else {
1333 			underline = PANGO_UNDERLINE_SINGLE;
1334 		}
1335 
1336 		gtk_tree_path_free (path);
1337 	} else {
1338 		underline = PANGO_UNDERLINE_NONE;
1339 	}
1340 
1341 	g_object_set (G_OBJECT (renderer),
1342 		      "text", text,
1343 		      "underline", underline,
1344 		      NULL);
1345 	g_free (text);
1346 }
1347 
1348 static void
1349 set_up_pixbuf_size (NautilusListView *view)
1350 {
1351 	int icon_size;
1352 
1353 	/* Make all rows the same size. */
1354 	icon_size = nautilus_get_icon_size_for_zoom_level (view->details->zoom_level);
1355 	gtk_cell_renderer_set_fixed_size (GTK_CELL_RENDERER (view->details->pixbuf_cell),
1356 					  -1, icon_size);
1357 
1358 
1359 	/* FIXME: https://bugzilla.gnome.org/show_bug.cgi?id=641518 */
1360 	gtk_tree_view_columns_autosize (view->details->tree_view);
1361 }
1362 
1363 static void
1364 create_and_set_up_tree_view (NautilusListView *view)
1365 {
1366 	GtkCellRenderer *cell;
1367 	GtkTreeViewColumn *column;
1368 	AtkObject *atk_obj;
1369 	GList *nautilus_columns;
1370 	GList *l;
1371 	gchar **default_column_order, **default_visible_columns;
1372 	
1373 	view->details->tree_view = GTK_TREE_VIEW (gtk_tree_view_new ());
1374 	view->details->columns = g_hash_table_new_full (g_str_hash, 
1375 							g_str_equal,
1376 							(GDestroyNotify)g_free,
1377 							(GDestroyNotify) g_object_unref);
1378 	gtk_tree_view_set_enable_search (view->details->tree_view, FALSE);
1379 
1380 	view->details->drag_dest = 
1381 		nautilus_tree_view_drag_dest_new (view->details->tree_view);
1382 
1383 	g_signal_connect_object (view->details->drag_dest,
1384 				 "get_root_uri",
1385 				 G_CALLBACK (get_root_uri_callback),
1386 				 view, 0);
1387 	g_signal_connect_object (view->details->drag_dest,
1388 				 "get_file_for_path",
1389 				 G_CALLBACK (get_file_for_path_callback),
1390 				 view, 0);
1391 	g_signal_connect_object (view->details->drag_dest,
1392 				 "move_copy_items",
1393 				 G_CALLBACK (move_copy_items_callback),
1394 				 view, 0);
1395 	g_signal_connect_object (view->details->drag_dest, "handle_netscape_url",
1396 				 G_CALLBACK (list_view_handle_netscape_url), view, 0);
1397 	g_signal_connect_object (view->details->drag_dest, "handle_uri_list",
1398 				 G_CALLBACK (list_view_handle_uri_list), view, 0);
1399 	g_signal_connect_object (view->details->drag_dest, "handle_text",
1400 				 G_CALLBACK (list_view_handle_text), view, 0);
1401 	g_signal_connect_object (view->details->drag_dest, "handle_raw",
1402 				 G_CALLBACK (list_view_handle_raw), view, 0);
1403 
1404 	g_signal_connect_object (gtk_tree_view_get_selection (view->details->tree_view),
1405 				 "changed",
1406 				 G_CALLBACK (list_selection_changed_callback), view, 0);
1407 
1408 	g_signal_connect_object (view->details->tree_view, "drag_begin",
1409 				 G_CALLBACK (drag_begin_callback), view, 0);
1410 	g_signal_connect_object (view->details->tree_view, "drag_data_get",
1411 				 G_CALLBACK (drag_data_get_callback), view, 0);
1412 	g_signal_connect_object (view->details->tree_view, "motion_notify_event",
1413 				 G_CALLBACK (motion_notify_callback), view, 0);
1414 	g_signal_connect_object (view->details->tree_view, "enter_notify_event",
1415 				 G_CALLBACK (enter_notify_callback), view, 0);
1416 	g_signal_connect_object (view->details->tree_view, "leave_notify_event",
1417 				 G_CALLBACK (leave_notify_callback), view, 0);
1418 	g_signal_connect_object (view->details->tree_view, "button_press_event",
1419 				 G_CALLBACK (button_press_callback), view, 0);
1420 	g_signal_connect_object (view->details->tree_view, "button_release_event",
1421 				 G_CALLBACK (button_release_callback), view, 0);
1422 	g_signal_connect_object (view->details->tree_view, "key_press_event",
1423 				 G_CALLBACK (key_press_callback), view, 0);
1424 	g_signal_connect_object (view->details->tree_view, "popup_menu",
1425                                  G_CALLBACK (popup_menu_callback), view, 0);
1426 	g_signal_connect_object (view->details->tree_view, "row-activated",
1427                                  G_CALLBACK (row_activated_callback), view, 0);
1428 	
1429 	view->details->model = g_object_new (NAUTILUS_TYPE_LIST_MODEL, NULL);
1430 	gtk_tree_view_set_model (view->details->tree_view, GTK_TREE_MODEL (view->details->model));
1431 	/* Need the model for the dnd drop icon "accept" change */
1432 	nautilus_list_model_set_drag_view (NAUTILUS_LIST_MODEL (view->details->model),
1433 				     view->details->tree_view,  0, 0);
1434 
1435 	g_signal_connect_object (view->details->model, "sort_column_changed",
1436 				 G_CALLBACK (sort_column_changed_callback), view, 0);
1437 	
1438 	g_signal_connect_object (view->details->model, "subdirectory_unloaded",
1439 				 G_CALLBACK (subdirectory_unloaded_callback), view, 0);
1440 
1441 	gtk_tree_selection_set_mode (gtk_tree_view_get_selection (view->details->tree_view), GTK_SELECTION_MULTIPLE);
1442 	gtk_tree_view_set_rules_hint (view->details->tree_view, TRUE);
1443 
1444 	nautilus_columns = nautilus_get_all_columns ();
1445 
1446 	for (l = nautilus_columns; l != NULL; l = l->next) {
1447 		NautilusColumn *nautilus_column;
1448 		int column_num;		
1449 		char *name;
1450 		char *label;
1451 		float xalign;
1452 		GtkSortType sort_order;
1453 
1454 		nautilus_column = NAUTILUS_COLUMN (l->data);
1455 
1456 		g_object_get (nautilus_column, 
1457 			      "name", &name, 
1458 			      "label", &label,
1459 			      "xalign", &xalign,
1460 			      "default-sort-order", &sort_order,
1461 			      NULL);
1462 
1463 		column_num = nautilus_list_model_add_column (view->details->model,
1464 						       nautilus_column);
1465 
1466 		/* Created the name column specially, because it
1467 		 * has the icon in it.*/
1468 		if (!strcmp (name, "name")) {
1469 			/* Create the file name column */
1470 			cell = gtk_cell_renderer_pixbuf_new ();
1471 			view->details->pixbuf_cell = (GtkCellRendererPixbuf *)cell;
1472 			set_up_pixbuf_size (view);
1473 			
1474 			view->details->file_name_column = gtk_tree_view_column_new ();
1475 			g_object_ref_sink (view->details->file_name_column);
1476 			view->details->file_name_column_num = column_num;
1477 			
1478 			g_hash_table_insert (view->details->columns,
1479 					     g_strdup ("name"), 
1480 					     view->details->file_name_column);
1481 
1482 			gtk_tree_view_set_search_column (view->details->tree_view, column_num);
1483 
1484 			gtk_tree_view_column_set_sort_column_id (view->details->file_name_column, column_num);
1485 			gtk_tree_view_column_set_title (view->details->file_name_column, _("Name"));
1486 			gtk_tree_view_column_set_resizable (view->details->file_name_column, TRUE);
1487 			gtk_tree_view_column_set_expand (view->details->file_name_column, TRUE);
1488 
1489 			gtk_tree_view_column_pack_start (view->details->file_name_column, cell, FALSE);
1490 			gtk_tree_view_column_set_attributes (view->details->file_name_column,
1491 							     cell,
1492 							     "pixbuf", nautilus_list_model_get_column_id_from_zoom_level (view->details->zoom_level),
1493 							     NULL);
1494 			
1495 			cell = gtk_cell_renderer_text_new ();
1496 			view->details->file_name_cell = (GtkCellRendererText *)cell;
1497 			g_object_set (cell,
1498 				      "ellipsize", PANGO_ELLIPSIZE_END,
1499 				      "single-paragraph-mode", TRUE,
1500 				      "xpad", 5,
1501 				      NULL);
1502 
1503 			g_signal_connect (cell, "edited", G_CALLBACK (cell_renderer_edited), view);
1504 			g_signal_connect (cell, "editing-canceled", G_CALLBACK (cell_renderer_editing_canceled), view);
1505 			g_signal_connect (cell, "editing-started", G_CALLBACK (cell_renderer_editing_started_cb), view);
1506 
1507 			gtk_tree_view_column_pack_start (view->details->file_name_column, cell, TRUE);
1508 			gtk_tree_view_column_set_cell_data_func (view->details->file_name_column, cell,
1509 								 (GtkTreeCellDataFunc) filename_cell_data_func,
1510 								 view, NULL);
1511 		} else {
1512 			cell = gtk_cell_renderer_text_new ();
1513 			g_object_set (cell,
1514 				      "xalign", xalign,
1515 				      "xpad", 5,
1516 				      NULL);
1517 			view->details->cells = g_list_append (view->details->cells,
1518 							      cell);
1519 			column = gtk_tree_view_column_new_with_attributes (label,
1520 									   cell,
1521 									   "text", column_num,
1522 									   NULL);
1523 			g_object_ref_sink (column);
1524 			gtk_tree_view_column_set_sort_column_id (column, column_num);
1525 			g_hash_table_insert (view->details->columns, 
1526 					     g_strdup (name), 
1527 					     column);
1528 			
1529 			gtk_tree_view_column_set_resizable (column, TRUE);
1530 			gtk_tree_view_column_set_visible (column, TRUE);
1531 			gtk_tree_view_column_set_sort_order (column, sort_order);
1532 		}
1533 		g_free (name);
1534 		g_free (label);
1535 	}
1536 	nautilus_column_list_free (nautilus_columns);
1537 
1538 	default_visible_columns = g_settings_get_strv (nautilus_list_view_preferences,
1539 						       NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_VISIBLE_COLUMNS);
1540 	default_column_order = g_settings_get_strv (nautilus_list_view_preferences,
1541 						    NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_COLUMN_ORDER);
1542 
1543 	/* Apply the default column order and visible columns, to get it
1544 	 * right most of the time. The metadata will be checked when a 
1545 	 * folder is loaded */
1546 	apply_columns_settings (view,
1547 				default_column_order,
1548 				default_visible_columns);
1549 
1550 	gtk_widget_show (GTK_WIDGET (view->details->tree_view));
1551 	gtk_container_add (GTK_CONTAINER (view), GTK_WIDGET (view->details->tree_view));
1552 
1553         atk_obj = gtk_widget_get_accessible (GTK_WIDGET (view->details->tree_view));
1554         atk_object_set_name (atk_obj, _("List View"));
1555 
1556 	g_strfreev (default_visible_columns);
1557 	g_strfreev (default_column_order);
1558 }
1559 
1560 static void
1561 nautilus_list_view_add_file (NautilusView *view, NautilusFile *file, NautilusDirectory *directory)
1562 {
1563 	NautilusListModel *model;
1564 
1565 	model = NAUTILUS_LIST_VIEW (view)->details->model;
1566 	nautilus_list_model_add_file (model, file, directory);
1567 }
1568 
1569 static char **
1570 get_visible_columns (NautilusListView *list_view)
1571 {
1572 	NautilusFile *file;
1573 	GList *visible_columns;
1574 	char **ret;
1575 
1576 	ret = NULL;
1577 
1578 	file = nautilus_view_get_directory_as_file (NAUTILUS_VIEW (list_view));
1579 
1580 	visible_columns = nautilus_file_get_metadata_list 
1581 		(file,
1582 		 NAUTILUS_METADATA_KEY_LIST_VIEW_VISIBLE_COLUMNS);
1583 
1584 	if (visible_columns) {
1585 		GPtrArray *res;
1586 		GList *l;
1587 
1588 		res = g_ptr_array_new ();
1589 		for (l = visible_columns; l != NULL; l = l->next) {
1590 			g_ptr_array_add (res, l->data);
1591 		}
1592 		g_ptr_array_add (res, NULL);
1593 
1594 		ret = (char **) g_ptr_array_free (res, FALSE);
1595 		g_list_free (visible_columns);
1596 	}
1597 
1598 	if (ret != NULL) {
1599 		return ret;
1600 	}
1601 
1602 	return nautilus_file_is_in_trash (file) ?
1603 		g_strdupv ((gchar **) default_trash_visible_columns) :
1604 		g_settings_get_strv (nautilus_list_view_preferences,
1605 				     NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_VISIBLE_COLUMNS);
1606 }
1607 
1608 static char **
1609 get_column_order (NautilusListView *list_view)
1610 {
1611 	NautilusFile *file;
1612 	GList *column_order;
1613 	char **ret;
1614 
1615 	ret = NULL;
1616 
1617 	file = nautilus_view_get_directory_as_file (NAUTILUS_VIEW (list_view));
1618 
1619 	column_order = nautilus_file_get_metadata_list 
1620 		(file,
1621 		 NAUTILUS_METADATA_KEY_LIST_VIEW_COLUMN_ORDER);
1622 
1623 	if (column_order) {
1624 		GPtrArray *res;
1625 		GList *l;
1626 
1627 		res = g_ptr_array_new ();
1628 		for (l = column_order; l != NULL; l = l->next) {
1629 			g_ptr_array_add (res, l->data);
1630 		}
1631 		g_ptr_array_add (res, NULL);
1632 
1633 		ret = (char **) g_ptr_array_free (res, FALSE);
1634 		g_list_free (column_order);
1635 	}
1636 
1637 	if (ret != NULL) {
1638 		return ret;
1639 	}
1640 
1641 	return nautilus_file_is_in_trash (file) ?
1642 		g_strdupv ((gchar **) default_trash_columns_order) :
1643 		g_settings_get_strv (nautilus_list_view_preferences,
1644 				     NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_COLUMN_ORDER);
1645 }
1646 
1647 static void
1648 set_columns_settings_from_metadata_and_preferences (NautilusListView *list_view)
1649 {
1650 	char **column_order;
1651 	char **visible_columns;
1652 
1653 	column_order = get_column_order (list_view);
1654 	visible_columns = get_visible_columns (list_view);
1655 
1656 	apply_columns_settings (list_view, column_order, visible_columns);
1657 
1658 	g_strfreev (column_order);
1659 	g_strfreev (visible_columns);
1660 }
1661 
1662 static void
1663 set_sort_order_from_metadata_and_preferences (NautilusListView *list_view)
1664 {
1665 	char *sort_attribute;
1666 	int sort_column_id;
1667 	NautilusFile *file;
1668 	gboolean sort_reversed, default_sort_reversed;
1669 	const gchar *default_sort_order;
1670 	
1671 	file = nautilus_view_get_directory_as_file (NAUTILUS_VIEW (list_view));
1672 	sort_attribute = nautilus_file_get_metadata (file,
1673 						     NAUTILUS_METADATA_KEY_LIST_VIEW_SORT_COLUMN,
1674 						     NULL);
1675 	sort_column_id = nautilus_list_model_get_sort_column_id_from_attribute (list_view->details->model,
1676 									  g_quark_from_string (sort_attribute));
1677 	g_free (sort_attribute);
1678 
1679 	default_sort_order = get_default_sort_order (file, &default_sort_reversed);
1680 	
1681 	if (sort_column_id == -1) {
1682 		sort_column_id =
1683 			nautilus_list_model_get_sort_column_id_from_attribute (list_view->details->model,
1684 									 g_quark_from_string (default_sort_order));
1685 	}
1686 
1687 	sort_reversed = nautilus_file_get_boolean_metadata (file,
1688 							    NAUTILUS_METADATA_KEY_LIST_VIEW_SORT_REVERSED,
1689 							    default_sort_reversed);
1690 
1691 	gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (list_view->details->model),
1692 					      sort_column_id,
1693 					      sort_reversed ? GTK_SORT_DESCENDING : GTK_SORT_ASCENDING);					      
1694 }
1695 
1696 static NautilusZoomLevel
1697 get_default_zoom_level (void) {
1698 	NautilusZoomLevel default_zoom_level;
1699 
1700 	default_zoom_level = g_settings_get_enum (nautilus_list_view_preferences,
1701 						  NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_ZOOM_LEVEL);
1702 
1703 	if (default_zoom_level <  NAUTILUS_ZOOM_LEVEL_SMALLEST
1704 	    || NAUTILUS_ZOOM_LEVEL_LARGEST < default_zoom_level) {
1705 		default_zoom_level = NAUTILUS_ZOOM_LEVEL_SMALL;
1706 	}
1707 
1708 	return default_zoom_level;
1709 }
1710 
1711 static void
1712 nautilus_list_view_begin_loading (NautilusView *view)
1713 {
1714 	NautilusListView *list_view;
1715 
1716 	list_view = NAUTILUS_LIST_VIEW (view);
1717 
1718 	set_sort_order_from_metadata_and_preferences (list_view);
1719 	set_columns_settings_from_metadata_and_preferences (list_view);
1720 }
1721 
1722 static void
1723 stop_cell_editing (NautilusListView *list_view)
1724 {
1725 	GtkTreeViewColumn *column;
1726 
1727 	/* Stop an ongoing rename to commit the name changes when the user
1728 	 * changes directories without exiting cell edit mode. It also prevents
1729 	 * the edited handler from being called on the cleared list model.
1730 	 */
1731 	column = list_view->details->file_name_column;
1732 	if (column != NULL && list_view->details->editable_widget != NULL &&
1733 	    GTK_IS_CELL_EDITABLE (list_view->details->editable_widget)) {
1734 		gtk_cell_editable_editing_done (list_view->details->editable_widget);
1735 	}
1736 
1737 	g_clear_object (&list_view->details->renaming_file);
1738 }
1739 
1740 static void
1741 nautilus_list_view_clear (NautilusView *view)
1742 {
1743 	NautilusListView *list_view;
1744 
1745 	list_view = NAUTILUS_LIST_VIEW (view);
1746 
1747 	if (list_view->details->model != NULL) {
1748 		stop_cell_editing (list_view);
1749 		nautilus_list_model_clear (list_view->details->model);
1750 	}
1751 }
1752 
1753 static void
1754 nautilus_list_view_rename_callback (NautilusFile *file,
1755 				    GFile *result_location,
1756 				    GError *error,
1757 				    gpointer callback_data)
1758 {
1759 	NautilusListView *view;
1760 	
1761 	view = NAUTILUS_LIST_VIEW (callback_data);
1762 
1763 	if (view->details->renaming_file) {
1764 		view->details->rename_done = TRUE;
1765 		
1766 		if (error != NULL) {
1767 			/* If the rename failed (or was cancelled), kill renaming_file.
1768 			 * We won't get a change event for the rename, so otherwise
1769 			 * it would stay around forever.
1770 			 */
1771 			nautilus_file_unref (view->details->renaming_file);
1772 			view->details->renaming_file = NULL;
1773 		}
1774 	}
1775 	
1776 	g_object_unref (view);
1777 }
1778 
1779 
1780 static void
1781 nautilus_list_view_file_changed (NautilusView *view, NautilusFile *file, NautilusDirectory *directory)
1782 {
1783 	NautilusListView *listview;
1784 	GtkTreeIter iter;
1785 	GtkTreePath *file_path;
1786 
1787 	listview = NAUTILUS_LIST_VIEW (view);
1788 	
1789 	nautilus_list_model_file_changed (listview->details->model, file, directory);
1790 
1791 	if (listview->details->renaming_file != NULL &&
1792 	    file == listview->details->renaming_file &&
1793 	    listview->details->rename_done) {
1794 		/* This is (probably) the result of the rename operation, and
1795 		 * the tree-view changes above could have resorted the list, so
1796 		 * scroll to the new position
1797 		 */
1798 		if (nautilus_list_model_get_tree_iter_from_file (listview->details->model, file, directory, &iter)) {
1799 			file_path = gtk_tree_model_get_path (GTK_TREE_MODEL (listview->details->model), &iter);
1800 			gtk_tree_view_scroll_to_cell (listview->details->tree_view,
1801 						      file_path, NULL,
1802 						      FALSE, 0.0, 0.0);
1803 			gtk_tree_path_free (file_path);
1804 		}
1805 		
1806 		nautilus_file_unref (listview->details->renaming_file);
1807 		listview->details->renaming_file = NULL;
1808 	}
1809 }
1810 
1811 typedef struct {
1812 	GtkTreePath *path;
1813 	gboolean is_common;
1814 	gboolean is_root;
1815 } HasCommonParentData;
1816 
1817 static void
1818 tree_selection_has_common_parent_foreach_func (GtkTreeModel *model,
1819 						GtkTreePath *path,
1820 						GtkTreeIter *iter,
1821 						gpointer user_data)
1822 {
1823 	HasCommonParentData *data;
1824 	GtkTreePath *parent_path;
1825 	gboolean has_parent;
1826 
1827 	data = (HasCommonParentData *) user_data;
1828 
1829 	parent_path = gtk_tree_path_copy (path);
1830 	gtk_tree_path_up (parent_path);
1831 
1832 	has_parent = (gtk_tree_path_get_depth (parent_path) > 0) ? TRUE : FALSE;
1833 
1834 	if (!has_parent) {
1835 		data->is_root = TRUE;
1836 	}
1837 
1838 	if (data->is_common && !data->is_root) {
1839 		if (data->path == NULL) {
1840 			data->path = gtk_tree_path_copy (parent_path);
1841 		} else if (gtk_tree_path_compare (data->path, parent_path) != 0) {
1842 			data->is_common = FALSE;
1843 		}
1844 	}
1845 
1846 	gtk_tree_path_free (parent_path);
1847 }
1848 
1849 static void
1850 tree_selection_has_common_parent (GtkTreeSelection *selection,
1851 				  gboolean *is_common,
1852 				  gboolean *is_root)
1853 {
1854 	HasCommonParentData data;
1855 
1856 	g_assert (is_common != NULL);
1857 	g_assert (is_root != NULL);
1858 
1859 	data.path = NULL;
1860 	data.is_common = *is_common = TRUE;
1861 	data.is_root = *is_root = FALSE;
1862 
1863 	gtk_tree_selection_selected_foreach (selection,
1864 					     tree_selection_has_common_parent_foreach_func,
1865 					     &data);
1866 
1867 	*is_common = data.is_common;
1868 	*is_root = data.is_root;
1869 
1870 	if (data.path != NULL) {
1871 		gtk_tree_path_free (data.path);
1872 	}
1873 }
1874 
1875 static char *
1876 nautilus_list_view_get_backing_uri (NautilusView *view)
1877 {
1878 	NautilusListView *list_view;
1879 	NautilusListModel *list_model;
1880 	NautilusFile *file;
1881 	GtkTreeView *tree_view;
1882 	GtkTreeSelection *selection;
1883 	GtkTreePath *path;
1884 	GList *paths;
1885 	guint length;
1886 	char *uri;
1887 
1888 	g_return_val_if_fail (NAUTILUS_IS_LIST_VIEW (view), NULL);
1889 
1890 	list_view = NAUTILUS_LIST_VIEW (view);
1891 	list_model = list_view->details->model;
1892 	tree_view = list_view->details->tree_view;
1893 
1894 	g_assert (list_model);
1895 
1896 	/* We currently handle two common cases here:
1897 	 * (a) if the selection contains non-filesystem items (i.e., the
1898 	 *     "(Empty)" label), we return the uri of the parent.
1899 	 * (b) if the selection consists of either exactly one item or
1900 	 *     multiple items in the same directory, we return the URI
1901 	 *     of the common parent.
1902 	 */
1903 
1904 	uri = NULL;
1905 
1906 	selection = gtk_tree_view_get_selection (tree_view);
1907 	length = gtk_tree_selection_count_selected_rows (selection);
1908 
1909 	if (length == 1) {
1910 
1911 		paths = gtk_tree_selection_get_selected_rows (selection, NULL);
1912 		path = (GtkTreePath *) paths->data;
1913 
1914 		file = nautilus_list_model_file_for_path (list_model, path);
1915 		if (file == NULL) {
1916 			/* The selected item is a label, not a file */
1917 			gtk_tree_path_up (path);
1918 			file = nautilus_list_model_file_for_path (list_model, path);
Value stored to 'file' is never read
(emitted by clang-analyzer)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

1919 } 1920 1921 gtk_tree_path_free (path); 1922 g_list_free (paths); 1923 } 1924 1925 if (uri == NULL && length > 0) { 1926 1927 gboolean is_common, is_root; 1928 1929 /* Check that all the selected items belong to the same 1930 * directory and that directory is not the root directory (which 1931 * is handled by NautilusView::get_backing_directory.) */ 1932 1933 tree_selection_has_common_parent (selection, &is_common, &is_root); 1934 1935 if (is_common && !is_root) { 1936 1937 paths = gtk_tree_selection_get_selected_rows (selection, NULL); 1938 path = (GtkTreePath *) paths->data; 1939 1940 file = nautilus_list_model_file_for_path (list_model, path); 1941 g_assert (file != NULL); 1942 uri = nautilus_file_get_parent_uri (file); 1943 nautilus_file_unref (file); 1944 1945 g_list_foreach (paths, (GFunc) gtk_tree_path_free, NULL); 1946 g_list_free (paths); 1947 } 1948 } 1949 1950 if (uri != NULL) { 1951 return uri; 1952 } 1953 1954 return NAUTILUS_VIEW_CLASS (nautilus_list_view_parent_class)->get_backing_uri (view); 1955 } 1956 1957 static void 1958 nautilus_list_view_get_selection_foreach_func (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data) 1959 { 1960 GList **list; 1961 NautilusFile *file; 1962 1963 list = data; 1964 1965 gtk_tree_model_get (model, iter, 1966 NAUTILUS_LIST_MODEL_FILE_COLUMN, &file, 1967 -1); 1968 1969 if (file != NULL) { 1970 (* list) = g_list_prepend ((* list), file); 1971 } 1972 } 1973 1974 static GList * 1975 nautilus_list_view_get_selection (NautilusView *view) 1976 { 1977 GList *list; 1978 1979 list = NULL; 1980 1981 gtk_tree_selection_selected_foreach (gtk_tree_view_get_selection (NAUTILUS_LIST_VIEW (view)->details->tree_view), 1982 nautilus_list_view_get_selection_foreach_func, &list); 1983 1984 return g_list_reverse (list); 1985 } 1986 1987 static void 1988 nautilus_list_view_get_selection_for_file_transfer_foreach_func (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data) 1989 { 1990 NautilusFile *file; 1991 struct SelectionForeachData *selection_data; 1992 GtkTreeIter parent, child; 1993 1994 selection_data = data; 1995 1996 gtk_tree_model_get (model, iter, 1997 NAUTILUS_LIST_MODEL_FILE_COLUMN, &file, 1998 -1); 1999 2000 if (file != NULL) { 2001 /* If the parent folder is also selected, don't include this file in the 2002 * file operation, since that would copy it to the toplevel target instead 2003 * of keeping it as a child of the copied folder 2004 */ 2005 child = *iter; 2006 while (gtk_tree_model_iter_parent (model, &parent, &child)) { 2007 if (gtk_tree_selection_iter_is_selected (selection_data->selection, 2008 &parent)) { 2009 return; 2010 } 2011 child = parent; 2012 } 2013 2014 nautilus_file_ref (file); 2015 selection_data->list = g_list_prepend (selection_data->list, file); 2016 } 2017 } 2018 2019 2020 static GList * 2021 nautilus_list_view_get_selection_for_file_transfer (NautilusView *view) 2022 { 2023 struct SelectionForeachData selection_data; 2024 2025 selection_data.list = NULL; 2026 selection_data.selection = gtk_tree_view_get_selection (NAUTILUS_LIST_VIEW (view)->details->tree_view); 2027 2028 gtk_tree_selection_selected_foreach (selection_data.selection, 2029 nautilus_list_view_get_selection_for_file_transfer_foreach_func, &selection_data); 2030 2031 return g_list_reverse (selection_data.list); 2032 } 2033 2034 static gboolean 2035 nautilus_list_view_is_empty (NautilusView *view) 2036 { 2037 return nautilus_list_model_is_empty (NAUTILUS_LIST_VIEW (view)->details->model); 2038 } 2039 2040 static void 2041 nautilus_list_view_end_file_changes (NautilusView *view) 2042 { 2043 NautilusListView *list_view; 2044 2045 list_view = NAUTILUS_LIST_VIEW (view); 2046 2047 if (list_view->details->new_selection_path) { 2048 gtk_tree_view_set_cursor (list_view->details->tree_view, 2049 list_view->details->new_selection_path, 2050 NULL, FALSE); 2051 gtk_tree_path_free (list_view->details->new_selection_path); 2052 list_view->details->new_selection_path = NULL; 2053 } 2054 } 2055 2056 static void 2057 nautilus_list_view_remove_file (NautilusView *view, NautilusFile *file, NautilusDirectory *directory) 2058 { 2059 GtkTreePath *path; 2060 GtkTreePath *file_path; 2061 GtkTreeIter iter; 2062 GtkTreeIter temp_iter; 2063 GtkTreeRowReference* row_reference; 2064 NautilusListView *list_view; 2065 GtkTreeModel* tree_model; 2066 GtkTreeSelection *selection; 2067 2068 path = NULL; 2069 row_reference = NULL; 2070 list_view = NAUTILUS_LIST_VIEW (view); 2071 tree_model = GTK_TREE_MODEL(list_view->details->model); 2072 2073 if (nautilus_list_model_get_tree_iter_from_file (list_view->details->model, file, directory, &iter)) { 2074 selection = gtk_tree_view_get_selection (list_view->details->tree_view); 2075 file_path = gtk_tree_model_get_path (tree_model, &iter); 2076 2077 if (gtk_tree_selection_path_is_selected (selection, file_path)) { 2078 /* get reference for next element in the list view. If the element to be deleted is the 2079 * last one, get reference to previous element. If there is only one element in view 2080 * no need to select anything. 2081 */ 2082 temp_iter = iter; 2083 2084 if (gtk_tree_model_iter_next (tree_model, &iter)) { 2085 path = gtk_tree_model_get_path (tree_model, &iter); 2086 row_reference = gtk_tree_row_reference_new (tree_model, path); 2087 } else { 2088 path = gtk_tree_model_get_path (tree_model, &temp_iter); 2089 if (gtk_tree_path_prev (path)) { 2090 row_reference = gtk_tree_row_reference_new (tree_model, path); 2091 } 2092 } 2093 gtk_tree_path_free (path); 2094 } 2095 2096 gtk_tree_path_free (file_path); 2097 2098 nautilus_list_model_remove_file (list_view->details->model, file, directory); 2099 2100 if (gtk_tree_row_reference_valid (row_reference)) { 2101 if (list_view->details->new_selection_path) { 2102 gtk_tree_path_free (list_view->details->new_selection_path); 2103 } 2104 list_view->details->new_selection_path = gtk_tree_row_reference_get_path (row_reference); 2105 } 2106 2107 if (row_reference) { 2108 gtk_tree_row_reference_free (row_reference); 2109 } 2110 } 2111 2112 2113 } 2114 2115 static void 2116 nautilus_list_view_set_selection (NautilusView *view, GList *selection) 2117 { 2118 NautilusListView *list_view; 2119 GtkTreeSelection *tree_selection; 2120 GList *node; 2121 GList *iters, *l; 2122 NautilusFile *file; 2123 2124 list_view = NAUTILUS_LIST_VIEW (view); 2125 tree_selection = gtk_tree_view_get_selection (list_view->details->tree_view); 2126 2127 g_signal_handlers_block_by_func (tree_selection, list_selection_changed_callback, view); 2128 2129 gtk_tree_selection_unselect_all (tree_selection); 2130 for (node = selection; node != NULL; node = node->next) { 2131 file = node->data; 2132 iters = nautilus_list_model_get_all_iters_for_file (list_view->details->model, file); 2133 2134 for (l = iters; l != NULL; l = l->next) { 2135 gtk_tree_selection_select_iter (tree_selection, 2136 (GtkTreeIter *)l->data); 2137 } 2138 g_list_free_full (iters, g_free); 2139 } 2140 2141 g_signal_handlers_unblock_by_func (tree_selection, list_selection_changed_callback, view); 2142 nautilus_view_notify_selection_changed (view); 2143 } 2144 2145 static void 2146 nautilus_list_view_invert_selection (NautilusView *view) 2147 { 2148 NautilusListView *list_view; 2149 GtkTreeSelection *tree_selection; 2150 GList *node; 2151 GList *iters, *l; 2152 NautilusFile *file; 2153 GList *selection = NULL; 2154 2155 list_view = NAUTILUS_LIST_VIEW (view); 2156 tree_selection = gtk_tree_view_get_selection (list_view->details->tree_view); 2157 2158 g_signal_handlers_block_by_func (tree_selection, list_selection_changed_callback, view); 2159 2160 gtk_tree_selection_selected_foreach (tree_selection, 2161 nautilus_list_view_get_selection_foreach_func, &selection); 2162 2163 gtk_tree_selection_select_all (tree_selection); 2164 2165 for (node = selection; node != NULL; node = node->next) { 2166 file = node->data; 2167 iters = nautilus_list_model_get_all_iters_for_file (list_view->details->model, file); 2168 2169 for (l = iters; l != NULL; l = l->next) { 2170 gtk_tree_selection_unselect_iter (tree_selection, 2171 (GtkTreeIter *)l->data); 2172 } 2173 g_list_free_full (iters, g_free); 2174 } 2175 2176 g_list_free (selection); 2177 2178 g_signal_handlers_unblock_by_func (tree_selection, list_selection_changed_callback, view); 2179 nautilus_view_notify_selection_changed (view); 2180 } 2181 2182 static void 2183 nautilus_list_view_select_all (NautilusView *view) 2184 { 2185 gtk_tree_selection_select_all (gtk_tree_view_get_selection (NAUTILUS_LIST_VIEW (view)->details->tree_view)); 2186 } 2187 2188 static void 2189 nautilus_list_view_select_first (NautilusView *view) 2190 { 2191 GtkTreeSelection *selection; 2192 GtkTreeIter iter; 2193 2194 if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (NAUTILUS_LIST_VIEW (view)->details->model), &iter)) { 2195 return; 2196 } 2197 selection = gtk_tree_view_get_selection (NAUTILUS_LIST_VIEW (view)->details->tree_view); 2198 gtk_tree_selection_select_iter (selection, &iter); 2199 } 2200 2201 static void 2202 column_editor_response_callback (GtkWidget *dialog, 2203 int response_id, 2204 gpointer user_data) 2205 { 2206 gtk_widget_destroy (GTK_WIDGET (dialog)); 2207 } 2208 2209 static void 2210 column_chooser_changed_callback (NautilusColumnChooser *chooser, 2211 NautilusListView *view) 2212 { 2213 NautilusFile *file; 2214 char **visible_columns; 2215 char **column_order; 2216 GList *list; 2217 int i; 2218 2219 file = nautilus_view_get_directory_as_file (NAUTILUS_VIEW (view)); 2220 2221 nautilus_column_chooser_get_settings (chooser, 2222 &visible_columns, 2223 &column_order); 2224 2225 list = NULL; 2226 for (i = 0; visible_columns[i] != NULL; ++i) { 2227 list = g_list_prepend (list, visible_columns[i]); 2228 } 2229 list = g_list_reverse (list); 2230 nautilus_file_set_metadata_list (file, 2231 NAUTILUS_METADATA_KEY_LIST_VIEW_VISIBLE_COLUMNS, 2232 list); 2233 g_list_free (list); 2234 2235 list = NULL; 2236 for (i = 0; column_order[i] != NULL; ++i) { 2237 list = g_list_prepend (list, column_order[i]); 2238 } 2239 list = g_list_reverse (list); 2240 nautilus_file_set_metadata_list (file, 2241 NAUTILUS_METADATA_KEY_LIST_VIEW_COLUMN_ORDER, 2242 list); 2243 g_list_free (list); 2244 2245 apply_columns_settings (view, column_order, visible_columns); 2246 2247 g_strfreev (visible_columns); 2248 g_strfreev (column_order); 2249 } 2250 2251 static void 2252 column_chooser_set_from_arrays (NautilusColumnChooser *chooser, 2253 NautilusListView *view, 2254 char **visible_columns, 2255 char **column_order) 2256 { 2257 g_signal_handlers_block_by_func 2258 (chooser, G_CALLBACK (column_chooser_changed_callback), view); 2259 2260 nautilus_column_chooser_set_settings (chooser, 2261 visible_columns, 2262 column_order); 2263 2264 g_signal_handlers_unblock_by_func 2265 (chooser, G_CALLBACK (column_chooser_changed_callback), view); 2266 } 2267 2268 static void 2269 column_chooser_set_from_settings (NautilusColumnChooser *chooser, 2270 NautilusListView *view) 2271 { 2272 char **visible_columns; 2273 char **column_order; 2274 2275 visible_columns = get_visible_columns (view); 2276 column_order = get_column_order (view); 2277 2278 column_chooser_set_from_arrays (chooser, view, 2279 visible_columns, column_order); 2280 2281 g_strfreev (visible_columns); 2282 g_strfreev (column_order); 2283 } 2284 2285 static void 2286 column_chooser_use_default_callback (NautilusColumnChooser *chooser, 2287 NautilusListView *view) 2288 { 2289 NautilusFile *file; 2290 char **default_columns; 2291 char **default_order; 2292 2293 file = nautilus_view_get_directory_as_file 2294 (NAUTILUS_VIEW (view)); 2295 2296 nautilus_file_set_metadata_list (file, NAUTILUS_METADATA_KEY_LIST_VIEW_COLUMN_ORDER, NULL); 2297 nautilus_file_set_metadata_list (file, NAUTILUS_METADATA_KEY_LIST_VIEW_VISIBLE_COLUMNS, NULL); 2298 2299 /* set view values ourselves, as new metadata could not have been 2300 * updated yet. 2301 */ 2302 default_columns = nautilus_file_is_in_trash (file) ? 2303 g_strdupv ((gchar **) default_trash_visible_columns) : 2304 g_settings_get_strv (nautilus_list_view_preferences, 2305 NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_VISIBLE_COLUMNS); 2306 2307 default_order = nautilus_file_is_in_trash (file) ? 2308 g_strdupv ((gchar **) default_trash_columns_order) : 2309 g_settings_get_strv (nautilus_list_view_preferences, 2310 NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_COLUMN_ORDER); 2311 2312 apply_columns_settings (view, default_order, default_columns); 2313 column_chooser_set_from_arrays (chooser, view, 2314 default_columns, default_order); 2315 2316 g_strfreev (default_columns); 2317 g_strfreev (default_order); 2318 } 2319 2320 static GtkWidget * 2321 create_column_editor (NautilusListView *view) 2322 { 2323 GtkWidget *window; 2324 GtkWidget *label; 2325 GtkWidget *box; 2326 GtkWidget *column_chooser; 2327 GtkWidget *alignment; 2328 NautilusFile *file; 2329 char *str; 2330 char *name; 2331 const char *label_text; 2332 2333 file = nautilus_view_get_directory_as_file (NAUTILUS_VIEW (view)); 2334 name = nautilus_file_get_display_name (file); 2335 str = g_strdup_printf (_("%s Visible Columns"), name); 2336 g_free (name); 2337 2338 window = gtk_dialog_new_with_buttons (str, 2339 GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (view))), 2340 GTK_DIALOG_DESTROY_WITH_PARENT, 2341 GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, 2342 NULL); 2343 g_free (str); 2344 g_signal_connect (window, "response", 2345 G_CALLBACK (column_editor_response_callback), NULL); 2346 2347 gtk_window_set_default_size (GTK_WINDOW (window), 300, 400); 2348 2349 box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); 2350 gtk_container_set_border_width (GTK_CONTAINER (box), 12); 2351 gtk_widget_show (box); 2352 gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (window))), box, 2353 TRUE, TRUE, 0); 2354 2355 label_text = _("Choose the order of information to appear in this folder:"); 2356 str = g_strconcat ("<b>", label_text, "</b>", NULL); 2357 label = gtk_label_new (NULL); 2358 gtk_label_set_markup (GTK_LABEL (label), str); 2359 gtk_label_set_line_wrap (GTK_LABEL (label), FALSE); 2360 gtk_misc_set_alignment (GTK_MISC (label), 0, 0); 2361 gtk_widget_show (label); 2362 gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0); 2363 2364 g_free (str); 2365 2366 alignment = gtk_alignment_new (0.5, 0.5, 1, 1); 2367 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 2368 0, 0, 12, 0); 2369 gtk_widget_show (alignment); 2370 gtk_box_pack_start (GTK_BOX (box), alignment, TRUE, TRUE, 0); 2371 2372 column_chooser = nautilus_column_chooser_new (file); 2373 gtk_widget_show (column_chooser); 2374 gtk_container_add (GTK_CONTAINER (alignment), column_chooser); 2375 2376 g_signal_connect (column_chooser, "changed", 2377 G_CALLBACK (column_chooser_changed_callback), 2378 view); 2379 g_signal_connect (column_chooser, "use_default", 2380 G_CALLBACK (column_chooser_use_default_callback), 2381 view); 2382 2383 column_chooser_set_from_settings 2384 (NAUTILUS_COLUMN_CHOOSER (column_chooser), view); 2385 2386 return window; 2387 } 2388 2389 static void 2390 action_visible_columns_callback (GtkAction *action, 2391 gpointer callback_data) 2392 { 2393 NautilusListView *list_view; 2394 2395 list_view = NAUTILUS_LIST_VIEW (callback_data); 2396 2397 if (list_view->details->column_editor) { 2398 gtk_window_present (GTK_WINDOW (list_view->details->column_editor)); 2399 } else { 2400 list_view->details->column_editor = create_column_editor (list_view); 2401 g_object_add_weak_pointer (G_OBJECT (list_view->details->column_editor), 2402 (gpointer *) &list_view->details->column_editor); 2403 2404 gtk_widget_show (list_view->details->column_editor); 2405 } 2406 } 2407 2408 static const GtkActionEntry list_view_entries[] = { 2409 /* name, stock id */ { "Visible Columns", NULL, 2410 /* label, accelerator */ N_("Visible _Columns..."), NULL, 2411 /* tooltip */ N_("Select the columns visible in this folder"), 2412 G_CALLBACK (action_visible_columns_callback) }, 2413 }; 2414 2415 static void 2416 nautilus_list_view_merge_menus (NautilusView *view) 2417 { 2418 NautilusListView *list_view; 2419 GtkUIManager *ui_manager; 2420 GtkActionGroup *action_group; 2421 2422 list_view = NAUTILUS_LIST_VIEW (view); 2423 2424 NAUTILUS_VIEW_CLASS (nautilus_list_view_parent_class)->merge_menus (view); 2425 2426 ui_manager = nautilus_view_get_ui_manager (view); 2427 2428 action_group = gtk_action_group_new ("ListViewActions"); 2429 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE); 2430 list_view->details->list_action_group = action_group; 2431 gtk_action_group_add_actions (action_group, 2432 list_view_entries, G_N_ELEMENTS (list_view_entries), 2433 list_view); 2434 2435 gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); 2436 g_object_unref (action_group); /* owned by ui manager */ 2437 2438 list_view->details->list_merge_id = 2439 gtk_ui_manager_add_ui_from_resource (ui_manager, "/org/gnome/nautilus/nautilus-list-view-ui.xml", NULL); 2440 2441 list_view->details->menus_ready = TRUE; 2442 } 2443 2444 static void 2445 nautilus_list_view_unmerge_menus (NautilusView *view) 2446 { 2447 NautilusListView *list_view; 2448 GtkUIManager *ui_manager; 2449 2450 list_view = NAUTILUS_LIST_VIEW (view); 2451 2452 NAUTILUS_VIEW_CLASS (nautilus_list_view_parent_class)->unmerge_menus (view); 2453 2454 ui_manager = nautilus_view_get_ui_manager (view); 2455 if (ui_manager != NULL) { 2456 nautilus_ui_unmerge_ui (ui_manager, 2457 &list_view->details->list_merge_id, 2458 &list_view->details->list_action_group); 2459 } 2460 } 2461 2462 static void 2463 nautilus_list_view_update_menus (NautilusView *view) 2464 { 2465 NautilusListView *list_view; 2466 2467 list_view = NAUTILUS_LIST_VIEW (view); 2468 2469 /* don't update if the menus aren't ready */ 2470 if (!list_view->details->menus_ready) { 2471 return; 2472 } 2473 2474 NAUTILUS_VIEW_CLASS (nautilus_list_view_parent_class)->update_menus (view); 2475 } 2476 2477 /* Reset sort criteria and zoom level to match defaults */ 2478 static void 2479 nautilus_list_view_reset_to_defaults (NautilusView *view) 2480 { 2481 NautilusFile *file; 2482 const gchar *default_sort_order; 2483 gboolean default_sort_reversed; 2484 2485 file = nautilus_view_get_directory_as_file (view); 2486 2487 nautilus_file_set_metadata (file, NAUTILUS_METADATA_KEY_LIST_VIEW_SORT_COLUMN, NULL, NULL); 2488 nautilus_file_set_metadata (file, NAUTILUS_METADATA_KEY_LIST_VIEW_SORT_REVERSED, NULL, NULL); 2489 nautilus_file_set_metadata_list (file, NAUTILUS_METADATA_KEY_LIST_VIEW_COLUMN_ORDER, NULL); 2490 nautilus_file_set_metadata_list (file, NAUTILUS_METADATA_KEY_LIST_VIEW_VISIBLE_COLUMNS, NULL); 2491 2492 default_sort_order = get_default_sort_order (file, &default_sort_reversed); 2493 2494 gtk_tree_sortable_set_sort_column_id 2495 (GTK_TREE_SORTABLE (NAUTILUS_LIST_VIEW (view)->details->model), 2496 nautilus_list_model_get_sort_column_id_from_attribute (NAUTILUS_LIST_VIEW (view)->details->model, 2497 g_quark_from_string (default_sort_order)), 2498 default_sort_reversed ? GTK_SORT_DESCENDING : GTK_SORT_ASCENDING); 2499 2500 nautilus_list_view_set_zoom_level (NAUTILUS_LIST_VIEW (view), get_default_zoom_level (), FALSE); 2501 set_columns_settings_from_metadata_and_preferences (NAUTILUS_LIST_VIEW (view)); 2502 } 2503 2504 static void 2505 nautilus_list_view_set_zoom_level (NautilusListView *view, 2506 NautilusZoomLevel new_level, 2507 gboolean always_emit) 2508 { 2509 int column; 2510 2511 g_return_if_fail (NAUTILUS_IS_LIST_VIEW (view)); 2512 g_return_if_fail (new_level >= NAUTILUS_ZOOM_LEVEL_SMALLEST && 2513 new_level <= NAUTILUS_ZOOM_LEVEL_LARGEST); 2514 2515 if (view->details->zoom_level == new_level) { 2516 if (always_emit) { 2517 g_signal_emit_by_name (NAUTILUS_VIEW(view), "zoom_level_changed"); 2518 } 2519 return; 2520 } 2521 2522 view->details->zoom_level = new_level; 2523 g_signal_emit_by_name (NAUTILUS_VIEW(view), "zoom_level_changed"); 2524 2525 /* Select correctly scaled icons. */ 2526 column = nautilus_list_model_get_column_id_from_zoom_level (new_level); 2527 gtk_tree_view_column_set_attributes (view->details->file_name_column, 2528 GTK_CELL_RENDERER (view->details->pixbuf_cell), 2529 "pixbuf", column, 2530 NULL); 2531 2532 nautilus_view_update_menus (NAUTILUS_VIEW (view)); 2533 2534 set_up_pixbuf_size (view); 2535 } 2536 2537 static void 2538 nautilus_list_view_bump_zoom_level (NautilusView *view, int zoom_increment) 2539 { 2540 NautilusListView *list_view; 2541 gint new_level; 2542 2543 g_return_if_fail (NAUTILUS_IS_LIST_VIEW (view)); 2544 2545 list_view = NAUTILUS_LIST_VIEW (view); 2546 new_level = list_view->details->zoom_level + zoom_increment; 2547 2548 if (new_level >= NAUTILUS_ZOOM_LEVEL_SMALLEST && 2549 new_level <= NAUTILUS_ZOOM_LEVEL_LARGEST) { 2550 nautilus_list_view_set_zoom_level (list_view, new_level, FALSE); 2551 } 2552 } 2553 2554 static NautilusZoomLevel 2555 nautilus_list_view_get_zoom_level (NautilusView *view) 2556 { 2557 NautilusListView *list_view; 2558 2559 g_return_val_if_fail (NAUTILUS_IS_LIST_VIEW (view), NAUTILUS_ZOOM_LEVEL_STANDARD); 2560 2561 list_view = NAUTILUS_LIST_VIEW (view); 2562 2563 return list_view->details->zoom_level; 2564 } 2565 2566 static void 2567 nautilus_list_view_zoom_to_level (NautilusView *view, 2568 NautilusZoomLevel zoom_level) 2569 { 2570 NautilusListView *list_view; 2571 2572 g_return_if_fail (NAUTILUS_IS_LIST_VIEW (view)); 2573 2574 list_view = NAUTILUS_LIST_VIEW (view); 2575 2576 nautilus_list_view_set_zoom_level (list_view, zoom_level, FALSE); 2577 } 2578 2579 static void 2580 nautilus_list_view_restore_default_zoom_level (NautilusView *view) 2581 { 2582 NautilusListView *list_view; 2583 2584 g_return_if_fail (NAUTILUS_IS_LIST_VIEW (view)); 2585 2586 list_view = NAUTILUS_LIST_VIEW (view); 2587 2588 nautilus_list_view_set_zoom_level (list_view, get_default_zoom_level (), FALSE); 2589 } 2590 2591 static gboolean 2592 nautilus_list_view_can_zoom_in (NautilusView *view) 2593 { 2594 g_return_val_if_fail (NAUTILUS_IS_LIST_VIEW (view), FALSE); 2595 2596 return NAUTILUS_LIST_VIEW (view)->details->zoom_level < NAUTILUS_ZOOM_LEVEL_LARGEST; 2597 } 2598 2599 static gboolean 2600 nautilus_list_view_can_zoom_out (NautilusView *view) 2601 { 2602 g_return_val_if_fail (NAUTILUS_IS_LIST_VIEW (view), FALSE); 2603 2604 return NAUTILUS_LIST_VIEW (view)->details->zoom_level > NAUTILUS_ZOOM_LEVEL_SMALLEST; 2605 } 2606 2607 static void 2608 nautilus_list_view_start_renaming_file (NautilusView *view, 2609 NautilusFile *file, 2610 gboolean select_all) 2611 { 2612 NautilusListView *list_view; 2613 GtkTreeIter iter; 2614 GtkTreePath *path; 2615 2616 list_view = NAUTILUS_LIST_VIEW (view); 2617 2618 /* Select all if we are in renaming mode already */ 2619 if (list_view->details->file_name_column && list_view->details->editable_widget) { 2620 gtk_editable_select_region (GTK_EDITABLE (list_view->details->editable_widget), 2621 0, 2622 -1); 2623 return; 2624 } 2625 2626 if (!nautilus_list_model_get_first_iter_for_file (list_view->details->model, file, &iter)) { 2627 return; 2628 } 2629 2630 /* call parent class to make sure the right icon is selected */ 2631 NAUTILUS_VIEW_CLASS (nautilus_list_view_parent_class)->start_renaming_file (view, file, select_all); 2632 2633 /* Freeze updates to the view to prevent losing rename focus when the tree view updates */ 2634 nautilus_view_freeze_updates (NAUTILUS_VIEW (view)); 2635 2636 path = gtk_tree_model_get_path (GTK_TREE_MODEL (list_view->details->model), &iter); 2637 2638 /* Make filename-cells editable. */ 2639 g_object_set (G_OBJECT (list_view->details->file_name_cell), 2640 "editable", TRUE, 2641 NULL); 2642 2643 gtk_tree_view_scroll_to_cell (list_view->details->tree_view, 2644 NULL, 2645 list_view->details->file_name_column, 2646 TRUE, 0.0, 0.0); 2647 gtk_tree_view_set_cursor_on_cell (list_view->details->tree_view, 2648 path, 2649 list_view->details->file_name_column, 2650 GTK_CELL_RENDERER (list_view->details->file_name_cell), 2651 TRUE); 2652 2653 /* set cursor also triggers editing-started, where we save the editable widget */ 2654 if (list_view->details->editable_widget != NULL) { 2655 int start_offset = 0; 2656 int end_offset = -1; 2657 2658 if (!select_all) { 2659 eel_filename_get_rename_region (list_view->details->original_name, 2660 &start_offset, &end_offset); 2661 } 2662 2663 gtk_editable_select_region (GTK_EDITABLE (list_view->details->editable_widget), 2664 start_offset, end_offset); 2665 } 2666 2667 gtk_tree_path_free (path); 2668 } 2669 2670 static void 2671 nautilus_list_view_click_policy_changed (NautilusView *directory_view) 2672 { 2673 GdkWindow *win; 2674 GdkDisplay *display; 2675 NautilusListView *view; 2676 GtkTreeIter iter; 2677 GtkTreeView *tree; 2678 2679 view = NAUTILUS_LIST_VIEW (directory_view); 2680 2681 /* ensure that we unset the hand cursor and refresh underlined rows */ 2682 if (get_click_policy () == NAUTILUS_CLICK_POLICY_DOUBLE) { 2683 if (view->details->hover_path != NULL) { 2684 if (gtk_tree_model_get_iter (GTK_TREE_MODEL (view->details->model), 2685 &iter, view->details->hover_path)) { 2686 gtk_tree_model_row_changed (GTK_TREE_MODEL (view->details->model), 2687 view->details->hover_path, &iter); 2688 } 2689 2690 gtk_tree_path_free (view->details->hover_path); 2691 view->details->hover_path = NULL; 2692 } 2693 2694 tree = view->details->tree_view; 2695 if (gtk_widget_get_realized (GTK_WIDGET (tree))) { 2696 win = gtk_widget_get_window (GTK_WIDGET (tree)); 2697 gdk_window_set_cursor (win, NULL); 2698 2699 display = gtk_widget_get_display (GTK_WIDGET (view)); 2700 if (display != NULL) { 2701 gdk_display_flush (display); 2702 } 2703 } 2704 2705 g_clear_object (&hand_cursor); 2706 } else if (get_click_policy () == NAUTILUS_CLICK_POLICY_SINGLE) { 2707 if (hand_cursor == NULL) { 2708 hand_cursor = gdk_cursor_new(GDK_HAND2); 2709 } 2710 } 2711 } 2712 2713 static void 2714 default_sort_order_changed_callback (gpointer callback_data) 2715 { 2716 NautilusListView *list_view; 2717 2718 list_view = NAUTILUS_LIST_VIEW (callback_data); 2719 2720 set_sort_order_from_metadata_and_preferences (list_view); 2721 } 2722 2723 static void 2724 default_visible_columns_changed_callback (gpointer callback_data) 2725 { 2726 NautilusListView *list_view; 2727 2728 list_view = NAUTILUS_LIST_VIEW (callback_data); 2729 2730 set_columns_settings_from_metadata_and_preferences (list_view); 2731 } 2732 2733 static void 2734 default_column_order_changed_callback (gpointer callback_data) 2735 { 2736 NautilusListView *list_view; 2737 2738 list_view = NAUTILUS_LIST_VIEW (callback_data); 2739 2740 set_columns_settings_from_metadata_and_preferences (list_view); 2741 } 2742 2743 static void 2744 nautilus_list_view_sort_directories_first_changed (NautilusView *view) 2745 { 2746 NautilusListView *list_view; 2747 2748 list_view = NAUTILUS_LIST_VIEW (view); 2749 2750 nautilus_list_model_set_should_sort_directories_first (list_view->details->model, 2751 nautilus_view_should_sort_directories_first (view)); 2752 } 2753 2754 static int 2755 nautilus_list_view_compare_files (NautilusView *view, NautilusFile *file1, NautilusFile *file2) 2756 { 2757 NautilusListView *list_view; 2758 2759 list_view = NAUTILUS_LIST_VIEW (view); 2760 return nautilus_list_model_compare_func (list_view->details->model, file1, file2); 2761 } 2762 2763 static gboolean 2764 nautilus_list_view_using_manual_layout (NautilusView *view) 2765 { 2766 g_return_val_if_fail (NAUTILUS_IS_LIST_VIEW (view), FALSE); 2767 2768 return FALSE; 2769 } 2770 2771 static void 2772 nautilus_list_view_dispose (GObject *object) 2773 { 2774 NautilusListView *list_view; 2775 2776 list_view = NAUTILUS_LIST_VIEW (object); 2777 2778 if (list_view->details->model) { 2779 stop_cell_editing (list_view); 2780 g_object_unref (list_view->details->model); 2781 list_view->details->model = NULL; 2782 } 2783 2784 if (list_view->details->drag_dest) { 2785 g_object_unref (list_view->details->drag_dest); 2786 list_view->details->drag_dest = NULL; 2787 } 2788 2789 if (list_view->details->renaming_file_activate_timeout != 0) { 2790 g_source_remove (list_view->details->renaming_file_activate_timeout); 2791 list_view->details->renaming_file_activate_timeout = 0; 2792 } 2793 2794 if (list_view->details->clipboard_handler_id != 0) { 2795 g_signal_handler_disconnect (nautilus_clipboard_monitor_get (), 2796 list_view->details->clipboard_handler_id); 2797 list_view->details->clipboard_handler_id = 0; 2798 } 2799 2800 G_OBJECT_CLASS (nautilus_list_view_parent_class)->dispose (object); 2801 } 2802 2803 static void 2804 nautilus_list_view_finalize (GObject *object) 2805 { 2806 NautilusListView *list_view; 2807 2808 list_view = NAUTILUS_LIST_VIEW (object); 2809 2810 g_free (list_view->details->original_name); 2811 list_view->details->original_name = NULL; 2812 2813 if (list_view->details->double_click_path[0]) { 2814 gtk_tree_path_free (list_view->details->double_click_path[0]); 2815 } 2816 if (list_view->details->double_click_path[1]) { 2817 gtk_tree_path_free (list_view->details->double_click_path[1]); 2818 } 2819 if (list_view->details->new_selection_path) { 2820 gtk_tree_path_free (list_view->details->new_selection_path); 2821 } 2822 2823 g_list_free (list_view->details->cells); 2824 g_hash_table_destroy (list_view->details->columns); 2825 2826 if (list_view->details->hover_path != NULL) { 2827 gtk_tree_path_free (list_view->details->hover_path); 2828 } 2829 2830 if (list_view->details->column_editor != NULL) { 2831 gtk_widget_destroy (list_view->details->column_editor); 2832 } 2833 2834 g_free (list_view->details); 2835 2836 g_signal_handlers_disconnect_by_func (nautilus_preferences, 2837 default_sort_order_changed_callback, 2838 list_view); 2839 g_signal_handlers_disconnect_by_func (nautilus_list_view_preferences, 2840 default_visible_columns_changed_callback, 2841 list_view); 2842 g_signal_handlers_disconnect_by_func (nautilus_list_view_preferences, 2843 default_column_order_changed_callback, 2844 list_view); 2845 2846 G_OBJECT_CLASS (nautilus_list_view_parent_class)->finalize (object); 2847 } 2848 2849 static char * 2850 nautilus_list_view_get_first_visible_file (NautilusView *view) 2851 { 2852 NautilusFile *file; 2853 GtkTreePath *path; 2854 GtkTreeIter iter; 2855 NautilusListView *list_view; 2856 2857 list_view = NAUTILUS_LIST_VIEW (view); 2858 2859 if (gtk_tree_view_get_path_at_pos (list_view->details->tree_view, 2860 0, 0, 2861 &path, NULL, NULL, NULL)) { 2862 gtk_tree_model_get_iter (GTK_TREE_MODEL (list_view->details->model), 2863 &iter, path); 2864 2865 gtk_tree_path_free (path); 2866 2867 gtk_tree_model_get (GTK_TREE_MODEL (list_view->details->model), 2868 &iter, 2869 NAUTILUS_LIST_MODEL_FILE_COLUMN, &file, 2870 -1); 2871 if (file) { 2872 char *uri; 2873 2874 uri = nautilus_file_get_uri (file); 2875 2876 nautilus_file_unref (file); 2877 2878 return uri; 2879 } 2880 } 2881 2882 return NULL; 2883 } 2884 2885 static void 2886 nautilus_list_view_scroll_to_file (NautilusListView *view, 2887 NautilusFile *file) 2888 { 2889 GtkTreePath *path; 2890 GtkTreeIter iter; 2891 2892 if (!nautilus_list_model_get_first_iter_for_file (view->details->model, file, &iter)) { 2893 return; 2894 } 2895 2896 path = gtk_tree_model_get_path (GTK_TREE_MODEL (view->details->model), &iter); 2897 2898 gtk_tree_view_scroll_to_cell (view->details->tree_view, 2899 path, NULL, 2900 TRUE, 0.0, 0.0); 2901 2902 gtk_tree_path_free (path); 2903 } 2904 2905 static void 2906 list_view_scroll_to_file (NautilusView *view, 2907 const char *uri) 2908 { 2909 NautilusFile *file; 2910 2911 if (uri != NULL) { 2912 /* Only if existing, since we don't want to add the file to 2913 the directory if it has been removed since then */ 2914 file = nautilus_file_get_existing_by_uri (uri); 2915 if (file != NULL) { 2916 nautilus_list_view_scroll_to_file (NAUTILUS_LIST_VIEW (view), file); 2917 nautilus_file_unref (file); 2918 } 2919 } 2920 } 2921 2922 static void 2923 list_view_notify_clipboard_info (NautilusClipboardMonitor *monitor, 2924 NautilusClipboardInfo *info, 2925 NautilusListView *view) 2926 { 2927 /* this could be called as a result of _end_loading() being 2928 * called after _dispose(), where the model is cleared. 2929 */ 2930 if (view->details->model == NULL) { 2931 return; 2932 } 2933 2934 if (info != NULL && info->cut) { 2935 nautilus_list_model_set_highlight_for_files (view->details->model, info->files); 2936 } else { 2937 nautilus_list_model_set_highlight_for_files (view->details->model, NULL); 2938 } 2939 } 2940 2941 static void 2942 nautilus_list_view_end_loading (NautilusView *view, 2943 gboolean all_files_seen) 2944 { 2945 NautilusClipboardMonitor *monitor; 2946 NautilusClipboardInfo *info; 2947 2948 monitor = nautilus_clipboard_monitor_get (); 2949 info = nautilus_clipboard_monitor_get_clipboard_info (monitor); 2950 2951 list_view_notify_clipboard_info (monitor, info, NAUTILUS_LIST_VIEW (view)); 2952 } 2953 2954 static const char * 2955 nautilus_list_view_get_id (NautilusView *view) 2956 { 2957 return NAUTILUS_LIST_VIEW_ID; 2958 } 2959 2960 static void 2961 nautilus_list_view_class_init (NautilusListViewClass *class) 2962 { 2963 NautilusViewClass *nautilus_view_class; 2964 2965 nautilus_view_class = NAUTILUS_VIEW_CLASS (class); 2966 2967 G_OBJECT_CLASS (class)->dispose = nautilus_list_view_dispose; 2968 G_OBJECT_CLASS (class)->finalize = nautilus_list_view_finalize; 2969 2970 nautilus_view_class->add_file = nautilus_list_view_add_file; 2971 nautilus_view_class->begin_loading = nautilus_list_view_begin_loading; 2972 nautilus_view_class->end_loading = nautilus_list_view_end_loading; 2973 nautilus_view_class->bump_zoom_level = nautilus_list_view_bump_zoom_level; 2974 nautilus_view_class->can_zoom_in = nautilus_list_view_can_zoom_in; 2975 nautilus_view_class->can_zoom_out = nautilus_list_view_can_zoom_out; 2976 nautilus_view_class->click_policy_changed = nautilus_list_view_click_policy_changed; 2977 nautilus_view_class->clear = nautilus_list_view_clear; 2978 nautilus_view_class->file_changed = nautilus_list_view_file_changed; 2979 nautilus_view_class->get_backing_uri = nautilus_list_view_get_backing_uri; 2980 nautilus_view_class->get_selection = nautilus_list_view_get_selection; 2981 nautilus_view_class->get_selection_for_file_transfer = nautilus_list_view_get_selection_for_file_transfer; 2982 nautilus_view_class->is_empty = nautilus_list_view_is_empty; 2983 nautilus_view_class->remove_file = nautilus_list_view_remove_file; 2984 nautilus_view_class->merge_menus = nautilus_list_view_merge_menus; 2985 nautilus_view_class->unmerge_menus = nautilus_list_view_unmerge_menus; 2986 nautilus_view_class->update_menus = nautilus_list_view_update_menus; 2987 nautilus_view_class->reset_to_defaults = nautilus_list_view_reset_to_defaults; 2988 nautilus_view_class->restore_default_zoom_level = nautilus_list_view_restore_default_zoom_level; 2989 nautilus_view_class->reveal_selection = nautilus_list_view_reveal_selection; 2990 nautilus_view_class->select_all = nautilus_list_view_select_all; 2991 nautilus_view_class->select_first = nautilus_list_view_select_first; 2992 nautilus_view_class->set_selection = nautilus_list_view_set_selection; 2993 nautilus_view_class->invert_selection = nautilus_list_view_invert_selection; 2994 nautilus_view_class->compare_files = nautilus_list_view_compare_files; 2995 nautilus_view_class->sort_directories_first_changed = nautilus_list_view_sort_directories_first_changed; 2996 nautilus_view_class->start_renaming_file = nautilus_list_view_start_renaming_file; 2997 nautilus_view_class->get_zoom_level = nautilus_list_view_get_zoom_level; 2998 nautilus_view_class->zoom_to_level = nautilus_list_view_zoom_to_level; 2999 nautilus_view_class->end_file_changes = nautilus_list_view_end_file_changes; 3000 nautilus_view_class->using_manual_layout = nautilus_list_view_using_manual_layout; 3001 nautilus_view_class->get_view_id = nautilus_list_view_get_id; 3002 nautilus_view_class->get_first_visible_file = nautilus_list_view_get_first_visible_file; 3003 nautilus_view_class->scroll_to_file = list_view_scroll_to_file; 3004 } 3005 3006 static void 3007 nautilus_list_view_init (NautilusListView *list_view) 3008 { 3009 list_view->details = g_new0 (NautilusListViewDetails, 1); 3010 3011 /* ensure that the zoom level is always set before settings up the tree view columns */ 3012 list_view->details->zoom_level = get_default_zoom_level (); 3013 3014 create_and_set_up_tree_view (list_view); 3015 3016 g_signal_connect_swapped (nautilus_preferences, 3017 "changed::" NAUTILUS_PREFERENCES_DEFAULT_SORT_ORDER, 3018 G_CALLBACK (default_sort_order_changed_callback), 3019 list_view); 3020 g_signal_connect_swapped (nautilus_preferences, 3021 "changed::" NAUTILUS_PREFERENCES_DEFAULT_SORT_IN_REVERSE_ORDER, 3022 G_CALLBACK (default_sort_order_changed_callback), 3023 list_view); 3024 g_signal_connect_swapped (nautilus_list_view_preferences, 3025 "changed::" NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_VISIBLE_COLUMNS, 3026 G_CALLBACK (default_visible_columns_changed_callback), 3027 list_view); 3028 g_signal_connect_swapped (nautilus_list_view_preferences, 3029 "changed::" NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_COLUMN_ORDER, 3030 G_CALLBACK (default_column_order_changed_callback), 3031 list_view); 3032 3033 nautilus_list_view_click_policy_changed (NAUTILUS_VIEW (list_view)); 3034 3035 nautilus_list_view_sort_directories_first_changed (NAUTILUS_VIEW (list_view)); 3036 nautilus_list_view_set_zoom_level (list_view, get_default_zoom_level (), TRUE); 3037 3038 list_view->details->hover_path = NULL; 3039 list_view->details->clipboard_handler_id = 3040 g_signal_connect (nautilus_clipboard_monitor_get (), 3041 "clipboard_info", 3042 G_CALLBACK (list_view_notify_clipboard_info), list_view); 3043 } 3044 3045 static NautilusView * 3046 nautilus_list_view_create (NautilusWindowSlot *slot) 3047 { 3048 NautilusListView *view; 3049 3050 view = g_object_new (NAUTILUS_TYPE_LIST_VIEW, 3051 "window-slot", slot, 3052 NULL); 3053 return NAUTILUS_VIEW (view); 3054 } 3055 3056 static gboolean 3057 nautilus_list_view_supports_uri (const char *uri, 3058 GFileType file_type, 3059 const char *mime_type) 3060 { 3061 if (file_type == G_FILE_TYPE_DIRECTORY) { 3062 return TRUE; 3063 } 3064 if (strcmp (mime_type, NAUTILUS_SAVED_SEARCH_MIMETYPE) == 0){ 3065 return TRUE; 3066 } 3067 if (g_str_has_prefix (uri, "trash:")) { 3068 return TRUE; 3069 } 3070 if (g_str_has_prefix (uri, EEL_SEARCH_URI)) { 3071 return TRUE; 3072 } 3073 3074 return FALSE; 3075 } 3076 3077 static NautilusViewInfo nautilus_list_view = { 3078 NAUTILUS_LIST_VIEW_ID, 3079 /* translators: this is used in the view selection dropdown 3080 * of navigation windows and in the preferences dialog */ 3081 N_("List View"), 3082 /* translators: this is used in the view menu */ 3083 N_("_List"), 3084 N_("The list view encountered an error."), 3085 N_("The list view encountered an error while starting up."), 3086 N_("Display this location with the list view."), 3087 nautilus_list_view_create, 3088 nautilus_list_view_supports_uri 3089 }; 3090 3091 void 3092 nautilus_list_view_register (void) 3093 { 3094 nautilus_list_view.view_combo_label = _(nautilus_list_view.view_combo_label); 3095 nautilus_list_view.view_menu_label_with_mnemonic = _(nautilus_list_view.view_menu_label_with_mnemonic); 3096 nautilus_list_view.error_label = _(nautilus_list_view.error_label); 3097 nautilus_list_view.startup_error_label = _(nautilus_list_view.startup_error_label); 3098 nautilus_list_view.display_location_label = _(nautilus_list_view.display_location_label); 3099 3100 nautilus_view_factory_register (&nautilus_list_view); 3101 } 3102 3103 GtkTreeView* 3104 nautilus_list_view_get_tree_view (NautilusListView *list_view) 3105 { 3106 return list_view->details->tree_view; 3107 }