1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 * Copyright (C) Johannes Schmid 2007 <jhs@gnome.org>
6 * file-manager is free software.
8 * You may redistribute it and/or modify it under the terms of the
9 * GNU General Public License, as published by the Free Software
10 * Foundation; either version 2 of the License, or (at your option)
13 * file-manager 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.
16 * See the GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with file-manager. If not, write to:
20 * The Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor
22 * Boston, MA 02110-1301, USA.
25 #include "file-view.h"
26 #include "file-model.h"
27 #include "file-view-marshal.h"
29 #include <gtk/gtkcellrenderertext.h>
30 #include <gtk/gtkcellrendererpixbuf.h>
31 #include <gtk/gtkcellrendererprogress.h>
32 #include <gtk/gtktreestore.h>
33 #include <gtk/gtktreeselection.h>
34 #include <gtk/gtktreemodelsort.h>
35 #include <gtk/gtkversion.h>
41 #define HAVE_TOOLTIP_API (GTK_MAJOR_VERSION > 2 || (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 12))
42 #include <glib/gi18n.h>
44 #include <gtk/gtktooltip.h>
46 #include <libanjuta/anjuta-debug.h>
48 typedef struct _AnjutaFileViewPrivate AnjutaFileViewPrivate
;
50 struct _AnjutaFileViewPrivate
55 GtkTreeRowReference
* current_selection
;
58 #define ANJUTA_FILE_VIEW_GET_PRIVATE(o) \
59 (G_TYPE_INSTANCE_GET_PRIVATE((o), ANJUTA_TYPE_FILE_VIEW, AnjutaFileViewPrivate))
61 G_DEFINE_TYPE (AnjutaFileView
, file_view
, GTK_TYPE_TREE_VIEW
);
70 file_view_refresh (AnjutaFileView
* view
)
72 AnjutaFileViewPrivate
* priv
= ANJUTA_FILE_VIEW_GET_PRIVATE (view
);
73 GtkTreePath
* tree_path
;
75 file_model_refresh (priv
->model
);
77 tree_path
= gtk_tree_path_new_first ();
78 gtk_tree_view_expand_row (GTK_TREE_VIEW (view
), tree_path
, FALSE
);
79 gtk_tree_path_free (tree_path
);
82 void file_view_rename (AnjutaFileView
* view
)
87 gboolean
file_view_can_rename (AnjutaFileView
* view
)
94 file_view_get_selected (AnjutaFileView
* view
)
96 AnjutaFileViewPrivate
* priv
= ANJUTA_FILE_VIEW_GET_PRIVATE (view
);
97 GtkTreeSelection
* selection
=
98 gtk_tree_view_get_selection (GTK_TREE_VIEW (view
));
100 if (gtk_tree_selection_get_selected (selection
, NULL
, &selected
))
102 GFile
* file
= file_model_get_file (priv
->model
, &selected
);
110 file_view_button_press_event (GtkWidget
* widget
, GdkEventButton
* event
)
112 AnjutaFileView
* view
= ANJUTA_FILE_VIEW (widget
);
113 AnjutaFileViewPrivate
* priv
= ANJUTA_FILE_VIEW_GET_PRIVATE (view
);
114 GtkTreeIter selected
;
116 GtkTreePath
* path
= NULL
;
119 GtkTreeSelection
* selection
=
120 gtk_tree_view_get_selection (GTK_TREE_VIEW (view
));
122 if (gtk_tree_selection_get_selected (selection
, NULL
, &selected
))
124 GtkTreeIter select_iter
;
125 GtkTreeModel
* sort_model
= gtk_tree_view_get_model(GTK_TREE_VIEW(view
));
126 gtk_tree_model_sort_convert_iter_to_child_iter(GTK_TREE_MODEL_SORT(sort_model
),
127 &select_iter
, &selected
);
128 gtk_tree_model_get (GTK_TREE_MODEL(priv
->model
), &select_iter
,
129 COLUMN_IS_DIR
, &is_dir
,
131 file
= file_model_get_file (priv
->model
, &select_iter
);
133 path
= gtk_tree_model_get_path(sort_model
, &selected
);
141 switch (event
->button
)
143 case 1: /* Left mouse button */
145 if (event
->type
== GDK_2BUTTON_PRESS
)
149 if (!gtk_tree_view_row_expanded (GTK_TREE_VIEW (view
),
152 gtk_tree_view_expand_row (GTK_TREE_VIEW (view
),
158 gtk_tree_view_collapse_row (GTK_TREE_VIEW (view
),
164 g_signal_emit_by_name (G_OBJECT (view
),
171 case 3: /* Right mouse button */
173 g_signal_emit_by_name (G_OBJECT (view
),
182 g_object_unref (file
);
184 gtk_tree_path_free(path
);
186 GTK_WIDGET_CLASS (file_view_parent_class
)->button_press_event (widget
,
191 file_view_show_extended_data (AnjutaFileView
* view
, GtkTreeIter
* iter
)
193 AnjutaFileViewPrivate
* priv
= ANJUTA_FILE_VIEW_GET_PRIVATE (view
);
194 GtkTreeModel
* file_model
= GTK_TREE_MODEL (priv
->model
);
196 GFileInfo
* file_info
;
199 gtk_tree_model_get (file_model
, iter
, COLUMN_IS_DIR
, &is_dir
, -1);
204 gtk_tree_model_get (file_model
, iter
, COLUMN_FILE
, &file
, -1);
207 file_info
= g_file_query_info (file
,
208 "standard::*,time::changed",
209 G_FILE_QUERY_INFO_NONE
,
211 time
= g_file_info_get_attribute_uint64(file_info
, "time::changed");
212 strftime(time_str
, 127, "%x %X", localtime(&time
));
213 display
= g_markup_printf_escaped("%s\n"
214 "<small><tt>%s</tt></small>",
215 g_file_info_get_display_name(file_info
),
218 gtk_tree_store_set (GTK_TREE_STORE(file_model
), iter
,
219 COLUMN_DISPLAY
, display
,
222 g_object_unref (file_info
);
228 file_view_selection_changed (GtkTreeSelection
* selection
, AnjutaFileView
* view
)
230 AnjutaFileViewPrivate
* priv
= ANJUTA_FILE_VIEW_GET_PRIVATE (view
);
231 GtkTreeModel
* file_model
= GTK_TREE_MODEL(priv
->model
);
232 GtkTreeIter selected
;
233 GtkTreeModel
* model
= gtk_tree_view_get_model (GTK_TREE_VIEW(view
));
235 if (priv
->current_selection
)
238 GtkTreePath
* path
= gtk_tree_row_reference_get_path (priv
->current_selection
);
239 if (path
&& gtk_tree_model_get_iter (file_model
, &iter
, path
))
242 gtk_tree_model_get (file_model
, &iter
, COLUMN_FILENAME
, &filename
, -1);
243 gtk_tree_store_set (GTK_TREE_STORE (file_model
), &iter
,
244 COLUMN_DISPLAY
, filename
, -1);
246 gtk_tree_path_free(path
);
248 gtk_tree_row_reference_free(priv
->current_selection
);
249 priv
->current_selection
= NULL
;
252 if (gtk_tree_selection_get_selected (selection
, &model
, &selected
))
254 GtkTreeIter real_selection
;
257 gtk_tree_model_sort_convert_iter_to_child_iter(GTK_TREE_MODEL_SORT(model
),
258 &real_selection
, &selected
);
260 path
= gtk_tree_model_get_path(file_model
, &real_selection
);
261 priv
->current_selection
= gtk_tree_row_reference_new (file_model
, path
);
262 gtk_tree_path_free(path
);
264 file_view_show_extended_data (view
, &real_selection
);
266 file
= file_model_get_file(FILE_MODEL(file_model
), &real_selection
);
267 g_signal_emit_by_name (G_OBJECT (view
), "current-file-changed",
269 g_object_unref (file
);
273 g_signal_emit_by_name (G_OBJECT (view
), "current-file-changed",
276 DEBUG_PRINT ("selection_changed");
280 file_view_query_tooltip (GtkWidget
* widget
, gint x
, gint y
, gboolean keyboard
,
283 AnjutaFileView
* view
= ANJUTA_FILE_VIEW (widget
);
284 AnjutaFileViewPrivate
* priv
= ANJUTA_FILE_VIEW_GET_PRIVATE (view
);
285 GtkTreeModel
* model_sort
;
286 GtkTreeModel
* file_model
= GTK_TREE_MODEL (priv
->model
);
289 GtkTreeIter real_iter
;
292 if (!gtk_tree_view_get_tooltip_context (GTK_TREE_VIEW (view
),
299 gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT (model_sort
),
302 filename
= file_model_get_filename (FILE_MODEL (file_model
), &real_iter
);
303 gtk_tooltip_set_text (tooltip
, filename
);
304 gtk_tree_view_set_tooltip_row (GTK_TREE_VIEW (view
),
309 gtk_tree_path_free (path
);
315 file_view_sort_model(GtkTreeModel
* model
,
321 gchar
*filename1
= NULL
, *filename2
= NULL
;
322 gboolean is_dir1
, is_dir2
;
325 gtk_tree_model_get (model
, iter1
,
326 COLUMN_FILENAME
, &filename1
,
328 COLUMN_IS_DIR
, &is_dir1
, -1);
329 gtk_tree_model_get (model
, iter2
,
330 COLUMN_FILENAME
, &filename2
,
332 COLUMN_IS_DIR
, &is_dir2
, -1);
336 retval
= sort2
- sort1
;
338 else if (is_dir1
!= is_dir2
)
340 retval
= is_dir1
? -1 : 1;
342 else if (filename1
&& filename2
)
344 retval
= strcmp(filename1
, filename2
);
353 file_view_init (AnjutaFileView
*object
)
355 GtkCellRenderer
* renderer_pixbuf
;
356 GtkCellRenderer
* renderer_display
;
357 GtkTreeViewColumn
* column
;
358 GtkTreeSelection
* selection
;
359 GtkTreeModel
* sort_model
;
361 AnjutaFileViewPrivate
* priv
= ANJUTA_FILE_VIEW_GET_PRIVATE (object
);
363 priv
->current_selection
= NULL
;
365 priv
->model
= file_model_new (GTK_TREE_VIEW(object
), NULL
);
366 sort_model
= gtk_tree_model_sort_new_with_model(GTK_TREE_MODEL(priv
->model
));
368 gtk_tree_view_set_model (GTK_TREE_VIEW(object
), sort_model
);
369 gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE(sort_model
),
370 file_view_sort_model
,
374 renderer_pixbuf
= gtk_cell_renderer_pixbuf_new ();
375 renderer_display
= gtk_cell_renderer_text_new ();
377 column
= gtk_tree_view_column_new ();
378 gtk_tree_view_column_set_title (column
, _("Filename"));
379 gtk_tree_view_column_pack_start (column
, renderer_pixbuf
, FALSE
);
380 gtk_tree_view_column_pack_start (column
, renderer_display
, FALSE
);
381 gtk_tree_view_column_set_attributes (column
, renderer_pixbuf
,
382 "pixbuf", COLUMN_PIXBUF
, NULL
);
383 gtk_tree_view_column_set_attributes (column
, renderer_display
,
384 "markup", COLUMN_DISPLAY
, NULL
);
385 gtk_tree_view_append_column (GTK_TREE_VIEW (object
), column
);
388 gtk_tree_view_get_selection (GTK_TREE_VIEW (object
));
389 g_signal_connect (selection
, "changed",
390 G_CALLBACK (file_view_selection_changed
), object
);
392 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (object
), FALSE
);
394 g_object_set (object
, "has-tooltip", TRUE
, NULL
);
398 file_view_get_property (GObject
*object
, guint prop_id
, GValue
*value
,
401 AnjutaFileViewPrivate
*priv
= ANJUTA_FILE_VIEW_GET_PRIVATE (object
);
407 g_object_get (G_OBJECT(priv
->model
), "base_uri", &uri
, NULL
);
408 g_value_set_string (value
, uri
);
411 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
417 file_view_set_property (GObject
*object
, guint prop_id
, const GValue
*value
,
420 AnjutaFileViewPrivate
*priv
= ANJUTA_FILE_VIEW_GET_PRIVATE (object
);
425 g_object_set (G_OBJECT (priv
->model
), "base_uri", g_value_get_string (value
),
429 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
435 file_view_finalize (GObject
*object
)
437 G_OBJECT_CLASS (file_view_parent_class
)->finalize (object
);
441 file_view_class_init (AnjutaFileViewClass
*klass
)
443 GObjectClass
* object_class
= G_OBJECT_CLASS (klass
);
444 GtkWidgetClass
* widget_class
= GTK_WIDGET_CLASS (klass
);
446 g_type_class_add_private (klass
, sizeof (AnjutaFileViewPrivate
));
448 object_class
->finalize
= file_view_finalize
;
449 object_class
->set_property
= file_view_set_property
;
450 object_class
->get_property
= file_view_get_property
;
452 g_object_class_install_property (object_class
,
454 g_param_spec_string ("base_uri",
456 _("Uri of the top-most path displayed"),
461 g_signal_new ("file-open",
462 ANJUTA_TYPE_FILE_VIEW
,
464 G_STRUCT_OFFSET (AnjutaFileViewClass
, file_open
),
466 g_cclosure_marshal_VOID__OBJECT
,
472 g_signal_new ("current-file-changed",
473 ANJUTA_TYPE_FILE_VIEW
,
475 G_STRUCT_OFFSET (AnjutaFileViewClass
, current_uri_changed
),
477 g_cclosure_marshal_VOID__OBJECT
,
483 g_signal_new ("show-popup-menu",
484 ANJUTA_TYPE_FILE_VIEW
,
486 G_STRUCT_OFFSET (AnjutaFileViewClass
, show_popup_menu
),
488 file_view_cclosure_marshal_VOID__OBJECT_BOOLEAN_INT_INT
,
497 widget_class
->button_press_event
= file_view_button_press_event
;
500 widget_class
->query_tooltip
= file_view_query_tooltip
;
506 return g_object_new (ANJUTA_TYPE_FILE_VIEW
, NULL
);