Mercurial > pidgin
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 |