Mercurial > geeqie
annotate src/bar_info.c @ 174:126724275319
improved drawing of image frames
author | nadvornik |
---|---|
date | Mon, 11 Feb 2008 12:51:28 +0000 |
parents | 71e1ebee420e |
children | 0584cb78aa14 |
rev | line source |
---|---|
9 | 1 /* |
2 * GQview | |
3 * (C) 2004 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 "bar_info.h" | |
15 | |
16 #include "cache.h" | |
17 #include "filelist.h" | |
18 #include "info.h" | |
19 #include "utilops.h" | |
20 #include "ui_bookmark.h" | |
21 #include "ui_fileops.h" | |
22 #include "ui_misc.h" | |
23 #include "ui_utildlg.h" | |
24 | |
25 | |
26 #define BAR_KEYWORD_AUTOSAVE_TIME 10000 | |
27 | |
28 | |
29 static const gchar *keyword_favorite_defaults[] = { | |
30 N_("Favorite"), | |
31 N_("Todo"), | |
32 N_("People"), | |
33 N_("Places"), | |
34 N_("Art"), | |
35 N_("Nature"), | |
36 N_("Possessions"), | |
37 NULL | |
38 }; | |
39 | |
40 | |
41 static void bar_info_keyword_update_all(void); | |
42 | |
43 | |
44 /* | |
45 *------------------------------------------------------------------- | |
46 * keyword / comment utils | |
47 *------------------------------------------------------------------- | |
48 */ | |
49 | |
138 | 50 gint comment_write(gchar *path, GList *keywords, const gchar *comment) |
9 | 51 { |
52 FILE *f; | |
53 | |
54 f = fopen(path, "w"); | |
55 if (!f) return FALSE; | |
56 | |
57 fprintf(f, "#GQview comment (%s)\n\n", VERSION); | |
58 | |
59 fprintf(f, "[keywords]\n"); | |
60 while (keywords) | |
61 { | |
62 const gchar *word = keywords->data; | |
63 keywords = keywords->next; | |
64 | |
65 fprintf(f, "%s\n", word); | |
66 } | |
67 fprintf(f, "\n"); | |
68 | |
69 fprintf(f, "[comment]\n"); | |
70 fprintf(f, "%s\n", (comment) ? comment : ""); | |
71 | |
72 fprintf(f, "#end\n"); | |
73 | |
74 fclose(f); | |
75 | |
76 return TRUE; | |
77 } | |
78 | |
138 | 79 gint comment_cache_write(FileData *fd, GList *keywords, const gchar *comment) |
9 | 80 { |
81 gchar *comment_path; | |
82 gint success = FALSE; | |
83 | |
84 /* If an existing metadata file exists, we will try writing to | |
85 * it's location regardless of the user's preference. | |
86 */ | |
138 | 87 comment_path = cache_find_location(CACHE_TYPE_METADATA, fd->path); |
9 | 88 if (comment_path && !access_file(comment_path, W_OK)) |
89 { | |
90 g_free(comment_path); | |
91 comment_path = NULL; | |
92 } | |
93 | |
94 if (!comment_path) | |
95 { | |
96 gchar *comment_dir; | |
97 mode_t mode = 0755; | |
98 | |
138 | 99 comment_dir = cache_get_location(CACHE_TYPE_METADATA, fd->path, FALSE, &mode); |
9 | 100 if (cache_ensure_dir_exists(comment_dir, mode)) |
101 { | |
138 | 102 comment_path = g_strconcat(comment_dir, "/", fd->name, |
9 | 103 GQVIEW_CACHE_EXT_METADATA, NULL); |
104 } | |
105 g_free(comment_dir); | |
106 } | |
107 | |
108 if (comment_path) | |
109 { | |
110 gchar *comment_pathl; | |
111 | |
112 if (debug) printf("Saving comment: %s\n", comment_path); | |
113 | |
114 comment_pathl = path_from_utf8(comment_path); | |
115 | |
116 success = comment_write(comment_pathl, keywords, comment); | |
117 | |
118 g_free(comment_pathl); | |
119 g_free(comment_path); | |
120 } | |
121 | |
122 return success; | |
123 } | |
124 | |
138 | 125 gint comment_read(gchar *path, GList **keywords, gchar **comment) |
9 | 126 { |
127 FILE *f; | |
128 gchar s_buf[1024]; | |
129 gchar *key = NULL; | |
130 GList *list = NULL; | |
131 GString *comment_build = NULL; | |
132 | |
133 f = fopen(path, "r"); | |
134 if (!f) return FALSE; | |
135 | |
136 while (fgets(s_buf,sizeof(s_buf), f)) | |
137 { | |
138 if (s_buf[0]=='#') continue; | |
139 if (s_buf[0]=='[') | |
140 { | |
141 gint c = 0; | |
142 gchar *ptr = s_buf + 1; | |
143 | |
144 while(ptr[c] != ']' && ptr[c] != '\n' && ptr[c] != '\0') c++; | |
145 | |
146 g_free(key); | |
147 key = g_strndup(ptr, c); | |
148 } | |
149 else if (key) | |
150 { | |
151 gint newline = FALSE; | |
152 gchar *ptr = s_buf; | |
153 | |
154 while (*ptr != '\n' && *ptr != '\0') ptr++; | |
155 if (*ptr == '\n') | |
156 { | |
157 *ptr = '\0'; | |
158 newline = TRUE; | |
159 } | |
160 | |
161 if (strcasecmp(key, "keywords") == 0) | |
162 { | |
163 if (strlen(s_buf) > 0) list = g_list_prepend(list, g_strdup(s_buf)); | |
164 } | |
165 else if (strcasecmp(key, "comment") == 0) | |
166 { | |
167 if (!comment_build) comment_build = g_string_new(""); | |
168 g_string_append(comment_build, s_buf); | |
169 if (strlen(s_buf) > 0 && newline) g_string_append_c(comment_build, '\n'); | |
170 } | |
171 } | |
172 } | |
173 | |
174 fclose(f); | |
175 g_free(key); | |
176 | |
177 *keywords = g_list_reverse(list); | |
178 if (comment_build) | |
179 { | |
180 if (comment) *comment = g_strdup(comment_build->str); | |
181 g_string_free(comment_build, TRUE); | |
182 } | |
183 | |
184 return TRUE; | |
185 } | |
186 | |
138 | 187 gint comment_cache_read(FileData *fd, GList **keywords, gchar **comment) |
9 | 188 { |
189 gchar *comment_path; | |
190 gchar *comment_pathl; | |
191 gint success = FALSE; | |
138 | 192 if (!fd) return FALSE; |
9 | 193 |
138 | 194 comment_path = cache_find_location(CACHE_TYPE_METADATA, fd->path); |
9 | 195 if (!comment_path) return FALSE; |
196 | |
197 comment_pathl = path_from_utf8(comment_path); | |
198 | |
199 success = comment_read(comment_pathl, keywords, comment); | |
200 | |
201 g_free(comment_pathl); | |
202 g_free(comment_path); | |
203 | |
204 return success; | |
205 } | |
206 | |
207 static gchar *comment_pull(GtkWidget *textview) | |
208 { | |
209 GtkTextBuffer *buffer; | |
210 GtkTextIter start, end; | |
211 | |
212 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview)); | |
213 gtk_text_buffer_get_bounds(buffer, &start, &end); | |
214 | |
215 return gtk_text_buffer_get_text(buffer, &start, &end, FALSE); | |
216 } | |
217 | |
218 GList *keyword_list_pull(GtkWidget *text_widget) | |
219 { | |
220 GList *list = NULL; | |
221 gchar *text; | |
222 gchar *ptr; | |
223 | |
224 if (GTK_IS_TEXT_VIEW(text_widget)) | |
225 { | |
226 text = comment_pull(text_widget); | |
227 } | |
228 else if (GTK_IS_ENTRY(text_widget)) | |
229 { | |
230 text = g_strdup(gtk_entry_get_text(GTK_ENTRY(text_widget))); | |
231 } | |
232 else | |
233 { | |
234 return NULL; | |
235 } | |
236 | |
237 ptr = text; | |
238 while (*ptr != '\0') | |
239 { | |
240 gchar *begin; | |
241 gint l = 0; | |
242 | |
243 while (*ptr == ' ' || *ptr == ',' || *ptr == '\n' || *ptr == '\r' || *ptr == '\b') ptr++; | |
244 begin = ptr; | |
245 if (*ptr != '\0') | |
246 { | |
247 while (*ptr != ' ' && *ptr != ',' && | |
248 *ptr != '\n' && *ptr != '\r' && *ptr != '\b' && | |
249 *ptr != '\0') | |
250 { | |
251 ptr++; | |
252 l++; | |
253 } | |
254 } | |
255 | |
256 if (l > 0) list = g_list_append(list, g_strndup(begin, l)); | |
257 } | |
258 | |
259 g_free(text); | |
260 | |
261 return list; | |
262 } | |
263 | |
264 void keyword_list_push(GtkWidget *textview, GList *list) | |
265 { | |
266 GtkTextBuffer *buffer; | |
267 GtkTextIter start, end; | |
268 | |
269 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview)); | |
270 gtk_text_buffer_get_bounds(buffer, &start, &end); | |
271 gtk_text_buffer_delete (buffer, &start, &end); | |
272 | |
273 while (list) | |
274 { | |
275 const gchar *word = list->data; | |
276 GtkTextIter iter; | |
277 | |
278 gtk_text_buffer_get_end_iter(buffer, &iter); | |
279 if (word) gtk_text_buffer_insert(buffer, &iter, word, -1); | |
280 gtk_text_buffer_get_end_iter(buffer, &iter); | |
281 gtk_text_buffer_insert(buffer, &iter, "\n", -1); | |
282 | |
283 list = list->next; | |
284 } | |
285 } | |
286 | |
138 | 287 static void metadata_set_keywords(FileData *fd, GList *list, gint add) |
9 | 288 { |
289 gchar *comment = NULL; | |
290 GList *keywords = NULL; | |
291 GList *save_list = NULL; | |
292 | |
138 | 293 comment_cache_read(fd, &keywords, &comment); |
9 | 294 |
295 if (add) | |
296 { | |
297 GList *work; | |
298 | |
299 work = list; | |
300 while (work) | |
301 { | |
302 gchar *key; | |
303 GList *p; | |
304 | |
305 key = work->data; | |
306 work = work->next; | |
307 | |
308 p = keywords; | |
309 while (p && key) | |
310 { | |
311 gchar *needle = p->data; | |
312 p = p->next; | |
313 | |
314 if (strcmp(needle, key) == 0) key = NULL; | |
315 } | |
316 | |
317 if (key) keywords = g_list_append(keywords, g_strdup(key)); | |
318 } | |
319 save_list = keywords; | |
320 } | |
321 else | |
322 { | |
323 save_list = list; | |
324 } | |
325 | |
138 | 326 comment_cache_write(fd, save_list, comment); |
9 | 327 |
138 | 328 string_list_free(keywords); |
9 | 329 g_free(comment); |
330 } | |
331 | |
332 /* | |
333 *------------------------------------------------------------------- | |
334 * keyword list dialog | |
335 *------------------------------------------------------------------- | |
336 */ | |
337 | |
338 #define KEYWORD_DIALOG_WIDTH 200 | |
339 #define KEYWORD_DIALOG_HEIGHT 250 | |
340 | |
341 typedef struct _KeywordDlg KeywordDlg; | |
342 struct _KeywordDlg | |
343 { | |
344 GenericDialog *gd; | |
345 GtkWidget *treeview; | |
346 }; | |
347 | |
348 static KeywordDlg *keyword_dialog = NULL; | |
349 | |
350 | |
351 static void keyword_dialog_cancel_cb(GenericDialog *gd, gpointer data) | |
352 { | |
353 g_free(keyword_dialog); | |
354 keyword_dialog = NULL; | |
355 } | |
356 | |
357 static void keyword_dialog_ok_cb(GenericDialog *gd, gpointer data) | |
358 { | |
359 KeywordDlg *kd = data; | |
360 GtkTreeModel *store; | |
361 GtkTreeIter iter; | |
362 gint valid; | |
363 | |
364 history_list_free_key("keywords"); | |
365 | |
366 store = gtk_tree_view_get_model(GTK_TREE_VIEW(kd->treeview)); | |
367 valid = gtk_tree_model_get_iter_first(store, &iter); | |
368 while (valid) | |
369 { | |
370 gchar *key; | |
371 | |
372 gtk_tree_model_get(store, &iter, 0, &key, -1); | |
373 valid = gtk_tree_model_iter_next(store, &iter); | |
374 | |
375 history_list_add_to_key("keywords", key, 0); | |
376 } | |
377 | |
378 keyword_dialog_cancel_cb(gd, data); | |
379 | |
380 bar_info_keyword_update_all(); | |
381 } | |
382 | |
383 static void keyword_dialog_add_cb(GtkWidget *button, gpointer data) | |
384 { | |
385 KeywordDlg *kd = data; | |
386 GtkTreeSelection *selection; | |
387 GtkTreeModel *store; | |
388 GtkTreeIter sibling; | |
389 GtkTreeIter iter; | |
390 GtkTreePath *tpath; | |
391 | |
392 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(kd->treeview)); | |
393 if (gtk_tree_selection_get_selected(selection, &store, &sibling)) | |
394 { | |
395 gtk_list_store_insert_before(GTK_LIST_STORE(store), &iter, &sibling); | |
396 } | |
397 else | |
398 { | |
399 store = gtk_tree_view_get_model(GTK_TREE_VIEW(kd->treeview)); | |
400 gtk_list_store_append(GTK_LIST_STORE(store), &iter); | |
401 } | |
402 | |
403 gtk_list_store_set(GTK_LIST_STORE(store), &iter, 1, TRUE, -1); | |
404 | |
405 tpath = gtk_tree_model_get_path(store, &iter); | |
406 gtk_tree_view_set_cursor(GTK_TREE_VIEW(kd->treeview), tpath, | |
407 gtk_tree_view_get_column(GTK_TREE_VIEW(kd->treeview), 0), TRUE); | |
408 gtk_tree_path_free(tpath); | |
409 } | |
410 | |
411 static void keyword_dialog_remove_cb(GtkWidget *button, gpointer data) | |
412 { | |
413 KeywordDlg *kd = data; | |
414 GtkTreeSelection *selection; | |
415 GtkTreeModel *store; | |
416 GtkTreeIter iter; | |
417 GtkTreeIter next; | |
418 GtkTreePath *tpath; | |
419 | |
420 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(kd->treeview)); | |
421 if (!gtk_tree_selection_get_selected(selection, &store, &iter)) return; | |
422 | |
423 tpath = NULL; | |
424 next = iter; | |
425 if (gtk_tree_model_iter_next(store, &next)) | |
426 { | |
427 tpath = gtk_tree_model_get_path(store, &next); | |
428 } | |
429 else | |
430 { | |
431 tpath = gtk_tree_model_get_path(store, &iter); | |
432 if (!gtk_tree_path_prev(tpath)) | |
433 { | |
434 gtk_tree_path_free(tpath); | |
435 tpath = NULL; | |
436 } | |
437 } | |
438 if (tpath) | |
439 { | |
440 gtk_tree_view_set_cursor(GTK_TREE_VIEW(kd->treeview), tpath, | |
441 gtk_tree_view_get_column(GTK_TREE_VIEW(kd->treeview), 0), FALSE); | |
442 gtk_tree_path_free(tpath); | |
443 } | |
444 | |
445 gtk_list_store_remove(GTK_LIST_STORE(store), &iter); | |
446 } | |
447 | |
448 static void keyword_dialog_edit_cb(GtkCellRendererText *renderer, const gchar *path, | |
449 const gchar *new_text, gpointer data) | |
450 { | |
451 KeywordDlg *kd = data; | |
452 GtkTreeModel *store; | |
453 GtkTreeIter iter; | |
454 GtkTreePath *tpath; | |
455 | |
456 if (!new_text || strlen(new_text) == 0) return; | |
457 | |
458 store = gtk_tree_view_get_model(GTK_TREE_VIEW(kd->treeview)); | |
459 | |
460 tpath = gtk_tree_path_new_from_string(path); | |
461 gtk_tree_model_get_iter(store, &iter, tpath); | |
462 gtk_tree_path_free(tpath); | |
463 | |
464 gtk_list_store_set(GTK_LIST_STORE(store), &iter, 0, new_text, -1); | |
465 } | |
466 | |
467 static void keyword_dialog_populate(KeywordDlg *kd) | |
468 { | |
469 GtkListStore *store; | |
470 GList *list; | |
471 | |
472 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(kd->treeview))); | |
473 gtk_list_store_clear(store); | |
474 | |
475 list = history_list_get_by_key("keywords"); | |
476 list = g_list_last(list); | |
477 while (list) | |
478 { | |
479 GtkTreeIter iter; | |
480 | |
481 gtk_list_store_append(store, &iter); | |
482 gtk_list_store_set(store, &iter, 0, list->data, | |
483 1, TRUE, -1); | |
484 | |
485 list = list->prev; | |
486 } | |
487 } | |
488 | |
489 static void keyword_dialog_show(void) | |
490 { | |
491 GtkWidget *scrolled; | |
492 GtkListStore *store; | |
493 GtkTreeViewColumn *column; | |
494 GtkCellRenderer *renderer; | |
495 GtkWidget *hbox; | |
496 GtkWidget *button; | |
497 | |
498 if (keyword_dialog) | |
499 { | |
500 gtk_window_present(GTK_WINDOW(keyword_dialog->gd->dialog)); | |
501 return; | |
502 } | |
503 | |
504 keyword_dialog = g_new0(KeywordDlg, 1); | |
505 | |
506 keyword_dialog->gd = generic_dialog_new(_("Keyword Presets"), | |
507 "GQview", "keyword_presets", NULL, TRUE, | |
508 keyword_dialog_cancel_cb, keyword_dialog); | |
509 generic_dialog_add_message(keyword_dialog->gd, NULL, _("Favorite keywords list"), NULL); | |
510 | |
511 generic_dialog_add_button(keyword_dialog->gd, GTK_STOCK_OK, NULL, | |
512 keyword_dialog_ok_cb, TRUE); | |
513 | |
514 scrolled = gtk_scrolled_window_new(NULL, NULL); | |
515 gtk_widget_set_size_request(scrolled, KEYWORD_DIALOG_WIDTH, KEYWORD_DIALOG_HEIGHT); | |
516 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN); | |
517 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), | |
518 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); | |
519 gtk_box_pack_start(GTK_BOX(keyword_dialog->gd->vbox), scrolled, TRUE, TRUE, 5); | |
520 gtk_widget_show(scrolled); | |
521 | |
522 store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_BOOLEAN); | |
523 keyword_dialog->treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); | |
524 g_object_unref(store); | |
525 | |
526 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(keyword_dialog->treeview), FALSE); | |
527 gtk_tree_view_set_search_column(GTK_TREE_VIEW(keyword_dialog->treeview), 0); | |
528 gtk_tree_view_set_reorderable(GTK_TREE_VIEW(keyword_dialog->treeview), TRUE); | |
529 | |
530 column = gtk_tree_view_column_new(); | |
531 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); | |
532 renderer = gtk_cell_renderer_text_new(); | |
533 g_signal_connect(G_OBJECT(renderer), "edited", | |
534 G_CALLBACK(keyword_dialog_edit_cb), keyword_dialog); | |
535 gtk_tree_view_column_pack_start(column, renderer, TRUE); | |
536 gtk_tree_view_column_add_attribute(column, renderer, "text", 0); | |
537 gtk_tree_view_column_add_attribute(column, renderer, "editable", 1); | |
538 gtk_tree_view_append_column(GTK_TREE_VIEW(keyword_dialog->treeview), column); | |
539 | |
540 gtk_container_add(GTK_CONTAINER(scrolled), keyword_dialog->treeview); | |
541 gtk_widget_show(keyword_dialog->treeview); | |
542 | |
543 hbox = gtk_hbox_new(FALSE, 5); | |
544 gtk_box_pack_start(GTK_BOX(keyword_dialog->gd->vbox), hbox, FALSE, FALSE, 0); | |
545 gtk_widget_show(hbox); | |
546 | |
547 button = gtk_button_new_from_stock(GTK_STOCK_ADD); | |
548 g_signal_connect(G_OBJECT(button), "clicked", | |
549 G_CALLBACK(keyword_dialog_add_cb), keyword_dialog); | |
550 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); | |
551 gtk_widget_show(button); | |
552 | |
553 button = gtk_button_new_from_stock(GTK_STOCK_REMOVE); | |
554 g_signal_connect(G_OBJECT(button), "clicked", | |
555 G_CALLBACK(keyword_dialog_remove_cb), keyword_dialog); | |
556 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); | |
557 gtk_widget_show(button); | |
558 | |
559 keyword_dialog_populate(keyword_dialog); | |
560 | |
561 gtk_widget_show(keyword_dialog->gd->dialog); | |
562 } | |
563 | |
564 | |
565 static void bar_keyword_edit_cb(GtkWidget *button, gpointer data) | |
566 { | |
567 keyword_dialog_show(); | |
568 } | |
569 | |
570 | |
571 /* | |
572 *------------------------------------------------------------------- | |
573 * info bar | |
574 *------------------------------------------------------------------- | |
575 */ | |
576 | |
577 typedef enum { | |
578 BAR_SORT_COPY, | |
579 BAR_SORT_MOVE, | |
580 BAR_SORT_LINK | |
581 } SortActionType; | |
582 | |
583 enum { | |
584 KEYWORD_COLUMN_TOGGLE = 0, | |
585 KEYWORD_COLUMN_TEXT | |
586 }; | |
587 | |
588 typedef struct _BarInfoData BarInfoData; | |
589 struct _BarInfoData | |
590 { | |
591 GtkWidget *vbox; | |
592 GtkWidget *group_box; | |
593 GtkWidget *label_file_name; | |
594 GtkWidget *label_file_time; | |
595 | |
596 GtkWidget *keyword_view; | |
597 GtkWidget *keyword_treeview; | |
598 | |
599 GtkWidget *comment_view; | |
600 | |
601 GtkWidget *button_save; | |
602 GtkWidget *button_set_add; | |
603 GtkWidget *button_set_replace; | |
604 | |
138 | 605 FileData *fd; |
9 | 606 |
607 gint changed; | |
608 gint save_timeout_id; | |
609 | |
610 GList *(*list_func)(gpointer); | |
611 gpointer list_data; | |
612 }; | |
613 | |
614 | |
615 static GList *bar_list = NULL; | |
616 | |
617 | |
618 static void bar_info_write(BarInfoData *bd) | |
619 { | |
620 GList *list; | |
621 gchar *comment; | |
622 | |
138 | 623 if (!bd->fd) return; |
9 | 624 |
625 list = keyword_list_pull(bd->keyword_view); | |
626 comment = comment_pull(bd->comment_view); | |
627 | |
138 | 628 comment_cache_write(bd->fd, list, comment); |
9 | 629 |
138 | 630 string_list_free(list); |
9 | 631 g_free(comment); |
632 | |
633 bd->changed = FALSE; | |
634 gtk_widget_set_sensitive(bd->button_save, FALSE); | |
635 } | |
636 | |
637 static gint bar_info_autosave(gpointer data) | |
638 { | |
639 BarInfoData *bd = data; | |
640 | |
641 bar_info_write(bd); | |
642 | |
643 bd->save_timeout_id = -1; | |
644 | |
645 return FALSE; | |
646 } | |
647 | |
648 static void bar_info_save_update(BarInfoData *bd, gint enable) | |
649 { | |
650 if (bd->save_timeout_id != -1) | |
651 { | |
652 g_source_remove(bd->save_timeout_id); | |
653 bd->save_timeout_id = -1; | |
654 } | |
655 if (enable) | |
656 { | |
657 bd->save_timeout_id = g_timeout_add(BAR_KEYWORD_AUTOSAVE_TIME, bar_info_autosave, bd); | |
658 } | |
659 } | |
660 | |
661 static gint bar_keyword_list_find(GList *list, const gchar *keyword) | |
662 { | |
663 while (list) | |
664 { | |
665 gchar *haystack = list->data; | |
666 | |
667 if (haystack && keyword && strcmp(haystack, keyword) == 0) return TRUE; | |
668 | |
669 list = list->next; | |
670 } | |
671 | |
672 return FALSE; | |
673 } | |
674 | |
675 static void bar_keyword_list_sync(BarInfoData *bd, GList *keywords) | |
676 { | |
677 GList *list; | |
678 GtkListStore *store; | |
679 GtkTreeIter iter; | |
680 | |
681 list = history_list_get_by_key("keywords"); | |
682 if (!list) | |
683 { | |
684 /* blank? set up a few example defaults */ | |
685 | |
686 gint i = 0; | |
687 | |
688 while (keyword_favorite_defaults[i] != NULL) | |
689 { | |
690 history_list_add_to_key("keywords", _(keyword_favorite_defaults[i]), 0); | |
691 i++; | |
692 } | |
693 | |
694 list = history_list_get_by_key("keywords"); | |
695 } | |
696 | |
697 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(bd->keyword_treeview))); | |
698 | |
699 gtk_list_store_clear(store); | |
700 | |
701 list = g_list_last(list); | |
702 while (list) | |
703 { | |
704 gchar *key = list->data; | |
705 | |
706 gtk_list_store_append(store, &iter); | |
707 gtk_list_store_set(store, &iter, KEYWORD_COLUMN_TOGGLE, bar_keyword_list_find(keywords, key), | |
708 KEYWORD_COLUMN_TEXT, key, -1); | |
709 | |
710 list = list->prev; | |
711 } | |
712 } | |
713 | |
714 static void bar_info_keyword_update_all(void) | |
715 { | |
716 GList *work; | |
717 | |
718 work = bar_list; | |
719 while (work) | |
720 { | |
721 BarInfoData *bd; | |
722 GList *keywords; | |
723 | |
724 bd = work->data; | |
725 work = work->next; | |
726 | |
727 keywords = keyword_list_pull(bd->keyword_view); | |
728 bar_keyword_list_sync(bd, keywords); | |
138 | 729 string_list_free(keywords); |
9 | 730 } |
731 } | |
732 | |
733 static void bar_info_update(BarInfoData *bd) | |
734 { | |
735 GList *keywords = NULL; | |
736 gchar *comment = NULL; | |
737 | |
738 if (bd->label_file_name) | |
739 { | |
138 | 740 gtk_label_set_text(GTK_LABEL(bd->label_file_name), (bd->fd) ? bd->fd->name : ""); |
9 | 741 } |
742 if (bd->label_file_time) | |
743 { | |
138 | 744 gtk_label_set_text(GTK_LABEL(bd->label_file_time), (bd->fd) ? text_from_time(bd->fd->date) : ""); |
9 | 745 } |
746 | |
138 | 747 if (comment_cache_read(bd->fd, &keywords, &comment)) |
9 | 748 { |
749 keyword_list_push(bd->keyword_view, keywords); | |
750 gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(bd->comment_view)), | |
751 (comment) ? comment : "", -1); | |
752 | |
753 bar_keyword_list_sync(bd, keywords); | |
754 | |
138 | 755 string_list_free(keywords); |
9 | 756 g_free(comment); |
757 } | |
758 else | |
759 { | |
760 gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(bd->keyword_view)), "", -1); | |
761 gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(bd->comment_view)), "", -1); | |
762 | |
763 bar_keyword_list_sync(bd, NULL); | |
764 } | |
765 | |
766 bar_info_save_update(bd, FALSE); | |
767 bd->changed = FALSE; | |
768 gtk_widget_set_sensitive(bd->button_save, FALSE); | |
769 | |
138 | 770 gtk_widget_set_sensitive(bd->group_box, (bd->fd != NULL)); |
9 | 771 } |
772 | |
138 | 773 void bar_info_set(GtkWidget *bar, FileData *fd) |
9 | 774 { |
775 BarInfoData *bd; | |
776 | |
777 bd = g_object_get_data(G_OBJECT(bar), "bar_info_data"); | |
778 if (!bd) return; | |
779 | |
780 if (bd->changed) bar_info_write(bd); | |
781 | |
138 | 782 file_data_unref(bd->fd); |
783 bd->fd = file_data_ref(fd); | |
9 | 784 |
785 bar_info_update(bd); | |
786 } | |
787 | |
138 | 788 void bar_info_maint_renamed(GtkWidget *bar, FileData *fd) |
9 | 789 { |
790 BarInfoData *bd; | |
791 | |
792 bd = g_object_get_data(G_OBJECT(bar), "bar_info_data"); | |
793 if (!bd) return; | |
794 | |
138 | 795 file_data_unref(bd->fd); |
796 bd->fd = file_data_ref(fd); | |
9 | 797 |
798 if (bd->label_file_name) | |
799 { | |
138 | 800 gtk_label_set_text(GTK_LABEL(bd->label_file_name), (bd->fd) ? bd->fd->name : ""); |
9 | 801 } |
802 } | |
803 | |
804 gint bar_info_event(GtkWidget *bar, GdkEvent *event) | |
805 { | |
806 BarInfoData *bd; | |
807 | |
808 bd = g_object_get_data(G_OBJECT(bar), "bar_info_data"); | |
809 if (!bd) return FALSE; | |
810 | |
811 if (GTK_WIDGET_HAS_FOCUS(bd->keyword_view)) return gtk_widget_event(bd->keyword_view, event); | |
812 if (GTK_WIDGET_HAS_FOCUS(bd->comment_view)) return gtk_widget_event(bd->comment_view, event); | |
813 | |
814 return FALSE; | |
815 } | |
816 | |
817 static void bar_info_keyword_set(BarInfoData *bd, const gchar *keyword, gint active) | |
818 { | |
819 GList *list; | |
820 gint found; | |
821 | |
822 if (!keyword) return; | |
823 | |
824 list = keyword_list_pull(bd->keyword_view); | |
825 found = bar_keyword_list_find(list, keyword); | |
826 | |
827 if (active != found) | |
828 { | |
829 if (found) | |
830 { | |
831 GList *work = list; | |
832 | |
833 while (work) | |
834 { | |
835 gchar *key = work->data; | |
836 work = work->next; | |
837 | |
838 if (key && keyword && strcmp(key, keyword) == 0) | |
839 { | |
840 list = g_list_remove(list, key); | |
841 g_free(key); | |
842 } | |
843 } | |
844 } | |
845 else | |
846 { | |
847 list = g_list_append(list, g_strdup(keyword)); | |
848 } | |
849 | |
850 keyword_list_push(bd->keyword_view, list); | |
851 } | |
852 | |
138 | 853 string_list_free(list); |
9 | 854 } |
855 | |
856 static void bar_info_keyword_toggle(GtkCellRendererToggle *toggle, const gchar *path, gpointer data) | |
857 { | |
858 BarInfoData *bd = data; | |
859 GtkTreeModel *store; | |
860 GtkTreeIter iter; | |
861 GtkTreePath *tpath; | |
862 gchar *key = NULL; | |
863 gboolean active; | |
864 | |
865 store = gtk_tree_view_get_model(GTK_TREE_VIEW(bd->keyword_treeview)); | |
866 | |
867 tpath = gtk_tree_path_new_from_string(path); | |
868 gtk_tree_model_get_iter(store, &iter, tpath); | |
869 gtk_tree_path_free(tpath); | |
870 | |
871 gtk_tree_model_get(store, &iter, KEYWORD_COLUMN_TOGGLE, &active, | |
872 KEYWORD_COLUMN_TEXT, &key, -1); | |
873 active = (!active); | |
874 gtk_list_store_set(GTK_LIST_STORE(store), &iter, KEYWORD_COLUMN_TOGGLE, active, -1); | |
875 | |
876 bar_info_keyword_set(bd, key, active); | |
877 g_free(key); | |
878 } | |
879 | |
880 static void bar_info_save(GtkWidget *button, gpointer data) | |
881 { | |
882 BarInfoData *bd = data; | |
883 | |
884 bar_info_save_update(bd, FALSE); | |
885 bar_info_write(bd); | |
886 } | |
887 | |
888 static void bar_info_set_selection(BarInfoData *bd, gint add) | |
889 { | |
890 GList *keywords; | |
891 GList *list = NULL; | |
892 GList *work; | |
893 | |
894 if (!bd->list_func) return; | |
895 | |
896 keywords = keyword_list_pull(bd->keyword_view); | |
897 if (!keywords && add) return; | |
898 | |
899 list = bd->list_func(bd->list_data); | |
900 work = list; | |
901 while (work) | |
902 { | |
138 | 903 FileData *fd = work->data; |
9 | 904 work = work->next; |
905 | |
138 | 906 metadata_set_keywords(fd, keywords, add); |
9 | 907 } |
908 | |
138 | 909 filelist_free(list); |
910 string_list_free(keywords); | |
9 | 911 } |
912 | |
913 static void bar_info_set_add(GtkWidget *button, gpointer data) | |
914 { | |
915 BarInfoData *bd = data; | |
916 | |
917 bar_info_set_selection(bd, TRUE); | |
918 } | |
919 | |
920 static void bar_info_set_replace(GtkWidget *button, gpointer data) | |
921 { | |
922 BarInfoData *bd = data; | |
923 | |
924 bar_info_set_selection(bd, FALSE); | |
925 } | |
926 | |
927 static void bar_info_changed(GtkTextBuffer *buffer, gpointer data) | |
928 { | |
929 BarInfoData *bd = data; | |
930 | |
931 bd->changed = TRUE; | |
932 gtk_widget_set_sensitive(bd->button_save, TRUE); | |
933 | |
934 bar_info_save_update(bd, TRUE); | |
935 } | |
936 | |
937 void bar_info_close(GtkWidget *bar) | |
938 { | |
939 BarInfoData *bd; | |
940 | |
941 bd = g_object_get_data(G_OBJECT(bar), "bar_info_data"); | |
942 if (!bd) return; | |
943 | |
944 gtk_widget_destroy(bd->vbox); | |
945 } | |
946 | |
947 static void bar_info_destroy(GtkWidget *widget, gpointer data) | |
948 { | |
949 BarInfoData *bd = data; | |
950 | |
951 if (bd->changed) bar_info_write(bd); | |
952 bar_info_save_update(bd, FALSE); | |
953 | |
954 bar_list = g_list_remove(bar_list, bd); | |
955 | |
138 | 956 file_data_unref(bd->fd); |
9 | 957 |
958 g_free(bd); | |
959 } | |
960 | |
138 | 961 GtkWidget *bar_info_new(FileData *fd, gint metadata_only, GtkWidget *bounding_widget) |
9 | 962 { |
963 BarInfoData *bd; | |
964 GtkWidget *box; | |
965 GtkWidget *hbox; | |
966 GtkWidget *table; | |
967 GtkWidget *scrolled; | |
968 GtkTextBuffer *buffer; | |
969 GtkWidget *label; | |
970 GtkWidget *tbar; | |
971 GtkListStore *store; | |
972 GtkTreeViewColumn *column; | |
973 GtkCellRenderer *renderer; | |
974 | |
975 bd = g_new0(BarInfoData, 1); | |
976 | |
977 bd->list_func = NULL; | |
978 bd->list_data = NULL; | |
979 | |
980 bd->vbox = gtk_vbox_new(FALSE, PREF_PAD_GAP); | |
981 g_object_set_data(G_OBJECT(bd->vbox), "bar_info_data", bd); | |
982 g_signal_connect(G_OBJECT(bd->vbox), "destroy", | |
983 G_CALLBACK(bar_info_destroy), bd); | |
984 | |
985 if (!metadata_only) | |
986 { | |
987 hbox = pref_box_new(bd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_GAP); | |
988 | |
989 label = sizer_new(bd->vbox, bounding_widget, SIZER_POS_LEFT); | |
990 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); | |
991 gtk_widget_show(label); | |
992 | |
993 label = gtk_label_new(_("Keywords")); | |
994 pref_label_bold(label, TRUE, FALSE); | |
995 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0); | |
996 gtk_widget_show(label); | |
997 } | |
998 | |
999 bd->group_box = pref_box_new(bd->vbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP); | |
1000 | |
1001 if (!metadata_only) | |
1002 { | |
1003 GtkWidget *table; | |
1004 | |
1005 table = pref_table_new(bd->group_box, 2, 2, FALSE, FALSE); | |
1006 | |
1007 bd->label_file_name = table_add_line(table, 0, 0, _("Filename:"), NULL); | |
1008 bd->label_file_time = table_add_line(table, 0, 1, _("File date:"), NULL); | |
1009 } | |
1010 else | |
1011 { | |
1012 bd->label_file_name = NULL; | |
1013 bd->label_file_time = NULL; | |
1014 } | |
1015 | |
1016 table = gtk_table_new(3, 1, TRUE); | |
1017 gtk_table_set_row_spacings(GTK_TABLE(table), PREF_PAD_GAP); | |
1018 gtk_box_pack_start(GTK_BOX(bd->group_box), table, TRUE, TRUE, 0); | |
1019 gtk_widget_show(table); | |
1020 | |
1021 /* keyword entry */ | |
1022 | |
1023 box = gtk_vbox_new(FALSE, 0); | |
1024 gtk_table_attach(GTK_TABLE(table), box, 0, 1, 0, 2, | |
1025 GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); | |
1026 gtk_widget_show(box); | |
1027 | |
1028 label = pref_label_new(box, _("Keywords:")); | |
1029 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); | |
1030 pref_label_bold(label, TRUE, FALSE); | |
1031 | |
1032 hbox = pref_box_new(box, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_GAP); | |
1033 | |
1034 scrolled = gtk_scrolled_window_new(NULL, NULL); | |
1035 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN); | |
1036 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), | |
1037 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); | |
1038 gtk_box_pack_start(GTK_BOX(hbox), scrolled, TRUE, TRUE, 0); | |
1039 gtk_widget_show(scrolled); | |
1040 | |
1041 bd->keyword_view = gtk_text_view_new(); | |
1042 gtk_container_add(GTK_CONTAINER(scrolled), bd->keyword_view); | |
1043 gtk_widget_show(bd->keyword_view); | |
1044 | |
1045 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(bd->keyword_view)); | |
1046 g_signal_connect(G_OBJECT(buffer), "changed", | |
1047 G_CALLBACK(bar_info_changed), bd); | |
1048 | |
1049 scrolled = gtk_scrolled_window_new(NULL, NULL); | |
1050 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN); | |
1051 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), | |
1052 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); | |
1053 gtk_box_pack_start(GTK_BOX(hbox), scrolled, TRUE, TRUE, 0); | |
1054 gtk_widget_show(scrolled); | |
1055 | |
1056 store = gtk_list_store_new(2, G_TYPE_BOOLEAN, G_TYPE_STRING); | |
1057 bd->keyword_treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); | |
1058 g_object_unref(store); | |
1059 | |
1060 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(bd->keyword_treeview), FALSE); | |
1061 | |
1062 if (metadata_only) | |
1063 { | |
1064 gtk_tree_view_set_search_column(GTK_TREE_VIEW(bd->keyword_treeview), KEYWORD_COLUMN_TEXT); | |
1065 } | |
1066 else | |
1067 { | |
1068 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(bd->keyword_treeview), FALSE); | |
1069 } | |
1070 | |
1071 column = gtk_tree_view_column_new(); | |
1072 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); | |
1073 | |
1074 renderer = gtk_cell_renderer_toggle_new(); | |
1075 gtk_tree_view_column_pack_start(column, renderer, FALSE); | |
1076 gtk_tree_view_column_add_attribute(column, renderer, "active", KEYWORD_COLUMN_TOGGLE); | |
1077 g_signal_connect(G_OBJECT(renderer), "toggled", | |
1078 G_CALLBACK(bar_info_keyword_toggle), bd); | |
1079 | |
1080 renderer = gtk_cell_renderer_text_new(); | |
1081 gtk_tree_view_column_pack_start(column, renderer, TRUE); | |
1082 gtk_tree_view_column_add_attribute(column, renderer, "text", KEYWORD_COLUMN_TEXT); | |
1083 | |
1084 gtk_tree_view_append_column(GTK_TREE_VIEW(bd->keyword_treeview), column); | |
1085 | |
1086 gtk_container_add(GTK_CONTAINER(scrolled), bd->keyword_treeview); | |
1087 gtk_widget_show(bd->keyword_treeview); | |
1088 | |
1089 /* comment entry */ | |
1090 | |
1091 box = gtk_vbox_new(FALSE, 0); | |
1092 gtk_table_attach(GTK_TABLE(table), box, 0, 1, 2, 3, | |
1093 GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); | |
1094 gtk_widget_show(box); | |
1095 | |
1096 label = pref_label_new(box, _("Comment:")); | |
1097 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); | |
1098 pref_label_bold(label, TRUE, FALSE); | |
1099 | |
1100 scrolled = gtk_scrolled_window_new(NULL, NULL); | |
1101 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN); | |
1102 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), | |
1103 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); | |
1104 gtk_box_pack_start(GTK_BOX(box), scrolled, TRUE, TRUE, 0); | |
1105 gtk_widget_show(scrolled); | |
1106 | |
1107 bd->comment_view = gtk_text_view_new(); | |
1108 gtk_container_add(GTK_CONTAINER(scrolled), bd->comment_view); | |
1109 gtk_widget_show(bd->comment_view); | |
1110 | |
1111 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(bd->comment_view)); | |
1112 g_signal_connect(G_OBJECT(buffer), "changed", | |
1113 G_CALLBACK(bar_info_changed), bd); | |
1114 | |
1115 /* toolbar */ | |
1116 | |
1117 tbar = pref_toolbar_new(bd->group_box, GTK_TOOLBAR_ICONS); | |
1118 | |
41
6281cc38e5ca
Wed Apr 27 15:17:57 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
1119 pref_toolbar_button(tbar, GTK_STOCK_INDEX, NULL, FALSE, |
9 | 1120 _("Edit favorite keywords list."), |
1121 G_CALLBACK(bar_keyword_edit_cb), bd); | |
1122 pref_toolbar_spacer(tbar); | |
41
6281cc38e5ca
Wed Apr 27 15:17:57 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
1123 bd->button_set_add = pref_toolbar_button(tbar, GTK_STOCK_ADD, NULL, FALSE, |
9 | 1124 _("Add keywords to selected files"), |
1125 G_CALLBACK(bar_info_set_add), bd); | |
41
6281cc38e5ca
Wed Apr 27 15:17:57 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
1126 bd->button_set_replace = pref_toolbar_button(tbar, GTK_STOCK_CONVERT, NULL, FALSE, |
9 | 1127 _("Add keywords to selected files, replacing the existing ones."), |
1128 G_CALLBACK(bar_info_set_replace), bd); | |
1129 pref_toolbar_spacer(tbar); | |
41
6281cc38e5ca
Wed Apr 27 15:17:57 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
1130 bd->button_save = pref_toolbar_button(tbar, GTK_STOCK_SAVE, NULL, FALSE, |
9 | 1131 _("Save comment now"), |
1132 G_CALLBACK(bar_info_save), bd); | |
1133 | |
1134 bd->save_timeout_id = -1; | |
1135 | |
138 | 1136 bd->fd = file_data_ref(fd); |
9 | 1137 bar_info_update(bd); |
1138 | |
1139 bar_info_selection(bd->vbox, 0); | |
1140 | |
1141 bar_list = g_list_append(bar_list, bd); | |
1142 | |
1143 return bd->vbox; | |
1144 } | |
1145 | |
1146 void bar_info_set_selection_func(GtkWidget *bar, GList *(*list_func)(gpointer data), gpointer data) | |
1147 { | |
1148 BarInfoData *bd; | |
1149 | |
1150 bd = g_object_get_data(G_OBJECT(bar), "bar_info_data"); | |
1151 if (!bd) return; | |
1152 | |
1153 bd->list_func = list_func; | |
1154 bd->list_data = data; | |
1155 } | |
1156 | |
1157 void bar_info_selection(GtkWidget *bar, gint count) | |
1158 { | |
1159 BarInfoData *bd; | |
1160 gint enable; | |
1161 | |
1162 bd = g_object_get_data(G_OBJECT(bar), "bar_info_data"); | |
1163 if (!bd) return; | |
1164 | |
1165 enable = (count > 0 && bd->list_func != NULL); | |
1166 | |
1167 gtk_widget_set_sensitive(bd->button_set_add, enable); | |
1168 gtk_widget_set_sensitive(bd->button_set_replace, enable); | |
1169 } | |
1170 | |
1171 void bar_info_size_request(GtkWidget *bar, gint width) | |
1172 { | |
1173 BarInfoData *bd; | |
1174 | |
1175 bd = g_object_get_data(G_OBJECT(bar), "bar_info_data"); | |
1176 if (!bd) return; | |
1177 | |
1178 if (bd->label_file_name) | |
1179 { | |
1180 gtk_widget_set_size_request(bd->vbox, width, -1); | |
1181 } | |
1182 } | |
1183 |