1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 * Copyright (C) Johannes Schmid 2007 <jhs@gnome.org>
6 * anjuta 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 * anjuta 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 anjuta. 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-model.h"
26 #include <gdl/gdl-icons.h>
27 #include <glib/gi18n.h>
29 #include <libanjuta/anjuta-debug.h>
30 #include <libgnomevfs/gnome-vfs.h>
32 #define DIRECTORY_MIME_TYPE "x-directory/normal"
33 #define DIRECTORY_OPEN "x-directory/open"
45 const gchar
* binary_mime
[] = {
47 "application/x-shared-library-la.xml",
48 "application/x-sharedlib.xml",
52 const gchar
* binary_suffix
[] = {
59 typedef struct _FileModelPrivate FileModelPrivate
;
61 struct _FileModelPrivate
64 gboolean filter_binary
;
65 gboolean filter_hidden
;
66 gboolean filter_backup
;
73 typedef struct _FileModelIdleExpand FileModelIdleExpand
;
74 struct _FileModelIdleExpand
82 #define FILE_MODEL_GET_PRIVATE(o) \
83 (G_TYPE_INSTANCE_GET_PRIVATE((o), FILE_TYPE_MODEL, FileModelPrivate))
85 G_DEFINE_TYPE (FileModel
, file_model
, GTK_TYPE_TREE_STORE
);
88 file_model_filter_file (FileModel
* model
, GnomeVFSFileInfo
* info
)
90 FileModelPrivate
* priv
= FILE_MODEL_GET_PRIVATE(model
);
91 /* Ignore hidden files */
92 if (priv
->filter_hidden
&& g_str_has_prefix (info
->name
, "."))
96 /* Ignore backup files */
97 if (priv
->filter_backup
&& (g_str_has_suffix (info
->name
, "~") ||
98 g_str_has_suffix (info
->name
, ".bak")))
102 if (priv
->filter_binary
)
107 for (i
= 0; binary_mime
[i
] != NULL
; i
++)
109 if (g_str_equal (info
->mime_type
, binary_mime
[i
]))
113 for (i
= 0; binary_suffix
[i
] != NULL
; i
++)
115 if (g_str_has_suffix (info
->name
, binary_suffix
[i
]))
119 /* Be sure to ignore "." and ".." */
120 if (g_str_equal (info
->name
, ".") || g_str_equal (info
->name
, ".."))
128 file_model_cancel_expand_idle(FileModel
* model
)
130 FileModelPrivate
* priv
= FILE_MODEL_GET_PRIVATE(model
);
132 if (priv
->expand_idle_id
)
134 g_source_remove (priv
->expand_idle_id
);
135 priv
->expand_idle_id
= 0;
140 file_model_add_dummy (FileModel
* model
,
143 GtkTreeStore
* store
= GTK_TREE_STORE (model
);
146 gtk_tree_store_append (store
, &dummy
, iter
);
147 gtk_tree_store_set (store
, &dummy
,
148 COLUMN_FILENAME
, _("Loading..."),
153 file_model_expand_idle (gpointer data
)
155 FileModelIdleExpand
* expand
= (FileModelIdleExpand
*) data
;
156 FileModel
* model
= expand
->model
;
157 FileModelPrivate
* priv
= FILE_MODEL_GET_PRIVATE (model
);
158 GtkTreeStore
* store
= GTK_TREE_STORE (model
);
161 if (!gtk_tree_model_get_iter (GTK_TREE_MODEL(model
), &parent
, expand
->path
))
165 GList
* file
= expand
->files
;
166 GnomeVFSFileInfo
* info
= (GnomeVFSFileInfo
*) file
->data
;
167 GtkTreeIter new_iter
;
168 GdkPixbuf
* pixbuf
= NULL
;
169 gboolean directory
= FALSE
;
171 /* Set pointer to the next element */
172 expand
->files
= g_list_next (file
);
174 /* Ignore user-defined files */
175 if (file_model_filter_file (model
, info
))
180 /* Create file entry in tree */
181 const gchar
* mime_type
= gnome_vfs_file_info_get_mime_type (info
);
182 gchar
* uri
= g_build_filename (expand
->uri
, info
->name
, NULL
);
185 pixbuf
= gdl_icons_get_mime_icon (priv
->icons
, mime_type
);
187 gtk_tree_store_append (store
, &new_iter
, &parent
);
189 if (mime_type
&& g_str_equal (mime_type
, DIRECTORY_MIME_TYPE
))
191 file_model_add_dummy (model
, &new_iter
);
193 pixbuf
= gdl_icons_get_mime_icon (priv
->icons
, DIRECTORY_MIME_TYPE
);
197 gtk_tree_store_set (store
, &new_iter
,
198 COLUMN_FILENAME
, info
->name
,
200 COLUMN_PIXBUF
, pixbuf
,
201 COLUMN_IS_DIR
, directory
,
209 gnome_vfs_file_info_list_free (expand
->files
);
210 gtk_tree_model_iter_children (GTK_TREE_MODEL(model
), &dummy
, &parent
);
211 gtk_tree_store_remove (store
, &dummy
);
213 g_free (expand
->uri
);
215 priv
->expand_idle_id
= 0;
222 file_model_sort (gconstpointer a
, gconstpointer b
)
224 GnomeVFSFileInfo
* info_a
= (GnomeVFSFileInfo
*) a
;
225 GnomeVFSFileInfo
* info_b
= (GnomeVFSFileInfo
*) b
;
226 gboolean dir_a
= (info_a
->type
== GNOME_VFS_FILE_TYPE_DIRECTORY
);
227 gboolean dir_b
= (info_b
->type
== GNOME_VFS_FILE_TYPE_DIRECTORY
);
231 return strcasecmp (info_a
->name
, info_b
->name
);
246 file_model_row_expanded (GtkTreeView
* tree_view
, GtkTreeIter
* iter
,
247 GtkTreePath
* path
, gpointer data
)
249 FileModel
* model
= FILE_MODEL(data
);
250 FileModelPrivate
* priv
= FILE_MODEL_GET_PRIVATE (model
);
254 gtk_tree_model_get (GTK_TREE_MODEL(model
), iter
, COLUMN_URI
, &uri
, -1);
256 if (gnome_vfs_directory_list_load (&files
, uri
,
257 GNOME_VFS_FILE_INFO_GET_MIME_TYPE
) ==
260 files
= g_list_sort (files
, file_model_sort
);
261 FileModelIdleExpand
* expand
= g_new0 (FileModelIdleExpand
, 1);
262 expand
->files
= files
;
263 expand
->path
= gtk_tree_model_get_path (GTK_TREE_MODEL (model
), iter
);
264 expand
->model
= model
;
267 priv
->expand_idle_id
= g_idle_add_full (G_PRIORITY_HIGH_IDLE
,
268 (GSourceFunc
) file_model_expand_idle
,
270 (GDestroyNotify
) g_free
);
272 gtk_tree_store_set (GTK_TREE_STORE (model
), iter
,
274 gdl_icons_get_mime_icon (priv
->icons
, DIRECTORY_OPEN
),
281 file_model_row_collapsed (GtkTreeView
* tree_view
, GtkTreeIter
* iter
,
282 GtkTreePath
* path
, gpointer data
)
284 FileModel
* model
= FILE_MODEL(data
);
285 FileModelPrivate
* priv
= FILE_MODEL_GET_PRIVATE (model
);
288 while (gtk_tree_model_iter_children (GTK_TREE_MODEL(model
), &child
, iter
))
290 gtk_tree_store_remove (GTK_TREE_STORE (model
), &child
);
292 file_model_add_dummy (model
, iter
);
293 gtk_tree_store_set (GTK_TREE_STORE (model
), iter
,
295 gdl_icons_get_folder_icon (priv
->icons
),
300 file_model_init (FileModel
*object
)
302 FileModel
* model
= FILE_MODEL(object
);
303 FileModelPrivate
* priv
= FILE_MODEL_GET_PRIVATE (model
);
305 priv
->icons
= gdl_icons_new(ICON_SIZE
);
309 file_model_finalize (GObject
*object
)
311 FileModel
* model
= FILE_MODEL(object
);
312 FileModelPrivate
* priv
= FILE_MODEL_GET_PRIVATE(model
);
314 g_object_unref (G_OBJECT(priv
->icons
));
315 G_OBJECT_CLASS (file_model_parent_class
)->finalize (object
);
319 file_model_set_property (GObject
*object
, guint prop_id
, const GValue
*value
, GParamSpec
*pspec
)
321 g_return_if_fail (FILE_IS_MODEL (object
));
322 FileModel
* model
= FILE_MODEL(object
);
323 FileModelPrivate
* priv
= FILE_MODEL_GET_PRIVATE(model
);
328 g_free (priv
->base_uri
);
329 priv
->base_uri
= g_strdup (g_value_get_string (value
));
330 if (!priv
->base_uri
|| !strlen (priv
->base_uri
))
332 priv
->base_uri
= gnome_vfs_get_uri_from_local_path("/");
335 case PROP_FILTER_BINARY
:
336 priv
->filter_binary
= g_value_get_boolean (value
);
338 case PROP_FILTER_HIDDEN
:
339 priv
->filter_hidden
= g_value_get_boolean (value
);
341 case PROP_FILTER_BACKUP
:
342 priv
->filter_backup
= g_value_get_boolean (value
);
346 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
352 file_model_get_property (GObject
*object
, guint prop_id
, GValue
*value
, GParamSpec
*pspec
)
354 g_return_if_fail (FILE_IS_MODEL (object
));
355 FileModel
* model
= FILE_MODEL(object
);
356 FileModelPrivate
* priv
= FILE_MODEL_GET_PRIVATE(model
);
361 g_value_set_string (value
, priv
->base_uri
);
363 case PROP_FILTER_BINARY
:
364 g_value_set_boolean (value
, priv
->filter_binary
);
365 case PROP_FILTER_HIDDEN
:
366 g_value_set_boolean (value
, priv
->filter_hidden
);
367 case PROP_FILTER_BACKUP
:
368 g_value_set_boolean (value
, priv
->filter_backup
);
371 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
377 file_model_class_init (FileModelClass
*klass
)
379 GObjectClass
* object_class
= G_OBJECT_CLASS (klass
);
381 object_class
->finalize
= file_model_finalize
;
382 object_class
->set_property
= file_model_set_property
;
383 object_class
->get_property
= file_model_get_property
;
385 g_type_class_add_private (object_class
, sizeof(FileModelPrivate
));
387 g_object_class_install_property (object_class
,
389 g_param_spec_string ("base_uri",
393 G_PARAM_READABLE
| G_PARAM_WRITABLE
| G_PARAM_CONSTRUCT
));
394 g_object_class_install_property (object_class
,
396 g_param_spec_boolean ("filter_binary",
397 "Filter binary files",
400 G_PARAM_READABLE
| G_PARAM_WRITABLE
| G_PARAM_CONSTRUCT
));
402 g_object_class_install_property (object_class
,
404 g_param_spec_boolean ("filter_hidden",
405 "Filter hidden files",
408 G_PARAM_READABLE
| G_PARAM_WRITABLE
| G_PARAM_CONSTRUCT
));
410 g_object_class_install_property (object_class
,
412 g_param_spec_boolean ("filter_backup",
413 "Filter backup files",
416 G_PARAM_READABLE
| G_PARAM_WRITABLE
| G_PARAM_CONSTRUCT
));
422 file_model_new (GtkTreeView
* tree_view
, const gchar
* base_uri
)
425 g_object_new (FILE_TYPE_MODEL
, "base_uri", base_uri
, NULL
);
426 GType types
[N_COLUMNS
] = {GDK_TYPE_PIXBUF
, G_TYPE_STRING
, G_TYPE_STRING
,
429 g_signal_connect (G_OBJECT (tree_view
), "row-collapsed",
430 G_CALLBACK (file_model_row_collapsed
), model
);
431 g_signal_connect (G_OBJECT (tree_view
), "row-expanded",
432 G_CALLBACK (file_model_row_expanded
), model
);
434 gtk_tree_store_set_column_types (GTK_TREE_STORE (model
), N_COLUMNS
,
437 return FILE_MODEL(model
);
441 file_model_refresh (FileModel
* model
)
443 GtkTreeStore
* store
= GTK_TREE_STORE (model
);
445 FileModelPrivate
* priv
= FILE_MODEL_GET_PRIVATE(model
);
446 gchar
*path
, *basename
;
449 gtk_tree_store_clear (store
);
450 path
= gnome_vfs_get_local_path_from_uri (priv
->base_uri
);
454 basename
= g_path_get_basename (path
);
455 pixbuf
= gdl_icons_get_folder_icon (priv
->icons
);
457 file_model_cancel_expand_idle(model
);
459 gtk_tree_store_append (store
, &iter
, NULL
);
461 gtk_tree_store_set (store
, &iter
,
462 COLUMN_FILENAME
, basename
,
463 COLUMN_URI
, priv
->base_uri
,
464 COLUMN_PIXBUF
, pixbuf
,
470 file_model_add_dummy (model
, &iter
);
474 file_model_get_uri (FileModel
* model
, GtkTreeIter
* iter
)
477 gtk_tree_model_get (GTK_TREE_MODEL (model
), iter
, COLUMN_URI
, &uri
, -1);
483 file_model_get_filename (FileModel
* model
, GtkTreeIter
* iter
)
486 gtk_tree_model_get (GTK_TREE_MODEL (model
), iter
, COLUMN_FILENAME
, &filename
, -1);