1 /* gtkiconfileselection - gtkiconfileselection dialog widget for gtk+
2 * Copyright 1999-2001 Adrian E. Feiguin <feiguin@ifir.edu.ar>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 */
19
20 /**
21 * SECTION: gtkiconfilesel
22 * @short_description: A file selection dialog widget for GTK.
23 *
24 * It is a nice looking file selection dialog using icons.
25 * It combines GtkDirTree and GtkFileList to navigate the file system and select files.
26 * It has also two entries to select the file and filter.
27 */
28
29 /**
30 * GtkIconFileSelection:
31 *
32 * The GtkIconFileSelection structure contains only private data.
33 * It should only be accessed through the functions described below.
34 */
35
36 #include "config.h"
37 #include <gtk/gtk.h>
38 #include <gdk/gdkkeysyms.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41
42 #ifdef HAVE_UNISTD_H
43 # include <unistd.h>
44 #endif
45
46 #ifdef HAVE_DIRENT_H
47 # include <dirent.h>
48 #endif
49
50 #include <string.h>
51 #include <stdio.h>
52 #include <stdlib.h>
53
54 #include "gtkextra-compat.h"
55 #include "gtkiconfilesel.h"
56 #include "gtkextraicons.h"
57
58 #ifndef MAXHOSTNAMELEN
59 # define MAXHOSTNAMELEN 64
60 #endif
61
62 #ifndef MAXPATHLEN
63 # define MAXPATHLEN 1024
64 #endif
65
66 static void gtk_icon_file_selection_class_init (GtkIconFileSelClass *klass);
67 static void gtk_icon_file_selection_init (GtkIconFileSel *filesel);
68 static void gtk_icon_file_selection_destroy (GtkObject *object);
69 static void open_dir (GtkWidget *widget,
70 GtkCTreeNode *node,
71 gint n,
72 gpointer data);
73 static gboolean entry_set_file (GtkWidget *widget,
74 GdkEventKey *key,
75 gpointer data);
76 static void real_set_file (GtkWidget *widget,
77 gpointer data);
78 static gboolean set_filter (GtkWidget *widget,
79 GdkEventKey *key,
80 gpointer data);
81 static gboolean select_icon (GtkIconList *iconlist,
82 GtkIconListItem *icon,
83 GdkEvent *event,
84 gpointer data);
85 static gboolean insert_text (GtkEditable *editable,
86 const gchar *new_text,
87 gint new_text_length,
88 gint *position,
89 gpointer data);
90 static void init_history_combo (GtkIconFileSel *filesel,
91 const gchar *curr_dir);
92 static void update_history_combo (GtkIconFileSel *filesel,
93 const gchar *curr_dir);
94 static void go_to_history (const gchar *path,
95 gpointer data);
96 static gboolean combo_changed (GtkWidget *widget,
97 gpointer data);
98 static gboolean entry_key_press (GtkWidget *widget,
99 GdkEventKey *event,
100 gpointer data);
101 static gchar *get_real_path (const gchar *full_path);
102
103 static GtkWindowClass *parent_class = NULL;
104
105
106 GType
gtk_icon_file_selection_get_type(void)107 gtk_icon_file_selection_get_type (void)
108 {
109 static GType filesel_type = 0;
110
111 if (!filesel_type)
112 {
113 filesel_type = g_type_register_static_simple (
114 gtk_window_get_type(),
115 "GtkIconFileSel",
116 sizeof (GtkIconFileSelClass),
117 (GClassInitFunc) gtk_icon_file_selection_class_init,
118 sizeof (GtkIconFileSel),
119 (GInstanceInitFunc) gtk_icon_file_selection_init,
120 0);
121 }
122
123 return filesel_type;
124 }
125
126 GtkWidget*
gtk_icon_file_selection_new(const gchar * title)127 gtk_icon_file_selection_new (const gchar *title)
128 {
129 GtkWidget *widget;
130
131 widget = gtk_widget_new (gtk_icon_file_selection_get_type(), NULL);
132
133 gtk_icon_file_selection_construct(GTK_ICON_FILESEL(widget), title);
134
135 return widget;
136 }
137
138 /**
139 * gtk_icon_file_selection_construct:
140 * @filesel: the #GtkIconFileSelection widget.
141 * @title: window title.
142 *
143 * Sets the window title for #GtkIconFileSelection widget.
144 */
145 void
gtk_icon_file_selection_construct(GtkIconFileSel * filesel,const gchar * title)146 gtk_icon_file_selection_construct (GtkIconFileSel *filesel, const gchar *title)
147 {
148 /* GTK_ICON_FILESEL(widget)->title = g_strdup(title);
149 */
150 gtk_window_set_title(GTK_WINDOW(filesel),title);
151 }
152
153 static void
gtk_icon_file_selection_class_init(GtkIconFileSelClass * klass)154 gtk_icon_file_selection_class_init (GtkIconFileSelClass *klass)
155 {
156 GtkWidgetClass *widget_class;
157 GtkObjectClass *object_class;
158
159 widget_class = (GtkWidgetClass*) klass;
160 object_class = (GtkObjectClass*) klass;
161 parent_class = g_type_class_ref (gtk_window_get_type ());
162
163 object_class->destroy = gtk_icon_file_selection_destroy;
164 }
165
166 static void
up_clicked(GtkWidget * widget,gpointer data)167 up_clicked(GtkWidget *widget, gpointer data)
168 {
169 GtkIconFileSel *filesel = GTK_ICON_FILESEL(widget);
170 gchar *current_dir;
171 gint dir_len;
172 gint i;
173
174 current_dir = g_strdup (GTK_FILE_LIST(filesel->file_list)->path);
175 dir_len = strlen (current_dir);
176
177 for (i = dir_len - 1; i >= 0; i--){
178
179 /* the i == dir_len is to catch the full path for the first
180 * entry. */
181 if ( current_dir[i] == G_DIR_SEPARATOR ) {
182 current_dir[i + 1] = '\0';
183 gtk_icon_file_selection_open_dir(filesel, current_dir);
184 break;
185 }
186 }
187
188 g_free(current_dir);
189 }
190
191 static void
refresh_clicked(GtkWidget * widget,gpointer data)192 refresh_clicked(GtkWidget *widget, gpointer data)
193 {
194 GtkIconFileSel *filesel = GTK_ICON_FILESEL(widget);
195 gtk_icon_file_selection_open_dir(filesel, GTK_FILE_LIST(filesel->file_list)->path);
196 }
197
198 static void
home_clicked(GtkWidget * widget,gpointer data)199 home_clicked(GtkWidget *widget, gpointer data)
200 {
201 GtkIconFileSel *filesel = GTK_ICON_FILESEL(widget);
202
203 gtk_icon_file_selection_open_dir(filesel, g_get_home_dir());
204 }
205
206
207 static void
gtk_icon_file_selection_init(GtkIconFileSel * filesel)208 gtk_icon_file_selection_init (GtkIconFileSel *filesel)
209 {
210 GtkWidget *main_vbox;
211 GtkWidget *hbox, *box;
212 GtkWidget *table;
213 GtkWidget *label;
214 GtkWidget *scrolled_window;
215 GtkWidget *wpixmap;
216 GtkTooltips *tp;
217 GdkPixmap *pixmap;
218 GdkBitmap *mask;
219 gchar cwd_path[2*MAXPATHLEN] = "";
220 gchar path[2*MAXPATHLEN] = "";
221 GdkColormap *colormap = gtk_widget_get_colormap(GTK_WIDGET(filesel));
222
223 filesel->show_tree = FALSE;
224
225 /* We don't use getcwd() on SUNOS, because, it does a popen("pwd")
226 * and, if that wasn't bad enough, hangs in doing so.
227 */
228 #if defined(sun) && !defined(__SVR4)
229 getwd (cwd_path);
230 #else
231 getcwd (cwd_path, MAXPATHLEN);
232 #endif
233 g_snprintf(path, MAXPATHLEN, "%s%s", cwd_path, G_DIR_SEPARATOR_S);
234
235 gtk_window_set_resizable(GTK_WINDOW(filesel), FALSE);
236 gtk_container_set_border_width (GTK_CONTAINER (filesel), 10);
237
238 main_vbox=gtk_vbox_new(FALSE,1);
239 gtk_container_set_border_width(GTK_CONTAINER(main_vbox),0);
240 gtk_container_add(GTK_CONTAINER(filesel), main_vbox);
241 gtk_widget_show(main_vbox);
242
243 hbox = gtk_hbox_new(FALSE, 1);
244 gtk_box_pack_start(GTK_BOX(main_vbox), hbox, FALSE, TRUE, 0);
245 gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new ("Go to: "), FALSE, FALSE, 0);
246 filesel->history_combo = gtk_combo_box_entry_new_text();
247 gtk_box_pack_start(GTK_BOX(hbox), filesel->history_combo, TRUE, TRUE, 0);
248 init_history_combo(filesel, path);
249 gtk_widget_show_all(hbox);
250
251 /* RRR */
252 g_signal_connect(GTK_OBJECT(GTK_COMBO_BOX(filesel->history_combo)),
253 "key_press_event",
254 (void *)entry_key_press, filesel);
255
256 g_signal_connect(GTK_OBJECT(GTK_COMBO_BOX(filesel->history_combo)),
257 "changed",
258 (void *)combo_changed, filesel);
259
260 filesel->up_button = gtk_button_new();
261 pixmap = gdk_pixmap_colormap_create_from_xpm_d(NULL, colormap, &mask, NULL,
262 up_xpm);
263 wpixmap = gtk_image_new_from_pixmap(pixmap, mask);
264 gdk_pixmap_unref(pixmap);
265 gdk_bitmap_unref(mask);
266
267 gtk_container_add(GTK_CONTAINER(filesel->up_button), wpixmap);
268 gtk_box_pack_start(GTK_BOX(hbox), filesel->up_button, FALSE, FALSE, 0);
269 gtk_widget_show_all(filesel->up_button);
270 g_signal_connect_swapped(GTK_OBJECT(filesel->up_button), "clicked",
271 (void *)up_clicked,
272 GTK_OBJECT(filesel));
273 tp = gtk_tooltips_new();
274 gtk_tooltips_set_tip(GTK_TOOLTIPS(tp), filesel->up_button, "Parent directory", "Parent directory");
275 gtk_tooltips_enable(GTK_TOOLTIPS(tp));
276
277 filesel->home_button = gtk_button_new();
278 pixmap = gdk_pixmap_colormap_create_from_xpm_d(NULL, colormap, &mask, NULL,
279 home_xpm);
280 wpixmap = gtk_image_new_from_pixmap(pixmap, mask);
281 gdk_pixmap_unref(pixmap);
282 gdk_bitmap_unref(mask);
283
284 gtk_container_add(GTK_CONTAINER(filesel->home_button), wpixmap);
285 gtk_box_pack_start(GTK_BOX(hbox), filesel->home_button, FALSE, FALSE, 0);
286 gtk_widget_show_all(filesel->home_button);
287 g_signal_connect_swapped(GTK_OBJECT(filesel->home_button), "clicked",
288 (void *)home_clicked,
289 GTK_OBJECT(filesel));
290 tp = gtk_tooltips_new();
291 gtk_tooltips_set_tip(GTK_TOOLTIPS(tp), filesel->home_button, "Home", "Home");
292 gtk_tooltips_enable(GTK_TOOLTIPS(tp));
293
294 filesel->refresh_button = gtk_button_new();
295 pixmap = gdk_pixmap_colormap_create_from_xpm_d(NULL, colormap, &mask, NULL,
296 refresh_xpm);
297 wpixmap = gtk_image_new_from_pixmap(pixmap, mask);
298 gdk_pixmap_unref(pixmap);
299 gdk_bitmap_unref(mask);
300
301 gtk_container_add(GTK_CONTAINER(filesel->refresh_button), wpixmap);
302 gtk_box_pack_start(GTK_BOX(hbox), filesel->refresh_button, FALSE, FALSE, 0);
303 gtk_widget_show_all(filesel->refresh_button);
304 g_signal_connect_swapped(GTK_OBJECT(filesel->refresh_button), "clicked",
305 (void *)refresh_clicked,
306 GTK_OBJECT(filesel));
307 tp = gtk_tooltips_new();
308 gtk_tooltips_set_tip(GTK_TOOLTIPS(tp), filesel->refresh_button, "Refresh", "Refresh");
309 gtk_tooltips_enable(GTK_TOOLTIPS(tp));
310
311 filesel->path_label = gtk_label_new(path);
312 gtk_misc_set_alignment(GTK_MISC(filesel->path_label), 0., .5);
313 gtk_box_pack_start(GTK_BOX(main_vbox), filesel->path_label, FALSE, TRUE, 0);
314 gtk_widget_show(filesel->path_label);
315
316 hbox=gtk_hbox_new(FALSE,1);
317 gtk_box_pack_start(GTK_BOX(main_vbox), hbox, TRUE, TRUE, 0);
318 gtk_widget_show(hbox);
319
320 filesel->tree_window = scrolled_window=gtk_scrolled_window_new(NULL, NULL);
321 gtk_widget_set_size_request(scrolled_window, 200, 250);
322 gtk_box_pack_start(GTK_BOX(hbox), scrolled_window, TRUE, TRUE, 0);
323 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
324 GTK_POLICY_AUTOMATIC,
325 GTK_POLICY_AUTOMATIC);
326
327 /* FIXME
328 filesel->dir_tree = gtk_dir_tree_new();
329 GTK_DIR_TREE(filesel->dir_tree)->show_hidden = TRUE;
330 gtk_container_add(GTK_CONTAINER(scrolled_window), filesel->dir_tree);
331 gtk_widget_show(filesel->dir_tree);
332
333 gtk_box_pack_start(GTK_BOX(hbox), gtk_vseparator_new(), TRUE, TRUE, 0);
334 */
335
336 filesel->list_window = scrolled_window=gtk_scrolled_window_new(NULL, NULL);
337 gtk_box_pack_start(GTK_BOX(hbox), scrolled_window, TRUE, TRUE, 0);
338 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
339 GTK_POLICY_ALWAYS,
340 GTK_POLICY_AUTOMATIC);
341
342 filesel->file_list = gtk_file_list_new(20, GTK_ICON_LIST_TEXT_RIGHT, G_DIR_SEPARATOR_S);
343 GTK_ICON_LIST(filesel->file_list)->is_editable = FALSE;
344 GTK_FILE_LIST(filesel->file_list)->show_folders = TRUE;
345 GTK_FILE_LIST(filesel->file_list)->show_hidden = TRUE;
346 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window),
347 filesel->file_list);
348 gtk_widget_show(filesel->file_list);
349
350 if(filesel->show_tree){
351 gtk_icon_file_selection_show_tree(filesel, TRUE);
352 gtk_widget_set_size_request(filesel->list_window, 380, 250);
353 }else{
354 gtk_widget_set_size_request(filesel->list_window, 550, 250);
355 }
356
357 gtk_widget_show(scrolled_window);
358
359 g_signal_connect(GTK_OBJECT(filesel->file_list), "select_icon",
360 (void *)select_icon, filesel);
361
362 filesel->action_area = table = gtk_table_new(TRUE, 2, 4);
363 gtk_box_pack_start(GTK_BOX(main_vbox), table, TRUE, TRUE, 3);
364 gtk_widget_show(table);
365
366 label = gtk_label_new("File: ");
367 gtk_misc_set_alignment(GTK_MISC(label), 1., 0.5);
368 gtk_table_attach_defaults(GTK_TABLE(table),
369 label,
370 0, 1, 0, 1);
371 gtk_widget_show(label);
372
373 label = gtk_label_new("Filter: ");
374 gtk_misc_set_alignment(GTK_MISC(label), 1., 0.5);
375 gtk_table_attach_defaults(GTK_TABLE(table),
376 label,
377 0, 1, 1, 2);
378 gtk_widget_show(label);
379
380 filesel->file_entry = gtk_entry_new();
381 gtk_table_attach_defaults(GTK_TABLE(table), filesel->file_entry, 1, 3, 0, 1);
382 gtk_widget_show(filesel->file_entry);
383
384 g_signal_connect(GTK_OBJECT(filesel->file_entry), "key_press_event",
385 (void *)entry_set_file, filesel);
386
387 filesel->filter_entry = gtk_entry_new();
388 gtk_table_attach_defaults(GTK_TABLE(table), filesel->filter_entry, 1, 3, 1, 2);
389 gtk_widget_show(filesel->filter_entry);
390
391 g_signal_connect(GTK_OBJECT(filesel->filter_entry), "key_press_event",
392 (void *)set_filter, filesel);
393
394 /* FIXME
395 g_signal_connect(GTK_OBJECT(filesel->filter_entry), "insert_text",
396 (void *)insert_text, NULL);
397 */
398
399 box = gtk_vbutton_box_new();
400 gtk_table_attach_defaults(GTK_TABLE(table), box, 3, 4, 0, 2);
401 gtk_widget_show(box);
402
403 pixmap = gdk_pixmap_colormap_create_from_xpm_d(NULL, colormap, &mask, NULL,
404 ok_xpm);
405 wpixmap = gtk_image_new_from_pixmap(pixmap, mask);
406 gdk_pixmap_unref(pixmap);
407 gdk_bitmap_unref(mask);
408
409 filesel->ok_button = gtk_button_new_from_stock(GTK_STOCK_OK);
410 gtk_box_pack_end (GTK_BOX (box), filesel->ok_button, TRUE, TRUE, 0);
411 gtk_widget_show(filesel->ok_button);
412
413 g_signal_connect(GTK_OBJECT(filesel->ok_button), "clicked",
414 (void *)real_set_file, filesel);
415
416 pixmap = gdk_pixmap_colormap_create_from_xpm_d(NULL, colormap, &mask, NULL,
417 cancel_xpm);
418 wpixmap = gtk_image_new_from_pixmap(pixmap, mask);
419 gdk_pixmap_unref(pixmap);
420 gdk_bitmap_unref(mask);
421
422 filesel->cancel_button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
423 gtk_box_pack_end (GTK_BOX (box), filesel->cancel_button, TRUE, TRUE, 0);
424 gtk_widget_show(filesel->cancel_button);
425
426 gtk_icon_file_selection_open_dir(filesel, path);
427
428 filesel->selection = NULL;
429 }
430
431 static void
gtk_icon_file_selection_destroy(GtkObject * object)432 gtk_icon_file_selection_destroy(GtkObject *object)
433 {
434 if(GTK_ICON_FILESEL(object)->selection)
435 g_free(GTK_ICON_FILESEL(object)->selection);
436 GTK_ICON_FILESEL(object)->selection = NULL;
437
438 if (GTK_OBJECT_CLASS (parent_class)->destroy)
439 (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
440 }
441
442 /**
443 * gtk_icon_file_selection_show_tree:
444 * @filesel: the #GtkIconFileSelection widget.
445 * @show: TRUE(show) or FALSE(don't show).
446 *
447 * Show icon file selection tree in filesel widget.
448 */
449 void
gtk_icon_file_selection_show_tree(GtkIconFileSel * filesel,gboolean show)450 gtk_icon_file_selection_show_tree(GtkIconFileSel *filesel, gboolean show)
451 {
452 /* FIXME
453 if(show == filesel->show_tree) return;
454
455 filesel->show_tree = show;
456
457 if(show){
458 const gchar *path;
459
460 filesel->tree_signal_id = g_signal_connect(GTK_OBJECT(filesel->dir_tree),
461 "tree_select_row",
462 (void *)open_dir,
463 filesel);
464
465 path = gtk_file_list_get_path(GTK_FILE_LIST(filesel->file_list));
466 gtk_dir_tree_open_dir(GTK_DIR_TREE(filesel->dir_tree), path);
467
468 gtk_widget_set_size_request(filesel->list_window, 380, 250);
469 gtk_widget_show(filesel->tree_window);
470 } else {
471 g_signal_disconnect(GTK_OBJECT(filesel->dir_tree),
472 filesel->tree_signal_id);
473 gtk_widget_hide(filesel->tree_window);
474 gtk_widget_set_size_request(filesel->list_window, 550, 250);
475 }
476 */
477 }
478
479 static gboolean
insert_text(GtkEditable * editable,const gchar * new_text,gint new_text_length,gint * position,gpointer data)480 insert_text (GtkEditable *editable,
481 const gchar *new_text,
482 gint new_text_length,
483 gint *position,
484 gpointer data)
485 {
486 g_object_ref(editable);
487 g_signal_stop_emission_by_name (GTK_OBJECT(editable), "insert_text");
488 if(new_text[0] != ' '){
489 GTK_EDITABLE_CLASS (g_type_class_ref(gtk_editable_get_type ()))->insert_text(editable,
490 new_text,
491 new_text_length,
492 position);
493
494
495 }
496 g_object_unref(editable);
497 return TRUE;
498 }
499
500 static gboolean
select_icon(GtkIconList * iconlist,GtkIconListItem * icon,GdkEvent * event,gpointer data)501 select_icon(GtkIconList *iconlist,
502 GtkIconListItem *icon,
503 GdkEvent *event, gpointer data)
504 {
505 GtkIconFileSel *filesel;
506 GdkModifierType mods;
507 const gchar *path = NULL;
508 gchar *real_path = NULL;
509 gchar *full_path = NULL;
510 const gchar *file = NULL;
511 GtkFileListItem *item;
512 gboolean return_val = FALSE;
513
514 item = (GtkFileListItem *)icon->link;
515
516 filesel = GTK_ICON_FILESEL(data);
517
518 if(item->type != GTK_FILE_LIST_FOLDER){
519 GList *list = iconlist->selection;
520 if(iconlist->selection_mode == GTK_SELECTION_MULTIPLE && list != NULL){
521 gchar *text = g_strdup(((GtkIconListItem *)list->data)->label);
522 list = list->next;
523 while(list){
524 text = g_strconcat(text,";",((GtkIconListItem *)list->data)->label,NULL);
525 list = list->next;
526 }
527 text = g_strconcat(text,";",icon->label,NULL);
528 gtk_entry_set_text(GTK_ENTRY(filesel->file_entry), text);
529 g_free(text);
530 } else {
531 gtk_entry_set_text(GTK_ENTRY(filesel->file_entry), icon->label);
532 }
533 return TRUE;
534 }else{
535 gtk_entry_set_text(GTK_ENTRY(filesel->file_entry), "");
536 }
537
538 if(!event) return FALSE;
539
540 if(event->type == GDK_BUTTON_PRESS || event->type == GDK_2BUTTON_PRESS)
541 gdk_window_get_pointer(event->button.window, NULL, NULL, &mods);
542 else
543 return FALSE;
544
545 path = gtk_file_list_get_path(GTK_FILE_LIST(filesel->file_list));
546 file = gtk_file_list_get_filename(GTK_FILE_LIST(filesel->file_list));
547 file = icon->label;
548
549 if(strlen(path) == 1)
550 full_path = g_strconcat(G_DIR_SEPARATOR_S,file,G_DIR_SEPARATOR_S,NULL);
551 else
552 full_path = g_strconcat(path,G_DIR_SEPARATOR_S,file,G_DIR_SEPARATOR_S,NULL);
553 real_path = get_real_path((const gchar *)full_path);
554
555 if(filesel->selection) g_free(filesel->selection);
556 filesel->selection = NULL;
557 if(item->type != GTK_FILE_LIST_FOLDER){
558 filesel->selection = g_strdup(real_path);
559 }
560
561 if((mods & GDK_BUTTON1_MASK) && event->type == GDK_2BUTTON_PRESS){
562 gtk_label_set_text(GTK_LABEL(filesel->path_label), "Scanning...");
563 if(filesel->show_tree){
564 /* FIXME
565 return_val = gtk_dir_tree_open_dir(GTK_DIR_TREE(filesel->dir_tree), real_path);
566 */
567 } else
568 return_val = gtk_file_list_open_dir(GTK_FILE_LIST(filesel->file_list), real_path);
569
570 update_history_combo(filesel, real_path);
571
572 gtk_label_set_text(GTK_LABEL(filesel->path_label), real_path);
573 }
574
575 g_free(full_path);
576 g_free(real_path);
577 return (!return_val);
578 }
579
580 static gboolean
entry_set_file(GtkWidget * widget,GdkEventKey * key,gpointer data)581 entry_set_file(GtkWidget *widget, GdkEventKey *key, gpointer data)
582 {
583 GtkIconFileSel *filesel = GTK_ICON_FILESEL(data);
584
585 if (key->keyval != GDK_KEY_Return && key->keyval != GDK_KEY_KP_Enter)
586 return FALSE;
587
588 /* real_set_file(widget, data); */
589
590 g_signal_emit_by_name(GTK_OBJECT(filesel->ok_button), "clicked", filesel);
591
592 return FALSE;
593 }
594
595 static void
real_set_file(GtkWidget * widget,gpointer data)596 real_set_file(GtkWidget *widget, gpointer data)
597 {
598 GtkIconFileSel *filesel;
599 GtkIconListItem *item;
600 GList *list;
601 const gchar *c;
602 gchar *last, *text;
603 gchar *folder;
604 gchar *file;
605 gint nlen, file_len;
606
607 filesel = (GtkIconFileSel *)data;
608
609 c = gtk_entry_get_text(GTK_ENTRY(filesel->file_entry));
610 folder = NULL;
611 file = NULL;
612 last = NULL;
613 file_len = nlen = 0;
614
615 while(*c != '\0' && *c != '\n' && c != NULL){
616 nlen++;
617 file_len++;
618 folder = (char *)g_realloc(folder, (nlen+1)*sizeof(char));
619 folder[nlen-1] = *c;
620 folder[nlen]='\0';
621 file = (char *)g_realloc(file, (file_len+1)*sizeof(char));
622 file[file_len-1] = *c;
623 file[file_len]='\0';
624 if(*c == G_DIR_SEPARATOR){
625 g_free(file);
626 g_free(last);
627 last = g_strdup(folder);
628 file_len = 0;
629 file = NULL;
630 }
631 c++;
632 }
633
634 if(last) gtk_icon_file_selection_open_dir(filesel, last);
635
636 if(file){
637 list = GTK_ICON_LIST(filesel->file_list)->icons;
638 while(list){
639 item = (GtkIconListItem *)list->data;
640 text = ((GtkFileListItem *)item->link)->file_name;
641 if(strcmp(text, file) == 0){
642 item->state = GTK_STATE_SELECTED;
643 /*
644 gtk_icon_list_select_icon(GTK_ICON_LIST(filesel->file_list), item);
645 */
646 break;
647 }
648 list = list->next;
649 }
650 }
651
652
653 g_free(folder);
654 g_free(file);
655 g_free(last);
656 }
657
658 static gboolean
set_filter(GtkWidget * widget,GdkEventKey * key,gpointer data)659 set_filter(GtkWidget *widget, GdkEventKey *key, gpointer data)
660 {
661 GtkIconFileSel *filesel;
662
663 if (key->keyval != GDK_KEY_Return && key->keyval != GDK_KEY_KP_Enter)
664 return FALSE;
665
666 filesel = (GtkIconFileSel *)data;
667
668 gtk_file_list_set_filter(GTK_FILE_LIST(filesel->file_list),
669 gtk_entry_get_text(GTK_ENTRY(widget)));
670
671 return TRUE;
672 }
673
674 static void
open_dir(GtkWidget * widget,GtkCTreeNode * node,gint n,gpointer data)675 open_dir(GtkWidget *widget, GtkCTreeNode *node, gint n, gpointer data)
676 {
677 DIR *dir;
678 GtkDirTreeNode *dirnode;
679 gchar *path;
680 const gchar *last_path;
681 GtkIconFileSel *filesel;
682
683 filesel = GTK_ICON_FILESEL(data);
684
685
686 dirnode=gtk_ctree_node_get_row_data(GTK_CTREE(widget),node);
687
688 path = dirnode->path;
689
690 last_path = gtk_file_list_get_path(GTK_FILE_LIST(filesel->file_list));
691
692 if(strcmp(last_path, G_DIR_SEPARATOR_S) !=0 && strcmp(last_path, path) == 0) return;
693
694 gtk_widget_unmap(filesel->file_list);
695
696 if((dir = opendir(path)) == NULL){
697 return;
698 }
699 closedir(dir);
700
701 gtk_label_set_text(GTK_LABEL(filesel->path_label), "Scanning...");
702
703 gtk_file_list_open_dir(GTK_FILE_LIST(filesel->file_list), path);
704
705 update_history_combo(filesel, path);
706
707 gtk_widget_map(filesel->file_list);
708
709 gtk_label_set_text(GTK_LABEL(filesel->path_label), path);
710 }
711
712 /**
713 * gtk_icon_file_selection_open_dir:
714 * @filesel: the #GtkIconFileSelection widget.
715 * @path: directory path.
716 *
717 * Show the file from path directory in filesel widget.
718 *
719 * Returns: TRUE or FALSE depending on success
720 */
721 gint
gtk_icon_file_selection_open_dir(GtkIconFileSel * filesel,const gchar * path)722 gtk_icon_file_selection_open_dir(GtkIconFileSel *filesel, const gchar *path)
723 {
724 DIR *dir;
725 gint return_val = TRUE;
726 gchar *real_path = NULL;
727
728 if(!path) return FALSE;
729 real_path = get_real_path(path);
730
731 if((dir = opendir(real_path)) == NULL){
732 g_warning("Can not open folder: %s",real_path);
733 g_free(real_path);
734 return FALSE;
735 }
736
737 gtk_label_set_text(GTK_LABEL(filesel->path_label), "Scanning...");
738
739 if(filesel->show_tree){
740 /* FIXME
741 return_val = gtk_dir_tree_open_dir(GTK_DIR_TREE(filesel->dir_tree), real_path);
742 */
743 } else
744 return_val = gtk_file_list_open_dir(GTK_FILE_LIST(filesel->file_list), real_path);
745
746 gtk_label_set_text(GTK_LABEL(filesel->path_label), real_path);
747
748 update_history_combo(filesel, (const gchar *)real_path);
749
750 g_free(real_path);
751
752 return return_val;
753 }
754
755 /**
756 * gtk_icon_file_selection_show_hidden:
757 * @filesel: the #GtkIconFileSelection widget.
758 * @visible: TRUE(show hidden files) or FALSE(don't show hidden files).
759 *
760 * Set the visibility of hidden files.
761 */
762 void
gtk_icon_file_selection_show_hidden(GtkIconFileSel * filesel,gboolean visible)763 gtk_icon_file_selection_show_hidden(GtkIconFileSel *filesel, gboolean visible)
764 {
765 /* FIXME
766 GTK_DIR_TREE(filesel->dir_tree)->show_hidden = visible;
767 */
768 GTK_FILE_LIST(filesel->file_list)->show_hidden = visible;
769 }
770
771 /**
772 * gtk_icon_file_selection_set_filter:
773 * @filesel: the #GtkIconFileSelection widget.
774 * @filter: filter to be applied on files.
775 *
776 * Set a filter for the files show in filelist.
777 */
778 void
gtk_icon_file_selection_set_filter(GtkIconFileSel * filesel,const gchar * filter)779 gtk_icon_file_selection_set_filter(GtkIconFileSel *filesel, const gchar *filter)
780 {
781 GTK_FILE_LIST(filesel->file_list)->filter = g_strdup(filter);
782 gtk_file_list_open_dir(GTK_FILE_LIST(filesel->file_list), GTK_FILE_LIST(filesel->file_list)->path);
783 update_history_combo(filesel, GTK_FILE_LIST(filesel->file_list)->path);
784 if(filter != NULL)
785 gtk_entry_set_text(GTK_ENTRY(filesel->filter_entry),filter);
786 }
787
788 static gchar *
get_real_path(const gchar * full_path)789 get_real_path(const gchar *full_path)
790 {
791 gchar root[5], root1[5], root2[5], root3[5], root4[5];
792 gchar *aux_path;
793 gint length;
794
795 /* GET ABSOLUTE PATH */
796
797 sprintf(root,"%s",G_DIR_SEPARATOR_S);
798 sprintf(root1,"%s.",G_DIR_SEPARATOR_S);
799 sprintf(root2,"%s..",G_DIR_SEPARATOR_S);
800 sprintf(root3,"%s..%s",G_DIR_SEPARATOR_S,G_DIR_SEPARATOR_S);
801 sprintf(root4,"%s.%s",G_DIR_SEPARATOR_S,G_DIR_SEPARATOR_S);
802
803 aux_path = g_strdup(full_path);
804 length = strlen(aux_path);
805
806 if(strcmp(aux_path + length - 2, root1) == 0){
807 if(length == 2) {
808 g_free(aux_path);
809 aux_path = g_strdup(root);
810 } else {
811 aux_path[length - 2] = '\0';
812 }
813 } else if(strcmp(aux_path + length - 3, root2) == 0){
814 if(length == 3) {
815 g_free(aux_path);
816 aux_path = g_strdup(root);
817 } else {
818 gint i = length - 4;
819 while(i >= 0){
820 if(aux_path[i] == root[0]){
821 aux_path[i] = '\0';
822 break;
823 }
824 i--;
825 }
826 }
827 } else if(strcmp(aux_path + length - 4, root3) == 0){
828 if(length == 4) {
829 g_free(aux_path);
830 aux_path = g_strdup(root);
831 } else {
832 gint i = length - 5;
833 while(i >= 0){
834 if(aux_path[i] == root[0]){
835 aux_path[i] = '\0';
836 break;
837 }
838 i--;
839 }
840 }
841 } else if(strcmp(aux_path + length - 3, root4) == 0){
842 if(length == 3) {
843 g_free(aux_path);
844 aux_path = g_strdup(root);
845 } else {
846 aux_path[length - 3] = '\0';
847 }
848 } else if(strcmp(aux_path + length - 1, root) == 0 && length > 1){
849 aux_path[length - 1] = '\0';
850 }
851
852 if(strlen(aux_path) == 0)
853 {
854 g_free(aux_path);
855 aux_path = g_strdup(G_DIR_SEPARATOR_S);
856 }
857
858 return(aux_path);
859 }
860
861 static void
init_history_combo(GtkIconFileSel * filesel,const gchar * current_directory)862 init_history_combo(GtkIconFileSel *filesel, const gchar *current_directory)
863 {
864 gchar *current_dir;
865 gint dir_len;
866 gint i;
867
868 current_dir = g_strdup (current_directory);
869 dir_len = strlen (current_dir);
870
871 for (i = dir_len - 1; i >= 0; i--){
872
873 /* the i == dir_len is to catch the full path for the first
874 * entry. */
875 if ( current_dir[i] == G_DIR_SEPARATOR )
876 {
877
878 current_dir[i + 1] = '\0';
879 gtk_combo_box_append_text(GTK_COMBO_BOX(filesel->history_combo),
880 current_dir);
881 }
882 }
883 gtk_combo_box_set_active (GTK_COMBO_BOX(filesel->history_combo), 0);
884 g_free(current_dir);
885 }
886
887
888 static void
update_history_combo(GtkIconFileSel * filesel,const gchar * current_directory)889 update_history_combo(GtkIconFileSel *filesel, const gchar *current_directory)
890 {
891 GtkComboBox *combo;
892 gchar *sel_dir;
893
894 combo = GTK_COMBO_BOX(filesel->history_combo);
895 sel_dir = gtk_combo_box_get_active_text(GTK_COMBO_BOX(filesel->history_combo));
896 if (strcmp(current_directory, sel_dir) == 0)
897 return;
898 gtk_combo_box_prepend_text(combo, current_directory);
899 gtk_combo_box_set_active(combo, 0);
900 return;
901 }
902
903 static void
go_to_history(const gchar * path,gpointer data)904 go_to_history(const gchar *path, gpointer data)
905 {
906 gchar *real_path;
907
908 if(path[strlen(path)-1] != G_DIR_SEPARATOR)
909 real_path = g_strconcat(path, G_DIR_SEPARATOR_S, NULL);
910 else
911 real_path = g_strdup(path);
912 gtk_icon_file_selection_open_dir(GTK_ICON_FILESEL(data), real_path);
913 g_free(real_path);
914 }
915
916 static gboolean
combo_changed(GtkWidget * widget,gpointer data)917 combo_changed(GtkWidget *widget, gpointer data)
918 {
919 GtkComboBox *comboBox;
920 GtkIconFileSel *filesel;
921 gchar *dir_selected;
922
923 filesel = GTK_ICON_FILESEL(data);
924 comboBox = GTK_COMBO_BOX(filesel->history_combo);
925
926 dir_selected = gtk_combo_box_get_active_text(comboBox);
927 go_to_history(dir_selected, filesel);
928 return TRUE;
929
930 }
931
932 static gboolean
entry_key_press(GtkWidget * widget,GdkEventKey * event,gpointer data)933 entry_key_press(GtkWidget *widget,
934 GdkEventKey *event,
935 gpointer data)
936 {
937 GtkEntry *entry = GTK_ENTRY (widget);
938
939 if (event->keyval == GDK_KEY_Return)
940 {
941 g_signal_stop_emission_by_name( GTK_OBJECT(entry), "key_press_event");
942 //RRRgo_to_history(entry, data);
943 return TRUE;
944 }
945 return FALSE;
946 }
947
948 /**
949 * gtk_icon_file_selection_get_selection:
950 * @filesel: the #GtkIconFileSelection widget.
951 *
952 * Gets the current selection applied on #GtkIconFileSelection.
953 *
954 * Returns: the current selection.
955 */
956 const gchar *
gtk_icon_file_selection_get_selection(GtkIconFileSel * filesel)957 gtk_icon_file_selection_get_selection(GtkIconFileSel *filesel)
958 {
959 return filesel->selection;
960 }
961