comparison finch/libgnt/gntfilesel.c @ 15988:e05e5b148723

Allow using different methods for reading directory entries.
author Sadrul Habib Chowdhury <imadil@gmail.com>
date Wed, 04 Apr 2007 08:33:50 +0000
parents 8a54f74fecdf
children e78b15c2c60f
comparison
equal deleted inserted replaced
15987:7adb832667fd 15988:e05e5b148723
9 #include <string.h> 9 #include <string.h>
10 #include <sys/types.h> 10 #include <sys/types.h>
11 #include <sys/stat.h> 11 #include <sys/stat.h>
12 #include <unistd.h> 12 #include <unistd.h>
13 13
14 #if 0
14 #include <glob.h> 15 #include <glob.h>
16 #endif
15 17
16 enum 18 enum
17 { 19 {
18 SIG_FILE_SELECTED, 20 SIG_FILE_SELECTED,
19 SIGS 21 SIGS
85 gboolean find = g_list_find_custom(sel->tags, ret, (GCompareFunc)g_utf8_collate) != NULL; 87 gboolean find = g_list_find_custom(sel->tags, ret, (GCompareFunc)g_utf8_collate) != NULL;
86 g_free(ret); 88 g_free(ret);
87 return find; 89 return find;
88 } 90 }
89 91
92 GntFile* gnt_file_new_dir(const char *name)
93 {
94 GntFile *file = g_new0(GntFile, 1);
95 file->basename = g_strdup(name);
96 file->type = GNT_FILE_DIR;
97 return file;
98 }
99
100 GntFile* gnt_file_new(const char *name, unsigned long size)
101 {
102 GntFile *file = g_new0(GntFile, 1);
103 file->basename = g_strdup(name);
104 file->type = GNT_FILE_REGULAR;
105 file->size = size;
106 return file;
107 }
108
109 static gboolean
110 local_read_fn(const char *path, GList **files, GError **error)
111 {
112 GDir *dir;
113 GntFile *file;
114 const char *str;
115
116 dir = g_dir_open(path, 0, error);
117 if (dir == NULL || (error && *error)) {
118 return FALSE;
119 }
120
121 *files = NULL;
122 if (*path != '\0' && strcmp(path, G_DIR_SEPARATOR_S)) {
123 file = gnt_file_new_dir("..");
124 *files = g_list_prepend(*files, file);
125 }
126
127 while ((str = g_dir_read_name(dir)) != NULL) {
128 char *fp = g_build_filename(path, str, NULL);
129 struct stat st;
130
131 if (stat(fp, &st)) {
132 g_printerr("Error stating location %s\n", fp);
133 } else {
134 if (S_ISDIR(st.st_mode)) {
135 file = gnt_file_new_dir(str);
136 } else {
137 file = gnt_file_new(str, (long)st.st_size);
138 }
139 *files = g_list_prepend(*files, file);
140 }
141 g_free(fp);
142 }
143
144 *files = g_list_reverse(*files);
145 return TRUE;
146 }
147
148 static void
149 gnt_file_free(GntFile *file)
150 {
151 g_free(file->fullpath);
152 g_free(file->basename);
153 g_free(file);
154 }
155
90 static gboolean 156 static gboolean
91 location_changed(GntFileSel *sel, GError **err) 157 location_changed(GntFileSel *sel, GError **err)
92 { 158 {
93 GDir *dir; 159 GList *files, *iter;
94 const char *str; 160 gboolean success;
95 161
96 if (!sel->dirs) 162 if (!sel->dirs)
97 return TRUE; 163 return TRUE;
98 164
99 gnt_tree_remove_all(GNT_TREE(sel->dirs)); 165 gnt_tree_remove_all(GNT_TREE(sel->dirs));
103 if (sel->current == NULL) { 169 if (sel->current == NULL) {
104 if (GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(sel), GNT_WIDGET_MAPPED)) 170 if (GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(sel), GNT_WIDGET_MAPPED))
105 gnt_widget_draw(GNT_WIDGET(sel)); 171 gnt_widget_draw(GNT_WIDGET(sel));
106 return TRUE; 172 return TRUE;
107 } 173 }
174
175 /* XXX:\
176 * XXX: This is blocking.
177 * XXX:/
178 */
179 files = NULL;
180 if (sel->read_fn)
181 success = sel->read_fn(sel->current, &files, err);
182 else
183 success = local_read_fn(sel->current, &files, err);
108 184
109 dir = g_dir_open(sel->current, 0, err); 185 if (!success || *err) {
110 if (dir == NULL || *err) {
111 g_printerr("GntFileSel: error opening location %s (%s)\n", 186 g_printerr("GntFileSel: error opening location %s (%s)\n",
112 sel->current, *err ? (*err)->message : "reason unknown"); 187 sel->current, *err ? (*err)->message : "reason unknown");
113 return FALSE; 188 return FALSE;
114 } 189 }
115 190
116 if (*sel->current != '\0' && strcmp(sel->current, G_DIR_SEPARATOR_S)) 191 for (iter = files; iter; iter = iter->next) {
117 gnt_tree_add_row_after(GNT_TREE(sel->dirs), g_strdup(".."), 192 GntFile *file = iter->data;
118 gnt_tree_create_row(GNT_TREE(sel->dirs), ".."), NULL, NULL); 193 char *str = file->basename;
119 194 if (file->type == GNT_FILE_DIR) {
120 while ((str = g_dir_read_name(dir)) != NULL) { 195 gnt_tree_add_row_after(GNT_TREE(sel->dirs), g_strdup(str),
121 char *fp = g_build_filename(sel->current, str, NULL); 196 gnt_tree_create_row(GNT_TREE(sel->dirs), str), NULL, NULL);
122 struct stat st; 197 if (sel->multiselect && sel->dirsonly && is_tagged(sel, str))
123 198 gnt_tree_set_row_flags(GNT_TREE(sel->dirs), (gpointer)str, GNT_TEXT_FLAG_BOLD);
124 if (stat(fp, &st)) { 199 } else if (!sel->dirsonly) {
125 g_printerr("Error stating location %s\n", fp); 200 char size[128];
126 } else { 201 snprintf(size, sizeof(size), "%ld", file->size);
127 if (S_ISDIR(st.st_mode)) { 202
128 gnt_tree_add_row_after(GNT_TREE(sel->dirs), g_strdup(str), 203 gnt_tree_add_row_after(GNT_TREE(sel->files), g_strdup(str),
129 gnt_tree_create_row(GNT_TREE(sel->dirs), str), NULL, NULL); 204 gnt_tree_create_row(GNT_TREE(sel->files), str, size, ""), NULL, NULL);
130 if (sel->multiselect && sel->dirsonly && is_tagged(sel, str)) 205 if (sel->multiselect && is_tagged(sel, str))
131 gnt_tree_set_row_flags(GNT_TREE(sel->dirs), (gpointer)str, GNT_TEXT_FLAG_BOLD); 206 gnt_tree_set_row_flags(GNT_TREE(sel->files), (gpointer)str, GNT_TEXT_FLAG_BOLD);
132 } else if (!sel->dirsonly) {
133 char size[128];
134 snprintf(size, sizeof(size), "%ld", (long)st.st_size);
135
136 gnt_tree_add_row_after(GNT_TREE(sel->files), g_strdup(str),
137 gnt_tree_create_row(GNT_TREE(sel->files), str, size, ""), NULL, NULL);
138 if (sel->multiselect && is_tagged(sel, str))
139 gnt_tree_set_row_flags(GNT_TREE(sel->files), (gpointer)str, GNT_TEXT_FLAG_BOLD);
140 }
141 } 207 }
142 g_free(fp); 208 }
143 } 209 g_list_foreach(files, (GFunc)gnt_file_free, NULL);
210 g_list_free(files);
144 if (GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(sel), GNT_WIDGET_MAPPED)) 211 if (GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(sel), GNT_WIDGET_MAPPED))
145 gnt_widget_draw(GNT_WIDGET(sel)); 212 gnt_widget_draw(GNT_WIDGET(sel));
146 return TRUE; 213 return TRUE;
147 } 214 }
148 215
149 static gboolean 216 static gboolean
150 dir_key_pressed(GntTree *tree, const char *key, GntFileSel *sel) 217 dir_key_pressed(GntTree *tree, const char *key, GntFileSel *sel)
151 { 218 {
152 if (strcmp(key, "\r") == 0) { 219 if (strcmp(key, "\r") == 0) {
153 char *str = g_strdup(gnt_tree_get_selection_data(tree)); 220 char *str = g_strdup(gnt_tree_get_selection_data(tree));
154 char *path = g_build_filename(sel->current, str, NULL); 221 char *path, *dir;
155 char *dir = g_path_get_basename(sel->current); 222
223 if (!str)
224 return TRUE;
225
226 path = g_build_filename(sel->current, str, NULL);
227 dir = g_path_get_basename(sel->current);
156 if (!gnt_file_sel_set_current_location(sel, path)) { 228 if (!gnt_file_sel_set_current_location(sel, path)) {
157 gnt_tree_set_selected(tree, str); 229 gnt_tree_set_selected(tree, str);
158 } else if (strcmp(str, "..") == 0) { 230 } else if (strcmp(str, "..") == 0) {
159 gnt_tree_set_selected(tree, dir); 231 gnt_tree_set_selected(tree, dir);
160 } 232 }
167 } 239 }
168 240
169 static gboolean 241 static gboolean
170 location_key_pressed(GntTree *tree, const char *key, GntFileSel *sel) 242 location_key_pressed(GntTree *tree, const char *key, GntFileSel *sel)
171 { 243 {
172 if (strcmp(key, "\r") == 0) { 244 char *path;
173 int count; 245 char *str;
174 glob_t gl; 246 #if 0
175 char *path; 247 int count;
176 char *str; 248 glob_t gl;
177 struct stat st; 249 struct stat st;
178 int glob_ret; 250 int glob_ret;
179 251 #endif
180 str = (char*)gnt_entry_get_text(GNT_ENTRY(sel->location)); 252 if (strcmp(key, "\r"))
181 if (*str == G_DIR_SEPARATOR) 253 return FALSE;
182 path = g_strdup(str); 254
183 else 255 str = (char*)gnt_entry_get_text(GNT_ENTRY(sel->location));
184 path = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", sel->current, str); 256 if (*str == G_DIR_SEPARATOR)
185 str = process_path(path); 257 path = g_strdup(str);
258 else
259 path = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", sel->current, str);
260 str = process_path(path);
261 g_free(path);
262 path = g_path_get_dirname(str);
263 g_free(str);
264
265 if (!gnt_file_sel_set_current_location(sel, path)) {
186 g_free(path); 266 g_free(path);
187 path = str; 267 return FALSE;
188 268 }
189 if (!stat(path, &st)) { 269 #if 0
190 if (S_ISDIR(st.st_mode)) { 270 /* XXX: there needs to be a way to allow other methods for globbing,
191 gnt_file_sel_set_current_location(sel, path); 271 * like the read_fn stuff. */
192 goto success; 272 glob_ret = glob(path, GLOB_MARK, NULL, &gl);
273 if (!glob_ret) { /* XXX: do something with the return value */
274 char *loc = g_path_get_dirname(gl.gl_pathv[0]);
275
276 stat(gl.gl_pathv[0], &st);
277 gnt_file_sel_set_current_location(sel, loc); /* XXX: check the return value */
278 g_free(loc);
279 if (!S_ISDIR(st.st_mode) && !sel->dirsonly) {
280 gnt_tree_remove_all(GNT_TREE(sel->files));
281 for (count = 0; count < gl.gl_pathc; count++) {
282 char *tmp = process_path(gl.gl_pathv[count]);
283 loc = g_path_get_dirname(tmp);
284 if (g_utf8_collate(sel->current, loc) == 0) {
285 char *base = g_path_get_basename(tmp);
286 char size[128];
287 snprintf(size, sizeof(size), "%ld", (long)st.st_size);
288 gnt_tree_add_row_after(GNT_TREE(sel->files), base,
289 gnt_tree_create_row(GNT_TREE(sel->files), base, size, ""), NULL, NULL);
290 }
291 g_free(loc);
292 g_free(tmp);
193 } 293 }
194 }
195
196 glob_ret = glob(path, GLOB_MARK, NULL, &gl);
197 if (!glob_ret) { /* XXX: do something with the return value */
198 char *loc = g_path_get_dirname(gl.gl_pathv[0]);
199
200 stat(gl.gl_pathv[0], &st);
201 gnt_file_sel_set_current_location(sel, loc); /* XXX: check the return value */
202 g_free(loc);
203 if (!S_ISDIR(st.st_mode) && !sel->dirsonly) {
204 gnt_tree_remove_all(GNT_TREE(sel->files));
205 for (count = 0; count < gl.gl_pathc; count++) {
206 char *tmp = process_path(gl.gl_pathv[count]);
207 loc = g_path_get_dirname(tmp);
208 if (g_utf8_collate(sel->current, loc) == 0) {
209 char *base = g_path_get_basename(tmp);
210 char size[128];
211 snprintf(size, sizeof(size), "%ld", (long)st.st_size);
212 gnt_tree_add_row_after(GNT_TREE(sel->files), base,
213 gnt_tree_create_row(GNT_TREE(sel->files), base, size, ""), NULL, NULL);
214 }
215 g_free(loc);
216 g_free(tmp);
217 }
218 gnt_widget_draw(sel->files);
219 }
220 } else if (sel->files) {
221 gnt_tree_remove_all(GNT_TREE(sel->files));
222 gnt_widget_draw(sel->files); 294 gnt_widget_draw(sel->files);
223 } 295 }
224 globfree(&gl); 296 } else if (sel->files) {
297 gnt_tree_remove_all(GNT_TREE(sel->files));
298 gnt_widget_draw(sel->files);
299 }
300 globfree(&gl);
225 success: 301 success:
226 g_free(path); 302 #endif
227 return TRUE; 303 g_free(path);
228 } 304 return TRUE;
229 return FALSE;
230 } 305 }
231 306
232 static void 307 static void
233 file_sel_changed(GntWidget *widget, gpointer old, gpointer current, GntFileSel *sel) 308 file_sel_changed(GntWidget *widget, gpointer old, gpointer current, GntFileSel *sel)
234 { 309 {
327 gnt_tree_set_row_flags(GNT_TREE(tree), iter->data, GNT_TEXT_FLAG_NORMAL); 402 gnt_tree_set_row_flags(GNT_TREE(tree), iter->data, GNT_TEXT_FLAG_NORMAL);
328 403
329 return TRUE; 404 return TRUE;
330 } 405 }
331 406
407 static gboolean
408 up_directory(GntBindable *bind, GList *null)
409 {
410 char *path, *dir;
411 GntFileSel *sel = GNT_FILE_SEL(bind);
412 if (!gnt_widget_has_focus(sel->dirs) &&
413 !gnt_widget_has_focus(sel->files))
414 return FALSE;
415
416 path = g_build_filename(sel->current, "..", NULL);
417 dir = g_path_get_basename(sel->current);
418 if (gnt_file_sel_set_current_location(sel, path))
419 gnt_tree_set_selected(GNT_TREE(sel->dirs), dir);
420 g_free(dir);
421 g_free(path);
422 return TRUE;
423 }
424
332 static void 425 static void
333 gnt_file_sel_class_init(GntFileSelClass *klass) 426 gnt_file_sel_class_init(GntFileSelClass *klass)
334 { 427 {
335 GntBindableClass *bindable = GNT_BINDABLE_CLASS(klass); 428 GntBindableClass *bindable = GNT_BINDABLE_CLASS(klass);
336 GntWidgetClass *kl = GNT_WIDGET_CLASS(klass); 429 GntWidgetClass *kl = GNT_WIDGET_CLASS(klass);
348 gnt_closure_marshal_VOID__STRING_STRING, 441 gnt_closure_marshal_VOID__STRING_STRING,
349 G_TYPE_NONE, 0); 442 G_TYPE_NONE, 0);
350 443
351 gnt_bindable_class_register_action(bindable, "toggle-tag", toggle_tag_selection, "t", NULL); 444 gnt_bindable_class_register_action(bindable, "toggle-tag", toggle_tag_selection, "t", NULL);
352 gnt_bindable_class_register_action(bindable, "clear-tags", clear_tags, "c", NULL); 445 gnt_bindable_class_register_action(bindable, "clear-tags", clear_tags, "c", NULL);
446 gnt_bindable_class_register_action(bindable, "up-directory", up_directory, GNT_KEY_BACKSPACE, NULL);
353 gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass)); 447 gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass));
354 448
355 GNTDEBUG; 449 GNTDEBUG;
356 } 450 }
357 451
503 list = g_list_prepend(list, str); 597 list = g_list_prepend(list, str);
504 list = g_list_reverse(list); 598 list = g_list_reverse(list);
505 return list; 599 return list;
506 } 600 }
507 601
602 void gnt_file_sel_set_read_fn(GntFileSel *sel, gboolean (*read_fn)(const char *path, GList **files, GError **error))
603 {
604 sel->read_fn = read_fn;
605 }
606
607