Updated Spanish translation
[anjuta-git-plugin.git] / plugins / file-manager / file-model.c
blob811604225178e143fa98f89106befb50830dabe8
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 * anjuta
4 * Copyright (C) Johannes Schmid 2007 <jhs@gnome.org>
5 *
6 * anjuta is free software.
7 *
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)
11 * any later version.
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>
28 #include <string.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"
34 #define ICON_SIZE 12
36 enum
38 PROP_0,
39 PROP_BASE_URI,
40 PROP_FILTER_BINARY,
41 PROP_FILTER_HIDDEN,
42 PROP_FILTER_BACKUP
45 const gchar* binary_mime[] = {
46 "application/x-core",
47 "application/x-shared-library-la.xml",
48 "application/x-sharedlib.xml",
49 NULL
52 const gchar* binary_suffix[] = {
53 ".lo",
54 ".o",
55 ".a",
56 NULL
59 typedef struct _FileModelPrivate FileModelPrivate;
61 struct _FileModelPrivate
63 gchar* base_uri;
64 gboolean filter_binary;
65 gboolean filter_hidden;
66 gboolean filter_backup;
68 GdlIcons* icons;
70 guint expand_idle_id;
73 typedef struct _FileModelIdleExpand FileModelIdleExpand;
74 struct _FileModelIdleExpand
76 FileModel* model;
77 GList* files;
78 GtkTreePath* path;
79 gchar* uri;
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);
87 static gboolean
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, "."))
94 return TRUE;
96 /* Ignore backup files */
97 if (priv->filter_backup && (g_str_has_suffix (info->name, "~") ||
98 g_str_has_suffix (info->name, ".bak")))
100 return TRUE;
102 if (priv->filter_binary)
104 int i;
105 if (info->mime_type)
107 for (i = 0; binary_mime[i] != NULL; i++)
109 if (g_str_equal (info->mime_type, binary_mime[i]))
110 return TRUE;
113 for (i = 0; binary_suffix[i] != NULL; i++)
115 if (g_str_has_suffix (info->name, binary_suffix[i]))
116 return TRUE;
119 /* Be sure to ignore "." and ".." */
120 if (g_str_equal (info->name, ".") || g_str_equal (info->name, ".."))
122 return TRUE;
124 return FALSE;
127 static void
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;
139 static void
140 file_model_add_dummy (FileModel* model,
141 GtkTreeIter* iter)
143 GtkTreeStore* store = GTK_TREE_STORE (model);
144 GtkTreeIter dummy;
146 gtk_tree_store_append (store, &dummy, iter);
147 gtk_tree_store_set (store, &dummy,
148 COLUMN_FILENAME, _("Loading..."),
149 -1);
152 static gboolean
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);
159 GtkTreeIter parent;
161 if (!gtk_tree_model_get_iter (GTK_TREE_MODEL(model), &parent, expand->path))
162 return FALSE;
163 if (expand->files)
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))
177 return TRUE;
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);
184 if (mime_type)
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);
192 if (!pixbuf)
193 pixbuf = gdl_icons_get_mime_icon (priv->icons, DIRECTORY_MIME_TYPE);
194 directory = TRUE;
197 gtk_tree_store_set (store, &new_iter,
198 COLUMN_FILENAME, info->name,
199 COLUMN_URI, uri,
200 COLUMN_PIXBUF, pixbuf,
201 COLUMN_IS_DIR, directory,
202 -1);
203 g_free (uri);
204 return TRUE;
206 else
208 GtkTreeIter dummy;
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;
217 return FALSE;
221 static int
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);
229 if (dir_a == dir_b)
231 return strcasecmp (info_a->name, info_b->name);
233 else if (dir_a)
235 return -1;
237 else if (dir_b)
239 return 1;
241 else
242 return 0;
245 static void
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);
251 gchar* uri;
252 GList* files = NULL;
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) ==
258 GNOME_VFS_OK)
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;
265 expand->uri = uri;
267 priv->expand_idle_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE,
268 (GSourceFunc) file_model_expand_idle,
269 (gpointer) expand,
270 (GDestroyNotify) g_free);
272 gtk_tree_store_set (GTK_TREE_STORE (model), iter,
273 COLUMN_PIXBUF,
274 gdl_icons_get_mime_icon (priv->icons, DIRECTORY_OPEN),
275 -1);
280 static void
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);
286 GtkTreeIter child;
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,
294 COLUMN_PIXBUF,
295 gdl_icons_get_folder_icon (priv->icons),
296 -1);
299 static void
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);
308 static void
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);
318 static void
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);
325 switch (prop_id)
327 case PROP_BASE_URI:
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("/");
334 break;
335 case PROP_FILTER_BINARY:
336 priv->filter_binary = g_value_get_boolean (value);
337 break;
338 case PROP_FILTER_HIDDEN:
339 priv->filter_hidden = g_value_get_boolean (value);
340 break;
341 case PROP_FILTER_BACKUP:
342 priv->filter_backup = g_value_get_boolean (value);
343 break;
345 default:
346 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
347 break;
351 static void
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);
358 switch (prop_id)
360 case PROP_BASE_URI:
361 g_value_set_string (value, priv->base_uri);
362 break;
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);
370 default:
371 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
372 break;
376 static void
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,
388 PROP_BASE_URI,
389 g_param_spec_string ("base_uri",
390 "Base uri",
391 "Base uri",
392 "NULL",
393 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
394 g_object_class_install_property (object_class,
395 PROP_FILTER_BINARY,
396 g_param_spec_boolean ("filter_binary",
397 "Filter binary files",
398 "file_binary",
399 TRUE,
400 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
402 g_object_class_install_property (object_class,
403 PROP_FILTER_HIDDEN,
404 g_param_spec_boolean ("filter_hidden",
405 "Filter hidden files",
406 "file_hidden",
407 TRUE,
408 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
410 g_object_class_install_property (object_class,
411 PROP_FILTER_BACKUP,
412 g_param_spec_boolean ("filter_backup",
413 "Filter backup files",
414 "file_backup",
415 TRUE,
416 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
421 FileModel*
422 file_model_new (GtkTreeView* tree_view, const gchar* base_uri)
424 GObject* model =
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,
427 G_TYPE_BOOLEAN};
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,
435 types);
437 return FILE_MODEL(model);
440 void
441 file_model_refresh (FileModel* model)
443 GtkTreeStore* store = GTK_TREE_STORE (model);
444 GtkTreeIter iter;
445 FileModelPrivate* priv = FILE_MODEL_GET_PRIVATE(model);
446 gchar *path, *basename;
447 GdkPixbuf *pixbuf;
449 gtk_tree_store_clear (store);
450 path = gnome_vfs_get_local_path_from_uri (priv->base_uri);
451 if (!path)
452 return;
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,
465 COLUMN_IS_DIR, TRUE,
466 -1);
467 g_free (basename);
468 g_free (path);
470 file_model_add_dummy (model, &iter);
473 gchar*
474 file_model_get_uri (FileModel* model, GtkTreeIter* iter)
476 gchar* uri;
477 gtk_tree_model_get (GTK_TREE_MODEL (model), iter, COLUMN_URI, &uri, -1);
479 return uri;
482 gchar*
483 file_model_get_filename (FileModel* model, GtkTreeIter* iter)
485 gchar* filename;
486 gtk_tree_model_get (GTK_TREE_MODEL (model), iter, COLUMN_FILENAME, &filename, -1);
488 return filename;