Mercurial > geeqie.yaz
annotate src/search.c @ 276:4f526d436873
Implement secure rc file saving.
First data is written to a temporary file, then if nothing
was wrong, this file is renamed to the final name.
This way the risk of corrupted rc file is greatly reduced.
The code is borrowed from ELinks (http://elinks.cz).
author | zas_ |
---|---|
date | Tue, 08 Apr 2008 21:55:58 +0000 |
parents | 9faf34f047b1 |
children | 9995c5fb202a |
rev | line source |
---|---|
9 | 1 /* |
196 | 2 * Geeqie |
9 | 3 * (C) 2005 John Ellis |
4 * | |
5 * Author: John Ellis | |
6 * | |
7 * This software is released under the GNU General Public License (GNU GPL). | |
8 * Please read the included file COPYING for more information. | |
9 * This software comes with no warranty of any kind, use at your own risk! | |
10 */ | |
11 | |
12 | |
13 #include "gqview.h" | |
14 #include "search.h" | |
15 | |
16 #include "bar_info.h" | |
17 #include "cache.h" | |
18 #include "collect.h" | |
19 #include "collect-table.h" | |
20 #include "dnd.h" | |
21 #include "dupe.h" | |
22 #include "image-load.h" | |
23 #include "info.h" | |
24 #include "editors.h" | |
25 #include "img-view.h" | |
26 #include "filelist.h" | |
27 #include "layout_image.h" | |
28 #include "menu.h" | |
29 #include "print.h" | |
30 #include "thumb.h" | |
31 #include "utilops.h" | |
32 #include "ui_bookmark.h" | |
33 #include "ui_fileops.h" | |
34 #include "ui_menu.h" | |
35 #include "ui_misc.h" | |
36 #include "ui_spinner.h" | |
37 #include "ui_tabcomp.h" | |
38 #include "ui_tree_edit.h" | |
39 | |
40 #include <gdk/gdkkeysyms.h> /* for keyboard values */ | |
41 | |
42 | |
43 #define DEF_SEARCH_WIDTH 700 | |
44 #define DEF_SEARCH_HEIGHT 450 | |
45 | |
46 #define SEARCH_BUFFER_MATCH_LOAD 20 | |
47 #define SEARCH_BUFFER_MATCH_HIT 5 | |
48 #define SEARCH_BUFFER_MATCH_MISS 1 | |
49 #define SEARCH_BUFFER_FLUSH_SIZE 99 | |
50 | |
51 | |
52 typedef enum { | |
53 SEARCH_MATCH_NONE, | |
54 SEARCH_MATCH_EQUAL, | |
55 SEARCH_MATCH_CONTAINS, | |
56 SEARCH_MATCH_UNDER, | |
57 SEARCH_MATCH_OVER, | |
58 SEARCH_MATCH_BETWEEN, | |
59 SEARCH_MATCH_ALL, | |
60 SEARCH_MATCH_ANY | |
61 } MatchType; | |
62 | |
63 enum { | |
64 SEARCH_COLUMN_POINTER = 0, | |
65 SEARCH_COLUMN_RANK, | |
66 SEARCH_COLUMN_THUMB, | |
67 SEARCH_COLUMN_NAME, | |
68 SEARCH_COLUMN_SIZE, | |
69 SEARCH_COLUMN_DATE, | |
70 SEARCH_COLUMN_DIMENSIONS, | |
71 SEARCH_COLUMN_PATH, | |
72 SEARCH_COLUMN_COUNT /* total columns */ | |
73 }; | |
74 | |
75 typedef struct _SearchData SearchData; | |
76 struct _SearchData | |
77 { | |
78 GtkWidget *window; | |
79 | |
80 GtkWidget *button_thumbs; | |
81 GtkWidget *label_status; | |
82 GtkWidget *label_progress; | |
83 GtkWidget *button_start; | |
84 GtkWidget *button_stop; | |
85 GtkWidget *spinner; | |
86 | |
87 GtkWidget *box_search; | |
88 | |
89 GtkWidget *menu_path; | |
90 GtkWidget *path_entry; | |
91 GtkWidget *check_recurse; | |
92 | |
93 GtkWidget *result_view; | |
94 | |
95 GtkWidget *check_name; | |
96 GtkWidget *menu_name; | |
97 GtkWidget *entry_name; | |
98 GtkWidget *check_name_match_case; | |
99 | |
100 GtkWidget *check_size; | |
101 GtkWidget *menu_size; | |
102 GtkWidget *spin_size; | |
103 GtkWidget *spin_size_end; | |
104 | |
105 GtkWidget *check_date; | |
106 GtkWidget *menu_date; | |
107 GtkWidget *date_sel; | |
108 GtkWidget *date_sel_end; | |
109 | |
110 GtkWidget *check_dimensions; | |
111 GtkWidget *menu_dimensions; | |
112 GtkWidget *spin_width; | |
113 GtkWidget *spin_height; | |
114 GtkWidget *spin_width_end; | |
115 GtkWidget *spin_height_end; | |
116 | |
117 GtkWidget *check_similarity; | |
118 GtkWidget *spin_similarity; | |
119 GtkWidget *entry_similarity; | |
120 | |
121 GtkWidget *check_keywords; | |
122 GtkWidget *menu_keywords; | |
123 GtkWidget *entry_keywords; | |
124 | |
125 gchar *search_path; | |
126 gint search_path_recurse; | |
127 gchar *search_name; | |
128 gint search_name_match_case; | |
129 gint64 search_size; | |
130 gint64 search_size_end; | |
131 gint search_date_y; | |
132 gint search_date_m; | |
133 gint search_date_d; | |
134 gint search_date_end_y; | |
135 gint search_date_end_m; | |
136 gint search_date_end_d; | |
137 gint search_width; | |
138 gint search_height; | |
139 gint search_width_end; | |
140 gint search_height_end; | |
141 gint search_similarity; | |
142 gchar *search_similarity_path; | |
143 CacheData *search_similarity_cd; | |
144 GList *search_keyword_list; | |
145 | |
146 MatchType search_type; | |
147 | |
148 MatchType match_name; | |
149 MatchType match_size; | |
150 MatchType match_date; | |
151 MatchType match_dimensions; | |
152 MatchType match_keywords; | |
153 | |
154 gboolean match_name_enable; | |
155 gboolean match_size_enable; | |
156 gboolean match_date_enable; | |
157 gboolean match_dimensions_enable; | |
158 gboolean match_similarity_enable; | |
159 gboolean match_keywords_enable; | |
160 | |
161 GList *search_folder_list; | |
162 GList *search_done_list; | |
163 GList *search_file_list; | |
164 GList *search_buffer_list; | |
165 | |
166 gint search_count; | |
167 gint search_total; | |
168 gint search_buffer_count; | |
169 | |
170 gint search_idle_id; | |
171 gint update_idle_id; | |
172 | |
173 ImageLoader *img_loader; | |
174 CacheData *img_cd; | |
175 | |
176 FileData *click_fd; | |
177 | |
178 ThumbLoader *thumb_loader; | |
179 gint thumb_enable; | |
180 FileData *thumb_fd; | |
181 }; | |
182 | |
183 typedef struct _MatchFileData MatchFileData; | |
184 struct _MatchFileData | |
185 { | |
138 | 186 FileData *fd; |
9 | 187 gint width; |
188 gint height; | |
189 gint rank; | |
190 }; | |
191 | |
192 typedef struct _MatchList MatchList; | |
193 struct _MatchList | |
194 { | |
195 const gchar *text; | |
196 const MatchType type; | |
197 }; | |
198 | |
199 static const MatchList text_search_menu_path[] = { | |
200 { N_("folder"), SEARCH_MATCH_NONE }, | |
201 { N_("comments"), SEARCH_MATCH_ALL }, | |
202 { N_("results"), SEARCH_MATCH_CONTAINS } | |
203 }; | |
204 | |
205 static const MatchList text_search_menu_name[] = { | |
206 { N_("contains"), SEARCH_MATCH_CONTAINS }, | |
207 { N_("is"), SEARCH_MATCH_EQUAL } | |
208 }; | |
209 | |
210 static const MatchList text_search_menu_size[] = { | |
211 { N_("equal to"), SEARCH_MATCH_EQUAL }, | |
212 { N_("less than"), SEARCH_MATCH_UNDER }, | |
213 { N_("greater than"), SEARCH_MATCH_OVER }, | |
214 { N_("between"), SEARCH_MATCH_BETWEEN } | |
215 }; | |
216 | |
217 static const MatchList text_search_menu_date[] = { | |
218 { N_("equal to"), SEARCH_MATCH_EQUAL }, | |
219 { N_("before"), SEARCH_MATCH_UNDER }, | |
220 { N_("after"), SEARCH_MATCH_OVER }, | |
221 { N_("between"), SEARCH_MATCH_BETWEEN } | |
222 }; | |
223 | |
224 static const MatchList text_search_menu_keyword[] = { | |
225 { N_("match all"), SEARCH_MATCH_ALL }, | |
226 { N_("match any"), SEARCH_MATCH_ANY }, | |
227 { N_("exclude"), SEARCH_MATCH_NONE } | |
228 }; | |
229 | |
230 static GList *search_window_list = NULL; | |
231 | |
232 | |
233 static gint search_result_selection_count(SearchData *sd, gint64 *bytes); | |
234 static gint search_result_count(SearchData *sd, gint64 *bytes); | |
235 | |
236 static void search_window_close(SearchData *sd); | |
237 | |
238 | |
239 /* | |
240 *------------------------------------------------------------------- | |
241 * utils | |
242 *------------------------------------------------------------------- | |
243 */ | |
244 | |
245 static time_t convert_dmy_to_time(gint day, gint month, gint year) | |
246 { | |
247 struct tm lt; | |
248 | |
249 lt.tm_sec = 0; | |
250 lt.tm_min = 0; | |
251 lt.tm_hour = 0; | |
252 lt.tm_mday = day; | |
253 lt.tm_mon = month - 1; | |
254 lt.tm_year = year - 1900; | |
255 lt.tm_isdst = 0; | |
256 | |
257 return mktime(<); | |
258 } | |
259 | |
260 static void search_status_update(SearchData *sd) | |
261 { | |
262 gchar *buf; | |
263 gint t; | |
264 gint s; | |
265 gint64 t_bytes; | |
266 gint64 s_bytes; | |
267 gchar *tt; | |
268 gchar *ts; | |
269 | |
270 t = search_result_count(sd, &t_bytes); | |
271 s = search_result_selection_count(sd, &s_bytes); | |
272 | |
273 if (s > 0) | |
274 { | |
275 tt = text_from_size_abrev(t_bytes); | |
276 ts = text_from_size_abrev(s_bytes); | |
277 buf = g_strdup_printf(_("%s, %d files (%s, %d)"), tt, t, ts, s); | |
278 g_free(tt); | |
279 g_free(ts); | |
280 } | |
281 else | |
282 { | |
283 tt = text_from_size_abrev(t_bytes); | |
284 buf = g_strdup_printf(_("%s, %d files"), tt, t); | |
285 g_free(tt); | |
286 } | |
287 | |
288 gtk_label_set_text(GTK_LABEL(sd->label_status), buf); | |
289 g_free(buf); | |
290 } | |
291 | |
292 static void search_progress_update(SearchData *sd, gint search, gdouble thumbs) | |
293 { | |
294 | |
295 if (search || thumbs >= 0.0) | |
296 { | |
297 gchar *buf; | |
298 const gchar *message; | |
299 | |
300 if (search && (sd->search_folder_list || sd->search_file_list)) | |
301 message = _("Searching..."); | |
302 else if (thumbs >= 0.0) | |
303 message = _("Loading thumbs..."); | |
304 else | |
305 message = ""; | |
306 | |
307 buf = g_strdup_printf("%s(%d / %d)", message, sd->search_count, sd->search_total); | |
308 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(sd->label_progress), buf); | |
309 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(sd->label_progress), | |
310 (thumbs >= 0.0) ? thumbs : 0.0); | |
311 g_free(buf); | |
312 } | |
313 else | |
314 { | |
315 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(sd->label_progress), ""); | |
316 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(sd->label_progress), 0.0); | |
317 } | |
318 } | |
319 | |
320 /* | |
321 *------------------------------------------------------------------- | |
322 * result list | |
323 *------------------------------------------------------------------- | |
324 */ | |
325 | |
326 static gint search_result_find_row(SearchData *sd, FileData *fd, GtkTreeIter *iter) | |
327 { | |
328 GtkTreeModel *store; | |
329 gint valid; | |
330 gint n = 0; | |
331 | |
332 store = gtk_tree_view_get_model(GTK_TREE_VIEW(sd->result_view)); | |
333 valid = gtk_tree_model_get_iter_first(store, iter); | |
334 while (valid) | |
335 { | |
138 | 336 MatchFileData *mfd; |
9 | 337 n++; |
338 | |
138 | 339 gtk_tree_model_get(store, iter, SEARCH_COLUMN_POINTER, &mfd, -1); |
340 if (mfd->fd == fd) return n; | |
9 | 341 valid = gtk_tree_model_iter_next(store, iter); |
342 } | |
343 | |
344 return -1; | |
345 } | |
346 | |
347 static gint search_result_row_selected(SearchData *sd, FileData *fd) | |
348 { | |
349 GtkTreeModel *store; | |
350 GtkTreeSelection *selection; | |
351 GList *slist; | |
352 GList *work; | |
353 gint found = FALSE; | |
354 | |
355 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(sd->result_view)); | |
356 slist = gtk_tree_selection_get_selected_rows(selection, &store); | |
357 work = slist; | |
358 while (!found && work) | |
359 { | |
360 GtkTreePath *tpath = work->data; | |
138 | 361 MatchFileData *mfd_n; |
9 | 362 GtkTreeIter iter; |
363 | |
364 gtk_tree_model_get_iter(store, &iter, tpath); | |
138 | 365 gtk_tree_model_get(store, &iter, SEARCH_COLUMN_POINTER, &mfd_n, -1); |
366 if (mfd_n->fd == fd) found = TRUE; | |
9 | 367 work = work->next; |
368 } | |
369 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL); | |
370 g_list_free(slist); | |
371 | |
372 return found; | |
373 } | |
374 | |
375 static gint search_result_selection_util(SearchData *sd, gint64 *bytes, GList **list) | |
376 { | |
377 GtkTreeModel *store; | |
378 GtkTreeSelection *selection; | |
379 GList *slist; | |
380 GList *work; | |
381 gint n = 0; | |
382 gint64 total = 0; | |
383 GList *plist = NULL; | |
384 | |
385 store = gtk_tree_view_get_model(GTK_TREE_VIEW(sd->result_view)); | |
386 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(sd->result_view)); | |
387 slist = gtk_tree_selection_get_selected_rows(selection, &store); | |
388 work = slist; | |
389 while (work) | |
390 { | |
391 n++; | |
392 | |
393 if (bytes || list) | |
394 { | |
395 GtkTreePath *tpath = work->data; | |
138 | 396 MatchFileData *mfd; |
9 | 397 GtkTreeIter iter; |
398 | |
399 gtk_tree_model_get_iter(store, &iter, tpath); | |
138 | 400 gtk_tree_model_get(store, &iter, SEARCH_COLUMN_POINTER, &mfd, -1); |
401 total += mfd->fd->size; | |
402 | |
403 if (list) plist = g_list_prepend(plist, file_data_ref(mfd->fd)); | |
9 | 404 } |
405 | |
406 work = work->next; | |
407 } | |
408 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL); | |
409 g_list_free(slist); | |
410 | |
411 if (bytes) *bytes = total; | |
412 if (list) *list = g_list_reverse(plist); | |
413 | |
414 return n; | |
415 } | |
416 | |
417 static GList *search_result_selection_list(SearchData *sd) | |
418 { | |
419 GList *list; | |
420 | |
421 search_result_selection_util(sd, NULL, &list); | |
422 return list; | |
423 } | |
424 | |
425 static gint search_result_selection_count(SearchData *sd, gint64 *bytes) | |
426 { | |
427 return search_result_selection_util(sd, bytes, NULL); | |
428 } | |
429 | |
430 static gint search_result_util(SearchData *sd, gint64 *bytes, GList **list) | |
431 { | |
432 GtkTreeModel *store; | |
433 GtkTreeIter iter; | |
434 gint valid; | |
435 gint n = 0; | |
436 gint64 total = 0; | |
437 GList *plist = NULL; | |
438 | |
439 store = gtk_tree_view_get_model(GTK_TREE_VIEW(sd->result_view)); | |
440 | |
441 valid = gtk_tree_model_get_iter_first(store, &iter); | |
442 while (valid) | |
443 { | |
444 n++; | |
445 if (bytes || list) | |
446 { | |
138 | 447 MatchFileData *mfd; |
448 | |
449 gtk_tree_model_get(store, &iter, SEARCH_COLUMN_POINTER, &mfd, -1); | |
450 total += mfd->fd->size; | |
451 | |
452 if (list) plist = g_list_prepend(plist, file_data_ref(mfd->fd)); | |
9 | 453 } |
454 valid = gtk_tree_model_iter_next(store, &iter); | |
455 } | |
456 | |
457 if (bytes) *bytes = total; | |
458 if (list) *list = g_list_reverse(plist); | |
459 | |
460 return n; | |
461 } | |
462 | |
138 | 463 static GList *search_result_get_filelist(SearchData *sd) |
9 | 464 { |
465 GList *list = NULL; | |
466 | |
467 search_result_util(sd, NULL, &list); | |
468 return list; | |
469 } | |
470 | |
471 static gint search_result_count(SearchData *sd, gint64 *bytes) | |
472 { | |
473 return search_result_util(sd, bytes, NULL); | |
474 } | |
475 | |
476 static void search_result_append(SearchData *sd, MatchFileData *mfd) | |
477 { | |
478 FileData *fd; | |
479 GtkListStore *store; | |
480 GtkTreeIter iter; | |
481 gchar *text_size; | |
482 gchar *text_dim = NULL; | |
483 | |
138 | 484 fd = mfd->fd; |
9 | 485 |
486 if (!fd) return; | |
487 | |
488 text_size = text_from_size(fd->size); | |
489 if (mfd->width > 0 && mfd->height > 0) text_dim = g_strdup_printf("%d x %d", mfd->width, mfd->height); | |
490 | |
491 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(sd->result_view))); | |
492 gtk_list_store_append(store, &iter); | |
493 gtk_list_store_set(store, &iter, | |
138 | 494 SEARCH_COLUMN_POINTER, mfd, |
9 | 495 SEARCH_COLUMN_RANK, mfd->rank, |
496 SEARCH_COLUMN_THUMB, fd->pixbuf, | |
497 SEARCH_COLUMN_NAME, fd->name, | |
498 SEARCH_COLUMN_SIZE, text_size, | |
499 SEARCH_COLUMN_DATE, text_from_time(fd->date), | |
500 SEARCH_COLUMN_DIMENSIONS, text_dim, | |
501 SEARCH_COLUMN_PATH, fd->path, | |
502 -1); | |
503 | |
504 g_free(text_size); | |
505 g_free(text_dim); | |
506 } | |
507 | |
508 static GList *search_result_refine_list(SearchData *sd) | |
509 { | |
510 GList *list = NULL; | |
511 GtkTreeModel *store; | |
512 GtkTreeIter iter; | |
513 gint valid; | |
514 | |
515 store = gtk_tree_view_get_model(GTK_TREE_VIEW(sd->result_view)); | |
516 | |
517 valid = gtk_tree_model_get_iter_first(store, &iter); | |
518 while (valid) | |
519 { | |
138 | 520 MatchFileData *mfd; |
521 | |
522 gtk_tree_model_get(store, &iter, SEARCH_COLUMN_POINTER, &mfd, -1); | |
523 list = g_list_prepend(list, mfd->fd); | |
9 | 524 |
525 valid = gtk_tree_model_iter_next(store, &iter); | |
526 } | |
527 | |
528 /* clear it here, so that the FileData in list is not freed */ | |
529 gtk_list_store_clear(GTK_LIST_STORE(store)); | |
530 | |
531 return g_list_reverse(list); | |
532 } | |
533 | |
534 static gboolean search_result_free_node(GtkTreeModel *store, GtkTreePath *tpath, | |
535 GtkTreeIter *iter, gpointer data) | |
536 { | |
138 | 537 MatchFileData *mfd; |
538 | |
539 gtk_tree_model_get(store, iter, SEARCH_COLUMN_POINTER, &mfd, -1); | |
540 file_data_unref(mfd->fd); | |
541 g_free(mfd); | |
9 | 542 |
543 return FALSE; | |
544 } | |
545 | |
546 static void search_result_clear(SearchData *sd) | |
547 { | |
548 GtkListStore *store; | |
549 | |
550 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(sd->result_view))); | |
551 | |
552 gtk_tree_model_foreach(GTK_TREE_MODEL(store), search_result_free_node, sd); | |
553 gtk_list_store_clear(store); | |
554 | |
555 sd->click_fd = NULL; | |
556 | |
557 thumb_loader_free(sd->thumb_loader); | |
558 sd->thumb_loader = NULL; | |
559 sd->thumb_fd = NULL; | |
560 | |
561 search_status_update(sd); | |
562 } | |
563 | |
138 | 564 static void search_result_remove_item(SearchData *sd, MatchFileData *mfd, GtkTreeIter *iter) |
9 | 565 { |
566 GtkTreeModel *store; | |
567 | |
138 | 568 if (!mfd || !iter) return; |
9 | 569 |
570 store = gtk_tree_view_get_model(GTK_TREE_VIEW(sd->result_view)); | |
571 | |
572 tree_view_move_cursor_away(GTK_TREE_VIEW(sd->result_view), iter, TRUE); | |
573 | |
574 gtk_list_store_remove(GTK_LIST_STORE(store), iter); | |
138 | 575 if (sd->click_fd == mfd->fd) sd->click_fd = NULL; |
576 if (sd->thumb_fd == mfd->fd) sd->thumb_fd = NULL; | |
577 file_data_unref(mfd->fd); | |
578 g_free(mfd); | |
9 | 579 } |
580 | |
581 static void search_result_remove(SearchData *sd, FileData *fd) | |
582 { | |
583 GtkTreeModel *store; | |
584 GtkTreeIter iter; | |
585 gint valid; | |
586 | |
587 store = gtk_tree_view_get_model(GTK_TREE_VIEW(sd->result_view)); | |
588 valid = gtk_tree_model_get_iter_first(store, &iter); | |
589 while (valid) | |
590 { | |
138 | 591 MatchFileData *mfd; |
592 | |
593 gtk_tree_model_get(store, &iter, SEARCH_COLUMN_POINTER, &mfd, -1); | |
594 if (mfd->fd == fd) | |
9 | 595 { |
138 | 596 search_result_remove_item(sd, mfd, &iter); |
9 | 597 return; |
598 } | |
599 | |
600 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter); | |
601 } | |
602 } | |
603 | |
604 static void search_result_remove_selection(SearchData *sd) | |
605 { | |
606 GtkTreeSelection *selection; | |
607 GtkTreeModel *store; | |
608 GList *slist; | |
609 GList *flist = NULL; | |
610 GList *work; | |
611 | |
612 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(sd->result_view)); | |
613 slist = gtk_tree_selection_get_selected_rows(selection, &store); | |
614 work = slist; | |
615 while (work) | |
616 { | |
617 GtkTreePath *tpath = work->data; | |
618 GtkTreeIter iter; | |
138 | 619 MatchFileData *mfd; |
9 | 620 |
621 gtk_tree_model_get_iter(store, &iter, tpath); | |
138 | 622 gtk_tree_model_get(store, &iter, SEARCH_COLUMN_POINTER, &mfd, -1); |
623 flist = g_list_prepend(flist, mfd->fd); | |
9 | 624 work = work->next; |
625 } | |
626 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL); | |
627 g_list_free(slist); | |
628 | |
629 work = flist; | |
630 while (work) | |
631 { | |
632 FileData *fd = work->data; | |
633 work = work->next; | |
634 | |
635 search_result_remove(sd, fd); | |
636 } | |
637 g_list_free(flist); | |
638 | |
639 search_status_update(sd); | |
640 } | |
641 | |
642 static void search_result_edit_selected(SearchData *sd, gint n) | |
643 { | |
644 GList *list; | |
645 | |
646 list = search_result_selection_list(sd); | |
138 | 647 start_editor_from_filelist(n, list); |
648 filelist_free(list); | |
9 | 649 } |
650 | |
651 static void search_result_collection_from_selection(SearchData *sd) | |
652 { | |
653 CollectWindow *w; | |
654 GList *list; | |
655 | |
656 list = search_result_selection_list(sd); | |
657 w = collection_window_new(NULL); | |
138 | 658 collection_table_add_filelist(w->table, list); |
659 filelist_free(list); | |
9 | 660 } |
661 | |
662 static gint search_result_update_idle_cb(gpointer data) | |
663 { | |
664 SearchData *sd = data; | |
665 | |
666 search_status_update(sd); | |
667 | |
668 sd->update_idle_id = -1; | |
669 return FALSE; | |
670 } | |
671 | |
672 static void search_result_update_idle_cancel(SearchData *sd) | |
673 { | |
674 if (sd->update_idle_id != -1) g_source_remove(sd->update_idle_id); | |
675 sd->update_idle_id = -1; | |
676 } | |
677 | |
678 static gboolean search_result_select_cb(GtkTreeSelection *selection, GtkTreeModel *store, | |
679 GtkTreePath *tpath, gboolean selected, gpointer data) | |
680 { | |
681 SearchData *sd = data; | |
682 | |
683 if (sd->update_idle_id == -1) | |
684 { | |
685 sd->update_idle_id = g_idle_add(search_result_update_idle_cb, sd); | |
686 } | |
687 | |
688 return TRUE; | |
689 } | |
690 | |
691 /* | |
692 *------------------------------------------------------------------- | |
693 * result list thumbs | |
694 *------------------------------------------------------------------- | |
695 */ | |
696 | |
697 static void search_result_thumb_step(SearchData *sd); | |
698 | |
699 | |
700 static void search_result_thumb_set(SearchData *sd, FileData *fd, GtkTreeIter *iter) | |
701 { | |
702 GtkListStore *store; | |
703 GtkTreeIter iter_n; | |
704 | |
705 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(sd->result_view))); | |
706 if (!iter) | |
707 { | |
708 if (search_result_find_row(sd, fd, &iter_n) >= 0) iter = &iter_n; | |
709 } | |
710 | |
711 if (iter) gtk_list_store_set(store, iter, SEARCH_COLUMN_THUMB, fd->pixbuf, -1); | |
712 } | |
713 | |
714 static void search_result_thumb_do(SearchData *sd) | |
715 { | |
716 FileData *fd; | |
717 | |
718 if (!sd->thumb_loader || !sd->thumb_fd) return; | |
719 fd = sd->thumb_fd; | |
720 | |
721 if (fd->pixbuf) g_object_unref(fd->pixbuf); | |
722 fd->pixbuf = thumb_loader_get_pixbuf(sd->thumb_loader, TRUE); | |
723 | |
724 search_result_thumb_set(sd, fd, NULL); | |
725 } | |
726 | |
727 static void search_result_thumb_done_cb(ThumbLoader *tl, gpointer data) | |
728 { | |
729 SearchData *sd = data; | |
730 | |
731 search_result_thumb_do(sd); | |
732 search_result_thumb_step(sd); | |
733 } | |
734 | |
735 static void search_result_thumb_step(SearchData *sd) | |
736 { | |
737 GtkTreeModel *store; | |
738 GtkTreeIter iter; | |
138 | 739 MatchFileData *mfd = NULL; |
9 | 740 gint valid; |
741 gint row = 0; | |
742 gint length = 0; | |
743 | |
744 if (!sd->thumb_enable) return; | |
745 | |
746 store = gtk_tree_view_get_model(GTK_TREE_VIEW(sd->result_view)); | |
747 | |
748 valid = gtk_tree_model_get_iter_first(store, &iter); | |
138 | 749 while (!mfd && valid) |
9 | 750 { |
751 GdkPixbuf *pixbuf; | |
752 | |
753 length++; | |
138 | 754 gtk_tree_model_get(store, &iter, SEARCH_COLUMN_POINTER, &mfd, SEARCH_COLUMN_THUMB, &pixbuf, -1); |
755 if (pixbuf || mfd->fd->pixbuf) | |
9 | 756 { |
138 | 757 if (!pixbuf) gtk_list_store_set(GTK_LIST_STORE(store), &iter, SEARCH_COLUMN_THUMB, mfd->fd->pixbuf, -1); |
9 | 758 row++; |
138 | 759 mfd = NULL; |
9 | 760 } |
761 valid = gtk_tree_model_iter_next(store, &iter); | |
762 } | |
763 if (valid) | |
764 { | |
765 while (gtk_tree_model_iter_next(store, &iter)) length++; | |
766 } | |
767 | |
138 | 768 if (!mfd) |
9 | 769 { |
770 sd->thumb_fd = NULL; | |
771 thumb_loader_free(sd->thumb_loader); | |
772 sd->thumb_loader = NULL; | |
773 | |
774 search_progress_update(sd, TRUE, -1.0); | |
775 return; | |
776 } | |
777 | |
778 search_progress_update(sd, FALSE, (gdouble)row/length); | |
779 | |
138 | 780 sd->thumb_fd = mfd->fd; |
9 | 781 thumb_loader_free(sd->thumb_loader); |
782 sd->thumb_loader = thumb_loader_new(thumb_max_width, thumb_max_height); | |
783 | |
784 thumb_loader_set_callbacks(sd->thumb_loader, | |
785 search_result_thumb_done_cb, | |
786 search_result_thumb_done_cb, | |
787 NULL, | |
788 sd); | |
138 | 789 if (!thumb_loader_start(sd->thumb_loader, mfd->fd->path)) |
9 | 790 { |
791 search_result_thumb_do(sd); | |
792 search_result_thumb_step(sd); | |
793 } | |
794 } | |
795 | |
796 static void search_result_thumb_height(SearchData *sd) | |
797 { | |
798 GtkTreeViewColumn *column; | |
799 GtkCellRenderer *cell; | |
800 GList *list; | |
801 | |
802 column = gtk_tree_view_get_column(GTK_TREE_VIEW(sd->result_view), SEARCH_COLUMN_THUMB - 1); | |
803 if (!column) return; | |
804 | |
805 gtk_tree_view_column_set_fixed_width(column, (sd->thumb_enable) ? thumb_max_width : 4); | |
806 | |
807 list = gtk_tree_view_column_get_cell_renderers(column); | |
808 if (!list) return; | |
809 cell = list->data; | |
810 g_list_free(list); | |
811 | |
812 g_object_set(G_OBJECT(cell), "height", (sd->thumb_enable) ? thumb_max_height : -1, NULL); | |
813 gtk_tree_view_columns_autosize(GTK_TREE_VIEW(sd->result_view)); | |
814 } | |
815 | |
816 static void search_result_thumb_enable(SearchData *sd, gint enable) | |
817 { | |
818 if (sd->thumb_enable == enable) return; | |
819 | |
820 if (sd->thumb_enable) | |
821 { | |
822 GtkTreeModel *store; | |
823 GtkTreeIter iter; | |
824 gint valid; | |
825 | |
826 thumb_loader_free(sd->thumb_loader); | |
827 sd->thumb_loader = NULL; | |
828 | |
829 store = gtk_tree_view_get_model(GTK_TREE_VIEW(sd->result_view)); | |
830 valid = gtk_tree_model_get_iter_first(store, &iter); | |
831 while (valid) | |
832 { | |
833 gtk_list_store_set(GTK_LIST_STORE(store), &iter, SEARCH_COLUMN_THUMB, NULL, -1); | |
834 valid = gtk_tree_model_iter_next(store, &iter); | |
835 } | |
836 search_progress_update(sd, TRUE, -1.0); | |
837 } | |
838 | |
839 sd->thumb_enable = enable; | |
840 | |
841 search_result_thumb_height(sd); | |
842 if (!sd->search_folder_list && !sd->search_file_list) search_result_thumb_step(sd); | |
843 } | |
844 | |
845 /* | |
846 *------------------------------------------------------------------- | |
847 * result list menu | |
848 *------------------------------------------------------------------- | |
849 */ | |
850 | |
851 static void sr_menu_view_cb(GtkWidget *widget, gpointer data) | |
852 { | |
853 SearchData *sd = data; | |
854 | |
138 | 855 if (sd->click_fd) layout_image_set_fd(NULL, sd->click_fd); |
9 | 856 } |
857 | |
858 static void sr_menu_viewnew_cb(GtkWidget *widget, gpointer data) | |
859 { | |
860 SearchData *sd = data; | |
861 GList *list; | |
862 | |
863 list = search_result_selection_list(sd); | |
864 view_window_new_from_list(list); | |
138 | 865 filelist_free(list); |
9 | 866 } |
867 | |
868 static void sr_menu_select_all_cb(GtkWidget *widget, gpointer data) | |
869 { | |
870 SearchData *sd = data; | |
871 GtkTreeSelection *selection; | |
872 | |
873 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(sd->result_view)); | |
874 gtk_tree_selection_select_all(selection); | |
875 } | |
876 | |
877 static void sr_menu_select_none_cb(GtkWidget *widget, gpointer data) | |
878 { | |
879 SearchData *sd = data; | |
880 GtkTreeSelection *selection; | |
881 | |
882 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(sd->result_view)); | |
883 gtk_tree_selection_unselect_all(selection); | |
884 } | |
885 | |
886 static void sr_menu_edit_cb(GtkWidget *widget, gpointer data) | |
887 { | |
888 SearchData *sd; | |
889 gint n; | |
890 | |
891 sd = submenu_item_get_data(widget); | |
892 n = GPOINTER_TO_INT(data); | |
893 if (!sd) return; | |
894 | |
895 search_result_edit_selected(sd, n); | |
896 } | |
897 | |
898 static void sr_menu_info_cb(GtkWidget *widget, gpointer data) | |
899 { | |
900 SearchData *sd = data; | |
901 | |
902 info_window_new(NULL, search_result_selection_list(sd)); | |
903 } | |
904 | |
905 static void sr_menu_collection_cb(GtkWidget *widget, gpointer data) | |
906 { | |
907 SearchData *sd = data; | |
908 | |
909 search_result_collection_from_selection(sd); | |
910 } | |
911 | |
912 static void sr_menu_print_cb(GtkWidget *widget, gpointer data) | |
913 { | |
914 SearchData *sd = data; | |
250 | 915 |
138 | 916 print_window_new(sd->click_fd, search_result_selection_list(sd), |
917 search_result_get_filelist(sd), sd->window); | |
9 | 918 } |
919 | |
920 static void sr_menu_copy_cb(GtkWidget *widget, gpointer data) | |
921 { | |
922 SearchData *sd = data; | |
923 | |
924 file_util_copy(NULL, search_result_selection_list(sd), NULL, sd->window); | |
925 } | |
926 | |
927 static void sr_menu_move_cb(GtkWidget *widget, gpointer data) | |
928 { | |
929 SearchData *sd = data; | |
930 | |
931 file_util_move(NULL, search_result_selection_list(sd), NULL, sd->window); | |
932 } | |
933 | |
934 static void sr_menu_rename_cb(GtkWidget *widget, gpointer data) | |
935 { | |
936 SearchData *sd = data; | |
937 | |
938 file_util_rename(NULL, search_result_selection_list(sd), sd->window); | |
939 } | |
940 | |
941 static void sr_menu_delete_cb(GtkWidget *widget, gpointer data) | |
942 { | |
943 SearchData *sd = data; | |
944 | |
945 file_util_delete(NULL, search_result_selection_list(sd), sd->window); | |
946 } | |
947 | |
948 static void sr_menu_remove_cb(GtkWidget *widget, gpointer data) | |
949 { | |
950 SearchData *sd = data; | |
951 | |
952 search_result_remove_selection(sd); | |
953 } | |
954 | |
955 static void sr_menu_clear_cb(GtkWidget *widget, gpointer data) | |
956 { | |
957 SearchData *sd = data; | |
958 | |
959 search_result_clear(sd); | |
960 } | |
961 | |
962 static GtkWidget *search_result_menu(SearchData *sd, gint on_row, gint empty) | |
963 { | |
964 GtkWidget *menu; | |
965 GtkWidget *item; | |
966 | |
967 menu = popup_menu_short_lived(); | |
968 menu_item_add_sensitive(menu, _("_View"), on_row, | |
969 G_CALLBACK(sr_menu_view_cb), sd); | |
970 menu_item_add_stock_sensitive(menu, _("View in _new window"), GTK_STOCK_NEW, on_row, | |
971 G_CALLBACK(sr_menu_viewnew_cb), sd); | |
972 menu_item_add_divider(menu); | |
973 menu_item_add_sensitive(menu, _("Select all"), !empty, | |
974 G_CALLBACK(sr_menu_select_all_cb), sd); | |
975 menu_item_add_sensitive(menu, _("Select none"), !empty, | |
976 G_CALLBACK(sr_menu_select_none_cb), sd); | |
977 menu_item_add_divider(menu); | |
978 submenu_add_edit(menu, &item, G_CALLBACK(sr_menu_edit_cb), sd); | |
979 if (!on_row) gtk_widget_set_sensitive(item, FALSE); | |
980 menu_item_add_stock_sensitive(menu, _("_Properties"), GTK_STOCK_PROPERTIES, on_row, | |
981 G_CALLBACK(sr_menu_info_cb), sd); | |
982 menu_item_add_stock_sensitive(menu, _("Add to new collection"), GTK_STOCK_INDEX, on_row, | |
983 G_CALLBACK(sr_menu_collection_cb), sd); | |
984 menu_item_add_stock_sensitive(menu, _("Print..."), GTK_STOCK_PRINT, on_row, | |
985 G_CALLBACK(sr_menu_print_cb), sd); | |
986 menu_item_add_divider(menu); | |
987 menu_item_add_stock_sensitive(menu, _("_Copy..."), GTK_STOCK_COPY, on_row, | |
988 G_CALLBACK(sr_menu_copy_cb), sd); | |
989 menu_item_add_sensitive(menu, _("_Move..."), on_row, | |
990 G_CALLBACK(sr_menu_move_cb), sd); | |
991 menu_item_add_sensitive(menu, _("_Rename..."), on_row, | |
992 G_CALLBACK(sr_menu_rename_cb), sd); | |
993 menu_item_add_stock_sensitive(menu, _("_Delete..."), GTK_STOCK_DELETE, on_row, | |
994 G_CALLBACK(sr_menu_delete_cb), sd); | |
995 menu_item_add_divider(menu); | |
996 menu_item_add_stock_sensitive(menu, _("Rem_ove"), GTK_STOCK_REMOVE, on_row, | |
997 G_CALLBACK(sr_menu_remove_cb), sd); | |
998 menu_item_add_stock_sensitive(menu, _("C_lear"), GTK_STOCK_CLEAR, !empty, | |
999 G_CALLBACK(sr_menu_clear_cb), sd); | |
1000 | |
1001 return menu; | |
1002 } | |
1003 | |
1004 static void search_result_menu_pos_cb(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer data) | |
1005 { | |
1006 SearchData *sd = data; | |
1007 GtkTreePath *tpath; | |
1008 gint cx, cy, cw, ch; | |
1009 | |
1010 gtk_tree_view_get_cursor(GTK_TREE_VIEW(sd->result_view), &tpath, NULL); | |
1011 if (!tpath) return; | |
1012 | |
1013 tree_view_get_cell_clamped(GTK_TREE_VIEW(sd->result_view), tpath, | |
1014 SEARCH_COLUMN_NAME - 1, TRUE, &cx, &cy, &cw, &ch); | |
1015 gtk_tree_path_free(tpath); | |
1016 cy += ch; | |
1017 popup_menu_position_clamp(menu, &cx, &cy, 0); | |
1018 *x = cx; | |
1019 *y = cy; | |
1020 } | |
1021 | |
1022 /* | |
1023 *------------------------------------------------------------------- | |
1024 * result list input | |
1025 *------------------------------------------------------------------- | |
1026 */ | |
1027 | |
1028 static gint search_result_press_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data) | |
1029 { | |
1030 SearchData *sd = data; | |
1031 GtkTreeModel *store; | |
1032 GtkTreePath *tpath; | |
1033 GtkTreeIter iter; | |
138 | 1034 MatchFileData *mfd = NULL; |
9 | 1035 |
1036 store = gtk_tree_view_get_model(GTK_TREE_VIEW(widget)); | |
1037 | |
1038 if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), bevent->x, bevent->y, | |
1039 &tpath, NULL, NULL, NULL)) | |
1040 { | |
1041 gtk_tree_model_get_iter(store, &iter, tpath); | |
138 | 1042 gtk_tree_model_get(store, &iter, SEARCH_COLUMN_POINTER, &mfd, -1); |
9 | 1043 gtk_tree_path_free(tpath); |
1044 } | |
1045 | |
138 | 1046 sd->click_fd = mfd ? mfd->fd : NULL; |
9 | 1047 |
1048 if (bevent->button == 3) | |
1049 { | |
1050 GtkWidget *menu; | |
1051 | |
138 | 1052 menu = search_result_menu(sd, (mfd != NULL), (search_result_count(sd, NULL) == 0)); |
9 | 1053 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, bevent->button, bevent->time); |
1054 } | |
1055 | |
138 | 1056 if (!mfd) return FALSE; |
9 | 1057 |
1058 if (bevent->button == 1 && bevent->type == GDK_2BUTTON_PRESS) | |
1059 { | |
138 | 1060 layout_image_set_fd(NULL, mfd->fd); |
9 | 1061 } |
1062 | |
1063 if (bevent->button == 2) return TRUE; | |
1064 | |
1065 if (bevent->button == 3) | |
1066 { | |
138 | 1067 if (!search_result_row_selected(sd, mfd->fd)) |
9 | 1068 { |
1069 GtkTreeSelection *selection; | |
1070 | |
1071 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); | |
1072 gtk_tree_selection_unselect_all(selection); | |
1073 gtk_tree_selection_select_iter(selection, &iter); | |
1074 | |
1075 tpath = gtk_tree_model_get_path(store, &iter); | |
1076 gtk_tree_view_set_cursor(GTK_TREE_VIEW(widget), tpath, NULL, FALSE); | |
1077 gtk_tree_path_free(tpath); | |
1078 } | |
1079 return TRUE; | |
1080 } | |
1081 | |
1082 if (bevent->button == 1 && bevent->type == GDK_BUTTON_PRESS && | |
1083 !(bevent->state & GDK_SHIFT_MASK ) && | |
1084 !(bevent->state & GDK_CONTROL_MASK ) && | |
138 | 1085 search_result_row_selected(sd, mfd->fd)) |
9 | 1086 { |
1087 /* this selection handled on release_cb */ | |
1088 gtk_widget_grab_focus(widget); | |
1089 return TRUE; | |
1090 } | |
1091 | |
1092 return FALSE; | |
1093 } | |
1094 | |
1095 static gint search_result_release_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data) | |
1096 { | |
1097 SearchData *sd = data; | |
1098 GtkTreeModel *store; | |
1099 GtkTreePath *tpath; | |
1100 GtkTreeIter iter; | |
1101 | |
138 | 1102 MatchFileData *mfd = NULL; |
9 | 1103 |
1104 if (bevent->button != 1 && bevent->button != 2) return TRUE; | |
1105 | |
1106 store = gtk_tree_view_get_model(GTK_TREE_VIEW(widget)); | |
1107 | |
1108 if ((bevent->x != 0 || bevent->y != 0) && | |
1109 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), bevent->x, bevent->y, | |
1110 &tpath, NULL, NULL, NULL)) | |
1111 { | |
1112 gtk_tree_model_get_iter(store, &iter, tpath); | |
138 | 1113 gtk_tree_model_get(store, &iter, SEARCH_COLUMN_POINTER, &mfd, -1); |
9 | 1114 gtk_tree_path_free(tpath); |
1115 } | |
1116 | |
1117 if (bevent->button == 2) | |
1118 { | |
138 | 1119 if (mfd && sd->click_fd == mfd->fd) |
9 | 1120 { |
1121 GtkTreeSelection *selection; | |
1122 | |
1123 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); | |
138 | 1124 if (search_result_row_selected(sd, mfd->fd)) |
9 | 1125 { |
1126 gtk_tree_selection_unselect_iter(selection, &iter); | |
1127 } | |
1128 else | |
1129 { | |
1130 gtk_tree_selection_select_iter(selection, &iter); | |
1131 } | |
1132 } | |
1133 return TRUE; | |
1134 } | |
1135 | |
138 | 1136 if (mfd && sd->click_fd == mfd->fd && |
9 | 1137 !(bevent->state & GDK_SHIFT_MASK ) && |
1138 !(bevent->state & GDK_CONTROL_MASK ) && | |
138 | 1139 search_result_row_selected(sd, mfd->fd)) |
9 | 1140 { |
1141 GtkTreeSelection *selection; | |
1142 | |
1143 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); | |
1144 gtk_tree_selection_unselect_all(selection); | |
1145 gtk_tree_selection_select_iter(selection, &iter); | |
1146 | |
1147 tpath = gtk_tree_model_get_path(store, &iter); | |
1148 gtk_tree_view_set_cursor(GTK_TREE_VIEW(widget), tpath, NULL, FALSE); | |
1149 gtk_tree_path_free(tpath); | |
1150 | |
1151 return TRUE; | |
1152 } | |
1153 | |
1154 return FALSE; | |
1155 } | |
1156 | |
1157 static gint search_result_keypress_cb(GtkWidget *widget, GdkEventKey *event, gpointer data) | |
1158 { | |
1159 SearchData *sd = data; | |
1160 gint stop_signal = FALSE; | |
1161 GtkTreeModel *store; | |
1162 GtkTreeSelection *selection; | |
1163 GList *slist; | |
138 | 1164 MatchFileData *mfd = NULL; |
9 | 1165 |
1166 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(sd->result_view)); | |
1167 slist = gtk_tree_selection_get_selected_rows(selection, &store); | |
1168 if (slist) | |
1169 { | |
1170 GtkTreePath *tpath; | |
1171 GtkTreeIter iter; | |
1172 GList *last; | |
1173 | |
1174 last = g_list_last(slist); | |
1175 tpath = last->data; | |
1176 | |
1177 /* last is newest selected file */ | |
1178 gtk_tree_model_get_iter(store, &iter, tpath); | |
138 | 1179 gtk_tree_model_get(store, &iter, SEARCH_COLUMN_POINTER, &mfd, -1); |
9 | 1180 } |
1181 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL); | |
1182 g_list_free(slist); | |
1183 | |
1184 if (event->state & GDK_CONTROL_MASK) | |
1185 { | |
1186 gint edit_val = -1; | |
1187 | |
85
9d5c75b5ec28
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
1188 stop_signal = TRUE; |
9 | 1189 switch (event->keyval) |
1190 { | |
1191 case '1': | |
1192 edit_val = 0; | |
1193 break; | |
1194 case '2': | |
1195 edit_val = 1; | |
1196 break; | |
1197 case '3': | |
1198 edit_val = 2; | |
1199 break; | |
1200 case '4': | |
1201 edit_val = 3; | |
1202 break; | |
1203 case '5': | |
1204 edit_val = 4; | |
1205 break; | |
1206 case '6': | |
1207 edit_val = 5; | |
1208 break; | |
1209 case '7': | |
1210 edit_val = 6; | |
1211 break; | |
1212 case '8': | |
1213 edit_val = 7; | |
1214 break; | |
1215 case '9': | |
1216 edit_val = 8; | |
1217 break; | |
1218 case '0': | |
1219 edit_val = 9; | |
1220 break; | |
1221 case 'C': case 'c': | |
1222 file_util_copy(NULL, search_result_selection_list(sd), NULL, widget); | |
1223 break; | |
1224 case 'M': case 'm': | |
1225 file_util_move(NULL, search_result_selection_list(sd), NULL, widget); | |
1226 break; | |
1227 case 'R': case 'r': | |
1228 file_util_rename(NULL, search_result_selection_list(sd), widget); | |
1229 break; | |
1230 case 'D': case 'd': | |
1231 file_util_delete(NULL, search_result_selection_list(sd), widget); | |
1232 break; | |
1233 case 'P': case 'p': | |
1234 info_window_new(NULL, search_result_selection_list(sd)); | |
1235 break; | |
1236 case 'A': case 'a': | |
1237 if (event->state & GDK_SHIFT_MASK) | |
1238 { | |
1239 gtk_tree_selection_unselect_all(selection); | |
1240 } | |
1241 else | |
1242 { | |
1243 gtk_tree_selection_select_all(selection); | |
1244 } | |
1245 break; | |
1246 case GDK_Delete: case GDK_KP_Delete: | |
1247 search_result_clear(sd); | |
1248 break; | |
1249 default: | |
85
9d5c75b5ec28
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
1250 stop_signal = FALSE; |
9 | 1251 break; |
1252 } | |
1253 | |
1254 if (edit_val >= 0) | |
1255 { | |
1256 search_result_edit_selected(sd, edit_val); | |
1257 } | |
1258 } | |
1259 else | |
1260 { | |
85
9d5c75b5ec28
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
1261 stop_signal = TRUE; |
9 | 1262 switch (event->keyval) |
1263 { | |
1264 case GDK_Return: case GDK_KP_Enter: | |
138 | 1265 if (mfd) layout_image_set_fd(NULL, mfd->fd); |
9 | 1266 break; |
1267 case 'V': case 'v': | |
1268 { | |
1269 GList *list; | |
1270 | |
1271 list = search_result_selection_list(sd); | |
1272 view_window_new_from_list(list); | |
138 | 1273 filelist_free(list); |
9 | 1274 } |
1275 break; | |
1276 case GDK_Delete: case GDK_KP_Delete: | |
1277 search_result_remove_selection(sd); | |
1278 break; | |
1279 case 'C': case 'c': | |
1280 search_result_collection_from_selection(sd); | |
1281 break; | |
1282 case GDK_Menu: | |
1283 case GDK_F10: | |
1284 { | |
1285 GtkWidget *menu; | |
1286 | |
138 | 1287 sd->click_fd = mfd->fd; |
1288 menu = search_result_menu(sd, (mfd != NULL), (search_result_count(sd, NULL) > 0)); | |
9 | 1289 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, |
1290 search_result_menu_pos_cb, sd, 0, GDK_CURRENT_TIME); | |
1291 } | |
1292 break; | |
1293 default: | |
85
9d5c75b5ec28
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
1294 stop_signal = FALSE; |
9 | 1295 break; |
1296 } | |
1297 } | |
1298 | |
1299 return stop_signal; | |
1300 } | |
1301 | |
1302 static gint search_window_keypress_cb(GtkWidget *widget, GdkEventKey *event, gpointer data) | |
1303 { | |
1304 SearchData *sd = data; | |
1305 gint stop_signal = FALSE; | |
1306 | |
1307 if (event->state & GDK_CONTROL_MASK) | |
1308 { | |
85
9d5c75b5ec28
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
1309 stop_signal = TRUE; |
9 | 1310 switch (event->keyval) |
1311 { | |
1312 case 'T': case 't': | |
1313 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(sd->button_thumbs), | |
1314 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sd->button_thumbs))); | |
1315 break; | |
1316 case 'W': case 'w': | |
1317 search_window_close(sd); | |
1318 break; | |
1319 default: | |
85
9d5c75b5ec28
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
1320 stop_signal = FALSE; |
9 | 1321 break; |
1322 } | |
1323 } | |
1324 | |
1325 return stop_signal; | |
1326 } | |
1327 | |
1328 /* | |
1329 *------------------------------------------------------------------- | |
1330 * dnd | |
1331 *------------------------------------------------------------------- | |
1332 */ | |
1333 | |
1334 static GtkTargetEntry result_drag_types[] = { | |
1335 { "text/uri-list", 0, TARGET_URI_LIST }, | |
1336 { "text/plain", 0, TARGET_TEXT_PLAIN } | |
1337 }; | |
1338 static gint n_result_drag_types = 2; | |
1339 | |
1340 static void search_dnd_data_set(GtkWidget *widget, GdkDragContext *context, | |
1341 GtkSelectionData *selection_data, guint info, | |
1342 guint time, gpointer data) | |
1343 { | |
1344 SearchData *sd = data; | |
1345 gchar *uri_text; | |
1346 gint length; | |
1347 GList *list; | |
1348 | |
1349 switch (info) | |
1350 { | |
1351 case TARGET_URI_LIST: | |
1352 case TARGET_TEXT_PLAIN: | |
1353 list = search_result_selection_list(sd); | |
1354 if (!list) return; | |
138 | 1355 uri_text = uri_text_from_filelist(list, &length, (info == TARGET_TEXT_PLAIN)); |
1356 filelist_free(list); | |
9 | 1357 break; |
1358 default: | |
1359 uri_text = NULL; | |
1360 break; | |
1361 } | |
1362 | |
1363 if (uri_text) gtk_selection_data_set(selection_data, selection_data->target, | |
64
04ff0df3ad2f
Mon Aug 15 17:13:57 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
1364 8, (guchar *)uri_text, length); |
9 | 1365 g_free(uri_text); |
1366 } | |
1367 | |
1368 static void search_dnd_begin(GtkWidget *widget, GdkDragContext *context, gpointer data) | |
1369 { | |
1370 SearchData *sd = data; | |
1371 | |
1372 if (sd->click_fd && !search_result_row_selected(sd, sd->click_fd)) | |
1373 { | |
1374 GtkListStore *store; | |
1375 GtkTreeIter iter; | |
1376 | |
1377 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(widget))); | |
1378 if (search_result_find_row(sd, sd->click_fd, &iter) >= 0) | |
1379 { | |
1380 GtkTreeSelection *selection; | |
1381 GtkTreePath *tpath; | |
1382 | |
1383 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); | |
1384 gtk_tree_selection_unselect_all(selection); | |
1385 gtk_tree_selection_select_iter(selection, &iter); | |
1386 | |
1387 tpath = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iter); | |
1388 gtk_tree_view_set_cursor(GTK_TREE_VIEW(widget), tpath, NULL, FALSE); | |
1389 gtk_tree_path_free(tpath); | |
1390 } | |
1391 } | |
1392 | |
1393 if (sd->thumb_enable && | |
1394 sd->click_fd && sd->click_fd->pixbuf) | |
1395 { | |
1396 dnd_set_drag_icon(widget, context, sd->click_fd->pixbuf, search_result_selection_count(sd, NULL)); | |
1397 } | |
1398 } | |
1399 | |
1400 static void search_dnd_init(SearchData *sd) | |
1401 { | |
1402 gtk_drag_source_set(sd->result_view, GDK_BUTTON1_MASK | GDK_BUTTON2_MASK, | |
1403 result_drag_types, n_result_drag_types, | |
1404 GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK); | |
1405 g_signal_connect(G_OBJECT(sd->result_view), "drag_data_get", | |
1406 G_CALLBACK(search_dnd_data_set), sd); | |
1407 g_signal_connect(G_OBJECT(sd->result_view), "drag_begin", | |
1408 G_CALLBACK(search_dnd_begin), sd); | |
1409 #if 0 | |
1410 g_signal_connect(G_OBJECT(sd->result_view), "drag_end", | |
1411 G_CALLBACK(search_dnd_end), sd); | |
1412 #endif | |
1413 | |
1414 } | |
1415 | |
1416 /* | |
1417 *------------------------------------------------------------------- | |
1418 * search core | |
1419 *------------------------------------------------------------------- | |
1420 */ | |
1421 | |
1422 #define MATCH_IS_BETWEEN(val, a, b) (b > a ? (val >= a && val <= b) : (val >= b && val <= a)) | |
1423 | |
1424 static gint search_step_cb(gpointer data); | |
1425 | |
1426 | |
1427 static void search_buffer_flush(SearchData *sd) | |
1428 { | |
1429 GList *work; | |
1430 | |
1431 work = g_list_last(sd->search_buffer_list); | |
1432 while (work) | |
1433 { | |
1434 MatchFileData *mfd = work->data; | |
1435 work = work->prev; | |
1436 | |
1437 search_result_append(sd, mfd); | |
1438 } | |
1439 | |
1440 g_list_free(sd->search_buffer_list); | |
1441 sd->search_buffer_list = NULL; | |
1442 sd->search_buffer_count = 0; | |
1443 } | |
1444 | |
1445 static void search_stop(SearchData *sd) | |
1446 { | |
1447 if (sd->search_idle_id != -1) | |
1448 { | |
1449 g_source_remove(sd->search_idle_id); | |
1450 sd->search_idle_id = -1; | |
1451 } | |
1452 | |
1453 image_loader_free(sd->img_loader); | |
1454 sd->img_loader = NULL; | |
1455 cache_sim_data_free(sd->img_cd); | |
1456 sd->img_cd = NULL; | |
1457 | |
1458 cache_sim_data_free(sd->search_similarity_cd); | |
1459 sd->search_similarity_cd = NULL; | |
1460 | |
1461 search_buffer_flush(sd); | |
1462 | |
1463 filelist_free(sd->search_folder_list); | |
1464 sd->search_folder_list = NULL; | |
1465 | |
1466 g_list_free(sd->search_done_list); | |
1467 sd->search_done_list = NULL; | |
1468 | |
1469 filelist_free(sd->search_file_list); | |
1470 sd->search_file_list = NULL; | |
1471 | |
1472 gtk_widget_set_sensitive(sd->box_search, TRUE); | |
1473 spinner_set_interval(sd->spinner, -1); | |
1474 gtk_widget_set_sensitive(sd->button_start, TRUE); | |
1475 gtk_widget_set_sensitive(sd->button_stop, FALSE); | |
1476 search_progress_update(sd, TRUE, -1.0); | |
1477 search_status_update(sd); | |
1478 } | |
1479 | |
1480 static void search_file_load_process(SearchData *sd, CacheData *cd) | |
1481 { | |
1482 GdkPixbuf *pixbuf; | |
1483 | |
1484 pixbuf = image_loader_get_pixbuf(sd->img_loader); | |
1485 | |
1486 if (cd && pixbuf) | |
1487 { | |
1488 if (!cd->dimensions) | |
1489 { | |
1490 cache_sim_data_set_dimensions(cd, gdk_pixbuf_get_width(pixbuf), | |
1491 gdk_pixbuf_get_height(pixbuf)); | |
1492 } | |
1493 | |
1494 if (sd->match_similarity_enable && !cd->similarity) | |
1495 { | |
1496 ImageSimilarityData *sim; | |
1497 | |
1498 sim = image_sim_new_from_pixbuf(pixbuf); | |
1499 cache_sim_data_set_similarity(cd, sim); | |
1500 image_sim_free(sim); | |
1501 } | |
1502 | |
1503 if (enable_thumb_caching && | |
138 | 1504 sd->img_loader && sd->img_loader->fd) |
9 | 1505 { |
1506 gchar *base; | |
1507 const gchar *path; | |
1508 mode_t mode = 0755; | |
1509 | |
138 | 1510 path = sd->img_loader->fd->path; |
9 | 1511 base = cache_get_location(CACHE_TYPE_SIM, path, FALSE, &mode); |
1512 if (cache_ensure_dir_exists(base, mode)) | |
1513 { | |
1514 g_free(cd->path); | |
1515 cd->path = cache_get_location(CACHE_TYPE_SIM, path, TRUE, NULL); | |
1516 if (cache_sim_data_save(cd)) | |
1517 { | |
138 | 1518 filetime_set(cd->path, filetime(sd->img_loader->fd->path)); |
9 | 1519 } |
1520 } | |
1521 g_free(base); | |
1522 } | |
1523 } | |
1524 | |
1525 image_loader_free(sd->img_loader); | |
1526 sd->img_loader = NULL; | |
1527 | |
1528 sd->search_idle_id = g_idle_add(search_step_cb, sd); | |
1529 } | |
1530 | |
1531 static void search_file_load_done_cb(ImageLoader *il, gpointer data) | |
1532 { | |
1533 SearchData *sd = data; | |
1534 search_file_load_process(sd, sd->img_cd); | |
1535 } | |
1536 | |
1537 static gint search_file_do_extra(SearchData *sd, FileData *fd, gint *match, | |
1538 gint *width, gint *height, gint *simval) | |
1539 { | |
1540 gint new_data = FALSE; | |
1541 gint tmatch = TRUE; | |
1542 gint tested = FALSE; | |
1543 | |
1544 if (!sd->img_cd) | |
1545 { | |
1546 gchar *cd_path; | |
1547 | |
1548 new_data = TRUE; | |
1549 | |
1550 cd_path = cache_find_location(CACHE_TYPE_SIM, fd->path); | |
1551 if (cd_path && filetime(fd->path) == filetime(cd_path)) | |
1552 { | |
1553 sd->img_cd = cache_sim_data_load(cd_path); | |
1554 } | |
1555 g_free(cd_path); | |
1556 } | |
1557 | |
1558 if (!sd->img_cd) | |
1559 { | |
1560 sd->img_cd = cache_sim_data_new(); | |
1561 } | |
1562 | |
1563 if (new_data) | |
1564 { | |
1565 if ((sd->match_dimensions_enable && !sd->img_cd->dimensions) || | |
1566 (sd->match_similarity_enable && !sd->img_cd->similarity)) | |
1567 { | |
138 | 1568 sd->img_loader = image_loader_new(fd); |
9 | 1569 image_loader_set_error_func(sd->img_loader, search_file_load_done_cb, sd); |
1570 if (image_loader_start(sd->img_loader, search_file_load_done_cb, sd)) | |
1571 { | |
1572 return TRUE; | |
1573 } | |
1574 else | |
1575 { | |
1576 image_loader_free(sd->img_loader); | |
1577 sd->img_loader = NULL; | |
1578 } | |
1579 } | |
1580 } | |
1581 | |
1582 if (tmatch && sd->match_dimensions_enable && sd->img_cd->dimensions) | |
1583 { | |
1584 CacheData *cd = sd->img_cd; | |
1585 | |
1586 tmatch = FALSE; | |
1587 tested = TRUE; | |
1588 | |
1589 if (sd->match_dimensions == SEARCH_MATCH_EQUAL) | |
1590 { | |
1591 tmatch = (cd->width == sd->search_width && cd->height == sd->search_height); | |
1592 } | |
1593 else if (sd->match_dimensions == SEARCH_MATCH_UNDER) | |
1594 { | |
1595 tmatch = (cd->width < sd->search_width && cd->height < sd->search_height); | |
1596 } | |
1597 else if (sd->match_dimensions == SEARCH_MATCH_OVER) | |
1598 { | |
1599 tmatch = (cd->width > sd->search_width && cd->height > sd->search_height); | |
1600 } | |
1601 else if (sd->match_dimensions == SEARCH_MATCH_BETWEEN) | |
1602 { | |
1603 tmatch = (MATCH_IS_BETWEEN(cd->width, sd->search_width, sd->search_width_end) && | |
1604 MATCH_IS_BETWEEN(cd->height, sd->search_height, sd->search_height_end)); | |
1605 } | |
1606 } | |
1607 | |
1608 if (tmatch && sd->match_similarity_enable && sd->img_cd->similarity) | |
1609 { | |
1610 gdouble value = 0.0; | |
1611 | |
1612 tmatch = FALSE; | |
1613 tested = TRUE; | |
1614 | |
1615 /* fixme: implement similarity checking */ | |
1616 if (sd->search_similarity_cd && sd->search_similarity_cd->similarity) | |
1617 { | |
1618 gdouble result; | |
1619 | |
1620 result = image_sim_compare_fast(sd->search_similarity_cd->sim, sd->img_cd->sim, | |
1621 (gdouble)sd->search_similarity / 100.0); | |
1622 result *= 100.0; | |
1623 if (result >= (gdouble)sd->search_similarity) | |
1624 { | |
1625 tmatch = TRUE; | |
1626 value = (gint)result; | |
1627 } | |
1628 } | |
1629 | |
1630 if (simval) *simval = value; | |
1631 } | |
1632 | |
1633 if (sd->img_cd->dimensions) | |
1634 { | |
1635 if (width) *width = sd->img_cd->width; | |
1636 if (height) *height = sd->img_cd->height; | |
1637 } | |
1638 | |
1639 cache_sim_data_free(sd->img_cd); | |
1640 sd->img_cd = NULL; | |
1641 | |
1642 *match = (tmatch && tested); | |
1643 | |
1644 return FALSE; | |
1645 } | |
1646 | |
1647 static gint search_file_next(SearchData *sd) | |
1648 { | |
1649 FileData *fd; | |
1650 gint match = TRUE; | |
1651 gint tested = FALSE; | |
1652 gint extra_only = FALSE; | |
1653 gint width = 0; | |
1654 gint height = 0; | |
1655 gint sim = 0; | |
1656 | |
1657 if (!sd->search_file_list) return FALSE; | |
1658 | |
1659 if (sd->img_cd) | |
1660 { | |
1661 /* on end of a CacheData load, skip recomparing non-extra match types */ | |
1662 extra_only = TRUE; | |
1663 match = FALSE; | |
1664 } | |
1665 else | |
1666 { | |
1667 sd->search_total++; | |
1668 } | |
1669 | |
1670 fd = sd->search_file_list->data; | |
1671 | |
1672 if (match && sd->match_name_enable && sd->search_name) | |
1673 { | |
1674 tested = TRUE; | |
1675 match = FALSE; | |
1676 | |
1677 if (sd->match_name == SEARCH_MATCH_EQUAL) | |
1678 { | |
1679 if (sd->search_name_match_case) | |
1680 { | |
1681 match = (strcmp(fd->name, sd->search_name) == 0); | |
1682 } | |
1683 else | |
1684 { | |
1685 match = (strcasecmp(fd->name, sd->search_name) == 0); | |
1686 } | |
1687 } | |
1688 else if (sd->match_name == SEARCH_MATCH_CONTAINS) | |
1689 { | |
1690 if (sd->search_name_match_case) | |
1691 { | |
1692 match = (strstr(fd->name, sd->search_name) != NULL); | |
1693 } | |
1694 else | |
1695 { | |
1696 /* sd->search_name is converted in search_start() */ | |
1697 gchar *haystack = g_utf8_strdown(fd->name, -1); | |
1698 match = (strstr(haystack, sd->search_name) != NULL); | |
1699 g_free(haystack); | |
1700 } | |
1701 } | |
1702 } | |
1703 | |
1704 if (match && sd->match_size_enable) | |
1705 { | |
1706 tested = TRUE; | |
1707 match = FALSE; | |
1708 | |
1709 if (sd->match_size == SEARCH_MATCH_EQUAL) | |
1710 { | |
1711 match = (fd->size == sd->search_size); | |
1712 } | |
1713 else if (sd->match_size == SEARCH_MATCH_UNDER) | |
1714 { | |
1715 match = (fd->size < sd->search_size); | |
1716 } | |
1717 else if (sd->match_size == SEARCH_MATCH_OVER) | |
1718 { | |
1719 match = (fd->size > sd->search_size); | |
1720 } | |
1721 else if (sd->match_size == SEARCH_MATCH_BETWEEN) | |
1722 { | |
1723 match = MATCH_IS_BETWEEN(fd->size, sd->search_size, sd->search_size_end); | |
1724 } | |
1725 } | |
1726 | |
1727 if (match && sd->match_date_enable) | |
1728 { | |
1729 tested = TRUE; | |
1730 match = FALSE; | |
1731 | |
1732 if (sd->match_date == SEARCH_MATCH_EQUAL) | |
1733 { | |
1734 struct tm *lt; | |
1735 | |
1736 lt = localtime(&fd->date); | |
1737 match = (lt && | |
1738 lt->tm_year == sd->search_date_y - 1900 && | |
1739 lt->tm_mon == sd->search_date_m - 1 && | |
1740 lt->tm_mday == sd->search_date_d); | |
1741 } | |
1742 else if (sd->match_date == SEARCH_MATCH_UNDER) | |
1743 { | |
1744 match = (fd->date < convert_dmy_to_time(sd->search_date_d, sd->search_date_m, sd->search_date_y)); | |
1745 } | |
1746 else if (sd->match_date == SEARCH_MATCH_OVER) | |
1747 { | |
1748 match = (fd->date > convert_dmy_to_time(sd->search_date_d, sd->search_date_m, sd->search_date_y) + 60 * 60 * 24 - 1); | |
1749 } | |
1750 else if (sd->match_date == SEARCH_MATCH_BETWEEN) | |
1751 { | |
1752 time_t a = convert_dmy_to_time(sd->search_date_d, sd->search_date_m, sd->search_date_y); | |
1753 time_t b = convert_dmy_to_time(sd->search_date_end_d, sd->search_date_end_m, sd->search_date_end_y); | |
1754 | |
1755 if (b >= a) | |
1756 { | |
1757 b += 60 * 60 * 24 - 1; | |
1758 } | |
1759 else | |
1760 { | |
1761 a += 60 * 60 * 24 - 1; | |
1762 } | |
1763 match = MATCH_IS_BETWEEN(fd->date, a, b); | |
1764 } | |
1765 } | |
1766 | |
1767 if (match && sd->match_keywords_enable && sd->search_keyword_list) | |
1768 { | |
1769 GList *list; | |
1770 | |
1771 tested = TRUE; | |
1772 match = FALSE; | |
1773 | |
188
0584cb78aa14
write comment and keywords to xmp, sidecars are used if exist
nadvornik
parents:
138
diff
changeset
|
1774 if (comment_read(fd, &list, NULL)) |
9 | 1775 { |
1776 GList *needle; | |
1777 GList *haystack; | |
1778 | |
1779 if (sd->match_keywords == SEARCH_MATCH_ALL) | |
1780 { | |
1781 gint found = TRUE; | |
1782 | |
1783 needle = sd->search_keyword_list; | |
1784 while (needle && found) | |
1785 { | |
1786 found = FALSE; | |
1787 haystack = list; | |
1788 while (haystack && !found) | |
1789 { | |
1790 found = (strcasecmp((gchar *)needle->data, | |
1791 (gchar *)haystack->data) == 0); | |
1792 haystack = haystack->next; | |
1793 } | |
1794 needle = needle->next; | |
1795 } | |
1796 | |
1797 match = found; | |
1798 } | |
1799 else if (sd->match_keywords == SEARCH_MATCH_ANY) | |
1800 { | |
1801 gint found = FALSE; | |
1802 | |
1803 needle = sd->search_keyword_list; | |
1804 while (needle && !found) | |
1805 { | |
1806 haystack = list; | |
1807 while (haystack && !found) | |
1808 { | |
1809 found = (strcasecmp((gchar *)needle->data, | |
1810 (gchar *)haystack->data) == 0); | |
1811 haystack = haystack->next; | |
1812 } | |
1813 needle = needle->next; | |
1814 } | |
1815 | |
1816 match = found; | |
1817 } | |
1818 else if (sd->match_keywords == SEARCH_MATCH_NONE) | |
1819 { | |
1820 gint found = FALSE; | |
1821 | |
1822 needle = sd->search_keyword_list; | |
1823 while (needle && !found) | |
1824 { | |
1825 haystack = list; | |
1826 while (haystack && !found) | |
1827 { | |
1828 found = (strcasecmp((gchar *)needle->data, | |
1829 (gchar *)haystack->data) == 0); | |
1830 haystack = haystack->next; | |
1831 } | |
1832 needle = needle->next; | |
1833 } | |
1834 | |
1835 match = !found; | |
1836 } | |
138 | 1837 string_list_free(list); |
9 | 1838 } |
1839 else | |
1840 { | |
1841 match = (sd->match_keywords == SEARCH_MATCH_NONE); | |
1842 } | |
1843 } | |
1844 | |
1845 if ((match || extra_only) && | |
1846 (sd->match_dimensions_enable || sd->match_similarity_enable)) | |
1847 { | |
1848 tested = TRUE; | |
1849 | |
1850 if (search_file_do_extra(sd, fd, &match, &width, &height, &sim)) | |
1851 { | |
1852 sd->search_buffer_count += SEARCH_BUFFER_MATCH_LOAD; | |
1853 return TRUE; | |
1854 } | |
1855 } | |
1856 | |
1857 sd->search_file_list = g_list_remove(sd->search_file_list, fd); | |
1858 | |
1859 if (tested && match) | |
1860 { | |
1861 MatchFileData *mfd; | |
1862 | |
1863 mfd = g_new(MatchFileData, 1); | |
138 | 1864 mfd->fd = fd; |
9 | 1865 |
1866 mfd->width = width; | |
1867 mfd->height = height; | |
1868 mfd->rank = sim; | |
1869 | |
1870 sd->search_buffer_list = g_list_prepend(sd->search_buffer_list, mfd); | |
1871 sd->search_buffer_count += SEARCH_BUFFER_MATCH_HIT; | |
1872 sd->search_count++; | |
1873 search_progress_update(sd, TRUE, -1.0); | |
1874 } | |
1875 else | |
1876 { | |
138 | 1877 file_data_unref(fd); |
9 | 1878 sd->search_buffer_count += SEARCH_BUFFER_MATCH_MISS; |
1879 } | |
1880 | |
1881 return FALSE; | |
1882 } | |
1883 | |
1884 static gint search_step_cb(gpointer data) | |
1885 { | |
1886 SearchData *sd = data; | |
1887 FileData *fd; | |
1888 | |
1889 if (sd->search_buffer_count > SEARCH_BUFFER_FLUSH_SIZE) | |
1890 { | |
1891 search_buffer_flush(sd); | |
1892 search_progress_update(sd, TRUE, -1.0); | |
1893 } | |
1894 | |
1895 if (sd->search_file_list) | |
1896 { | |
1897 if (search_file_next(sd)) | |
1898 { | |
1899 sd->search_idle_id = -1; | |
1900 return FALSE; | |
1901 } | |
1902 return TRUE; | |
1903 } | |
1904 | |
1905 if (!sd->search_file_list && !sd->search_folder_list) | |
1906 { | |
1907 sd->search_idle_id = -1; | |
1908 | |
1909 search_stop(sd); | |
1910 search_result_thumb_step(sd); | |
1911 | |
1912 return FALSE; | |
1913 } | |
1914 | |
1915 fd = sd->search_folder_list->data; | |
1916 | |
1917 if (g_list_find(sd->search_done_list, fd) == NULL) | |
1918 { | |
1919 GList *list = NULL; | |
1920 GList *dlist = NULL; | |
1921 gint success = FALSE; | |
1922 | |
1923 sd->search_done_list = g_list_prepend(sd->search_done_list, fd); | |
1924 | |
1925 if (sd->search_type == SEARCH_MATCH_NONE) | |
1926 { | |
1927 success = filelist_read(fd->path, &list, &dlist); | |
1928 } | |
1929 else if (sd->search_type == SEARCH_MATCH_ALL && | |
1930 sd->search_path && | |
1931 strlen(fd->path) >= strlen(sd->search_path)) | |
1932 { | |
1933 const gchar *path; | |
1934 | |
1935 path = fd->path + strlen(sd->search_path); | |
1936 if (path != fd->path) success = filelist_read(path, &list, NULL); | |
1937 success |= filelist_read(fd->path, NULL, &dlist); | |
1938 if (success) | |
1939 { | |
1940 GList *work; | |
1941 | |
1942 work = list; | |
1943 while (work) | |
1944 { | |
1945 FileData *fdp; | |
1946 GList *link; | |
1947 gchar *meta_path; | |
1948 | |
1949 fdp = work->data; | |
1950 link = work; | |
1951 work = work->next; | |
1952 | |
1953 meta_path = cache_find_location(CACHE_TYPE_METADATA, fdp->path); | |
1954 if (!meta_path) | |
1955 { | |
1956 list = g_list_delete_link(list, link); | |
138 | 1957 file_data_unref(fdp); |
9 | 1958 } |
1959 g_free(meta_path); | |
1960 } | |
1961 } | |
1962 } | |
1963 | |
1964 if (success) | |
1965 { | |
1966 list = filelist_sort(list, SORT_NAME, TRUE); | |
1967 sd->search_file_list = list; | |
1968 | |
1969 if (sd->search_path_recurse) | |
1970 { | |
1971 dlist = filelist_sort(dlist, SORT_NAME, TRUE); | |
1972 sd->search_folder_list = g_list_concat(dlist, sd->search_folder_list); | |
1973 } | |
1974 else | |
1975 { | |
1976 filelist_free(dlist); | |
1977 } | |
1978 } | |
1979 } | |
1980 else | |
1981 { | |
1982 sd->search_folder_list = g_list_remove(sd->search_folder_list, fd); | |
1983 sd->search_done_list = g_list_remove(sd->search_done_list, fd); | |
138 | 1984 file_data_unref(fd); |
9 | 1985 } |
1986 | |
1987 return TRUE; | |
1988 } | |
1989 | |
1990 static void search_similarity_load_done_cb(ImageLoader *il, gpointer data) | |
1991 { | |
1992 SearchData *sd = data; | |
1993 search_file_load_process(sd, sd->search_similarity_cd); | |
1994 } | |
1995 | |
1996 static void search_start(SearchData *sd) | |
1997 { | |
1998 search_stop(sd); | |
1999 search_result_clear(sd); | |
2000 | |
2001 if (sd->search_path) | |
2002 { | |
2003 sd->search_folder_list = g_list_prepend(sd->search_folder_list, | |
2004 file_data_new_simple(sd->search_path)); | |
2005 } | |
2006 | |
2007 if (!sd->search_name_match_case) | |
2008 { | |
2009 /* convert to lowercase here, so that this is only done once per search */ | |
2010 gchar *tmp = g_utf8_strdown(sd->search_name, -1); | |
2011 g_free(sd->search_name); | |
2012 sd->search_name = tmp; | |
2013 } | |
2014 | |
2015 sd->search_count = 0; | |
2016 sd->search_total = 0; | |
2017 | |
2018 gtk_widget_set_sensitive(sd->box_search, FALSE); | |
2019 spinner_set_interval(sd->spinner, SPINNER_SPEED); | |
2020 gtk_widget_set_sensitive(sd->button_start, FALSE); | |
2021 gtk_widget_set_sensitive(sd->button_stop, TRUE); | |
2022 search_progress_update(sd, TRUE, -1.0); | |
2023 | |
2024 if (sd->match_similarity_enable && | |
2025 !sd->search_similarity_cd && | |
2026 isfile(sd->search_similarity_path)) | |
2027 { | |
2028 gchar *cd_path; | |
2029 | |
2030 cd_path = cache_find_location(CACHE_TYPE_SIM, sd->search_similarity_path); | |
2031 if (cd_path && filetime(sd->search_similarity_path) == filetime(cd_path)) | |
2032 { | |
2033 sd->search_similarity_cd = cache_sim_data_load(cd_path); | |
2034 } | |
2035 g_free(cd_path); | |
2036 | |
2037 if (!sd->search_similarity_cd || !sd->search_similarity_cd->similarity) | |
2038 { | |
2039 if (!sd->search_similarity_cd) | |
2040 { | |
2041 sd->search_similarity_cd = cache_sim_data_new(); | |
2042 } | |
2043 | |
138 | 2044 sd->img_loader = image_loader_new(file_data_new_simple(sd->search_similarity_path)); |
9 | 2045 image_loader_set_error_func(sd->img_loader, search_similarity_load_done_cb, sd); |
2046 if (image_loader_start(sd->img_loader, search_similarity_load_done_cb, sd)) | |
2047 { | |
2048 return; | |
2049 } | |
2050 image_loader_free(sd->img_loader); | |
2051 sd->img_loader = NULL; | |
2052 } | |
2053 | |
2054 } | |
2055 | |
2056 sd->search_idle_id = g_idle_add(search_step_cb, sd); | |
2057 } | |
2058 | |
2059 static void search_start_cb(GtkWidget *widget, gpointer data) | |
2060 { | |
2061 SearchData *sd = data; | |
2062 GtkTreeViewColumn *column; | |
2063 gchar *path; | |
2064 | |
2065 if (sd->search_folder_list) | |
2066 { | |
2067 search_stop(sd); | |
2068 search_result_thumb_step(sd); | |
2069 return; | |
2070 } | |
2071 | |
2072 if (sd->match_name_enable) history_combo_append_history(sd->entry_name, NULL); | |
2073 g_free(sd->search_name); | |
2074 sd->search_name = g_strdup(gtk_entry_get_text(GTK_ENTRY(sd->entry_name))); | |
2075 | |
2076 g_free(sd->search_similarity_path); | |
2077 sd->search_similarity_path = g_strdup(gtk_entry_get_text(GTK_ENTRY(sd->entry_similarity))); | |
2078 if (sd->match_similarity_enable) | |
2079 { | |
2080 if (!isfile(sd->search_similarity_path)) | |
2081 { | |
2082 file_util_warning_dialog(_("File not found"), | |
2083 _("Please enter an existing file for image content."), | |
2084 GTK_STOCK_DIALOG_WARNING, sd->window); | |
2085 return; | |
2086 } | |
2087 tab_completion_append_to_history(sd->entry_similarity, sd->search_similarity_path); | |
2088 } | |
2089 | |
138 | 2090 string_list_free(sd->search_keyword_list); |
9 | 2091 sd->search_keyword_list = keyword_list_pull(sd->entry_keywords); |
2092 | |
2093 date_selection_get(sd->date_sel, &sd->search_date_d, &sd->search_date_m, &sd->search_date_y); | |
2094 date_selection_get(sd->date_sel_end, &sd->search_date_end_d, &sd->search_date_end_m, &sd->search_date_end_y); | |
2095 | |
2096 column = gtk_tree_view_get_column(GTK_TREE_VIEW(sd->result_view), SEARCH_COLUMN_RANK - 1); | |
2097 gtk_tree_view_column_set_visible(column, sd->match_similarity_enable); | |
2098 if (!sd->match_similarity_enable) | |
2099 { | |
2100 GtkTreeSortable *sortable; | |
2101 gint id; | |
2102 GtkSortType order; | |
2103 | |
2104 sortable = GTK_TREE_SORTABLE(gtk_tree_view_get_model(GTK_TREE_VIEW(sd->result_view))); | |
2105 if (gtk_tree_sortable_get_sort_column_id(sortable, &id, &order) && | |
2106 id == SEARCH_COLUMN_RANK) | |
2107 { | |
2108 gtk_tree_sortable_set_sort_column_id(sortable, SEARCH_COLUMN_PATH, GTK_SORT_ASCENDING); | |
2109 } | |
2110 } | |
2111 | |
2112 if (sd->search_type == SEARCH_MATCH_NONE) | |
2113 { | |
2114 /* search path */ | |
2115 | |
2116 path = remove_trailing_slash(gtk_entry_get_text(GTK_ENTRY(sd->path_entry))); | |
2117 if (isdir(path)) | |
2118 { | |
2119 g_free(sd->search_path); | |
2120 sd->search_path = path; | |
2121 path = NULL; | |
2122 | |
2123 tab_completion_append_to_history(sd->path_entry, sd->search_path); | |
2124 | |
2125 search_start(sd); | |
2126 } | |
2127 else | |
2128 { | |
2129 file_util_warning_dialog(_("Folder not found"), | |
2130 _("Please enter an existing folder to search."), | |
2131 GTK_STOCK_DIALOG_WARNING, sd->window); | |
2132 } | |
2133 | |
2134 g_free(path); | |
2135 } | |
2136 else if (sd->search_type == SEARCH_MATCH_ALL) | |
2137 { | |
2138 /* search metadata */ | |
2139 | |
2140 g_free(sd->search_path); | |
2141 sd->search_path = g_strconcat(homedir(), "/", GQVIEW_CACHE_RC_METADATA, NULL); | |
2142 | |
2143 search_start(sd); | |
2144 } | |
2145 else if (sd->search_type == SEARCH_MATCH_CONTAINS) | |
2146 { | |
2147 /* search current result list */ | |
2148 GList *list; | |
2149 | |
2150 list = search_result_refine_list(sd); | |
2151 | |
2152 g_free(sd->search_path); | |
2153 sd->search_path = NULL; | |
2154 | |
2155 search_start(sd); | |
2156 | |
2157 sd->search_file_list = g_list_concat(sd->search_file_list, list); | |
2158 } | |
2159 } | |
2160 | |
2161 /* | |
2162 *------------------------------------------------------------------- | |
2163 * window construct | |
2164 *------------------------------------------------------------------- | |
2165 */ | |
2166 | |
2167 enum { | |
2168 MENU_CHOICE_COLUMN_NAME = 0, | |
2169 MENU_CHOICE_COLUMN_VALUE | |
2170 }; | |
2171 | |
2172 static void search_thumb_toggle_cb(GtkWidget *button, gpointer data) | |
2173 { | |
2174 SearchData *sd = data; | |
2175 | |
2176 search_result_thumb_enable(sd, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button))); | |
2177 } | |
2178 | |
2179 static gint sort_matchdata_dimensions(MatchFileData *a, MatchFileData *b) | |
2180 { | |
2181 gint sa; | |
2182 gint sb; | |
2183 | |
2184 sa = a->width * a->height; | |
2185 sb = b->width * b->height; | |
2186 | |
2187 if (sa > sb) return 1; | |
2188 if (sa < sb) return -1; | |
2189 return 0; | |
2190 } | |
2191 | |
2192 static gint search_result_sort_cb(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer data) | |
2193 { | |
2194 gint n = GPOINTER_TO_INT(data); | |
138 | 2195 MatchFileData *fda; |
2196 MatchFileData *fdb; | |
9 | 2197 |
2198 gtk_tree_model_get(model, a, SEARCH_COLUMN_POINTER, &fda, -1); | |
2199 gtk_tree_model_get(model, b, SEARCH_COLUMN_POINTER, &fdb, -1); | |
2200 | |
2201 if (!fda || !fdb) return 0; | |
2202 | |
2203 switch (n) | |
2204 { | |
2205 case SEARCH_COLUMN_RANK: | |
138 | 2206 if (((MatchFileData *)fda)->rank > (fdb)->rank) return 1; |
2207 if (((MatchFileData *)fda)->rank < (fdb)->rank) return -1; | |
9 | 2208 return 0; |
2209 break; | |
2210 case SEARCH_COLUMN_NAME: | |
138 | 2211 return CASE_SORT(fda->fd->name, fdb->fd->name); |
9 | 2212 break; |
2213 case SEARCH_COLUMN_SIZE: | |
138 | 2214 if (fda->fd->size > fdb->fd->size) return 1; |
2215 if (fda->fd->size < fdb->fd->size) return -1; | |
9 | 2216 return 0; |
2217 break; | |
2218 case SEARCH_COLUMN_DATE: | |
138 | 2219 if (fda->fd->date > fdb->fd->date) return 1; |
2220 if (fda->fd->date < fdb->fd->date) return -1; | |
9 | 2221 return 0; |
2222 break; | |
2223 case SEARCH_COLUMN_DIMENSIONS: | |
138 | 2224 return sort_matchdata_dimensions(fda, fdb); |
9 | 2225 break; |
2226 case SEARCH_COLUMN_PATH: | |
138 | 2227 return CASE_SORT(fda->fd->path, fdb->fd->path); |
9 | 2228 break; |
2229 default: | |
2230 break; | |
2231 } | |
2232 | |
2233 return 0; | |
2234 } | |
2235 | |
2236 static void search_result_add_column(SearchData * sd, gint n, const gchar *title, gint image, gint right_justify) | |
2237 { | |
2238 GtkTreeViewColumn *column; | |
2239 GtkCellRenderer *renderer; | |
2240 | |
2241 column = gtk_tree_view_column_new(); | |
2242 gtk_tree_view_column_set_title(column, title); | |
2243 gtk_tree_view_column_set_min_width(column, 4); | |
2244 | |
2245 if (n != SEARCH_COLUMN_THUMB) gtk_tree_view_column_set_resizable(column, TRUE); | |
2246 | |
2247 if (!image) | |
2248 { | |
2249 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_GROW_ONLY); | |
2250 renderer = gtk_cell_renderer_text_new(); | |
2251 if (right_justify) g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL); | |
2252 gtk_tree_view_column_pack_start(column, renderer, TRUE); | |
2253 gtk_tree_view_column_add_attribute(column, renderer, "text", n); | |
2254 | |
2255 gtk_tree_view_column_set_sort_column_id(column, n); | |
2256 } | |
2257 else | |
2258 { | |
2259 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED); | |
2260 renderer = gtk_cell_renderer_pixbuf_new(); | |
2261 cell_renderer_height_override(renderer); | |
2262 gtk_tree_view_column_pack_start(column, renderer, TRUE); | |
2263 gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", n); | |
2264 } | |
2265 | |
2266 gtk_tree_view_append_column(GTK_TREE_VIEW(sd->result_view), column); | |
2267 } | |
2268 | |
2269 static void menu_choice_set_visible(GtkWidget *widget, gint visible) | |
2270 { | |
2271 if (visible) | |
2272 { | |
2273 if (!GTK_WIDGET_VISIBLE(widget)) gtk_widget_show(widget); | |
2274 } | |
2275 else | |
2276 { | |
2277 if (GTK_WIDGET_VISIBLE(widget)) gtk_widget_hide(widget); | |
2278 } | |
2279 } | |
2280 | |
2281 static void menu_choice_path_cb(GtkWidget *combo, gpointer data) | |
2282 { | |
2283 SearchData *sd = data; | |
2284 GtkTreeModel *store; | |
2285 GtkTreeIter iter; | |
2286 | |
2287 store = gtk_combo_box_get_model(GTK_COMBO_BOX(combo)); | |
2288 if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo), &iter)) return; | |
2289 gtk_tree_model_get(store, &iter, MENU_CHOICE_COLUMN_VALUE, &sd->search_type, -1); | |
2290 | |
2291 menu_choice_set_visible(gtk_widget_get_parent(sd->check_recurse), | |
2292 (sd->search_type == SEARCH_MATCH_NONE)); | |
2293 } | |
2294 | |
2295 static void menu_choice_name_cb(GtkWidget *combo, gpointer data) | |
2296 { | |
2297 SearchData *sd = data; | |
2298 GtkTreeModel *store; | |
2299 GtkTreeIter iter; | |
2300 | |
2301 store = gtk_combo_box_get_model(GTK_COMBO_BOX(combo)); | |
2302 if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo), &iter)) return; | |
2303 gtk_tree_model_get(store, &iter, MENU_CHOICE_COLUMN_VALUE, &sd->match_name, -1); | |
2304 } | |
2305 | |
2306 static void menu_choice_size_cb(GtkWidget *combo, gpointer data) | |
2307 { | |
2308 SearchData *sd = data; | |
2309 GtkTreeModel *store; | |
2310 GtkTreeIter iter; | |
2311 | |
2312 store = gtk_combo_box_get_model(GTK_COMBO_BOX(combo)); | |
2313 if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo), &iter)) return; | |
2314 gtk_tree_model_get(store, &iter, MENU_CHOICE_COLUMN_VALUE, &sd->match_size, -1); | |
2315 | |
2316 menu_choice_set_visible(gtk_widget_get_parent(sd->spin_size_end), | |
2317 (sd->match_size == SEARCH_MATCH_BETWEEN)); | |
2318 } | |
2319 | |
2320 static void menu_choice_date_cb(GtkWidget *combo, gpointer data) | |
2321 { | |
2322 SearchData *sd = data; | |
2323 GtkTreeModel *store; | |
2324 GtkTreeIter iter; | |
2325 | |
2326 store = gtk_combo_box_get_model(GTK_COMBO_BOX(combo)); | |
2327 if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo), &iter)) return; | |
2328 gtk_tree_model_get(store, &iter, MENU_CHOICE_COLUMN_VALUE, &sd->match_date, -1); | |
2329 | |
2330 menu_choice_set_visible(gtk_widget_get_parent(sd->date_sel_end), | |
2331 (sd->match_date == SEARCH_MATCH_BETWEEN)); | |
2332 } | |
2333 | |
2334 static void menu_choice_dimensions_cb(GtkWidget *combo, gpointer data) | |
2335 { | |
2336 SearchData *sd = data; | |
2337 GtkTreeModel *store; | |
2338 GtkTreeIter iter; | |
2339 | |
2340 store = gtk_combo_box_get_model(GTK_COMBO_BOX(combo)); | |
2341 if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo), &iter)) return; | |
2342 gtk_tree_model_get(store, &iter, MENU_CHOICE_COLUMN_VALUE, &sd->match_dimensions, -1); | |
2343 | |
2344 menu_choice_set_visible(gtk_widget_get_parent(sd->spin_width_end), | |
2345 (sd->match_dimensions == SEARCH_MATCH_BETWEEN)); | |
2346 } | |
2347 | |
2348 static void menu_choice_keyword_cb(GtkWidget *combo, gpointer data) | |
2349 { | |
2350 SearchData *sd = data; | |
2351 GtkTreeModel *store; | |
2352 GtkTreeIter iter; | |
2353 | |
2354 store = gtk_combo_box_get_model(GTK_COMBO_BOX(combo)); | |
2355 if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo), &iter)) return; | |
2356 gtk_tree_model_get(store, &iter, MENU_CHOICE_COLUMN_VALUE, &sd->match_keywords, -1); | |
2357 } | |
2358 | |
2359 static void menu_choice_spin_cb(GtkAdjustment *adjustment, gpointer data) | |
2360 { | |
2361 gint *value = data; | |
2362 | |
2363 *value = (gint)gtk_adjustment_get_value(adjustment); | |
2364 } | |
2365 | |
2366 static GtkWidget *menu_spin(GtkWidget *box, gdouble min, gdouble max, gint value, | |
2367 GCallback func, gpointer data) | |
2368 { | |
2369 GtkWidget *spin; | |
2370 GtkAdjustment *adj; | |
2371 | |
2372 spin = gtk_spin_button_new_with_range(min, max, 1); | |
2373 gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin), (gdouble)value); | |
2374 adj = gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(spin)); | |
2375 if (func) g_signal_connect(G_OBJECT(adj), "value_changed", | |
2376 G_CALLBACK(func), data); | |
2377 gtk_box_pack_start(GTK_BOX(box), spin, FALSE, FALSE, 0); | |
2378 gtk_widget_show(spin); | |
2379 | |
2380 return spin; | |
2381 } | |
2382 | |
2383 static void menu_choice_check_cb(GtkWidget *button, gpointer data) | |
2384 { | |
2385 GtkWidget *widget = data; | |
2386 gboolean active; | |
2387 gboolean *value; | |
2388 | |
2389 active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)); | |
2390 gtk_widget_set_sensitive(widget, active); | |
2391 | |
2392 value = g_object_get_data(G_OBJECT(button), "check_var"); | |
2393 if (value) *value = active; | |
2394 } | |
2395 | |
2396 static GtkWidget *menu_choice_menu(const MatchList *items, gint item_count, | |
2397 GCallback func, gpointer data) | |
2398 { | |
2399 GtkWidget *combo; | |
2400 GtkCellRenderer *renderer; | |
2401 GtkListStore *store; | |
2402 gint i; | |
2403 | |
2404 store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT); | |
2405 combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store)); | |
2406 g_object_unref(store); | |
2407 | |
2408 renderer = gtk_cell_renderer_text_new(); | |
2409 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), renderer, TRUE); | |
2410 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo), renderer, | |
2411 "text", MENU_CHOICE_COLUMN_NAME, NULL); | |
2412 | |
2413 for (i = 0; i < item_count; i++) | |
2414 { | |
2415 GtkTreeIter iter; | |
2416 | |
2417 gtk_list_store_append(store, &iter); | |
2418 gtk_list_store_set(store, &iter, MENU_CHOICE_COLUMN_NAME, _(items[i].text), | |
2419 MENU_CHOICE_COLUMN_VALUE, items[i].type, -1); | |
2420 } | |
2421 | |
2422 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0); | |
2423 | |
2424 if (func) g_signal_connect(G_OBJECT(combo), "changed", | |
2425 G_CALLBACK(func), data); | |
2426 | |
2427 return combo; | |
2428 } | |
2429 | |
2430 static GtkWidget *menu_choice(GtkWidget *box, GtkWidget **check, GtkWidget **menu, | |
2431 const gchar *text, gboolean *value, | |
2432 const MatchList *items, gint item_count, | |
2433 GCallback func, gpointer data) | |
2434 { | |
2435 GtkWidget *base_box; | |
2436 GtkWidget *hbox; | |
2437 GtkWidget *button; | |
2438 GtkWidget *option; | |
2439 | |
2440 base_box = gtk_hbox_new(FALSE, PREF_PAD_GAP); | |
2441 gtk_box_pack_start(GTK_BOX(box), base_box, FALSE, FALSE, 0); | |
2442 gtk_widget_show(base_box); | |
2443 | |
2444 button = gtk_check_button_new(); | |
2445 if (value) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), *value); | |
2446 gtk_box_pack_start(GTK_BOX(base_box), button, FALSE, FALSE, 0); | |
2447 gtk_widget_show(button); | |
2448 if (check) *check = button; | |
2449 if (value) g_object_set_data(G_OBJECT(button), "check_var", value); | |
2450 | |
2451 hbox = gtk_hbox_new(FALSE, PREF_PAD_SPACE); | |
2452 gtk_box_pack_start(GTK_BOX(base_box), hbox, TRUE, TRUE, 0); | |
2453 gtk_widget_show(hbox); | |
2454 | |
2455 g_signal_connect(G_OBJECT(button), "toggled", | |
2456 G_CALLBACK(menu_choice_check_cb), hbox); | |
2457 gtk_widget_set_sensitive(hbox, (value) ? *value : FALSE); | |
2458 | |
2459 pref_label_new(hbox, text); | |
2460 | |
2461 if (!items && !menu) return hbox; | |
2462 | |
2463 option = menu_choice_menu(items, item_count, func, data); | |
2464 gtk_box_pack_start(GTK_BOX(hbox), option, FALSE, FALSE, 0); | |
2465 gtk_widget_show(option); | |
2466 if (menu) *menu = option; | |
2467 | |
2468 return hbox; | |
2469 } | |
2470 | |
2471 static void search_window_close(SearchData *sd) | |
2472 { | |
2473 gtk_widget_destroy(sd->window); | |
2474 } | |
2475 | |
2476 static gint search_window_delete_cb(GtkWidget *widget, GdkEventAny *event, gpointer data) | |
2477 { | |
2478 SearchData *sd = data; | |
2479 | |
2480 search_window_close(sd); | |
2481 return TRUE; | |
2482 } | |
2483 | |
2484 static void search_window_destroy_cb(GtkWidget *widget, gpointer data) | |
2485 { | |
2486 SearchData *sd = data; | |
2487 | |
2488 search_window_list = g_list_remove(search_window_list, sd); | |
2489 | |
2490 search_result_update_idle_cancel(sd); | |
2491 | |
2492 filelist_free(sd->search_buffer_list); | |
2493 sd->search_buffer_list = NULL; | |
2494 | |
2495 search_stop(sd); | |
2496 search_result_clear(sd); | |
2497 | |
2498 g_free(sd->search_path); | |
2499 g_free(sd->search_name); | |
2500 g_free(sd->search_similarity_path); | |
138 | 2501 string_list_free(sd->search_keyword_list); |
9 | 2502 |
2503 g_free(sd); | |
2504 } | |
2505 | |
2506 void search_new(const gchar *path, const gchar *example_file) | |
2507 { | |
2508 SearchData *sd; | |
2509 GtkWidget *vbox; | |
2510 GtkWidget *hbox; | |
2511 GtkWidget *hbox2; | |
2512 GtkWidget *pad_box; | |
2513 GtkWidget *frame; | |
2514 GtkWidget *scrolled; | |
2515 GtkListStore *store; | |
2516 GtkTreeSortable *sortable; | |
2517 GtkTreeSelection *selection; | |
2518 GtkWidget *combo; | |
2519 GdkGeometry geometry; | |
2520 | |
2521 sd = g_new0(SearchData, 1); | |
2522 | |
2523 sd->search_path = g_strdup(path); | |
2524 sd->search_path_recurse = TRUE; | |
2525 sd->search_size = 0; | |
2526 sd->search_width = 640; | |
2527 sd->search_height = 480; | |
2528 sd->search_width_end = 1024; | |
2529 sd->search_height_end = 768; | |
2530 sd->search_name = NULL; | |
2531 sd->search_name_match_case = FALSE; | |
2532 | |
2533 sd->search_type = SEARCH_MATCH_NONE; | |
2534 | |
2535 sd->match_name = SEARCH_MATCH_CONTAINS; | |
2536 sd->match_size = SEARCH_MATCH_EQUAL; | |
2537 sd->match_date = SEARCH_MATCH_EQUAL; | |
2538 sd->match_dimensions = SEARCH_MATCH_EQUAL; | |
2539 sd->match_keywords = SEARCH_MATCH_ALL; | |
2540 | |
2541 sd->match_name_enable = TRUE; | |
2542 sd->match_size_enable = FALSE; | |
2543 sd->match_date_enable = FALSE; | |
2544 sd->match_dimensions_enable = FALSE; | |
2545 sd->match_similarity_enable = FALSE; | |
2546 sd->match_keywords_enable = FALSE; | |
2547 | |
2548 sd->search_similarity = 95; | |
2549 sd->search_similarity_path = g_strdup(example_file); | |
2550 sd->search_similarity_cd = NULL; | |
2551 | |
2552 sd->search_idle_id = -1; | |
2553 sd->update_idle_id = -1; | |
2554 | |
2555 sd->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | |
2556 window_set_icon(sd->window, NULL, NULL); | |
2557 | |
2558 gtk_window_set_resizable(GTK_WINDOW(sd->window), TRUE); | |
196 | 2559 gtk_window_set_title(GTK_WINDOW(sd->window), _("Image search - Geeqie")); |
254
9faf34f047b1
Make the wmclass value unique among the code by defining
zas_
parents:
250
diff
changeset
|
2560 gtk_window_set_wmclass(GTK_WINDOW(sd->window), "search", GQ_WMCLASS); |
9 | 2561 |
2562 geometry.min_width = 32; | |
2563 geometry.min_height = 32; | |
2564 geometry.base_width = DEF_SEARCH_WIDTH; | |
2565 geometry.base_height = DEF_SEARCH_HEIGHT; | |
2566 gtk_window_set_geometry_hints(GTK_WINDOW(sd->window), NULL, &geometry, | |
2567 GDK_HINT_MIN_SIZE | GDK_HINT_BASE_SIZE); | |
2568 | |
2569 gtk_window_set_default_size(GTK_WINDOW(sd->window), DEF_SEARCH_WIDTH, DEF_SEARCH_HEIGHT); | |
2570 | |
2571 g_signal_connect(G_OBJECT(sd->window), "delete_event", | |
2572 G_CALLBACK(search_window_delete_cb), sd); | |
2573 g_signal_connect(G_OBJECT(sd->window), "destroy", | |
2574 G_CALLBACK(search_window_destroy_cb), sd); | |
2575 | |
2576 g_signal_connect(G_OBJECT(sd->window), "key_press_event", | |
2577 G_CALLBACK(search_window_keypress_cb), sd); | |
2578 | |
2579 vbox = gtk_vbox_new(FALSE, PREF_PAD_GAP); | |
2580 gtk_container_set_border_width(GTK_CONTAINER(vbox), PREF_PAD_GAP); | |
2581 gtk_container_add(GTK_CONTAINER(sd->window), vbox); | |
2582 gtk_widget_show(vbox); | |
2583 | |
2584 sd->box_search = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP); | |
2585 | |
2586 hbox = pref_box_new(sd->box_search, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE); | |
2587 | |
2588 pref_label_new(hbox, _("Search:")); | |
2589 | |
2590 sd->menu_path = menu_choice_menu(text_search_menu_path, sizeof(text_search_menu_path) / sizeof(MatchList), | |
2591 G_CALLBACK(menu_choice_path_cb), sd); | |
2592 gtk_box_pack_start(GTK_BOX(hbox), sd->menu_path, FALSE, FALSE, 0); | |
2593 gtk_widget_show(sd->menu_path); | |
2594 | |
2595 hbox2 = pref_box_new(hbox, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE); | |
2596 combo = tab_completion_new_with_history(&sd->path_entry, sd->search_path, | |
2597 "search_path", -1, | |
2598 NULL, NULL); | |
2599 tab_completion_add_select_button(sd->path_entry, NULL, TRUE); | |
2600 gtk_box_pack_start(GTK_BOX(hbox2), combo, TRUE, TRUE, 0); | |
2601 gtk_widget_show(combo); | |
2602 sd->check_recurse = pref_checkbox_new_int(hbox2, _("Recurse"), | |
2603 sd->search_path_recurse, &sd->search_path_recurse); | |
2604 | |
2605 hbox = menu_choice(sd->box_search, &sd->check_name, &sd->menu_name, | |
2606 _("File name"), &sd->match_name_enable, | |
2607 text_search_menu_name, sizeof(text_search_menu_name) / sizeof(MatchList), | |
2608 G_CALLBACK(menu_choice_name_cb), sd); | |
2609 combo = history_combo_new(&sd->entry_name, "", "search_name", -1); | |
2610 gtk_box_pack_start(GTK_BOX(hbox), combo, TRUE, TRUE, 0); | |
2611 gtk_widget_show(combo); | |
2612 pref_checkbox_new_int(hbox, _("Match case"), | |
2613 sd->search_name_match_case, &sd->search_name_match_case); | |
2614 | |
2615 hbox = menu_choice(sd->box_search, &sd->check_size, &sd->menu_size, | |
2616 _("File size is"), &sd->match_size_enable, | |
2617 text_search_menu_size, sizeof(text_search_menu_size) / sizeof(MatchList), | |
2618 G_CALLBACK(menu_choice_size_cb), sd); | |
2619 sd->spin_size = menu_spin(hbox, 0, 1024*1024*1024, sd->search_size, | |
2620 G_CALLBACK(menu_choice_spin_cb), &sd->search_size); | |
2621 hbox2 = gtk_hbox_new(FALSE, PREF_PAD_SPACE); | |
2622 gtk_box_pack_start(GTK_BOX(hbox), hbox2, FALSE, FALSE, 0); | |
2623 pref_label_new(hbox2, _("and")); | |
2624 sd->spin_size_end = menu_spin(hbox2, 0, 1024*1024*1024, sd->search_size_end, | |
2625 G_CALLBACK(menu_choice_spin_cb), &sd->search_size_end); | |
2626 | |
2627 hbox = menu_choice(sd->box_search, &sd->check_date, &sd->menu_date, | |
2628 _("File date is"), &sd->match_date_enable, | |
2629 text_search_menu_date, sizeof(text_search_menu_date) / sizeof(MatchList), | |
2630 G_CALLBACK(menu_choice_date_cb), sd); | |
2631 sd->date_sel = date_selection_new(); | |
2632 date_selection_time_set(sd->date_sel, time(NULL)); | |
2633 gtk_box_pack_start(GTK_BOX(hbox), sd->date_sel, FALSE, FALSE, 0); | |
2634 gtk_widget_show(sd->date_sel); | |
2635 | |
2636 hbox2 = gtk_hbox_new(FALSE, PREF_PAD_SPACE); | |
2637 gtk_box_pack_start(GTK_BOX(hbox), hbox2, FALSE, FALSE, 0); | |
2638 pref_label_new(hbox2, _("and")); | |
2639 sd->date_sel_end = date_selection_new(); | |
2640 date_selection_time_set(sd->date_sel_end, time(NULL)); | |
2641 gtk_box_pack_start(GTK_BOX(hbox2), sd->date_sel_end, FALSE, FALSE, 0); | |
2642 gtk_widget_show(sd->date_sel_end); | |
2643 | |
2644 hbox = menu_choice(sd->box_search, &sd->check_dimensions, &sd->menu_dimensions, | |
2645 _("Image dimensions are"), &sd->match_dimensions_enable, | |
2646 text_search_menu_size, sizeof(text_search_menu_size) / sizeof(MatchList), | |
2647 G_CALLBACK(menu_choice_dimensions_cb), sd); | |
2648 pad_box = pref_box_new(hbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 2); | |
2649 sd->spin_width = menu_spin(pad_box, 0, 1000000, sd->search_width, | |
2650 G_CALLBACK(menu_choice_spin_cb), &sd->search_width); | |
2651 pref_label_new(pad_box, "x"); | |
2652 sd->spin_height = menu_spin(pad_box, 0, 1000000, sd->search_height, | |
2653 G_CALLBACK(menu_choice_spin_cb), &sd->search_height); | |
2654 hbox2 = gtk_hbox_new(FALSE, 2); | |
2655 gtk_box_pack_start(GTK_BOX(hbox), hbox2, FALSE, FALSE, 0); | |
2656 pref_label_new(hbox2, _("and")); | |
2657 pref_spacer(hbox2, PREF_PAD_SPACE - 2*2); | |
2658 sd->spin_width_end = menu_spin(hbox2, 0, 1000000, sd->search_width_end, | |
2659 G_CALLBACK(menu_choice_spin_cb), &sd->search_width_end); | |
2660 pref_label_new(hbox2, "x"); | |
2661 sd->spin_height_end = menu_spin(hbox2, 0, 1000000, sd->search_height_end, | |
2662 G_CALLBACK(menu_choice_spin_cb), &sd->search_height_end); | |
2663 | |
2664 hbox = menu_choice(sd->box_search, &sd->check_similarity, NULL, | |
2665 _("Image content is"), &sd->match_similarity_enable, | |
2666 NULL, 0, NULL, sd); | |
2667 sd->spin_similarity = menu_spin(hbox, 80, 100, sd->search_similarity, | |
2668 G_CALLBACK(menu_choice_spin_cb), &sd->search_similarity); | |
2669 | |
2670 /* xgettext:no-c-format */ | |
2671 pref_label_new(hbox, _("% similar to")); | |
2672 | |
2673 combo = tab_completion_new_with_history(&sd->entry_similarity, | |
2674 (sd->search_similarity_path) ? sd->search_similarity_path : "", | |
2675 "search_similarity_path", -1, NULL, NULL); | |
2676 tab_completion_add_select_button(sd->entry_similarity, NULL, FALSE); | |
2677 gtk_box_pack_start(GTK_BOX(hbox), combo, TRUE, TRUE, 0); | |
2678 gtk_widget_show(combo); | |
2679 | |
2680 hbox = menu_choice(sd->box_search, &sd->check_keywords, &sd->menu_keywords, | |
2681 _("Keywords"), &sd->match_keywords_enable, | |
2682 text_search_menu_keyword, sizeof(text_search_menu_keyword) / sizeof(MatchList), | |
2683 G_CALLBACK(menu_choice_keyword_cb), sd); | |
2684 sd->entry_keywords = gtk_entry_new(); | |
2685 gtk_box_pack_start(GTK_BOX(hbox), sd->entry_keywords, TRUE, TRUE, 0); | |
2686 gtk_widget_set_sensitive(sd->entry_keywords, sd->match_keywords_enable); | |
2687 g_signal_connect(G_OBJECT(sd->check_keywords), "toggled", | |
2688 G_CALLBACK(menu_choice_check_cb), sd->entry_keywords); | |
2689 gtk_widget_show(sd->entry_keywords); | |
2690 | |
2691 scrolled = gtk_scrolled_window_new(NULL, NULL); | |
2692 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN); | |
2693 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), | |
2694 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); | |
2695 gtk_box_pack_start(GTK_BOX(vbox), scrolled, TRUE, TRUE, 0); | |
2696 gtk_widget_show(scrolled); | |
2697 | |
2698 store = gtk_list_store_new(8, G_TYPE_POINTER, G_TYPE_INT, GDK_TYPE_PIXBUF, | |
2699 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, | |
2700 G_TYPE_STRING, G_TYPE_STRING); | |
2701 | |
2702 /* set up sorting */ | |
2703 sortable = GTK_TREE_SORTABLE(store); | |
2704 gtk_tree_sortable_set_sort_func(sortable, SEARCH_COLUMN_RANK, search_result_sort_cb, | |
2705 GINT_TO_POINTER(SEARCH_COLUMN_RANK), NULL); | |
2706 gtk_tree_sortable_set_sort_func(sortable, SEARCH_COLUMN_NAME, search_result_sort_cb, | |
2707 GINT_TO_POINTER(SEARCH_COLUMN_NAME), NULL); | |
2708 gtk_tree_sortable_set_sort_func(sortable, SEARCH_COLUMN_SIZE, search_result_sort_cb, | |
2709 GINT_TO_POINTER(SEARCH_COLUMN_SIZE), NULL); | |
2710 gtk_tree_sortable_set_sort_func(sortable, SEARCH_COLUMN_DATE, search_result_sort_cb, | |
2711 GINT_TO_POINTER(SEARCH_COLUMN_DATE), NULL); | |
2712 gtk_tree_sortable_set_sort_func(sortable, SEARCH_COLUMN_DIMENSIONS, search_result_sort_cb, | |
2713 GINT_TO_POINTER(SEARCH_COLUMN_DIMENSIONS), NULL); | |
2714 gtk_tree_sortable_set_sort_func(sortable, SEARCH_COLUMN_PATH, search_result_sort_cb, | |
2715 GINT_TO_POINTER(SEARCH_COLUMN_PATH), NULL); | |
2716 | |
2717 #if 0 | |
2718 /* by default, search results are unsorted until user selects a sort column - for speed, | |
2719 * using sort slows search speed by an order of magnitude with 1000's of results :-/ | |
2720 */ | |
2721 gtk_tree_sortable_set_sort_column_id(sortable, SEARCH_COLUMN_PATH, GTK_SORT_ASCENDING); | |
2722 #endif | |
2723 | |
2724 sd->result_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); | |
2725 g_object_unref(store); | |
2726 gtk_container_add(GTK_CONTAINER(scrolled), sd->result_view); | |
2727 gtk_widget_show(sd->result_view); | |
2728 | |
2729 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(sd->result_view)); | |
2730 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE); | |
2731 gtk_tree_selection_set_select_function(selection, search_result_select_cb, sd, NULL); | |
2732 | |
2733 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(sd->result_view), TRUE); | |
2734 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(sd->result_view), FALSE); | |
2735 | |
2736 #if 0 | |
2737 gtk_tree_view_set_search_column(GTK_TREE_VIEW(sd->result_view), SEARCH_COLUMN_NAME); | |
2738 #endif | |
2739 | |
2740 search_result_add_column(sd, SEARCH_COLUMN_RANK, _("Rank"), FALSE, FALSE); | |
2741 search_result_add_column(sd, SEARCH_COLUMN_THUMB, "", TRUE, FALSE); | |
2742 search_result_add_column(sd, SEARCH_COLUMN_NAME, _("Name"), FALSE, FALSE); | |
2743 search_result_add_column(sd, SEARCH_COLUMN_SIZE, _("Size"), FALSE, TRUE); | |
2744 search_result_add_column(sd, SEARCH_COLUMN_DATE, _("Date"), FALSE, TRUE); | |
2745 search_result_add_column(sd, SEARCH_COLUMN_DIMENSIONS, _("Dimensions"), FALSE, FALSE); | |
2746 search_result_add_column(sd, SEARCH_COLUMN_PATH, _("Path"), FALSE, FALSE); | |
2747 | |
2748 search_dnd_init(sd); | |
2749 | |
2750 g_signal_connect(G_OBJECT(sd->result_view), "button_press_event", | |
2751 G_CALLBACK(search_result_press_cb), sd); | |
2752 g_signal_connect(G_OBJECT(sd->result_view), "button_release_event", | |
2753 G_CALLBACK(search_result_release_cb), sd); | |
2754 g_signal_connect(G_OBJECT(sd->result_view), "key_press_event", | |
2755 G_CALLBACK(search_result_keypress_cb), sd); | |
2756 | |
2757 hbox = pref_box_new(vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0); | |
2758 | |
2759 sd->button_thumbs = pref_checkbox_new(hbox, _("Thumbnails"), FALSE, | |
2760 G_CALLBACK(search_thumb_toggle_cb), sd); | |
2761 | |
2762 frame = gtk_frame_new(NULL); | |
2763 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN); | |
2764 gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, PREF_PAD_SPACE); | |
2765 gtk_widget_show(frame); | |
2766 | |
2767 sd->label_status = gtk_label_new(""); | |
2768 gtk_widget_set_size_request(sd->label_status, 50, -1); | |
2769 gtk_container_add(GTK_CONTAINER(frame), sd->label_status); | |
2770 gtk_widget_show(sd->label_status); | |
2771 | |
2772 sd->label_progress = gtk_progress_bar_new(); | |
2773 gtk_widget_set_size_request(sd->label_progress, 50, -1); | |
2774 gtk_box_pack_start(GTK_BOX(hbox), sd->label_progress, TRUE, TRUE, 0); | |
2775 gtk_widget_show(sd->label_progress); | |
2776 | |
2777 sd->spinner = spinner_new(NULL, -1); | |
2778 gtk_box_pack_start(GTK_BOX(hbox), sd->spinner, FALSE, FALSE, 0); | |
2779 gtk_widget_show(sd->spinner); | |
2780 | |
2781 sd->button_start = pref_button_new(hbox, GTK_STOCK_FIND, NULL, FALSE, | |
2782 G_CALLBACK(search_start_cb), sd); | |
2783 pref_spacer(hbox, PREF_PAD_BUTTON_GAP); | |
2784 sd->button_stop = pref_button_new(hbox, GTK_STOCK_STOP, NULL, FALSE, | |
2785 G_CALLBACK(search_start_cb), sd); | |
2786 gtk_widget_set_sensitive(sd->button_stop, FALSE); | |
2787 | |
2788 search_status_update(sd); | |
2789 search_progress_update(sd, FALSE, -1.0); | |
2790 | |
2791 search_window_list = g_list_append(search_window_list, sd); | |
2792 | |
2793 gtk_widget_show(sd->window); | |
2794 } | |
2795 | |
2796 /* | |
2797 *------------------------------------------------------------------- | |
2798 * maintenance (move, delete, etc.) | |
2799 *------------------------------------------------------------------- | |
2800 */ | |
2801 | |
138 | 2802 static void search_result_change_path(SearchData *sd, FileData *fd) |
9 | 2803 { |
2804 GtkTreeModel *store; | |
2805 GtkTreeIter iter; | |
2806 gint valid; | |
2807 | |
2808 store = gtk_tree_view_get_model(GTK_TREE_VIEW(sd->result_view)); | |
2809 valid = gtk_tree_model_get_iter_first(store, &iter); | |
2810 while (valid) | |
2811 { | |
2812 GtkTreeIter current; | |
138 | 2813 MatchFileData *mfd; |
9 | 2814 |
2815 current = iter; | |
2816 valid = gtk_tree_model_iter_next(store, &iter); | |
2817 | |
138 | 2818 gtk_tree_model_get(store, ¤t, SEARCH_COLUMN_POINTER, &mfd, -1); |
2819 if (mfd->fd == fd) | |
9 | 2820 { |
138 | 2821 if (fd->change && fd->change->dest) |
9 | 2822 { |
2823 gtk_list_store_set(GTK_LIST_STORE(store), ¤t, | |
138 | 2824 SEARCH_COLUMN_NAME, mfd->fd->name, |
2825 SEARCH_COLUMN_PATH, mfd->fd->path, -1); | |
9 | 2826 } |
2827 else | |
2828 { | |
138 | 2829 search_result_remove_item(sd, mfd, ¤t); |
9 | 2830 } |
2831 } | |
2832 } | |
2833 } | |
2834 | |
138 | 2835 void search_maint_renamed(FileData *fd) |
9 | 2836 { |
2837 GList *work; | |
2838 | |
2839 work = search_window_list; | |
2840 while (work) | |
2841 { | |
2842 SearchData *sd = work->data; | |
2843 work = work->next; | |
2844 | |
138 | 2845 search_result_change_path(sd, fd); |
9 | 2846 } |
2847 } | |
2848 | |
138 | 2849 void search_maint_removed(FileData *fd) |
9 | 2850 { |
138 | 2851 search_maint_renamed(fd); |
9 | 2852 } |
2853 |