Mercurial > geeqie
annotate src/ui_pathsel.c @ 391:fcaf9c175742
Fix a crash introduced in revision 477.
author | zas_ |
---|---|
date | Wed, 16 Apr 2008 22:23:43 +0000 |
parents | 61a3c8b05b24 |
children | 4b2d7f9af171 |
rev | line source |
---|---|
9 | 1 /* |
2 * (SLIK) SimpLIstic sKin functions | |
69
31759d770628
Fri Oct 13 10:27:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
3 * (C) 2006 John Ellis |
9 | 4 * |
5 * Author: John Ellis | |
6 * | |
7 * This software is released under the GNU General Public License (GNU GPL). | |
8 * Please read the included file COPYING for more information. | |
9 * This software comes with no warranty of any kind, use at your own risk! | |
10 */ | |
11 | |
12 #ifdef HAVE_CONFIG_H | |
13 # include "config.h" | |
14 #endif | |
15 #include "intl.h" | |
16 | |
17 #include <stdio.h> | |
18 #include <stdlib.h> | |
19 #include <string.h> | |
20 | |
21 #include <dirent.h> | |
22 #include <fcntl.h> | |
23 #include <unistd.h> | |
24 #include <sys/types.h> | |
25 #include <sys/stat.h> | |
26 | |
27 #include <gtk/gtk.h> | |
28 | |
29 #include <gdk/gdkkeysyms.h> /* for key values */ | |
30 | |
281 | 31 #include "main.h" |
9 | 32 #include "ui_pathsel.h" |
33 | |
34 #include "ui_bookmark.h" | |
35 #include "ui_fileops.h" | |
36 #include "ui_menu.h" | |
37 #include "ui_misc.h" | |
38 #include "ui_utildlg.h" | |
39 #include "ui_tabcomp.h" | |
40 #include "ui_tree_edit.h" | |
41 | |
42 | |
43 #define DEST_WIDTH 250 | |
44 #define DEST_HEIGHT 210 | |
45 | |
46 #define RENAME_PRESS_DELAY 333 /* 1/3 second, to allow double clicks */ | |
47 | |
48 #define PATH_SEL_USE_HEADINGS FALSE | |
49 | |
50 enum { | |
51 FILTER_COLUMN_NAME = 0, | |
52 FILTER_COLUMN_FILTER | |
53 }; | |
54 | |
55 typedef struct _Dest_Data Dest_Data; | |
56 struct _Dest_Data | |
57 { | |
58 GtkWidget *d_view; | |
59 GtkWidget *f_view; | |
60 GtkWidget *entry; | |
61 gchar *filter; | |
62 gchar *path; | |
63 | |
64 GList *filter_list; | |
65 GList *filter_text_list; | |
66 GtkWidget *filter_combo; | |
67 | |
68 gint show_hidden; | |
69 GtkWidget *hidden_button; | |
70 | |
71 GtkWidget *bookmark_list; | |
72 | |
73 GtkTreePath *right_click_path; | |
74 | |
75 void (*select_func)(const gchar *path, gpointer data); | |
76 gpointer select_data; | |
77 | |
78 GenericDialog *gd; /* any open confirm dialogs ? */ | |
79 }; | |
80 | |
81 typedef struct _DestDel_Data DestDel_Data; | |
82 struct _DestDel_Data | |
83 { | |
84 Dest_Data *dd; | |
85 gchar *path; | |
86 }; | |
87 | |
88 | |
89 static void dest_view_delete_dlg_cancel(GenericDialog *gd, gpointer data); | |
90 | |
91 | |
92 /* | |
93 *----------------------------------------------------------------------------- | |
94 * (private) | |
95 *----------------------------------------------------------------------------- | |
96 */ | |
97 | |
98 static void dest_free_data(GtkWidget *widget, gpointer data) | |
99 { | |
100 Dest_Data *dd = data; | |
101 | |
102 if (dd->gd) | |
103 { | |
104 GenericDialog *gd = dd->gd; | |
105 dest_view_delete_dlg_cancel(dd->gd, dd->gd->data); | |
106 generic_dialog_close(gd); | |
107 } | |
108 if (dd->right_click_path) gtk_tree_path_free(dd->right_click_path); | |
109 | |
110 g_free(dd->filter); | |
111 g_free(dd->path); | |
112 g_free(dd); | |
113 } | |
114 | |
115 static gint dest_check_filter(const gchar *filter, const gchar *file) | |
116 { | |
117 const gchar *f_ptr = filter; | |
118 const gchar *strt_ptr; | |
119 gint i; | |
120 gint l; | |
121 | |
122 l = strlen(file); | |
123 | |
124 if (filter[0] == '*') return TRUE; | |
125 while (f_ptr < filter + strlen(filter)) | |
126 { | |
127 strt_ptr = f_ptr; | |
128 i=0; | |
129 while (*f_ptr != ';' && *f_ptr != '\0') | |
130 { | |
131 f_ptr++; | |
132 i++; | |
133 } | |
134 if (*f_ptr != '\0' && f_ptr[1] == ' ') f_ptr++; /* skip space immediately after separator */ | |
135 f_ptr++; | |
136 if (l >= i && strncasecmp(file + l - i, strt_ptr, i) == 0) return TRUE; | |
137 } | |
138 return FALSE; | |
139 } | |
140 | |
141 #ifndef CASE_SORT | |
142 #define CASE_SORT strcmp | |
143 #endif | |
144 | |
145 static gint dest_sort_cb(void *a, void *b) | |
146 { | |
147 return CASE_SORT((gchar *)a, (gchar *)b); | |
148 } | |
149 | |
150 static gint is_hidden(const gchar *name) | |
151 { | |
152 if (name[0] != '.') return FALSE; | |
153 if (name[1] == '\0') return FALSE; | |
154 if (name[1] == '.' && name[2] == '\0') return FALSE; | |
155 return TRUE; | |
156 } | |
157 | |
158 static void dest_populate(Dest_Data *dd, const gchar *path) | |
159 { | |
160 DIR *dp; | |
161 struct dirent *dir; | |
162 struct stat ent_sbuf; | |
163 GList *path_list = NULL; | |
164 GList *file_list = NULL; | |
165 GList *list; | |
166 GtkListStore *store; | |
167 gchar *pathl; | |
168 | |
42
606fcf461a68
Sat May 14 13:04:23 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
169 if (!path) return; |
9 | 170 |
171 pathl = path_from_utf8(path); | |
172 dp = opendir(pathl); | |
173 if (!dp) | |
174 { | |
175 /* dir not found */ | |
176 g_free(pathl); | |
177 return; | |
178 } | |
179 while ((dir = readdir(dp)) != NULL) | |
180 { | |
373
61a3c8b05b24
Add a new option in Preferences > Filtering to allow the
zas_
parents:
281
diff
changeset
|
181 if (!options->file_filter.show_dot_directory |
61a3c8b05b24
Add a new option in Preferences > Filtering to allow the
zas_
parents:
281
diff
changeset
|
182 && dir->d_name[0] == '.' && dir->d_name[1] == '\0') |
61a3c8b05b24
Add a new option in Preferences > Filtering to allow the
zas_
parents:
281
diff
changeset
|
183 continue; |
61a3c8b05b24
Add a new option in Preferences > Filtering to allow the
zas_
parents:
281
diff
changeset
|
184 if (dir->d_name[0] == '.' && dir->d_name[1] == '.' && dir->d_name[2] == '\0' |
61a3c8b05b24
Add a new option in Preferences > Filtering to allow the
zas_
parents:
281
diff
changeset
|
185 && pathl[0] == '/' && pathl[1] == '\0') |
61a3c8b05b24
Add a new option in Preferences > Filtering to allow the
zas_
parents:
281
diff
changeset
|
186 continue; /* no .. for root directory */ |
69
31759d770628
Fri Oct 13 10:27:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
187 if (dd->show_hidden || !is_hidden(dir->d_name)) |
9 | 188 { |
189 gchar *name = dir->d_name; | |
190 gchar *filepath = g_strconcat(pathl, "/", name, NULL); | |
191 if (stat(filepath, &ent_sbuf) >= 0 && S_ISDIR(ent_sbuf.st_mode)) | |
192 { | |
193 path_list = g_list_prepend(path_list, path_to_utf8(name)); | |
194 } | |
195 else if (dd->f_view) | |
196 { | |
197 if (!dd->filter || (dd->filter && dest_check_filter(dd->filter, name))) | |
198 file_list = g_list_prepend(file_list, path_to_utf8(name)); | |
199 } | |
200 g_free(filepath); | |
201 } | |
202 } | |
203 closedir(dp); | |
204 g_free(pathl); | |
205 | |
206 path_list = g_list_sort(path_list, (GCompareFunc) dest_sort_cb); | |
207 file_list = g_list_sort(file_list, (GCompareFunc) dest_sort_cb); | |
208 | |
209 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(dd->d_view))); | |
210 gtk_list_store_clear(store); | |
211 | |
212 list = path_list; | |
213 while (list) | |
214 { | |
215 GtkTreeIter iter; | |
216 gchar *filepath; | |
217 | |
218 if (strcmp(list->data, ".") == 0) | |
219 { | |
220 filepath = g_strdup(path); | |
221 } | |
222 else if (strcmp(list->data, "..") == 0) | |
223 { | |
224 gchar *p; | |
225 filepath = g_strdup(path); | |
226 p = (gchar *)filename_from_path(filepath); | |
227 if (p - 1 != filepath) p--; | |
228 p[0] = '\0'; | |
229 } | |
230 else | |
231 { | |
232 filepath = concat_dir_and_file(path, list->data); | |
233 } | |
234 | |
235 gtk_list_store_append(store, &iter); | |
236 gtk_list_store_set(store, &iter, 0, list->data, 1, filepath, -1); | |
237 | |
238 g_free(filepath); | |
239 list = list->next; | |
240 } | |
241 | |
242 path_list_free(path_list); | |
243 | |
244 | |
245 if (dd->f_view) | |
246 { | |
247 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(dd->f_view))); | |
248 gtk_list_store_clear(store); | |
249 | |
250 list = file_list; | |
251 while (list) | |
252 { | |
253 GtkTreeIter iter; | |
254 gchar *filepath; | |
255 const gchar *name = list->data; | |
256 | |
257 filepath = concat_dir_and_file(path, name); | |
258 | |
259 gtk_list_store_append(store, &iter); | |
260 gtk_list_store_set(store, &iter, 0, name, 1, filepath, -1); | |
261 | |
262 g_free(filepath); | |
263 list = list->next; | |
264 } | |
265 | |
266 path_list_free(file_list); | |
267 } | |
268 | |
269 g_free(dd->path); | |
270 dd->path = g_strdup(path); | |
271 } | |
272 | |
273 static void dest_change_dir(Dest_Data *dd, const gchar *path, gint retain_name) | |
274 { | |
275 gchar *old_name = NULL; | |
276 gint s = 0; | |
277 | |
278 if (retain_name) | |
279 { | |
280 const gchar *buf = gtk_entry_get_text(GTK_ENTRY(dd->entry)); | |
281 if (!isdir(buf)) | |
282 { | |
283 if (path && strcmp(path, "/") == 0) | |
284 { | |
285 old_name = g_strdup(filename_from_path(buf)); | |
286 } | |
287 else | |
288 { | |
289 old_name = g_strconcat("/", filename_from_path(buf), NULL); | |
290 s = 1; | |
291 } | |
292 } | |
293 } | |
294 | |
295 gtk_entry_set_text(GTK_ENTRY(dd->entry), path); | |
296 | |
297 dest_populate(dd, path); | |
298 | |
299 /* remember filename */ | |
300 if (old_name) | |
301 { | |
302 gint pos = -1; | |
303 gtk_editable_insert_text(GTK_EDITABLE(dd->entry), old_name, -1, &pos); | |
304 gtk_editable_select_region(GTK_EDITABLE(dd->entry), strlen(path) + s, strlen(path) + strlen(old_name)); | |
305 g_free(old_name); | |
306 } | |
307 } | |
308 | |
309 /* | |
310 *----------------------------------------------------------------------------- | |
311 * drag and drop | |
312 *----------------------------------------------------------------------------- | |
313 */ | |
314 | |
315 enum { | |
316 TARGET_URI_LIST, | |
317 TARGET_TEXT_PLAIN | |
318 }; | |
319 | |
320 static GtkTargetEntry dest_drag_types[] = { | |
321 { "text/uri-list", 0, TARGET_URI_LIST }, | |
322 { "text/plain", 0, TARGET_TEXT_PLAIN } | |
323 }; | |
324 #define dest_drag_types_n 2 | |
325 | |
326 | |
327 static void dest_dnd_set_data(GtkWidget *view, | |
328 GdkDragContext *context, GtkSelectionData *selection_data, | |
329 guint info, guint time, gpointer data) | |
330 { | |
331 gchar *path = NULL; | |
332 gchar *uri_text = NULL; | |
333 GList *list = NULL; | |
334 gint length = 0; | |
335 GtkTreeModel *model; | |
336 GtkTreeSelection *selection; | |
337 GtkTreeIter iter; | |
338 | |
339 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); | |
340 if (!gtk_tree_selection_get_selected(selection, &model, &iter)) return; | |
341 | |
342 gtk_tree_model_get(model, &iter, 1, &path, -1); | |
343 if (!path) return; | |
344 | |
345 list = g_list_append(list, path); | |
346 | |
347 switch (info) | |
348 { | |
349 case TARGET_URI_LIST: | |
350 uri_text = uri_text_from_list(list, &length, FALSE); | |
351 break; | |
352 case TARGET_TEXT_PLAIN: | |
353 uri_text = uri_text_from_list(list, &length, TRUE); | |
354 break; | |
355 } | |
356 | |
357 path_list_free(list); | |
358 | |
359 if (!uri_text) return; | |
360 | |
361 gtk_selection_data_set(selection_data, selection_data->target, | |
64
04ff0df3ad2f
Mon Aug 15 17:13:57 2005 John Ellis <johne@verizon.net>
gqview
parents:
42
diff
changeset
|
362 8, (guchar *)uri_text, length); |
9 | 363 g_free(uri_text); |
364 } | |
365 | |
366 static void dest_dnd_init(Dest_Data *dd) | |
367 { | |
368 gtk_tree_view_enable_model_drag_source(GTK_TREE_VIEW(dd->d_view), GDK_BUTTON1_MASK, | |
369 dest_drag_types, dest_drag_types_n, | |
370 GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK | GDK_ACTION_ASK); | |
371 g_signal_connect(G_OBJECT(dd->d_view), "drag_data_get", | |
372 G_CALLBACK(dest_dnd_set_data), dd); | |
373 | |
374 if (dd->f_view) | |
375 { | |
376 gtk_tree_view_enable_model_drag_source(GTK_TREE_VIEW(dd->f_view), GDK_BUTTON1_MASK, | |
377 dest_drag_types, dest_drag_types_n, | |
378 GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK | GDK_ACTION_ASK); | |
379 g_signal_connect(G_OBJECT(dd->f_view), "drag_data_get", | |
380 G_CALLBACK(dest_dnd_set_data), dd); | |
381 } | |
382 } | |
383 | |
384 | |
385 /* | |
386 *----------------------------------------------------------------------------- | |
387 * destination widget file management utils | |
388 *----------------------------------------------------------------------------- | |
389 */ | |
390 | |
391 static void dest_view_store_selection(Dest_Data *dd, GtkTreeView *view) | |
392 { | |
393 GtkTreeModel *model; | |
394 GtkTreeSelection *selection; | |
395 GtkTreeIter iter; | |
396 | |
397 if (dd->right_click_path) gtk_tree_path_free(dd->right_click_path); | |
398 dd->right_click_path = NULL; | |
399 | |
400 selection = gtk_tree_view_get_selection(view); | |
401 if (!gtk_tree_selection_get_selected(selection, &model, &iter)) | |
402 { | |
403 return; | |
404 } | |
405 | |
406 dd->right_click_path = gtk_tree_model_get_path(model, &iter); | |
407 } | |
408 | |
409 static gint dest_view_rename_cb(TreeEditData *ted, const gchar *old, const gchar *new, gpointer data) | |
410 { | |
411 Dest_Data *dd = data; | |
412 GtkTreeModel *model; | |
413 GtkTreeIter iter; | |
414 gchar *buf; | |
415 gchar *old_path; | |
416 gchar *new_path; | |
417 | |
418 model = gtk_tree_view_get_model(GTK_TREE_VIEW(ted->tree)); | |
419 gtk_tree_model_get_iter(model, &iter, dd->right_click_path); | |
420 | |
421 gtk_tree_model_get(model, &iter, 1, &old_path, -1); | |
422 if (!old_path) return FALSE; | |
423 | |
424 buf = remove_level_from_path(old_path); | |
425 new_path = concat_dir_and_file(buf, new); | |
426 g_free(buf); | |
427 | |
428 if (isname(new_path)) | |
429 { | |
430 buf = g_strdup_printf(_("A file with name %s already exists."), new); | |
431 warning_dialog("Rename failed", buf, GTK_STOCK_DIALOG_INFO, dd->entry); | |
432 g_free(buf); | |
433 } | |
434 else if (!rename_file(old_path, new_path)) | |
435 { | |
436 buf = g_strdup_printf(_("Failed to rename %s to %s."), old, new); | |
437 warning_dialog("Rename failed", buf, GTK_STOCK_DIALOG_ERROR, dd->entry); | |
438 g_free(buf); | |
439 } | |
440 else | |
441 { | |
442 const gchar *text; | |
443 | |
444 gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0, new, 1, new_path, -1); | |
445 | |
446 text = gtk_entry_get_text(GTK_ENTRY(dd->entry)); | |
447 if (text && old_path && strcmp(text, old_path) == 0) | |
448 { | |
449 gtk_entry_set_text(GTK_ENTRY(dd->entry), new_path); | |
450 } | |
451 } | |
452 | |
453 g_free(old_path); | |
454 g_free(new_path); | |
455 | |
456 return TRUE; | |
457 } | |
458 | |
459 static void dest_view_rename(Dest_Data *dd, GtkTreeView *view) | |
460 { | |
461 GtkTreeModel *model; | |
462 GtkTreeIter iter; | |
463 gchar *text; | |
464 | |
465 if (!dd->right_click_path) return; | |
466 | |
467 model = gtk_tree_view_get_model(view); | |
468 gtk_tree_model_get_iter(model, &iter, dd->right_click_path); | |
469 gtk_tree_model_get(model, &iter, 0, &text, -1); | |
470 | |
471 tree_edit_by_path(view, dd->right_click_path, 0, text, | |
472 dest_view_rename_cb, dd); | |
473 | |
474 g_free(text); | |
475 } | |
476 | |
477 static void dest_view_delete_dlg_cancel(GenericDialog *gd, gpointer data) | |
478 { | |
479 DestDel_Data *dl = data; | |
480 | |
481 dl->dd->gd = NULL; | |
482 g_free(dl->path); | |
483 g_free(dl); | |
484 } | |
485 | |
486 static void dest_view_delete_dlg_ok_cb(GenericDialog *gd, gpointer data) | |
487 { | |
488 DestDel_Data *dl = data; | |
489 | |
490 if (!unlink_file(dl->path)) | |
491 { | |
492 gchar *text = g_strdup_printf(_("Unable to delete file:\n%s"), dl->path); | |
493 warning_dialog(_("File deletion failed"), text, GTK_STOCK_DIALOG_WARNING, dl->dd->entry); | |
494 g_free(text); | |
495 } | |
496 else if (dl->dd->path) | |
497 { | |
498 /* refresh list */ | |
499 gchar *path = g_strdup(dl->dd->path); | |
500 dest_populate(dl->dd, path); | |
501 g_free(path); | |
502 } | |
503 | |
504 dest_view_delete_dlg_cancel(gd, data); | |
505 } | |
506 | |
507 static void dest_view_delete(Dest_Data *dd, GtkTreeView *view) | |
508 { | |
509 gchar *path; | |
510 gchar *text; | |
511 DestDel_Data *dl; | |
512 GtkTreeModel *model; | |
513 GtkTreeIter iter; | |
514 | |
515 if (view != GTK_TREE_VIEW(dd->f_view)) return; | |
516 if (!dd->right_click_path) return; | |
517 | |
518 model = gtk_tree_view_get_model(view); | |
519 gtk_tree_model_get_iter(model, &iter, dd->right_click_path); | |
520 gtk_tree_model_get(model, &iter, 1, &path, -1); | |
521 | |
522 if (!path) return; | |
523 | |
524 dl = g_new(DestDel_Data, 1); | |
525 dl->dd = dd; | |
526 dl->path = path; | |
527 | |
528 if (dd->gd) | |
529 { | |
530 GenericDialog *gd = dd->gd; | |
531 dest_view_delete_dlg_cancel(dd->gd, dd->gd->data); | |
532 generic_dialog_close(gd); | |
533 } | |
534 | |
254
9faf34f047b1
Make the wmclass value unique among the code by defining
zas_
parents:
138
diff
changeset
|
535 dd->gd = generic_dialog_new(_("Delete file"), GQ_WMCLASS, "dlg_confirm", |
9 | 536 dd->entry, TRUE, |
537 dest_view_delete_dlg_cancel, dl); | |
538 | |
539 generic_dialog_add_button(dd->gd, GTK_STOCK_DELETE, NULL, dest_view_delete_dlg_ok_cb, TRUE); | |
540 | |
541 text = g_strdup_printf(_("About to delete the file:\n %s"), path); | |
542 generic_dialog_add_message(dd->gd, GTK_STOCK_DIALOG_QUESTION, | |
543 _("Delete file"), text); | |
544 g_free(text); | |
545 | |
546 gtk_widget_show(dd->gd->dialog); | |
547 } | |
548 | |
549 static void dest_view_bookmark(Dest_Data *dd, GtkTreeView *view) | |
550 { | |
551 GtkTreeModel *model; | |
552 GtkTreeIter iter; | |
553 gchar *path; | |
554 | |
555 if (!dd->right_click_path) return; | |
556 | |
557 model = gtk_tree_view_get_model(view); | |
558 gtk_tree_model_get_iter(model, &iter, dd->right_click_path); | |
559 gtk_tree_model_get(model, &iter, 1, &path, -1); | |
560 | |
561 bookmark_list_add(dd->bookmark_list, filename_from_path(path), path); | |
562 g_free(path); | |
563 } | |
564 | |
565 static void dest_popup_dir_rename_cb(GtkWidget *widget, gpointer data) | |
566 { | |
567 Dest_Data *dd = data; | |
568 dest_view_rename(dd, GTK_TREE_VIEW(dd->d_view)); | |
569 } | |
570 | |
571 static void dest_popup_dir_bookmark_cb(GtkWidget *widget, gpointer data) | |
572 { | |
573 Dest_Data *dd = data; | |
574 dest_view_bookmark(dd, GTK_TREE_VIEW(dd->d_view)); | |
575 } | |
576 | |
577 static void dest_popup_file_rename_cb(GtkWidget *widget, gpointer data) | |
578 { | |
579 Dest_Data *dd = data; | |
580 dest_view_rename(dd, GTK_TREE_VIEW(dd->f_view)); | |
581 } | |
582 | |
583 static void dest_popup_file_delete_cb(GtkWidget *widget, gpointer data) | |
584 { | |
585 Dest_Data *dd = data; | |
586 dest_view_delete(dd, GTK_TREE_VIEW(dd->f_view)); | |
587 } | |
588 | |
589 static void dest_popup_file_bookmark_cb(GtkWidget *widget, gpointer data) | |
590 { | |
591 Dest_Data *dd = data; | |
592 dest_view_bookmark(dd, GTK_TREE_VIEW(dd->f_view)); | |
593 } | |
594 | |
595 static void dest_popup_position_cb(GtkMenu *menu, gint *x, gint *y, | |
596 gboolean *push_in, gpointer data) | |
597 { | |
598 Dest_Data *dd = data; | |
599 GtkTreeView *view; | |
600 gint cw, ch; | |
601 | |
602 view = g_object_get_data(G_OBJECT(menu), "active_view"); | |
603 | |
604 tree_view_get_cell_clamped(view, dd->right_click_path, 0, TRUE, x, y, &cw, &ch); | |
605 *y += ch; | |
606 popup_menu_position_clamp(menu, x, y, 0); | |
607 } | |
608 | |
609 static gint dest_popup_menu(Dest_Data *dd, GtkTreeView *view, | |
610 gint button, guint32 time, gint local) | |
611 { | |
612 GtkWidget *menu; | |
613 | |
614 if (!dd->right_click_path) return FALSE; | |
615 | |
616 if (view == GTK_TREE_VIEW(dd->d_view)) | |
617 { | |
618 GtkTreeModel *model; | |
619 GtkTreeIter iter; | |
620 gchar *text; | |
621 gint normal_dir; | |
622 | |
623 model = gtk_tree_view_get_model(view); | |
624 gtk_tree_model_get_iter(model, &iter, dd->right_click_path); | |
625 gtk_tree_model_get(model, &iter, 0, &text, -1); | |
626 | |
627 if (!text) return FALSE; | |
628 | |
629 normal_dir = (strcmp(text, ".") == 0 || strcmp(text, "..") == 0); | |
630 | |
631 menu = popup_menu_short_lived(); | |
632 menu_item_add_sensitive(menu, _("_Rename"), !normal_dir, | |
633 G_CALLBACK(dest_popup_dir_rename_cb), dd); | |
634 menu_item_add_stock(menu, _("Add _Bookmark"), GTK_STOCK_JUMP_TO, | |
635 G_CALLBACK(dest_popup_dir_bookmark_cb), dd); | |
636 } | |
637 else | |
638 { | |
639 menu = popup_menu_short_lived(); | |
640 menu_item_add(menu, _("_Rename"), | |
641 G_CALLBACK(dest_popup_file_rename_cb), dd); | |
642 menu_item_add_stock(menu, _("_Delete"), GTK_STOCK_DELETE, | |
643 G_CALLBACK(dest_popup_file_delete_cb), dd); | |
644 menu_item_add_stock(menu, _("Add _Bookmark"), GTK_STOCK_JUMP_TO, | |
645 G_CALLBACK(dest_popup_file_bookmark_cb), dd); | |
646 } | |
647 | |
648 if (local) | |
649 { | |
650 g_object_set_data(G_OBJECT(menu), "active_view", view); | |
651 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, | |
652 dest_popup_position_cb, dd, button, time); | |
653 } | |
654 else | |
655 { | |
656 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, button, time); | |
657 } | |
658 | |
659 return TRUE; | |
660 } | |
661 | |
662 static gint dest_press_cb(GtkWidget *view, GdkEventButton *event, gpointer data) | |
663 { | |
664 Dest_Data *dd = data; | |
665 GtkTreePath *tpath; | |
666 GtkTreeViewColumn *column; | |
667 gint cell_x, cell_y; | |
668 GtkTreeModel *model; | |
669 GtkTreeIter iter; | |
670 GtkTreeSelection *selection; | |
671 | |
672 if (event->button != 3 || | |
673 !gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(view), event->x, event->y, | |
674 &tpath, &column, &cell_x, &cell_y)) | |
675 { | |
676 return FALSE; | |
677 } | |
678 | |
679 model = gtk_tree_view_get_model(GTK_TREE_VIEW(view)); | |
680 gtk_tree_model_get_iter(model, &iter, tpath); | |
681 | |
682 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); | |
683 gtk_tree_selection_select_iter(selection, &iter); | |
684 | |
685 if (dd->right_click_path) gtk_tree_path_free(dd->right_click_path); | |
686 dd->right_click_path = tpath; | |
687 | |
688 return dest_popup_menu(dd, GTK_TREE_VIEW(view), 0, event->time, FALSE); | |
689 } | |
690 | |
691 static gboolean dest_keypress_cb(GtkWidget *view, GdkEventKey *event, gpointer data) | |
692 { | |
693 Dest_Data *dd = data; | |
694 | |
695 switch (event->keyval) | |
696 { | |
697 case GDK_F10: | |
698 if (!(event->state & GDK_CONTROL_MASK)) return FALSE; | |
699 case GDK_Menu: | |
700 dest_view_store_selection(dd, GTK_TREE_VIEW(view)); | |
701 dest_popup_menu(dd, GTK_TREE_VIEW(view), 0, event->time, TRUE); | |
702 return TRUE; | |
703 break; | |
704 case 'R': case 'r': | |
705 if (event->state & GDK_CONTROL_MASK) | |
706 { | |
707 dest_view_store_selection(dd, GTK_TREE_VIEW(view)); | |
708 dest_view_rename(dd, GTK_TREE_VIEW(view)); | |
709 return TRUE; | |
710 } | |
711 break; | |
712 case GDK_Delete: | |
713 dest_view_store_selection(dd, GTK_TREE_VIEW(view)); | |
714 dest_view_delete(dd, GTK_TREE_VIEW(view)); | |
715 return TRUE; | |
716 break; | |
717 case 'B' : case 'b': | |
718 if (event->state & GDK_CONTROL_MASK) | |
719 { | |
720 dest_view_store_selection(dd, GTK_TREE_VIEW(view)); | |
721 dest_view_bookmark(dd, GTK_TREE_VIEW(view)); | |
722 return TRUE; | |
723 } | |
724 break; | |
725 } | |
726 | |
727 return FALSE; | |
728 } | |
729 | |
730 static void dest_new_dir_cb(GtkWidget *widget, gpointer data) | |
731 { | |
732 Dest_Data *dd = data; | |
733 gchar *path; | |
734 gchar *buf; | |
735 const gchar *tmp; | |
736 gint from_text = FALSE; | |
737 | |
738 tmp = gtk_entry_get_text(GTK_ENTRY(dd->entry)); | |
739 if (!isname(tmp)) | |
740 { | |
741 path = g_strdup(tmp); | |
742 from_text = TRUE; | |
743 } | |
744 else | |
745 { | |
746 buf = concat_dir_and_file(dd->path, _("New folder")); | |
747 path = unique_filename(buf, NULL, " ", FALSE); | |
748 g_free(buf); | |
749 } | |
750 | |
751 if (!mkdir_utf8(path, 0755)) | |
752 { | |
753 /* failed */ | |
754 gchar *text; | |
755 | |
756 text = g_strdup_printf(_("Unable to create folder:\n%s"), filename_from_path(path)); | |
757 warning_dialog(_("Error creating folder"), text, GTK_STOCK_DIALOG_ERROR, dd->entry); | |
758 g_free(text); | |
759 } | |
760 else | |
761 { | |
762 GtkTreeIter iter; | |
763 GtkListStore *store; | |
764 const gchar *text; | |
765 | |
766 if (from_text) gtk_entry_set_text(GTK_ENTRY(dd->entry), dd->path); | |
767 | |
768 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(dd->d_view))); | |
769 | |
770 text = filename_from_path(path); | |
771 | |
772 gtk_list_store_append(store, &iter); | |
773 gtk_list_store_set(store, &iter, 0, text, 1, path, -1); | |
774 | |
775 if (dd->right_click_path) gtk_tree_path_free(dd->right_click_path); | |
776 dd->right_click_path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iter); | |
777 | |
778 tree_edit_by_path(GTK_TREE_VIEW(dd->d_view), dd->right_click_path, 0, text, | |
779 dest_view_rename_cb, dd); | |
780 } | |
781 | |
782 g_free(path); | |
783 } | |
784 | |
785 /* | |
786 *----------------------------------------------------------------------------- | |
787 * destination widget file selection, traversal, view options | |
788 *----------------------------------------------------------------------------- | |
789 */ | |
790 | |
791 static void dest_select_cb(GtkTreeSelection *selection, gpointer data) | |
792 { | |
793 Dest_Data *dd = data; | |
794 GtkTreeView *view; | |
795 GtkTreeModel *store; | |
796 GtkTreeIter iter; | |
797 gchar *path; | |
798 | |
799 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return; | |
800 | |
801 view = gtk_tree_selection_get_tree_view(selection); | |
802 store = gtk_tree_view_get_model(view); | |
803 gtk_tree_model_get(store, &iter, 1, &path, -1); | |
804 | |
805 if (view == GTK_TREE_VIEW(dd->d_view)) | |
806 { | |
807 dest_change_dir(dd, path, (dd->f_view != NULL)); | |
808 } | |
809 else | |
810 { | |
811 gtk_entry_set_text(GTK_ENTRY(dd->entry), path); | |
812 } | |
813 | |
814 g_free(path); | |
815 } | |
816 | |
817 static void dest_activate_cb(GtkWidget *view, GtkTreePath *tpath, GtkTreeViewColumn *column, gpointer data) | |
818 { | |
819 Dest_Data *dd = data; | |
820 GtkTreeModel *store; | |
821 GtkTreeIter iter; | |
822 gchar *path; | |
823 | |
824 store = gtk_tree_view_get_model(GTK_TREE_VIEW(view)); | |
825 gtk_tree_model_get_iter(store, &iter, tpath); | |
826 gtk_tree_model_get(store, &iter, 1, &path, -1); | |
827 | |
828 if (view == dd->d_view) | |
829 { | |
830 dest_change_dir(dd, path, (dd->f_view != NULL)); | |
831 } | |
832 else | |
833 { | |
834 if (dd->select_func) | |
835 { | |
836 dd->select_func(path, dd->select_data); | |
837 } | |
838 } | |
839 | |
840 g_free(path); | |
841 } | |
842 | |
843 static void dest_home_cb(GtkWidget *widget, gpointer data) | |
844 { | |
845 Dest_Data *dd = data; | |
846 | |
847 dest_change_dir(dd, homedir(), (dd->f_view != NULL)); | |
848 } | |
849 | |
850 static void dest_show_hidden_cb(GtkWidget *widget, gpointer data) | |
851 { | |
852 Dest_Data *dd = data; | |
853 gchar *buf; | |
854 | |
855 dd->show_hidden = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dd->hidden_button)); | |
856 | |
857 buf = g_strdup(dd->path); | |
858 dest_populate(dd, buf); | |
859 g_free(buf); | |
860 } | |
861 | |
862 static void dest_entry_changed_cb(GtkEditable *editable, gpointer data) | |
863 { | |
864 Dest_Data *dd = data; | |
865 const gchar *path; | |
866 gchar *buf; | |
867 | |
868 path = gtk_entry_get_text(GTK_ENTRY(dd->entry)); | |
42
606fcf461a68
Sat May 14 13:04:23 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
869 if (dd->path && strcmp(path, dd->path) == 0) return; |
9 | 870 |
871 buf = remove_level_from_path(path); | |
872 | |
42
606fcf461a68
Sat May 14 13:04:23 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
873 if (buf && (!dd->path || strcmp(buf, dd->path) != 0)) |
9 | 874 { |
875 gchar *tmp = remove_trailing_slash(path); | |
876 if (isdir(tmp)) | |
877 { | |
878 dest_populate(dd, tmp); | |
879 } | |
880 else if (isdir(buf)) | |
881 { | |
882 dest_populate(dd, buf); | |
883 } | |
884 g_free(tmp); | |
885 } | |
886 g_free(buf); | |
887 } | |
888 | |
889 static void dest_filter_list_sync(Dest_Data *dd) | |
890 { | |
891 GtkWidget *entry; | |
892 GtkListStore *store; | |
893 gchar *old_text; | |
894 GList *fwork; | |
895 GList *twork; | |
896 | |
897 if (!dd->filter_list || !dd->filter_combo) return; | |
898 | |
899 entry = GTK_BIN(dd->filter_combo)->child; | |
900 old_text = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry))); | |
901 | |
902 store = GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(dd->filter_combo))); | |
903 gtk_list_store_clear(store); | |
904 | |
905 fwork = dd->filter_list; | |
906 twork = dd->filter_text_list; | |
907 while (fwork && twork) | |
908 { | |
909 GtkTreeIter iter; | |
910 gchar *name; | |
911 gchar *filter; | |
912 | |
913 name = twork->data; | |
914 filter = fwork->data; | |
915 | |
916 gtk_list_store_append(store, &iter); | |
917 gtk_list_store_set(store, &iter, FILTER_COLUMN_NAME, name, | |
918 FILTER_COLUMN_FILTER, filter, -1); | |
919 | |
920 if (strcmp(old_text, filter) == 0) | |
921 { | |
922 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(dd->filter_combo), &iter); | |
923 } | |
924 | |
925 fwork = fwork->next; | |
926 twork = twork->next; | |
927 } | |
928 | |
929 g_free(old_text); | |
930 } | |
931 | |
932 static void dest_filter_add(Dest_Data *dd, const gchar *filter, const gchar *description, gint set) | |
933 { | |
934 GList *work; | |
935 gchar *buf; | |
936 gint c = 0; | |
937 | |
938 if (!filter) return; | |
939 | |
940 work = dd->filter_list; | |
941 while (work) | |
942 { | |
943 gchar *f = work->data; | |
944 | |
945 if (strcmp(f, filter) == 0) | |
946 { | |
947 if (set) gtk_combo_box_set_active(GTK_COMBO_BOX(dd->filter_combo), c); | |
948 return; | |
949 } | |
950 work = work->next; | |
951 c++; | |
952 } | |
953 | |
954 dd->filter_list = uig_list_insert_link(dd->filter_list, g_list_last(dd->filter_list), g_strdup(filter)); | |
955 | |
956 if (description) | |
957 { | |
958 buf = g_strdup_printf("%s ( %s )", description, filter); | |
959 } | |
960 else | |
961 { | |
962 buf = g_strdup_printf("( %s )", filter); | |
963 } | |
964 dd->filter_text_list = uig_list_insert_link(dd->filter_text_list, g_list_last(dd->filter_text_list), buf); | |
965 | |
966 if (set) gtk_entry_set_text(GTK_ENTRY(GTK_BIN(dd->filter_combo)->child), filter); | |
967 dest_filter_list_sync(dd); | |
968 } | |
969 | |
970 static void dest_filter_clear(Dest_Data *dd) | |
971 { | |
972 path_list_free(dd->filter_list); | |
973 dd->filter_list = NULL; | |
974 | |
975 path_list_free(dd->filter_text_list); | |
976 dd->filter_text_list = NULL; | |
977 | |
978 dest_filter_add(dd, "*", _("All Files"), TRUE); | |
979 } | |
980 | |
981 static void dest_filter_changed_cb(GtkEditable *editable, gpointer data) | |
982 { | |
983 Dest_Data *dd = data; | |
984 GtkWidget *entry; | |
985 const gchar *buf; | |
986 gchar *path; | |
987 | |
988 entry = GTK_BIN(dd->filter_combo)->child; | |
989 buf = gtk_entry_get_text(GTK_ENTRY(entry)); | |
990 | |
991 g_free(dd->filter); | |
992 dd->filter = NULL; | |
993 if (strlen(buf) > 0) dd->filter = g_strdup(buf); | |
994 | |
995 path = g_strdup(dd->path); | |
996 dest_populate(dd, path); | |
997 g_free(path); | |
998 } | |
999 | |
1000 static void dest_bookmark_select_cb(const gchar *path, gpointer data) | |
1001 { | |
1002 Dest_Data *dd = data; | |
1003 | |
1004 if (isdir(path)) | |
1005 { | |
1006 dest_change_dir(dd, path, (dd->f_view != NULL)); | |
1007 } | |
1008 else if (isfile(path) && dd->f_view) | |
1009 { | |
1010 gtk_entry_set_text(GTK_ENTRY(dd->entry), path); | |
1011 } | |
1012 } | |
1013 | |
1014 /* | |
1015 *----------------------------------------------------------------------------- | |
1016 * destination widget setup routines (public) | |
1017 *----------------------------------------------------------------------------- | |
1018 */ | |
1019 | |
1020 GtkWidget *path_selection_new_with_files(GtkWidget *entry, const gchar *path, | |
1021 const gchar *filter, const gchar *filter_desc) | |
1022 { | |
1023 GtkWidget *hbox2; | |
1024 Dest_Data *dd; | |
1025 GtkWidget *scrolled; | |
1026 GtkWidget *table; | |
1027 GtkWidget *paned; | |
1028 GtkListStore *store; | |
1029 GtkTreeSelection *selection; | |
1030 GtkTreeViewColumn *column; | |
1031 GtkCellRenderer *renderer; | |
1032 | |
1033 dd = g_new0(Dest_Data, 1); | |
1034 dd->show_hidden = FALSE; | |
1035 dd->select_func = NULL; | |
1036 dd->select_data = NULL; | |
1037 dd->gd = NULL; | |
1038 | |
1039 table = gtk_table_new(4, (filter != NULL) ? 3 : 1, FALSE); | |
1040 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP); | |
1041 gtk_table_set_row_spacing(GTK_TABLE(table), 0, PREF_PAD_GAP); | |
1042 gtk_widget_show(table); | |
1043 | |
1044 dd->entry = entry; | |
1045 g_object_set_data(G_OBJECT(dd->entry), "destination_data", dd); | |
1046 | |
1047 hbox2 = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL); | |
1048 gtk_box_set_spacing(GTK_BOX(hbox2), PREF_PAD_BUTTON_GAP); | |
1049 pref_button_new(hbox2, NULL, _("Home"), FALSE, | |
1050 G_CALLBACK(dest_home_cb), dd); | |
1051 pref_button_new(hbox2, NULL, _("New folder"), FALSE, | |
1052 G_CALLBACK(dest_new_dir_cb), dd); | |
1053 | |
1054 dd->hidden_button = gtk_check_button_new_with_label(_("Show hidden")); | |
1055 g_signal_connect(G_OBJECT(dd->hidden_button), "clicked", | |
1056 G_CALLBACK(dest_show_hidden_cb), dd); | |
1057 gtk_box_pack_end(GTK_BOX(hbox2), dd->hidden_button, FALSE, FALSE, 0); | |
1058 gtk_widget_show(dd->hidden_button); | |
1059 | |
1060 hbox2 = gtk_hbox_new(FALSE, PREF_PAD_GAP); | |
1061 if (filter) | |
1062 { | |
1063 paned = gtk_hpaned_new(); | |
1064 gtk_table_attach(GTK_TABLE(table), paned, 0, 3, 1, 2, | |
1065 GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); | |
1066 gtk_widget_show(paned); | |
1067 gtk_paned_add1(GTK_PANED(paned), hbox2); | |
1068 } | |
1069 else | |
1070 { | |
1071 paned = NULL; | |
1072 gtk_table_attach(GTK_TABLE(table), hbox2, 0, 1, 1, 2, | |
1073 GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); | |
1074 } | |
1075 gtk_widget_show(hbox2); | |
1076 | |
1077 /* bookmarks */ | |
1078 scrolled = bookmark_list_new(NULL, dest_bookmark_select_cb, dd); | |
1079 gtk_box_pack_start(GTK_BOX(hbox2), scrolled, FALSE, FALSE, 0); | |
1080 gtk_widget_show(scrolled); | |
1081 | |
1082 dd->bookmark_list = scrolled; | |
1083 | |
1084 scrolled = gtk_scrolled_window_new(NULL, NULL); | |
1085 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN); | |
1086 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), | |
1087 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); | |
1088 gtk_box_pack_start(GTK_BOX(hbox2), scrolled, TRUE, TRUE, 0); | |
1089 gtk_widget_show(scrolled); | |
1090 | |
1091 store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING); | |
1092 dd->d_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); | |
1093 g_object_unref(store); | |
1094 | |
1095 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(dd->d_view), PATH_SEL_USE_HEADINGS); | |
1096 | |
1097 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dd->d_view)); | |
1098 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE); | |
1099 | |
1100 column = gtk_tree_view_column_new(); | |
1101 gtk_tree_view_column_set_title(column, _("Folders")); | |
1102 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); | |
1103 | |
1104 renderer = gtk_cell_renderer_text_new(); | |
1105 gtk_tree_view_column_pack_start(column, renderer, TRUE); | |
1106 gtk_tree_view_column_add_attribute(column, renderer, "text", 0); | |
1107 | |
1108 gtk_tree_view_append_column(GTK_TREE_VIEW(dd->d_view), column); | |
1109 | |
1110 #if 0 | |
1111 /* only for debugging */ | |
1112 column = gtk_tree_view_column_new(); | |
1113 gtk_tree_view_column_set_title(column, _("Path")); | |
1114 renderer = gtk_cell_renderer_text_new(); | |
1115 gtk_tree_view_column_pack_start(column, renderer, TRUE); | |
1116 gtk_tree_view_column_add_attribute(column, renderer, "text", 1); | |
1117 gtk_tree_view_append_column(GTK_TREE_VIEW(dd->d_view), column); | |
1118 #endif | |
1119 | |
1120 gtk_widget_set_size_request(dd->d_view, DEST_WIDTH, DEST_HEIGHT); | |
1121 gtk_container_add(GTK_CONTAINER(scrolled), dd->d_view); | |
1122 gtk_widget_show(dd->d_view); | |
1123 | |
1124 g_signal_connect(G_OBJECT(dd->d_view), "button_press_event", | |
1125 G_CALLBACK(dest_press_cb), dd); | |
1126 g_signal_connect(G_OBJECT(dd->d_view), "key_press_event", | |
1127 G_CALLBACK(dest_keypress_cb), dd); | |
1128 g_signal_connect(G_OBJECT(dd->d_view), "row_activated", | |
1129 G_CALLBACK(dest_activate_cb), dd); | |
1130 g_signal_connect(G_OBJECT(dd->d_view), "destroy", | |
1131 G_CALLBACK(dest_free_data), dd); | |
1132 | |
1133 if (filter) | |
1134 { | |
1135 GtkListStore *store; | |
1136 | |
1137 hbox2 = pref_table_box(table, 2, 0, GTK_ORIENTATION_HORIZONTAL, NULL); | |
1138 pref_label_new(hbox2, _("Filter:")); | |
1139 | |
1140 store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING); | |
1141 | |
1142 dd->filter_combo = gtk_combo_box_entry_new_with_model(GTK_TREE_MODEL(store), | |
1143 FILTER_COLUMN_FILTER); | |
1144 g_object_unref(store); | |
1145 gtk_cell_layout_clear(GTK_CELL_LAYOUT(dd->filter_combo)); | |
1146 renderer = gtk_cell_renderer_text_new(); | |
1147 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(dd->filter_combo), renderer, TRUE); | |
1148 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(dd->filter_combo), renderer, | |
1149 "text", FILTER_COLUMN_NAME, NULL); | |
1150 #if 0 | |
1151 gtk_combo_set_case_sensitive(GTK_COMBO(dd->filter_combo), TRUE); | |
1152 #endif | |
1153 gtk_box_pack_start(GTK_BOX(hbox2), dd->filter_combo, TRUE, TRUE, 0); | |
1154 gtk_widget_show(dd->filter_combo); | |
1155 | |
1156 scrolled = gtk_scrolled_window_new(NULL, NULL); | |
1157 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN); | |
1158 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), | |
1159 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); | |
1160 if (paned) | |
1161 { | |
1162 gtk_paned_add2(GTK_PANED(paned), scrolled); | |
1163 } | |
1164 else | |
1165 { | |
1166 gtk_table_attach(GTK_TABLE(table), scrolled, 2, 3, 1, 2, | |
1167 GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); | |
1168 } | |
1169 gtk_widget_show(scrolled); | |
1170 | |
1171 store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING); | |
1172 dd->f_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); | |
1173 g_object_unref(store); | |
1174 | |
1175 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(dd->f_view), PATH_SEL_USE_HEADINGS); | |
1176 | |
1177 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dd->f_view)); | |
1178 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE); | |
1179 | |
1180 column = gtk_tree_view_column_new(); | |
1181 gtk_tree_view_column_set_title(column, _("Files")); | |
1182 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); | |
1183 | |
1184 renderer = gtk_cell_renderer_text_new(); | |
1185 gtk_tree_view_column_pack_start(column, renderer, TRUE); | |
1186 gtk_tree_view_column_add_attribute(column, renderer, "text", 0); | |
1187 | |
1188 gtk_tree_view_append_column(GTK_TREE_VIEW(dd->f_view), column); | |
1189 | |
1190 gtk_widget_set_size_request(dd->f_view, DEST_WIDTH, DEST_HEIGHT); | |
1191 gtk_container_add(GTK_CONTAINER(scrolled), dd->f_view); | |
1192 gtk_widget_show(dd->f_view); | |
1193 | |
1194 g_signal_connect(G_OBJECT(dd->f_view), "button_press_event", | |
1195 G_CALLBACK(dest_press_cb), dd); | |
1196 g_signal_connect(G_OBJECT(dd->f_view), "key_press_event", | |
1197 G_CALLBACK(dest_keypress_cb), dd); | |
1198 g_signal_connect(G_OBJECT(dd->f_view), "row_activated", | |
1199 G_CALLBACK(dest_activate_cb), dd); | |
1200 g_signal_connect(selection, "changed", | |
1201 G_CALLBACK(dest_select_cb), dd); | |
1202 | |
1203 dest_filter_clear(dd); | |
1204 dest_filter_add(dd, filter, filter_desc, TRUE); | |
1205 | |
1206 dd->filter = g_strdup(gtk_entry_get_text(GTK_ENTRY(GTK_BIN(dd->filter_combo)->child))); | |
1207 } | |
1208 | |
1209 if (path && path[0] == '/' && isdir(path)) | |
1210 { | |
1211 dest_populate(dd, path); | |
1212 } | |
1213 else | |
1214 { | |
1215 gchar *buf = remove_level_from_path(path); | |
1216 if (buf && buf[0] == '/' && isdir(buf)) | |
1217 { | |
1218 dest_populate(dd, buf); | |
1219 } | |
1220 else | |
1221 { | |
1222 gint pos = -1; | |
1223 | |
1224 dest_populate(dd, (gchar *)homedir()); | |
1225 if (path) gtk_editable_insert_text(GTK_EDITABLE(dd->entry), "/", -1, &pos); | |
1226 if (path) gtk_editable_insert_text(GTK_EDITABLE(dd->entry), path, -1, &pos); | |
1227 } | |
1228 g_free(buf); | |
1229 } | |
1230 | |
1231 if (dd->filter_combo) | |
1232 { | |
1233 g_signal_connect(G_OBJECT(GTK_BIN(dd->filter_combo)->child), "changed", | |
1234 G_CALLBACK(dest_filter_changed_cb), dd); | |
1235 } | |
1236 g_signal_connect(G_OBJECT(dd->entry), "changed", | |
1237 G_CALLBACK(dest_entry_changed_cb), dd); | |
1238 | |
1239 dest_dnd_init(dd); | |
1240 | |
1241 return table; | |
1242 } | |
1243 | |
1244 GtkWidget *path_selection_new(const gchar *path, GtkWidget *entry) | |
1245 { | |
1246 return path_selection_new_with_files(entry, path, NULL, NULL); | |
1247 } | |
1248 | |
1249 void path_selection_sync_to_entry(GtkWidget *entry) | |
1250 { | |
1251 Dest_Data *dd = g_object_get_data(G_OBJECT(entry), "destination_data"); | |
1252 const gchar *path; | |
1253 | |
1254 if (!dd) return; | |
1255 | |
1256 path = gtk_entry_get_text(GTK_ENTRY(entry)); | |
1257 | |
42
606fcf461a68
Sat May 14 13:04:23 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
1258 if (isdir(path) && (!dd->path || strcmp(path, dd->path) != 0)) |
9 | 1259 { |
1260 dest_populate(dd, path); | |
1261 } | |
1262 else | |
1263 { | |
1264 gchar *buf = remove_level_from_path(path); | |
42
606fcf461a68
Sat May 14 13:04:23 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
1265 if (isdir(buf) && (!dd->path || strcmp(buf, dd->path) != 0)) |
9 | 1266 { |
1267 dest_populate(dd, buf); | |
1268 } | |
1269 g_free(buf); | |
1270 } | |
1271 } | |
1272 | |
1273 void path_selection_add_select_func(GtkWidget *entry, | |
1274 void (*func)(const gchar *, gpointer), gpointer data) | |
1275 { | |
1276 Dest_Data *dd = g_object_get_data(G_OBJECT(entry), "destination_data"); | |
1277 | |
1278 if (!dd) return; | |
1279 | |
1280 dd->select_func = func; | |
1281 dd->select_data = data; | |
1282 } | |
1283 | |
1284 void path_selection_add_filter(GtkWidget *entry, const gchar *filter, const gchar *description, gint set) | |
1285 { | |
1286 Dest_Data *dd = g_object_get_data(G_OBJECT(entry), "destination_data"); | |
1287 | |
1288 if (!dd) return; | |
1289 if (!filter) return; | |
1290 | |
1291 dest_filter_add(dd, filter, description, set); | |
1292 } | |
1293 | |
1294 void path_selection_clear_filter(GtkWidget *entry) | |
1295 { | |
1296 Dest_Data *dd = g_object_get_data(G_OBJECT(entry), "destination_data"); | |
1297 | |
1298 if (!dd) return; | |
1299 | |
1300 dest_filter_clear(dd); | |
1301 } | |
1302 |