1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /*
3  * Libbrasero-burn
4  * Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app@wanadoo.fr>
5  *
6  * Libbrasero-burn is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * The Libbrasero-burn authors hereby grant permission for non-GPL compatible
12  * GStreamer plugins to be used and distributed together with GStreamer
13  * and Libbrasero-burn. This permission is above and beyond the permissions granted
14  * by the GPL license by which Libbrasero-burn is covered. If you modify this code
15  * you may extend this exception to your version of the code, but you are not
16  * obligated to do so. If you do not wish to do so, delete this exception
17  * statement from your version.
18  *
19  * Libbrasero-burn is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to:
26  * 	The Free Software Foundation, Inc.,
27  * 	51 Franklin Street, Fifth Floor
28  * 	Boston, MA  02110-1301, USA.
29  */
30 
31 #ifndef _BRASERO_FILE_NODE_H
32 #define _BRASERO_FILE_NODE_H
33 
34 #include <glib.h>
35 
36 #include <gio/gio.h>
37 
38 #include "burn-volume.h"
39 
40 G_BEGIN_DECLS
41 
42 typedef struct _BraseroFileNode BraseroFileNode;
43 
44 struct _BraseroURINode {
45 	/* List of all nodes that share the same URI */
46 	GSList *nodes;
47 
48 	/* NOTE: uris are always escaped */
49 	gchar *uri;
50 };
51 typedef struct _BraseroURINode BraseroURINode;
52 
53 struct _BraseroGraft {
54 	/* The name on CD (which could be different) from the original */
55 	gchar *name;
56 	BraseroURINode *node;
57 };
58 typedef struct _BraseroGraft BraseroGraft;
59 
60 struct _BraseroImport {
61 	gchar *name;
62 	BraseroFileNode *replaced;
63 };
64 typedef struct _BraseroImport BraseroImport;
65 
66 /**
67  * NOTE: The root object keeps some statistics about its tree like
68  * - number of children (files+directories)
69  * - number of deep directories
70  * - number of files over 2 GiB
71  */
72 
73 struct _BraseroFileTreeStats {
74 	guint children;
75 	guint num_dir;
76 	guint num_deep;
77 	guint num_2GiB;
78 	guint num_sym;
79 };
80 typedef struct _BraseroFileTreeStats BraseroFileTreeStats;
81 
82 struct _BraseroFileNode {
83 	BraseroFileNode *parent;
84 	BraseroFileNode *next;
85 
86 	/**
87 	 * This union can be:
88 	 * - the name of the file on file system and on disc
89 	 * - a pointer to the graft node for all grafted nodes
90 	 * - a pointer to saved imported session files
91 	 * Check is_grafted to determine.
92 	 */
93 
94 	/* NOTE: names are unescaped (for display). */
95 
96 	union {
97 		BraseroImport *import;
98 		BraseroGraft *graft;
99 		gchar *name;
100 	} union1;
101 
102 	union {
103 		gchar *mime;
104 		BraseroFileNode *children;
105 	} union2;
106 
107 	/* NOTE: overflow for sectors will probably not be hit
108 	 * before a few years given that we store the size in
109 	 * sectors of 2048. For the time being DVD are usually
110 	 * 4.3 GiB. To overflow the following member (provided
111 	 * we are on a 32 architecture) they would have to be
112 	 * over 8192 GiB. I think it's reasonable to think we
113 	 * have time. And even then, by this time most of the
114 	 * computers will have switched to 64 architecture (in
115 	 * 2099) and I'll be dead anyway as well as optical
116 	 * discs. */
117 	union {
118 		guint sectors;
119 
120 		/* stores the address of the children records in image */
121 		guint imported_address;
122 		BraseroFileTreeStats *stats;
123 	} union3;
124 
125 	/* type of node */
126 	guint is_root:1;
127 	guint is_fake:1;
128 	guint is_file:1;
129 	guint is_symlink:1;
130 	guint is_imported:1;
131 	guint is_monitored:1;
132 
133 	/* status of union1 */
134 	guint is_grafted:1;
135 	guint has_import:1;
136 
137 	/* VFS status of node */
138 	guint is_loading:1;
139 	guint is_reloading:1;
140 	guint is_exploring:1;
141 
142 	/* that's for some special nodes (usually counted in statistics) */
143 	guint is_2GiB:1;
144 	guint is_deep:1;
145 
146 	/* This is for nodes created at project load time. This means
147 	 * that they can be replaced if a real directory is under the
148 	 * parent with the same name*/
149 	guint is_tmp_parent:1;
150 
151 	/* Used to determine if is should be shown */
152 	guint is_hidden:1;
153 
154 	/* Used by the model */
155 	/* This is a workaround for a warning in gailtreeview.c line 2946 where
156 	 * gail uses the GtkTreePath and not a copy which if the node inserted
157 	 * declares to have children and is not expanded leads to the path being
158 	 * upped and therefore wrong. */
159 	guint is_inserting:1;
160 
161 	guint is_expanded:1; /* Used to choose the icon for folders */
162 
163 	/* this is a ref count a max of 255 should be enough */
164 	guint is_visible:7;
165 };
166 
167 /** Returns a const gchar* (it shouldn't be freed). */
168 #define BRASERO_FILE_NODE_NAME(MACRO_node)					\
169 	((MACRO_node)->is_grafted?(MACRO_node)->union1.graft->name:		\
170 	 (MACRO_node)->has_import?(MACRO_node)->union1.import->name:		\
171 	 (MACRO_node)->union1.name)
172 
173 #define BRASERO_FILE_NODE_GRAFT(MACRO_node)					\
174 	((MACRO_node)->is_grafted?(MACRO_node)->union1.graft:NULL)
175 
176 #define BRASERO_FILE_NODE_IMPORT(MACRO_node)					\
177 	((MACRO_node)->has_import?(MACRO_node)->union1.import:NULL)
178 
179 #define BRASERO_FILE_NODE_CHILDREN(MACRO_node)					\
180 	((MACRO_node)->is_file?NULL:(MACRO_node)->union2.children)
181 
182 #define BRASERO_FILE_NODE_MIME(MACRO_node)					\
183 	((MACRO_node)->is_file?(MACRO_node)->union2.mime:"x-directory/normal")
184 
185 #define BRASERO_FILE_NODE_SECTORS(MACRO_node)					\
186 	((guint64) ((MACRO_node)->is_root?0:(MACRO_node)->union3.sectors))
187 
188 #define BRASERO_FILE_NODE_STATS(MACRO_root)					\
189 	((MACRO_root)->is_root?(MACRO_root)->union3.stats:NULL)
190 
191 #define BRASERO_FILE_NODE_VIRTUAL(MACRO_node)					\
192 	((MACRO_node)->is_hidden && (MACRO_node)->is_fake)
193 
194 #define BRASERO_FILE_NODE_IMPORTED_ADDRESS(MACRO_node)				\
195 	((MACRO_node) && (MACRO_node)->is_imported && (MACRO_node)->is_fake?(MACRO_node)->union3.imported_address:-1)
196 
197 #define BRASERO_FILE_2G_LIMIT		1048576
198 
199 BraseroFileNode *
200 brasero_file_node_root_new (void);
201 
202 BraseroFileNode *
203 brasero_file_node_get_root (BraseroFileNode *node,
204 			    guint *depth);
205 
206 BraseroFileTreeStats *
207 brasero_file_node_get_tree_stats (BraseroFileNode *node,
208 				  guint *depth);
209 
210 BraseroFileNode *
211 brasero_file_node_nth_child (BraseroFileNode *parent,
212 			     guint nth);
213 
214 guint
215 brasero_file_node_get_depth (BraseroFileNode *node);
216 
217 guint
218 brasero_file_node_get_pos_as_child (BraseroFileNode *node);
219 
220 guint
221 brasero_file_node_get_n_children (const BraseroFileNode *node);
222 
223 guint
224 brasero_file_node_get_pos_as_child (BraseroFileNode *node);
225 
226 gboolean
227 brasero_file_node_is_ancestor (BraseroFileNode *parent,
228 			       BraseroFileNode *node);
229 BraseroFileNode *
230 brasero_file_node_get_from_path (BraseroFileNode *root,
231 				 const gchar *path);
232 BraseroFileNode *
233 brasero_file_node_check_name_existence (BraseroFileNode *parent,
234 				        const gchar *name);
235 BraseroFileNode *
236 brasero_file_node_check_name_existence_case (BraseroFileNode *parent,
237 					     const gchar *name);
238 BraseroFileNode *
239 brasero_file_node_check_imported_sibling (BraseroFileNode *node);
240 
241 /**
242  * Nodes are strictly organised so there to be sort function all the time
243  */
244 
245 void
246 brasero_file_node_add (BraseroFileNode *parent,
247 		       BraseroFileNode *child,
248 		       GCompareFunc sort_func);
249 
250 BraseroFileNode *
251 brasero_file_node_new (const gchar *name);
252 
253 BraseroFileNode *
254 brasero_file_node_new_virtual (const gchar *name);
255 
256 BraseroFileNode *
257 brasero_file_node_new_loading (const gchar *name);
258 
259 BraseroFileNode *
260 brasero_file_node_new_empty_folder (const gchar *name);
261 
262 BraseroFileNode *
263 brasero_file_node_new_imported_session_file (GFileInfo *info);
264 
265 /**
266  * If there are any change in the order it cannot be handled in these functions
267  * A call to resort function must be made.
268  */
269 void
270 brasero_file_node_rename (BraseroFileNode *node,
271 			  const gchar *name);
272 void
273 brasero_file_node_set_from_info (BraseroFileNode *node,
274 				 BraseroFileTreeStats *stats,
275 				 GFileInfo *info);
276 
277 void
278 brasero_file_node_graft (BraseroFileNode *file_node,
279 			 BraseroURINode *uri_node);
280 void
281 brasero_file_node_ungraft (BraseroFileNode *node);
282 
283 void
284 brasero_file_node_move_from (BraseroFileNode *node,
285 			     BraseroFileTreeStats *stats);
286 void
287 brasero_file_node_move_to (BraseroFileNode *node,
288 			   BraseroFileNode *parent,
289 			   GCompareFunc sort_func);
290 
291 void
292 brasero_file_node_unlink (BraseroFileNode *node);
293 
294 void
295 brasero_file_node_destroy (BraseroFileNode *node,
296 			   BraseroFileTreeStats *stats);
297 
298 void
299 brasero_file_node_save_imported (BraseroFileNode *node,
300 				 BraseroFileTreeStats *stats,
301 				 BraseroFileNode *parent,
302 				 GCompareFunc sort_func);
303 
304 gint
305 brasero_file_node_sort_name_cb (gconstpointer obj_a, gconstpointer obj_b);
306 gint
307 brasero_file_node_sort_size_cb (gconstpointer obj_a, gconstpointer obj_b);
308 gint
309 brasero_file_node_sort_mime_cb (gconstpointer obj_a, gconstpointer obj_b);
310 gint
311 brasero_file_node_sort_default_cb (gconstpointer obj_a, gconstpointer obj_b);
312 gint *
313 brasero_file_node_sort_children (BraseroFileNode *parent,
314 				 GCompareFunc sort_func);
315 gint *
316 brasero_file_node_need_resort (BraseroFileNode *node,
317 			       GCompareFunc sort_func);
318 gint *
319 brasero_file_node_reverse_children (BraseroFileNode *parent);
320 
321 
322 G_END_DECLS
323 
324 #endif /* _BRASERO_FILE_NODE_H */
325