Mercurial > geeqie
annotate src/ui_tabcomp.c @ 1810:c416d099a3dc
GTK marks several functions as deprecated
The following functions has been replaced and deprecated by version
2.20:
- GTK_WIDGET_CAN_FOCUS
- GTK_WIDGET_DRAWABLE
- GTK_WIDGET_HAS_FOCUS
- GTK_WIDGET_HAS_GRAB
- GTK_WIDGET_IS_SENSITIVE
- GTK_WIDGET_NO_WINDOW
- GTK_WIDGET_REALIZED
- GTK_WIDGET_SENSITIVE
- GTK_WIDGET_STATE
- GTK_WIDGET_TOPLEVEL
- GTK_WIDGET_VISIBLE
author | mow |
---|---|
date | Mon, 10 May 2010 11:32:56 +0000 |
parents | 956aab097ea7 |
children |
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:
12
diff
changeset
|
3 * (C) 2006 John Ellis |
1802 | 4 * Copyright (C) 2008 - 2010 The Geeqie Team |
9 | 5 * |
6 * Author: John Ellis | |
7 * | |
8 * This software is released under the GNU General Public License (GNU GPL). | |
9 * Please read the included file COPYING for more information. | |
10 * This software comes with no warranty of any kind, use at your own risk! | |
11 */ | |
12 | |
13 #ifdef HAVE_CONFIG_H | |
14 # include "config.h" | |
15 #endif | |
16 #include "intl.h" | |
17 | |
18 #include <stdio.h> | |
19 #include <stdlib.h> | |
20 #include <string.h> | |
21 #include <unistd.h> | |
22 #include <sys/types.h> | |
23 #include <dirent.h> | |
24 | |
25 #include <gdk/gdk.h> | |
26 #include <gtk/gtk.h> | |
27 #include <gdk-pixbuf/gdk-pixbuf.h> | |
28 | |
281 | 29 #include "main.h" |
9 | 30 #include "ui_tabcomp.h" |
31 | |
902 | 32 #include "history_list.h" |
1022
9962b24b6b43
Move miscellaneous functions to their own files (new misc.[ch]).
zas_
parents:
991
diff
changeset
|
33 #include "misc.h" /* expand_tilde() */ |
9 | 34 #include "ui_fileops.h" |
35 #include "ui_spinner.h" | |
36 #include "ui_utildlg.h" | |
37 | |
38 #include <gdk/gdkkeysyms.h> /* for key values */ | |
39 | |
40 | |
41 /* define this to enable a pop-up menu that shows possible matches | |
42 * #define TAB_COMPLETION_ENABLE_POPUP_MENU | |
43 */ | |
44 #define TAB_COMPLETION_ENABLE_POPUP_MENU 1 | |
1388
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
45 #define TAB_COMP_POPUP_MAX 1000 |
9 | 46 |
47 #ifdef TAB_COMPLETION_ENABLE_POPUP_MENU | |
48 #include "ui_menu.h" | |
49 #endif | |
50 | |
51 | |
52 /* ---------------------------------------------------------------- | |
53 Tab completion routines, can be connected to any gtkentry widget | |
54 using the tab_completion_add_to_entry() function. | |
726 | 55 Use remove_trailing_slash() to strip the trailing G_DIR_SEPARATOR. |
9 | 56 ----------------------------------------------------------------*/ |
57 | |
58 typedef struct _TabCompData TabCompData; | |
59 struct _TabCompData | |
60 { | |
61 GtkWidget *entry; | |
62 gchar *dir_path; | |
63 GList *file_list; | |
64 void (*enter_func)(const gchar *, gpointer); | |
65 void (*tab_func)(const gchar *, gpointer); | |
1167
e812b1a7adda
Add a back button in the toolbar: it allows to go back and forth between two directories. Experimental, please test and comment on ml.
zas_
parents:
1055
diff
changeset
|
66 void (*tab_append_func)(const gchar *, gpointer, gint); |
e812b1a7adda
Add a back button in the toolbar: it allows to go back and forth between two directories. Experimental, please test and comment on ml.
zas_
parents:
1055
diff
changeset
|
67 |
9 | 68 gpointer enter_data; |
69 gpointer tab_data; | |
1167
e812b1a7adda
Add a back button in the toolbar: it allows to go back and forth between two directories. Experimental, please test and comment on ml.
zas_
parents:
1055
diff
changeset
|
70 gpointer tab_append_data; |
e812b1a7adda
Add a back button in the toolbar: it allows to go back and forth between two directories. Experimental, please test and comment on ml.
zas_
parents:
1055
diff
changeset
|
71 |
9 | 72 GtkWidget *combo; |
1448 | 73 gboolean has_history; |
9 | 74 gchar *history_key; |
75 gint history_levels; | |
76 | |
77 FileDialog *fd; | |
78 gchar *fd_title; | |
1448 | 79 gboolean fd_folders_only; |
9 | 80 GtkWidget *fd_button; |
1388
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
81 |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
82 guint choices; |
9 | 83 }; |
84 | |
85 | |
86 static void tab_completion_select_show(TabCompData *td); | |
1388
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
87 static gint tab_completion_do(TabCompData *td); |
9 | 88 |
89 static void tab_completion_free_list(TabCompData *td) | |
90 { | |
91 GList *list; | |
92 | |
93 g_free(td->dir_path); | |
94 td->dir_path = NULL; | |
95 | |
96 list = td->file_list; | |
97 | |
516 | 98 while (list) |
9 | 99 { |
100 g_free(list->data); | |
101 list = list->next; | |
102 } | |
103 | |
104 g_list_free(td->file_list); | |
105 td->file_list = NULL; | |
106 } | |
107 | |
108 static void tab_completion_read_dir(TabCompData *td, const gchar *path) | |
109 { | |
442 | 110 DIR *dp; |
111 struct dirent *dir; | |
112 GList *list = NULL; | |
9 | 113 gchar *pathl; |
114 | |
115 tab_completion_free_list(td); | |
116 | |
117 pathl = path_from_utf8(path); | |
442 | 118 dp = opendir(pathl); |
9 | 119 if (!dp) |
442 | 120 { |
121 /* dir not found */ | |
1385
b4e6fee484f7
Fix utf8/locale conversion warning: the path passed to isdir() is not in UTF8 (if local fs is not in UFT8) so do not use it (isdir() uses stat_utf8() which calls path_from_utf8()).
zas_
parents:
1382
diff
changeset
|
122 g_free(pathl); |
442 | 123 return; |
124 } | |
125 while ((dir = readdir(dp)) != NULL) | |
126 { | |
69
31759d770628
Fri Oct 13 10:27:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
12
diff
changeset
|
127 gchar *name = dir->d_name; |
31759d770628
Fri Oct 13 10:27:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
12
diff
changeset
|
128 if (strcmp(name, ".") != 0 && strcmp(name, "..") != 0) |
31759d770628
Fri Oct 13 10:27:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
12
diff
changeset
|
129 { |
1385
b4e6fee484f7
Fix utf8/locale conversion warning: the path passed to isdir() is not in UTF8 (if local fs is not in UFT8) so do not use it (isdir() uses stat_utf8() which calls path_from_utf8()).
zas_
parents:
1382
diff
changeset
|
130 gchar *abspath = g_build_filename(pathl, name, NULL); |
1370
0011d6859ec5
Add a directory separator at the end of names in tab completion list to indicate directories.
zas_
parents:
1365
diff
changeset
|
131 |
1385
b4e6fee484f7
Fix utf8/locale conversion warning: the path passed to isdir() is not in UTF8 (if local fs is not in UFT8) so do not use it (isdir() uses stat_utf8() which calls path_from_utf8()).
zas_
parents:
1382
diff
changeset
|
132 if (g_file_test(abspath, G_FILE_TEST_IS_DIR)) |
1370
0011d6859ec5
Add a directory separator at the end of names in tab completion list to indicate directories.
zas_
parents:
1365
diff
changeset
|
133 { |
0011d6859ec5
Add a directory separator at the end of names in tab completion list to indicate directories.
zas_
parents:
1365
diff
changeset
|
134 gchar *dname = g_strconcat(name, G_DIR_SEPARATOR_S, NULL); |
0011d6859ec5
Add a directory separator at the end of names in tab completion list to indicate directories.
zas_
parents:
1365
diff
changeset
|
135 list = g_list_prepend(list, path_to_utf8(dname)); |
1371 | 136 g_free(dname); |
1370
0011d6859ec5
Add a directory separator at the end of names in tab completion list to indicate directories.
zas_
parents:
1365
diff
changeset
|
137 } |
0011d6859ec5
Add a directory separator at the end of names in tab completion list to indicate directories.
zas_
parents:
1365
diff
changeset
|
138 else |
0011d6859ec5
Add a directory separator at the end of names in tab completion list to indicate directories.
zas_
parents:
1365
diff
changeset
|
139 { |
0011d6859ec5
Add a directory separator at the end of names in tab completion list to indicate directories.
zas_
parents:
1365
diff
changeset
|
140 list = g_list_prepend(list, path_to_utf8(name)); |
0011d6859ec5
Add a directory separator at the end of names in tab completion list to indicate directories.
zas_
parents:
1365
diff
changeset
|
141 } |
0011d6859ec5
Add a directory separator at the end of names in tab completion list to indicate directories.
zas_
parents:
1365
diff
changeset
|
142 g_free(abspath); |
69
31759d770628
Fri Oct 13 10:27:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
12
diff
changeset
|
143 } |
9 | 144 } |
442 | 145 closedir(dp); |
9 | 146 |
147 td->dir_path = g_strdup(path); | |
148 td->file_list = list; | |
1385
b4e6fee484f7
Fix utf8/locale conversion warning: the path passed to isdir() is not in UTF8 (if local fs is not in UFT8) so do not use it (isdir() uses stat_utf8() which calls path_from_utf8()).
zas_
parents:
1382
diff
changeset
|
149 g_free(pathl); |
9 | 150 } |
151 | |
152 static void tab_completion_destroy(GtkWidget *widget, gpointer data) | |
153 { | |
154 TabCompData *td = data; | |
155 | |
156 tab_completion_free_list(td); | |
157 g_free(td->history_key); | |
158 | |
159 if (td->fd) file_dialog_close(td->fd); | |
160 g_free(td->fd_title); | |
161 | |
162 g_free(td); | |
163 } | |
164 | |
991 | 165 static gchar *tab_completion_get_text(TabCompData *td) |
9 | 166 { |
167 gchar *text; | |
168 | |
169 text = g_strdup(gtk_entry_get_text(GTK_ENTRY(td->entry))); | |
170 | |
171 if (text[0] == '~') | |
172 { | |
173 gchar *t = text; | |
720
d8a88f279aca
Use expand_tilde() instead of simple concatenation, it allows correct expansion
zas_
parents:
673
diff
changeset
|
174 text = expand_tilde(text); |
9 | 175 g_free(t); |
176 } | |
177 | |
991 | 178 return text; |
179 } | |
180 | |
1448 | 181 static gboolean tab_completion_emit_enter_signal(TabCompData *td) |
991 | 182 { |
183 gchar *text; | |
184 if (!td->enter_func) return FALSE; | |
185 | |
186 text = tab_completion_get_text(td); | |
9 | 187 td->enter_func(text, td->enter_data); |
188 g_free(text); | |
189 | |
190 return TRUE; | |
191 } | |
192 | |
193 static void tab_completion_emit_tab_signal(TabCompData *td) | |
194 { | |
195 gchar *text; | |
196 if (!td->tab_func) return; | |
197 | |
991 | 198 text = tab_completion_get_text(td); |
9 | 199 td->tab_func(text, td->tab_data); |
200 g_free(text); | |
201 } | |
202 | |
203 #ifdef TAB_COMPLETION_ENABLE_POPUP_MENU | |
1388
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
204 void tab_completion_iter_menu_items(GtkWidget *widget, gpointer data) |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
205 { |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
206 TabCompData *td = data; |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
207 GtkWidget *child; |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
208 |
1810 | 209 #if GTK_CHECK_VERSION(2,20,0) |
210 if (!gtk_widget_get_visible(widget)) return; | |
211 #else | |
1388
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
212 if (!GTK_WIDGET_VISIBLE(widget)) return; |
1810 | 213 #endif |
1388
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
214 |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
215 child = gtk_bin_get_child(GTK_BIN(widget)); |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
216 if (GTK_IS_LABEL(child)) { |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
217 const gchar *text = gtk_label_get_text(GTK_LABEL(child)); |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
218 const gchar *entry_text = gtk_entry_get_text(GTK_ENTRY(td->entry)); |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
219 const gchar *prefix = filename_from_path(entry_text); |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
220 guint prefix_len = strlen(prefix); |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
221 |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
222 if (strlen(text) < prefix_len || strncmp(text, prefix, prefix_len)) |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
223 { |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
224 /* Hide menu items not matching */ |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
225 gtk_widget_hide(widget); |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
226 } |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
227 else |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
228 { |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
229 /* Count how many choices are left in the menu */ |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
230 td->choices++; |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
231 } |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
232 } |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
233 } |
9 | 234 |
1448 | 235 static gboolean tab_completion_popup_key_press(GtkWidget *widget, GdkEventKey *event, gpointer data) |
9 | 236 { |
237 TabCompData *td = data; | |
238 | |
239 if (event->keyval == GDK_Tab || | |
240 event->keyval == GDK_BackSpace || | |
241 (event->keyval >= 0x20 && event->keyval <= 0xFF) ) | |
242 { | |
243 if (event->keyval >= 0x20 && event->keyval <= 0xFF) | |
244 { | |
245 gchar buf[2]; | |
246 gint p = -1; | |
247 | |
248 buf[0] = event->keyval; | |
249 buf[1] = '\0'; | |
250 gtk_editable_insert_text(GTK_EDITABLE(td->entry), buf, 1, &p); | |
251 gtk_editable_set_position(GTK_EDITABLE(td->entry), -1); | |
1388
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
252 |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
253 /* Reduce the number of entries in the menu */ |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
254 td->choices = 0; |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
255 gtk_container_foreach(GTK_CONTAINER(widget), tab_completion_iter_menu_items, (gpointer) td); |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
256 if (td->choices > 1) return TRUE; /* multiple choices */ |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
257 if (td->choices > 0) tab_completion_do(td); /* one choice */ |
9 | 258 } |
1388
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
259 |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
260 /* close the menu */ |
9 | 261 gtk_menu_popdown(GTK_MENU(widget)); |
262 /* doing this does not emit the "selection done" signal, unref it ourselves */ | |
1043 | 263 #if GTK_CHECK_VERSION(2,12,0) |
264 g_object_unref(widget); | |
265 #else | |
9 | 266 gtk_widget_unref(widget); |
1043 | 267 #endif |
9 | 268 return TRUE; |
269 } | |
270 | |
271 return FALSE; | |
272 } | |
273 | |
274 static void tab_completion_popup_cb(GtkWidget *widget, gpointer data) | |
275 { | |
276 gchar *name = data; | |
277 TabCompData *td; | |
278 gchar *buf; | |
279 | |
280 td = g_object_get_data(G_OBJECT(widget), "tab_completion_data"); | |
281 if (!td) return; | |
282 | |
721
b736a2e3129b
tab_completion_popup_cb(): use g_build_filename() and simplify code.
zas_
parents:
720
diff
changeset
|
283 buf = g_build_filename(td->dir_path, name, NULL); |
9 | 284 gtk_entry_set_text(GTK_ENTRY(td->entry), buf); |
285 gtk_editable_set_position(GTK_EDITABLE(td->entry), strlen(buf)); | |
286 g_free(buf); | |
287 | |
288 tab_completion_emit_tab_signal(td); | |
289 } | |
290 | |
291 static void tab_completion_popup_pos_cb(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer data) | |
292 { | |
293 TabCompData *td = data; | |
294 gint height; | |
295 PangoLayout *layout; | |
296 PangoRectangle strong_pos, weak_pos; | |
297 gint length; | |
298 gint xoffset, yoffset; | |
12
147f4c4b9025
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
299 GtkRequisition req; |
147f4c4b9025
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
300 GdkScreen *screen; |
147f4c4b9025
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
301 gint monitor_num; |
147f4c4b9025
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
302 GdkRectangle monitor; |
9 | 303 |
304 gdk_window_get_origin(td->entry->window, x, y); | |
305 | |
12
147f4c4b9025
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
306 screen = gtk_widget_get_screen(GTK_WIDGET(menu)); |
147f4c4b9025
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
307 monitor_num = gdk_screen_get_monitor_at_window(screen, td->entry->window); |
147f4c4b9025
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
308 gdk_screen_get_monitor_geometry(screen, monitor_num, &monitor); |
147f4c4b9025
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
309 |
147f4c4b9025
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
310 gtk_widget_size_request(GTK_WIDGET(menu), &req); |
9 | 311 |
312 length = strlen(gtk_entry_get_text(GTK_ENTRY(td->entry))); | |
313 gtk_entry_get_layout_offsets(GTK_ENTRY(td->entry), &xoffset, &yoffset); | |
314 | |
315 layout = gtk_entry_get_layout(GTK_ENTRY(td->entry)); | |
316 pango_layout_get_cursor_pos(layout, length, &strong_pos, &weak_pos); | |
12
147f4c4b9025
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
317 |
9 | 318 *x += strong_pos.x / PANGO_SCALE + xoffset; |
12
147f4c4b9025
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
319 |
147f4c4b9025
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
320 height = MIN(td->entry->requisition.height, td->entry->allocation.height); |
147f4c4b9025
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
321 |
147f4c4b9025
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
322 if (req.height > monitor.y + monitor.height - *y - height && |
147f4c4b9025
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
323 *y - monitor.y > monitor.y + monitor.height - *y) |
147f4c4b9025
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
324 { |
147f4c4b9025
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
325 height = MIN(*y - monitor.y, req.height); |
147f4c4b9025
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
326 gtk_widget_set_size_request(GTK_WIDGET(menu), -1, height); |
147f4c4b9025
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
327 *y -= height; |
147f4c4b9025
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
328 } |
147f4c4b9025
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
329 else |
147f4c4b9025
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
330 { |
147f4c4b9025
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
331 *y += height; |
147f4c4b9025
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
332 } |
9 | 333 } |
334 | |
335 static void tab_completion_popup_list(TabCompData *td, GList *list) | |
336 { | |
337 GtkWidget *menu; | |
338 GList *work; | |
339 GdkEvent *event; | |
340 guint32 etime; | |
341 gint ebutton; | |
342 gint count = 0; | |
343 | |
344 if (!list) return; | |
345 | |
346 #if 0 | |
347 /* | |
348 * well, the menu would be too long anyway... | |
349 * (listing /dev causes gtk+ window allocation errors, -> too big a window) | |
350 * this is why menu popups are disabled, this really should be a popup scrollable listview. | |
351 */ | |
352 if (g_list_length(list) > 200) return; | |
353 #endif | |
354 | |
355 menu = popup_menu_short_lived(); | |
356 | |
357 work = list; | |
358 while (work && count < TAB_COMP_POPUP_MAX) | |
359 { | |
360 gchar *name = work->data; | |
361 GtkWidget *item; | |
362 | |
363 item = menu_item_add_simple(menu, name, G_CALLBACK(tab_completion_popup_cb), name); | |
364 g_object_set_data(G_OBJECT(item), "tab_completion_data", td); | |
365 | |
366 work = work->next; | |
367 count++; | |
368 } | |
369 | |
370 g_signal_connect(G_OBJECT(menu), "key_press_event", | |
371 G_CALLBACK(tab_completion_popup_key_press), td); | |
372 | |
373 /* peek at the current event to get the time, etc. */ | |
374 event = gtk_get_current_event(); | |
375 | |
376 if (event && event->type == GDK_BUTTON_RELEASE) | |
377 { | |
378 ebutton = event->button.button; | |
379 } | |
380 else | |
381 { | |
382 ebutton = 0; | |
383 } | |
384 | |
385 if (event) | |
386 { | |
387 etime = gdk_event_get_time(event); | |
388 gdk_event_free(event); | |
389 } | |
390 else | |
391 { | |
392 etime = 0; | |
393 } | |
394 | |
395 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, | |
396 tab_completion_popup_pos_cb, td, ebutton, etime); | |
397 } | |
398 | |
399 #ifndef CASE_SORT | |
400 #define CASE_SORT strcmp | |
401 #endif | |
402 | |
403 static gint simple_sort(gconstpointer a, gconstpointer b) | |
404 { | |
442 | 405 return CASE_SORT((gchar *)a, (gchar *)b); |
9 | 406 } |
407 | |
408 #endif | |
409 | |
1448 | 410 static gboolean tab_completion_do(TabCompData *td) |
9 | 411 { |
412 const gchar *entry_text = gtk_entry_get_text(GTK_ENTRY(td->entry)); | |
413 const gchar *entry_file; | |
414 gchar *entry_dir; | |
415 gchar *ptr; | |
1437 | 416 gboolean home_exp = FALSE; |
9 | 417 |
1388
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
418 if (entry_text[0] == '\0') |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
419 { |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
420 entry_dir = g_strdup(G_DIR_SEPARATOR_S); /* FIXME: root directory win32 */ |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
421 gtk_entry_set_text(GTK_ENTRY(td->entry), entry_dir); |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
422 gtk_editable_set_position(GTK_EDITABLE(td->entry), strlen(entry_dir)); |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
423 g_free(entry_dir); |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
424 return FALSE; |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
425 } |
2496a345c452
Try to improve tab completion: when a key is pressed while tab completion menu is shown, the number of entries is reduced, dhowing all matching entries but the menu is no more closed after each key pressure. Number of possible entries in this menu was increased from 500 to 1000. Pressing TAB when path entry is empty now adds / (root directory).
zas_
parents:
1385
diff
changeset
|
426 |
9 | 427 /* home dir expansion */ |
428 if (entry_text[0] == '~') | |
429 { | |
720
d8a88f279aca
Use expand_tilde() instead of simple concatenation, it allows correct expansion
zas_
parents:
673
diff
changeset
|
430 entry_dir = expand_tilde(entry_text); |
9 | 431 home_exp = TRUE; |
432 } | |
433 else | |
434 { | |
435 entry_dir = g_strdup(entry_text); | |
436 } | |
437 | |
438 if (isfile(entry_dir)) | |
439 { | |
440 if (home_exp) | |
441 { | |
442 gtk_entry_set_text(GTK_ENTRY(td->entry), entry_dir); | |
443 gtk_editable_set_position(GTK_EDITABLE(td->entry), strlen(entry_dir)); | |
444 } | |
445 g_free(entry_dir); | |
446 return home_exp; | |
447 } | |
722
9a145206ec2c
tab_completion_do(): use g_build_filename(), G_DIR_SEPARATOR, G_DIR_SEPARATOR_S.
zas_
parents:
721
diff
changeset
|
448 |
1382
31a747f9d268
Fix tab completion when entering "/et[TAB]" it was changed to "et", this is fixed.
zas_
parents:
1371
diff
changeset
|
449 entry_file = filename_from_path(entry_text); |
31a747f9d268
Fix tab completion when entering "/et[TAB]" it was changed to "et", this is fixed.
zas_
parents:
1371
diff
changeset
|
450 |
9 | 451 if (isdir(entry_dir) && strcmp(entry_file, ".") != 0 && strcmp(entry_file, "..") != 0) |
452 { | |
453 ptr = entry_dir + strlen(entry_dir) - 1; | |
722
9a145206ec2c
tab_completion_do(): use g_build_filename(), G_DIR_SEPARATOR, G_DIR_SEPARATOR_S.
zas_
parents:
721
diff
changeset
|
454 if (ptr[0] == G_DIR_SEPARATOR) |
9 | 455 { |
456 if (home_exp) | |
457 { | |
458 gtk_entry_set_text(GTK_ENTRY(td->entry), entry_dir); | |
459 gtk_editable_set_position(GTK_EDITABLE(td->entry), strlen(entry_dir)); | |
460 } | |
461 | |
462 tab_completion_read_dir(td, entry_dir); | |
463 td->file_list = g_list_sort(td->file_list, simple_sort); | |
464 if (td->file_list && !td->file_list->next) | |
465 { | |
466 gchar *buf; | |
467 const gchar *file; | |
468 | |
469 file = td->file_list->data; | |
722
9a145206ec2c
tab_completion_do(): use g_build_filename(), G_DIR_SEPARATOR, G_DIR_SEPARATOR_S.
zas_
parents:
721
diff
changeset
|
470 buf = g_build_filename(entry_dir, file, NULL); |
9 | 471 if (isdir(buf)) |
472 { | |
722
9a145206ec2c
tab_completion_do(): use g_build_filename(), G_DIR_SEPARATOR, G_DIR_SEPARATOR_S.
zas_
parents:
721
diff
changeset
|
473 gchar *tmp = g_strconcat(buf, G_DIR_SEPARATOR_S, NULL); |
9 | 474 g_free(buf); |
722
9a145206ec2c
tab_completion_do(): use g_build_filename(), G_DIR_SEPARATOR, G_DIR_SEPARATOR_S.
zas_
parents:
721
diff
changeset
|
475 buf = tmp; |
9 | 476 } |
477 gtk_entry_set_text(GTK_ENTRY(td->entry), buf); | |
478 gtk_editable_set_position(GTK_EDITABLE(td->entry), strlen(buf)); | |
479 g_free(buf); | |
480 } | |
481 | |
482 #ifdef TAB_COMPLETION_ENABLE_POPUP_MENU | |
483 | |
484 else | |
485 { | |
486 tab_completion_popup_list(td, td->file_list); | |
487 } | |
488 #endif | |
489 | |
490 g_free(entry_dir); | |
491 return home_exp; | |
492 } | |
493 else | |
494 { | |
722
9a145206ec2c
tab_completion_do(): use g_build_filename(), G_DIR_SEPARATOR, G_DIR_SEPARATOR_S.
zas_
parents:
721
diff
changeset
|
495 gchar *buf = g_strconcat(entry_dir, G_DIR_SEPARATOR_S, NULL); |
9 | 496 gtk_entry_set_text(GTK_ENTRY(td->entry), buf); |
497 gtk_editable_set_position(GTK_EDITABLE(td->entry), strlen(buf)); | |
498 g_free(buf); | |
499 g_free(entry_dir); | |
500 return TRUE; | |
501 } | |
502 } | |
503 | |
504 ptr = (gchar *)filename_from_path(entry_dir); | |
505 if (ptr > entry_dir) ptr--; | |
506 ptr[0] = '\0'; | |
1382
31a747f9d268
Fix tab completion when entering "/et[TAB]" it was changed to "et", this is fixed.
zas_
parents:
1371
diff
changeset
|
507 |
9 | 508 if (strlen(entry_dir) == 0) |
509 { | |
510 g_free(entry_dir); | |
722
9a145206ec2c
tab_completion_do(): use g_build_filename(), G_DIR_SEPARATOR, G_DIR_SEPARATOR_S.
zas_
parents:
721
diff
changeset
|
511 entry_dir = g_strdup(G_DIR_SEPARATOR_S); /* FIXME: win32 */ |
9 | 512 } |
513 | |
514 if (isdir(entry_dir)) | |
515 { | |
516 GList *list; | |
517 GList *poss = NULL; | |
518 gint l = strlen(entry_file); | |
519 | |
520 if (!td->dir_path || !td->file_list || strcmp(td->dir_path, entry_dir) != 0) | |
521 { | |
522 tab_completion_read_dir(td, entry_dir); | |
523 } | |
524 | |
525 list = td->file_list; | |
516 | 526 while (list) |
9 | 527 { |
528 gchar *file = list->data; | |
529 if (strncmp(entry_file, file, l) == 0) | |
530 { | |
531 poss = g_list_prepend(poss, file); | |
532 } | |
533 list = list->next; | |
534 } | |
535 | |
536 if (poss) | |
537 { | |
538 if (!poss->next) | |
539 { | |
540 gchar *file = poss->data; | |
541 gchar *buf; | |
542 | |
722
9a145206ec2c
tab_completion_do(): use g_build_filename(), G_DIR_SEPARATOR, G_DIR_SEPARATOR_S.
zas_
parents:
721
diff
changeset
|
543 buf = g_build_filename(entry_dir, file, NULL); |
9 | 544 gtk_entry_set_text(GTK_ENTRY(td->entry), buf); |
545 gtk_editable_set_position(GTK_EDITABLE(td->entry), strlen(buf)); | |
546 g_free(buf); | |
547 g_list_free(poss); | |
548 g_free(entry_dir); | |
549 return TRUE; | |
550 } | |
551 else | |
552 { | |
734
e6ebae313d46
Fix up some types, make some signed vs unsigned warnings quiet.
zas_
parents:
726
diff
changeset
|
553 gsize c = strlen(entry_file); |
1437 | 554 gboolean done = FALSE; |
9 | 555 gchar *test_file = poss->data; |
556 | |
557 while (!done) | |
558 { | |
559 list = poss; | |
560 if (!list) done = TRUE; | |
516 | 561 while (list && !done) |
9 | 562 { |
563 gchar *file = list->data; | |
564 if (strlen(file) < c || strncmp(test_file, file, c) != 0) | |
565 { | |
566 done = TRUE; | |
567 } | |
568 list = list->next; | |
569 } | |
570 c++; | |
571 } | |
572 c -= 2; | |
573 if (c > 0) | |
574 { | |
575 gchar *file; | |
576 gchar *buf; | |
577 file = g_strdup(test_file); | |
578 file[c] = '\0'; | |
722
9a145206ec2c
tab_completion_do(): use g_build_filename(), G_DIR_SEPARATOR, G_DIR_SEPARATOR_S.
zas_
parents:
721
diff
changeset
|
579 buf = g_build_filename(entry_dir, file, NULL); |
9 | 580 gtk_entry_set_text(GTK_ENTRY(td->entry), buf); |
581 gtk_editable_set_position(GTK_EDITABLE(td->entry), strlen(buf)); | |
582 | |
583 #ifdef TAB_COMPLETION_ENABLE_POPUP_MENU | |
584 | |
585 poss = g_list_sort(poss, simple_sort); | |
586 tab_completion_popup_list(td, poss); | |
587 | |
588 #endif | |
589 | |
590 g_free(file); | |
591 g_free(buf); | |
592 g_list_free(poss); | |
593 g_free(entry_dir); | |
594 return TRUE; | |
595 } | |
596 } | |
597 g_list_free(poss); | |
598 } | |
599 } | |
600 | |
601 g_free(entry_dir); | |
602 | |
603 return FALSE; | |
604 } | |
605 | |
1448 | 606 static gboolean tab_completion_key_pressed(GtkWidget *widget, GdkEventKey *event, gpointer data) |
9 | 607 { |
608 TabCompData *td = data; | |
1437 | 609 gboolean stop_signal = FALSE; |
9 | 610 |
611 switch (event->keyval) | |
612 { | |
442 | 613 case GDK_Tab: |
9 | 614 if (!(event->state & GDK_CONTROL_MASK)) |
615 { | |
616 if (tab_completion_do(td)) | |
617 { | |
618 tab_completion_emit_tab_signal(td); | |
619 } | |
620 stop_signal = TRUE; | |
621 } | |
622 break; | |
623 case GDK_Return: case GDK_KP_Enter: | |
624 if (td->fd_button && | |
625 (event->state & GDK_CONTROL_MASK)) | |
626 { | |
627 tab_completion_select_show(td); | |
628 stop_signal = TRUE; | |
629 } | |
630 else if (tab_completion_emit_enter_signal(td)) | |
631 { | |
632 stop_signal = TRUE; | |
633 } | |
634 break; | |
635 default: | |
636 break; | |
637 } | |
638 | |
639 if (stop_signal) g_signal_stop_emission_by_name(G_OBJECT(widget), "key_press_event"); | |
640 | |
641 return (stop_signal); | |
642 } | |
643 | |
644 static void tab_completion_button_pressed(GtkWidget *widget, gpointer data) | |
645 { | |
646 TabCompData *td; | |
647 GtkWidget *entry = data; | |
648 | |
649 td = g_object_get_data(G_OBJECT(entry), "tab_completion_data"); | |
650 | |
651 if (!td) return; | |
652 | |
1810 | 653 #if GTK_CHECK_VERSION(2,20,0) |
654 if (!gtk_widget_has_focus(entry)) | |
655 #else | |
9 | 656 if (!GTK_WIDGET_HAS_FOCUS(entry)) |
1810 | 657 #endif |
9 | 658 { |
659 gtk_widget_grab_focus(entry); | |
660 } | |
661 | |
662 if (tab_completion_do(td)) | |
663 { | |
664 tab_completion_emit_tab_signal(td); | |
665 } | |
666 } | |
667 | |
668 static void tab_completion_button_size_allocate(GtkWidget *button, GtkAllocation *allocation, gpointer data) | |
669 { | |
670 GtkWidget *parent = data; | |
671 | |
672 if (allocation->height > parent->allocation.height) | |
673 { | |
674 GtkAllocation button_allocation; | |
675 | |
676 button_allocation = button->allocation; | |
677 button_allocation.height = parent->allocation.height; | |
678 button_allocation.y = parent->allocation.y + | |
679 (parent->allocation.height - parent->allocation.height) / 2; | |
680 gtk_widget_size_allocate(button, &button_allocation); | |
681 } | |
682 } | |
683 | |
684 static GtkWidget *tab_completion_create_complete_button(GtkWidget *entry, GtkWidget *parent) | |
685 { | |
686 GtkWidget *button; | |
687 GtkWidget *icon; | |
688 GdkPixbuf *pixbuf; | |
689 | |
690 button = gtk_button_new(); | |
691 GTK_WIDGET_UNSET_FLAGS(button, GTK_CAN_FOCUS); | |
692 g_signal_connect(G_OBJECT(button), "size_allocate", | |
693 G_CALLBACK(tab_completion_button_size_allocate), parent); | |
694 g_signal_connect(G_OBJECT(button), "clicked", | |
695 G_CALLBACK(tab_completion_button_pressed), entry); | |
696 | |
697 pixbuf = gdk_pixbuf_new_from_inline(-1, icon_tabcomp, FALSE, NULL); | |
698 icon = gtk_image_new_from_pixbuf(pixbuf); | |
1043 | 699 g_object_unref(pixbuf); |
700 | |
9 | 701 gtk_container_add(GTK_CONTAINER(button), icon); |
702 gtk_widget_show(icon); | |
703 | |
704 return button; | |
705 } | |
706 | |
707 /* | |
708 *---------------------------------------------------------------------------- | |
709 * public interface | |
710 *---------------------------------------------------------------------------- | |
711 */ | |
712 | |
713 GtkWidget *tab_completion_new_with_history(GtkWidget **entry, const gchar *text, | |
714 const gchar *history_key, gint max_levels, | |
715 void (*enter_func)(const gchar *, gpointer), gpointer data) | |
716 { | |
717 GtkWidget *box; | |
718 GtkWidget *combo; | |
719 GtkWidget *combo_entry; | |
720 GtkWidget *button; | |
721 GList *work; | |
722 TabCompData *td; | |
723 gint n = 0; | |
724 | |
725 box = gtk_hbox_new(FALSE, 0); | |
726 | |
727 combo = gtk_combo_box_entry_new_text(); | |
728 gtk_box_pack_start(GTK_BOX(box), combo, TRUE, TRUE, 0); | |
729 gtk_widget_show(combo); | |
730 | |
731 combo_entry = GTK_BIN(combo)->child; | |
732 #if 0 | |
733 gtk_combo_set_case_sensitive(GTK_COMBO(combo), TRUE); | |
734 gtk_combo_set_use_arrows(GTK_COMBO(combo), FALSE); | |
735 #endif | |
736 | |
737 button = tab_completion_create_complete_button(combo_entry, combo); | |
738 gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 0); | |
739 gtk_widget_show(button); | |
740 | |
741 tab_completion_add_to_entry(combo_entry, enter_func, data); | |
742 | |
743 td = g_object_get_data(G_OBJECT(combo_entry), "tab_completion_data"); | |
744 if (!td) return NULL; /* this should never happen! */ | |
745 | |
746 td->combo = combo; | |
747 td->has_history = TRUE; | |
748 td->history_key = g_strdup(history_key); | |
749 td->history_levels = max_levels; | |
750 | |
751 work = history_list_get_by_key(td->history_key); | |
752 | |
753 work = history_list_get_by_key(history_key); | |
754 while (work) | |
755 { | |
756 gtk_combo_box_append_text(GTK_COMBO_BOX(combo), (gchar *)work->data); | |
757 work = work->next; | |
758 n++; | |
759 } | |
760 | |
761 if (text) | |
762 { | |
763 gtk_entry_set_text(GTK_ENTRY(combo_entry), text); | |
764 } | |
765 else if (n > 0) | |
766 { | |
767 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0); | |
768 } | |
769 | |
770 if (entry) *entry = combo_entry; | |
771 return box; | |
772 } | |
773 | |
774 const gchar *tab_completion_set_to_last_history(GtkWidget *entry) | |
775 { | |
776 TabCompData *td = g_object_get_data(G_OBJECT(entry), "tab_completion_data"); | |
777 const gchar *buf; | |
778 | |
779 if (!td || !td->has_history) return NULL; | |
780 | |
781 buf = history_list_find_last_path_by_key(td->history_key); | |
782 if (buf) | |
783 { | |
784 gtk_entry_set_text(GTK_ENTRY(td->entry), buf); | |
785 } | |
786 | |
787 return buf; | |
788 } | |
789 | |
790 void tab_completion_append_to_history(GtkWidget *entry, const gchar *path) | |
791 { | |
792 TabCompData *td; | |
793 GtkTreeModel *store; | |
794 GList *work; | |
1167
e812b1a7adda
Add a back button in the toolbar: it allows to go back and forth between two directories. Experimental, please test and comment on ml.
zas_
parents:
1055
diff
changeset
|
795 gint n = 0; |
9 | 796 |
797 td = g_object_get_data(G_OBJECT(entry), "tab_completion_data"); | |
798 | |
799 if (!path) return; | |
800 | |
801 if (!td || !td->has_history) return; | |
802 | |
803 history_list_add_to_key(td->history_key, path, td->history_levels); | |
804 | |
805 gtk_combo_box_set_active(GTK_COMBO_BOX(td->combo), -1); | |
806 | |
807 store = gtk_combo_box_get_model(GTK_COMBO_BOX(td->combo)); | |
808 gtk_list_store_clear(GTK_LIST_STORE(store)); | |
809 | |
810 work = history_list_get_by_key(td->history_key); | |
811 while (work) | |
812 { | |
813 gtk_combo_box_append_text(GTK_COMBO_BOX(td->combo), (gchar *)work->data); | |
814 work = work->next; | |
1167
e812b1a7adda
Add a back button in the toolbar: it allows to go back and forth between two directories. Experimental, please test and comment on ml.
zas_
parents:
1055
diff
changeset
|
815 n++; |
9 | 816 } |
1167
e812b1a7adda
Add a back button in the toolbar: it allows to go back and forth between two directories. Experimental, please test and comment on ml.
zas_
parents:
1055
diff
changeset
|
817 |
e812b1a7adda
Add a back button in the toolbar: it allows to go back and forth between two directories. Experimental, please test and comment on ml.
zas_
parents:
1055
diff
changeset
|
818 if (td->tab_append_func) { |
e812b1a7adda
Add a back button in the toolbar: it allows to go back and forth between two directories. Experimental, please test and comment on ml.
zas_
parents:
1055
diff
changeset
|
819 td->tab_append_func(path, td->tab_append_data, n); |
e812b1a7adda
Add a back button in the toolbar: it allows to go back and forth between two directories. Experimental, please test and comment on ml.
zas_
parents:
1055
diff
changeset
|
820 } |
9 | 821 } |
822 | |
823 GtkWidget *tab_completion_new(GtkWidget **entry, const gchar *text, | |
824 void (*enter_func)(const gchar *, gpointer), gpointer data) | |
825 { | |
826 GtkWidget *hbox; | |
827 GtkWidget *button; | |
828 GtkWidget *newentry; | |
829 | |
830 hbox = gtk_hbox_new(FALSE, 0); | |
831 | |
832 newentry = gtk_entry_new(); | |
833 if (text) gtk_entry_set_text(GTK_ENTRY(newentry), text); | |
834 gtk_box_pack_start(GTK_BOX(hbox), newentry, TRUE, TRUE, 0); | |
835 gtk_widget_show(newentry); | |
836 | |
837 button = tab_completion_create_complete_button(newentry, newentry); | |
838 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); | |
839 gtk_widget_show(button); | |
840 | |
841 tab_completion_add_to_entry(newentry, enter_func, data); | |
842 | |
843 if (entry) *entry = newentry; | |
844 return hbox; | |
845 } | |
846 | |
847 void tab_completion_add_to_entry(GtkWidget *entry, void (*enter_func)(const gchar *, gpointer), gpointer data) | |
848 { | |
849 TabCompData *td; | |
850 if (!entry) | |
851 { | |
673
fbebf5cf4a55
Do not use printf() directly but use new wrapper function log_printf() instead.
zas_
parents:
516
diff
changeset
|
852 log_printf("Tab completion error: entry != NULL\n"); |
9 | 853 return; |
854 } | |
855 | |
856 td = g_new0(TabCompData, 1); | |
1365
249bf204004a
When g_new0() is used, drop redundant initializations to NULL, FALSE or 0.
zas_
parents:
1284
diff
changeset
|
857 |
9 | 858 td->entry = entry; |
859 td->enter_func = enter_func; | |
860 td->enter_data = data; | |
861 | |
862 g_object_set_data(G_OBJECT(td->entry), "tab_completion_data", td); | |
863 | |
864 g_signal_connect(G_OBJECT(entry), "key_press_event", | |
865 G_CALLBACK(tab_completion_key_pressed), td); | |
866 g_signal_connect(G_OBJECT(entry), "destroy", | |
867 G_CALLBACK(tab_completion_destroy), td); | |
868 } | |
869 | |
870 void tab_completion_add_tab_func(GtkWidget *entry, void (*tab_func)(const gchar *, gpointer), gpointer data) | |
871 { | |
872 TabCompData *td = g_object_get_data(G_OBJECT(entry), "tab_completion_data"); | |
873 | |
874 if (!td) return; | |
875 | |
876 td->tab_func = tab_func; | |
877 td->tab_data = data; | |
878 } | |
879 | |
1167
e812b1a7adda
Add a back button in the toolbar: it allows to go back and forth between two directories. Experimental, please test and comment on ml.
zas_
parents:
1055
diff
changeset
|
880 /* Add a callback function called when a new entry is appended to the list */ |
e812b1a7adda
Add a back button in the toolbar: it allows to go back and forth between two directories. Experimental, please test and comment on ml.
zas_
parents:
1055
diff
changeset
|
881 void tab_completion_add_append_func(GtkWidget *entry, void (*tab_append_func)(const gchar *, gpointer, gint), gpointer data) |
e812b1a7adda
Add a back button in the toolbar: it allows to go back and forth between two directories. Experimental, please test and comment on ml.
zas_
parents:
1055
diff
changeset
|
882 { |
e812b1a7adda
Add a back button in the toolbar: it allows to go back and forth between two directories. Experimental, please test and comment on ml.
zas_
parents:
1055
diff
changeset
|
883 TabCompData *td = g_object_get_data(G_OBJECT(entry), "tab_completion_data"); |
e812b1a7adda
Add a back button in the toolbar: it allows to go back and forth between two directories. Experimental, please test and comment on ml.
zas_
parents:
1055
diff
changeset
|
884 |
e812b1a7adda
Add a back button in the toolbar: it allows to go back and forth between two directories. Experimental, please test and comment on ml.
zas_
parents:
1055
diff
changeset
|
885 if (!td) return; |
e812b1a7adda
Add a back button in the toolbar: it allows to go back and forth between two directories. Experimental, please test and comment on ml.
zas_
parents:
1055
diff
changeset
|
886 |
e812b1a7adda
Add a back button in the toolbar: it allows to go back and forth between two directories. Experimental, please test and comment on ml.
zas_
parents:
1055
diff
changeset
|
887 td->tab_append_func = tab_append_func; |
e812b1a7adda
Add a back button in the toolbar: it allows to go back and forth between two directories. Experimental, please test and comment on ml.
zas_
parents:
1055
diff
changeset
|
888 td->tab_append_data = data; |
e812b1a7adda
Add a back button in the toolbar: it allows to go back and forth between two directories. Experimental, please test and comment on ml.
zas_
parents:
1055
diff
changeset
|
889 } |
e812b1a7adda
Add a back button in the toolbar: it allows to go back and forth between two directories. Experimental, please test and comment on ml.
zas_
parents:
1055
diff
changeset
|
890 |
9 | 891 gchar *remove_trailing_slash(const gchar *path) |
892 { | |
893 gint l; | |
260
249a9a6cd27f
Improve remove_trailing_slash() so it allocates no more than
zas_
parents:
254
diff
changeset
|
894 |
9 | 895 if (!path) return NULL; |
896 | |
260
249a9a6cd27f
Improve remove_trailing_slash() so it allocates no more than
zas_
parents:
254
diff
changeset
|
897 l = strlen(path); |
726 | 898 while (l > 1 && path[l - 1] == G_DIR_SEPARATOR) l--; |
9 | 899 |
260
249a9a6cd27f
Improve remove_trailing_slash() so it allocates no more than
zas_
parents:
254
diff
changeset
|
900 return g_strndup(path, l); |
9 | 901 } |
902 | |
903 static void tab_completion_select_cancel_cb(FileDialog *fd, gpointer data) | |
904 { | |
905 TabCompData *td = data; | |
906 | |
907 td->fd = NULL; | |
908 file_dialog_close(fd); | |
909 } | |
910 | |
911 static void tab_completion_select_ok_cb(FileDialog *fd, gpointer data) | |
912 { | |
913 TabCompData *td = data; | |
914 | |
915 gtk_entry_set_text(GTK_ENTRY(td->entry), gtk_entry_get_text(GTK_ENTRY(fd->entry))); | |
916 | |
917 tab_completion_select_cancel_cb(fd, data); | |
918 | |
919 tab_completion_emit_enter_signal(td); | |
920 } | |
921 | |
922 static void tab_completion_select_show(TabCompData *td) | |
923 { | |
924 const gchar *title; | |
925 const gchar *path; | |
926 | |
927 if (td->fd) | |
928 { | |
929 gtk_window_present(GTK_WINDOW(GENERIC_DIALOG(td->fd)->dialog)); | |
930 return; | |
931 } | |
932 | |
933 title = (td->fd_title) ? td->fd_title : _("Select path"); | |
1174
0bea79d87065
Drop useless wmclass stuff. Gtk will take care of it and as said in the documentation using gtk_window_set_wmclass() is sort of pointless.
zas_
parents:
1167
diff
changeset
|
934 td->fd = file_dialog_new(title, "select_path", td->entry, |
9 | 935 tab_completion_select_cancel_cb, td); |
936 file_dialog_add_button(td->fd, GTK_STOCK_OK, NULL, | |
937 tab_completion_select_ok_cb, TRUE); | |
938 | |
939 generic_dialog_add_message(GENERIC_DIALOG(td->fd), NULL, title, NULL); | |
940 | |
941 path = gtk_entry_get_text(GTK_ENTRY(td->entry)); | |
942 if (strlen(path) == 0) path = NULL; | |
943 if (td->fd_folders_only) | |
944 { | |
945 file_dialog_add_path_widgets(td->fd, NULL, path, td->history_key, NULL, NULL); | |
946 } | |
947 else | |
948 { | |
949 file_dialog_add_path_widgets(td->fd, NULL, path, td->history_key, "*", _("All files")); | |
950 } | |
951 | |
952 gtk_widget_show(GENERIC_DIALOG(td->fd)->dialog); | |
953 } | |
954 | |
955 static void tab_completion_select_pressed(GtkWidget *widget, gpointer data) | |
956 { | |
957 TabCompData *td = data; | |
958 | |
959 tab_completion_select_show(td); | |
960 } | |
961 | |
1448 | 962 void tab_completion_add_select_button(GtkWidget *entry, const gchar *title, gboolean folders_only) |
9 | 963 { |
964 TabCompData *td; | |
965 GtkWidget *parent; | |
966 GtkWidget *hbox; | |
967 | |
968 td = g_object_get_data(G_OBJECT(entry), "tab_completion_data"); | |
969 | |
970 if (!td) return; | |
971 | |
972 g_free(td->fd_title); | |
973 td->fd_title = g_strdup(title); | |
974 td->fd_folders_only = folders_only; | |
975 | |
976 if (td->fd_button) return; | |
977 | |
978 parent = (td->combo) ? td->combo : td->entry; | |
979 | |
980 hbox = gtk_widget_get_parent(parent); | |
981 if (!GTK_IS_BOX(hbox)) return; | |
982 | |
983 td->fd_button = gtk_button_new_with_label("..."); | |
984 g_signal_connect(G_OBJECT(td->fd_button), "size_allocate", | |
985 G_CALLBACK(tab_completion_button_size_allocate), parent); | |
986 g_signal_connect(G_OBJECT(td->fd_button), "clicked", | |
987 G_CALLBACK(tab_completion_select_pressed), td); | |
988 | |
989 gtk_box_pack_start(GTK_BOX(hbox), td->fd_button, FALSE, FALSE, 0); | |
990 | |
991 gtk_widget_show(td->fd_button); | |
992 } | |
1055
1646720364cf
Adding a vim modeline to all files - patch by Klaus Ethgen
nadvornik
parents:
1043
diff
changeset
|
993 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ |