1 /* EasyTAG - tag editor for audio files
2 * Copyright (C) 2014,2015 David King <amigadave@amigadave.com>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc., 51
16 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 #include "config.h"
20
21 #include "tag_area.h"
22
23 #include <glib/gi18n.h>
24
25 #include "application_window.h"
26 #include "charset.h"
27 #include "easytag.h"
28 #include "file_list.h"
29 #include "genres.h"
30 #include "log.h"
31 #include "misc.h"
32 #include "picture.h"
33 #include "scan.h"
34 #include "scan_dialog.h"
35
36 typedef struct
37 {
38 GtkWidget *tag_label;
39 GtkWidget *tag_notebook;
40
41 GtkWidget *common_grid;
42
43 GtkWidget *title_label;
44 GtkWidget *title_entry;
45 GtkWidget *artist_label;
46 GtkWidget *artist_entry;
47 GtkWidget *album_artist_label;
48 GtkWidget *album_artist_entry;
49 GtkWidget *album_label;
50 GtkWidget *album_entry;
51 GtkWidget *disc_number_label;
52 GtkWidget *disc_number_entry;
53 GtkWidget *year_label;
54 GtkWidget *year_entry;
55 GtkWidget *track_label;
56 GtkWidget *track_combo_entry;
57 GtkWidget *track_total_entry;
58 GtkWidget *genre_label;
59 GtkWidget *genre_combo_entry;
60 GtkWidget *comment_label;
61 GtkWidget *comment_entry;
62 GtkWidget *composer_label;
63 GtkWidget *composer_entry;
64 GtkWidget *orig_artist_label;
65 GtkWidget *orig_artist_entry;
66 GtkWidget *copyright_label;
67 GtkWidget *copyright_entry;
68 GtkWidget *url_label;
69 GtkWidget *url_entry;
70 GtkWidget *encoded_by_label;
71 GtkWidget *encoded_by_entry;
72
73 GtkListStore *genre_combo_model;
74 GtkListStore *track_combo_model;
75
76 GtkWidget *images_view;
77
78 /* Other for picture. */
79 GtkWidget *remove_image_toolitem;
80 GtkWidget *add_image_toolitem;
81 GtkWidget *save_image_toolitem;
82 GtkWidget *image_properties_toolitem;
83
84 /* Notebook tabs. */
85 GtkWidget *images_grid;
86
87 /* Image treeview model. */
88 GtkListStore *images_model;
89
90 /* Mini buttons. */
91 GtkWidget *track_sequence_button;
92 GtkWidget *track_number_button;
93 GtkWidget *apply_image_toolitem;
94 } EtTagAreaPrivate;
95
96 G_DEFINE_TYPE_WITH_PRIVATE (EtTagArea, et_tag_area, GTK_TYPE_BIN)
97
98 enum
99 {
100 TRACK_COLUMN_TRACK_NUMBER,
101 TRACK_COLUMN_COUNT
102 };
103
104 enum
105 {
106 GENRE_COLUMN_GENRE,
107 GENRE_COLUMN_COUNT
108 };
109
110 enum
111 {
112 TARGET_URI_LIST
113 };
114
115 enum /* Columns for images_view. */
116 {
117 PICTURE_COLUMN_SURFACE,
118 PICTURE_COLUMN_TEXT,
119 PICTURE_COLUMN_DATA,
120 PICTURE_COLUMN_COUNT
121 };
122
123 enum /* Columns for list in properties window. */
124 {
125 PICTURE_TYPE_COLUMN_TEXT,
126 PICTURE_TYPE_COLUMN_TYPE_CODE,
127 PICTURE_TYPE_COLUMN_COUNT
128 };
129
130 static void
on_apply_to_selection(GObject * object,EtTagArea * self)131 on_apply_to_selection (GObject *object,
132 EtTagArea *self)
133 {
134 EtTagAreaPrivate *priv;
135 EtApplicationWindow *window;
136 GList *etfilelist = NULL;
137 GList *selection_filelist = NULL;
138 GList *l;
139 const gchar *string_to_set;
140 const gchar *string_to_set1;
141 gchar *msg = NULL;
142 ET_File *etfile;
143 File_Tag *FileTag;
144 GtkTreeSelection *selection;
145
146 g_return_if_fail (ETCore->ETFileDisplayedList != NULL);
147
148 priv = et_tag_area_get_instance_private (self);
149
150 window = ET_APPLICATION_WINDOW (MainWindow);
151
152 et_application_window_update_et_file_from_ui (window);
153
154 /* Warning : 'selection_filelist' is not a list of 'ETFile' items! */
155 selection = et_application_window_browser_get_selection (window);
156 selection_filelist = gtk_tree_selection_get_selected_rows (selection, NULL);
157
158 // Create an 'ETFile' list from 'selection_filelist'
159 for (l = selection_filelist; l != NULL; l = g_list_next (l))
160 {
161 etfile = et_application_window_browser_get_et_file_from_path (window,
162 l->data);
163 etfilelist = g_list_prepend (etfilelist, etfile);
164 }
165
166 etfilelist = g_list_reverse (etfilelist);
167 g_list_free_full (selection_filelist, (GDestroyNotify)gtk_tree_path_free);
168
169
170 if (object == G_OBJECT (priv->title_entry))
171 {
172 string_to_set = gtk_entry_get_text (GTK_ENTRY (priv->title_entry));
173
174 for (l = etfilelist; l != NULL; l = g_list_next (l))
175 {
176 etfile = (ET_File *)l->data;
177 FileTag = et_file_tag_new ();
178 et_file_tag_copy_into (FileTag, etfile->FileTag->data);
179 et_file_tag_set_title (FileTag, string_to_set);
180 ET_Manage_Changes_Of_File_Data(etfile,NULL,FileTag);
181 }
182
183 if (!et_str_empty (string_to_set))
184 {
185 msg = g_strdup_printf (_("Selected files tagged with title ‘%s’"),
186 string_to_set);
187 }
188 else
189 {
190 msg = g_strdup (_("Removed title from selected files"));
191 }
192 }
193 else if (object == G_OBJECT (priv->artist_entry))
194 {
195 string_to_set = gtk_entry_get_text (GTK_ENTRY (priv->artist_entry));
196
197 for (l = etfilelist; l != NULL; l = g_list_next (l))
198 {
199 etfile = (ET_File *)l->data;
200 FileTag = et_file_tag_new ();
201 et_file_tag_copy_into (FileTag, etfile->FileTag->data);
202 et_file_tag_set_artist (FileTag, string_to_set);
203 ET_Manage_Changes_Of_File_Data(etfile,NULL,FileTag);
204 }
205
206 if (!et_str_empty (string_to_set))
207 {
208 msg = g_strdup_printf (_("Selected files tagged with artist ‘%s’"),
209 string_to_set);
210 }
211 else
212 {
213 msg = g_strdup (_("Removed artist from selected files"));
214 }
215 }
216 else if (object == G_OBJECT (priv->album_artist_entry))
217 {
218 string_to_set = gtk_entry_get_text (GTK_ENTRY (priv->album_artist_entry));
219
220 for (l = etfilelist; l != NULL; l = g_list_next (l))
221 {
222 etfile = (ET_File *)l->data;
223 FileTag = et_file_tag_new ();
224 et_file_tag_copy_into (FileTag, etfile->FileTag->data);
225 et_file_tag_set_album_artist (FileTag, string_to_set);
226 ET_Manage_Changes_Of_File_Data(etfile,NULL,FileTag);
227 }
228
229 if (!et_str_empty (string_to_set))
230 {
231 msg = g_strdup_printf (_("Selected files tagged with album artist ‘%s’"),
232 string_to_set);
233 }
234 else
235 {
236 msg = g_strdup (_("Removed album artist from selected files"));
237 }
238 }
239 else if (object == G_OBJECT (priv->album_entry))
240 {
241 string_to_set = gtk_entry_get_text (GTK_ENTRY (priv->album_entry));
242
243 for (l = etfilelist; l != NULL; l = g_list_next (l))
244 {
245 etfile = (ET_File *)l->data;
246 FileTag = et_file_tag_new ();
247 et_file_tag_copy_into (FileTag, etfile->FileTag->data);
248 et_file_tag_set_album (FileTag, string_to_set);
249 ET_Manage_Changes_Of_File_Data(etfile,NULL,FileTag);
250 }
251
252 if (!et_str_empty (string_to_set))
253 {
254 msg = g_strdup_printf (_("Selected files tagged with album ‘%s’"),
255 string_to_set);
256 }
257 else
258 {
259 msg = g_strdup (_("Removed album name from selected files"));
260 }
261 }
262 else if (object == G_OBJECT (priv->disc_number_entry))
263 {
264 gchar *separator;
265 gchar *disc_number = NULL;
266
267 string_to_set = gtk_entry_get_text (GTK_ENTRY (priv->disc_number_entry));
268 /* strchr() does not allocate a new string, and should probably return
269 * a const gchar *. */
270 separator = strchr (string_to_set, '/');
271
272 if (separator)
273 {
274 string_to_set1 = separator + 1;
275 disc_number = g_strndup (string_to_set, separator - string_to_set);
276 }
277 else
278 {
279 string_to_set1 = NULL;
280 }
281
282 for (l = etfilelist; l != NULL; l = g_list_next (l))
283 {
284 etfile = (ET_File *)l->data;
285 FileTag = et_file_tag_new ();
286 et_file_tag_copy_into (FileTag, etfile->FileTag->data);
287 et_file_tag_set_disc_number (FileTag, disc_number ? disc_number
288 : string_to_set);
289 et_file_tag_set_disc_total (FileTag, string_to_set1);
290 ET_Manage_Changes_Of_File_Data(etfile,NULL,FileTag);
291 }
292
293 if (!et_str_empty (string_to_set))
294 {
295 if (!et_str_empty (string_to_set1))
296 {
297 msg = g_strdup_printf (_("Selected files tagged with disc number ‘%s/%s’"),
298 disc_number ? disc_number
299 : string_to_set,
300 string_to_set1);
301 }
302 else
303 {
304 msg = g_strdup_printf (_("Selected files tagged with disc number like ‘xx’"));
305 }
306 }
307 else
308 {
309 msg = g_strdup (_("Removed disc number from selected files"));
310 }
311
312 g_free (disc_number);
313 }
314 else if (object == G_OBJECT (priv->year_entry))
315 {
316 string_to_set = gtk_entry_get_text (GTK_ENTRY (priv->year_entry));
317
318 for (l = etfilelist; l != NULL; l = g_list_next (l))
319 {
320 etfile = (ET_File *)l->data;
321 FileTag = et_file_tag_new ();
322 et_file_tag_copy_into (FileTag, etfile->FileTag->data);
323 et_file_tag_set_year (FileTag, string_to_set);
324 ET_Manage_Changes_Of_File_Data(etfile,NULL,FileTag);
325 }
326
327 if (!et_str_empty (string_to_set))
328 {
329 msg = g_strdup_printf (_("Selected files tagged with year ‘%s’"),
330 string_to_set);
331 }
332 else
333 {
334 msg = g_strdup (_("Removed year from selected files"));
335 }
336 }
337 else if (object == G_OBJECT (priv->track_total_entry))
338 {
339 /* Used of Track and Total Track values */
340 string_to_set = gtk_entry_get_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (priv->track_combo_entry))));
341 string_to_set1 = gtk_entry_get_text (GTK_ENTRY (priv->track_total_entry));
342
343 for (l = etfilelist; l != NULL; l = g_list_next (l))
344 {
345 etfile = (ET_File *)l->data;
346 FileTag = et_file_tag_new ();
347 et_file_tag_copy_into (FileTag, etfile->FileTag->data);
348
349 // We apply the TrackEntry field to all others files only if it is to delete
350 // the field (string=""). Else we don't overwrite the track number
351 if (et_str_empty (string_to_set))
352 {
353 et_file_tag_set_track_number (FileTag, string_to_set);
354 }
355
356 et_file_tag_set_track_total (FileTag, string_to_set1);
357 ET_Manage_Changes_Of_File_Data(etfile,NULL,FileTag);
358 }
359
360 if (!et_str_empty (string_to_set))
361 {
362 if (!et_str_empty (string_to_set1))
363 {
364 msg = g_strdup_printf (_("Selected files tagged with track like ‘xx/%s’"),
365 string_to_set1);
366 }else
367 {
368 msg = g_strdup_printf (_("Selected files tagged with track like ‘xx’"));
369 }
370 }
371 else
372 {
373 msg = g_strdup (_("Removed track number from selected files"));
374 }
375 }
376 else if (object == G_OBJECT (priv->track_sequence_button))
377 {
378 /* This part doesn't set the same track number to all files, but sequence the tracks.
379 * So we must browse the whole 'etfilelistfull' to get position of each selected file.
380 * Note : 'etfilelistfull' and 'etfilelist' must be sorted in the same order */
381 GList *etfilelistfull = NULL;
382 gint sort_mode;
383 gchar *path = NULL;
384 gchar *path1 = NULL;
385 gint i = 0;
386
387 /* FIX ME!: see to fill also the Total Track (it's a good idea?) */
388 etfilelistfull = ETCore->ETFileList;
389
390 /* Sort 'etfilelistfull' and 'etfilelist' in the same order. */
391 sort_mode = g_settings_get_enum (MainSettings, "sort-mode");
392 etfilelist = ET_Sort_File_List (etfilelist, sort_mode);
393 etfilelistfull = ET_Sort_File_List (etfilelistfull, sort_mode);
394
395 while (etfilelist && etfilelistfull)
396 {
397 gchar *track_string;
398 // To get the path of the file
399 const File_Name *FileNameCur = (File_Name *)((ET_File *)etfilelistfull->data)->FileNameCur->data;
400 // The ETFile in the selected file list
401 etfile = etfilelist->data;
402
403 // Restart counter when entering a new directory
404 g_free(path1);
405 path1 = g_path_get_dirname(FileNameCur->value);
406 if ( path && path1 && strcmp(path,path1)!=0 )
407 i = 0;
408
409 track_string = et_track_number_to_string (++i);
410
411 // The file is in the selection?
412 if ( (ET_File *)etfilelistfull->data == etfile )
413 {
414 FileTag = et_file_tag_new ();
415 et_file_tag_copy_into (FileTag, etfile->FileTag->data);
416 et_file_tag_set_track_number (FileTag, track_string);
417 ET_Manage_Changes_Of_File_Data(etfile,NULL,FileTag);
418
419 if (!etfilelist->next) break;
420 etfilelist = g_list_next(etfilelist);
421 }
422
423 g_free (track_string);
424 g_free(path);
425 path = g_strdup(path1);
426
427 etfilelistfull = g_list_next(etfilelistfull);
428 }
429 g_free(path);
430 g_free(path1);
431 //msg = g_strdup_printf(_("All %d tracks numbered sequentially."), ETCore->ETFileSelectionList_Length);
432 msg = g_strdup_printf (_("Selected tracks numbered sequentially"));
433 }
434 else if (object==G_OBJECT(priv->track_number_button))
435 {
436 gchar *track_total = NULL;
437
438 /* Used of Track and Total Track values */
439 for (l = etfilelist; l != NULL; l = g_list_next (l))
440 {
441 const gchar *filename_utf8;
442 gchar *path_utf8;
443 gchar *track_string;
444
445 etfile = (ET_File *)l->data;
446 filename_utf8 = ((File_Name *)etfile->FileNameNew->data)->value_utf8;
447 path_utf8 = g_path_get_dirname(filename_utf8);
448
449 track_string = et_track_number_to_string (et_file_list_get_n_files_in_path (ETCore->ETFileList, path_utf8));
450
451 g_free (path_utf8);
452
453 if (!track_total)
454 {
455 /* Just for the message below, and only the first directory. */
456 track_total = g_strdup (track_string);
457 }
458
459 FileTag = et_file_tag_new ();
460 et_file_tag_copy_into (FileTag, etfile->FileTag->data);
461 et_file_tag_set_track_total (FileTag, track_string);
462 ET_Manage_Changes_Of_File_Data(etfile,NULL,FileTag);
463
464 g_free (track_string);
465 }
466
467 if (!et_str_empty (track_total))
468 {
469 msg = g_strdup_printf (_("Selected files tagged with track like ‘xx/%s’"),
470 track_total);
471 }
472 else
473 {
474 msg = g_strdup (_("Removed track number from selected files"));
475 }
476
477 g_free (track_total);
478 }
479 else if (object == G_OBJECT (gtk_bin_get_child (GTK_BIN (priv->genre_combo_entry))))
480 {
481 string_to_set = gtk_entry_get_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (priv->genre_combo_entry))));
482
483 for (l = etfilelist; l != NULL; l = g_list_next (l))
484 {
485 etfile = (ET_File *)l->data;
486 FileTag = et_file_tag_new ();
487 et_file_tag_copy_into (FileTag, etfile->FileTag->data);
488 et_file_tag_set_genre (FileTag, string_to_set);
489 ET_Manage_Changes_Of_File_Data(etfile,NULL,FileTag);
490 }
491
492 if (!et_str_empty (string_to_set))
493 {
494 msg = g_strdup_printf (_("Selected files tagged with genre ‘%s’"),
495 string_to_set);
496 }
497 else
498 {
499 msg = g_strdup (_("Removed genre from selected files"));
500 }
501 }
502 else if (object == G_OBJECT (priv->comment_entry))
503 {
504 //GtkTextBuffer *textbuffer;
505 //GtkTextIter start_iter;
506 //GtkTextIter end_iter;
507 //textbuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(CommentView));
508 //gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(textbuffer),&start_iter,&end_iter);
509 //string_to_set = gtk_text_buffer_get_text(GTK_TEXT_BUFFER(textbuffer),&start_iter,&end_iter,TRUE);
510
511 string_to_set = gtk_entry_get_text (GTK_ENTRY (priv->comment_entry));
512
513 for (l = etfilelist; l != NULL; l = g_list_next (l))
514 {
515 etfile = (ET_File *)l->data;
516 FileTag = et_file_tag_new ();
517 et_file_tag_copy_into (FileTag, etfile->FileTag->data);
518 et_file_tag_set_comment (FileTag, string_to_set);
519 ET_Manage_Changes_Of_File_Data(etfile,NULL,FileTag);
520 }
521
522 if (!et_str_empty (string_to_set))
523 {
524 msg = g_strdup_printf (_("Selected files tagged with comment ‘%s’"),
525 string_to_set);
526 }
527 else
528 {
529 msg = g_strdup (_("Removed comment from selected files"));
530 }
531 }
532 else if (object == G_OBJECT (priv->composer_entry))
533 {
534 string_to_set = gtk_entry_get_text (GTK_ENTRY (priv->composer_entry));
535
536 for (l = etfilelist; l != NULL; l = g_list_next (l))
537 {
538 etfile = (ET_File *)l->data;
539 FileTag = et_file_tag_new ();
540 et_file_tag_copy_into (FileTag, etfile->FileTag->data);
541 et_file_tag_set_composer (FileTag, string_to_set);
542 ET_Manage_Changes_Of_File_Data(etfile,NULL,FileTag);
543 }
544
545 if (!et_str_empty (string_to_set))
546 {
547 msg = g_strdup_printf (_("Selected files tagged with composer ‘%s’"),
548 string_to_set);
549 }
550 else
551 {
552 msg = g_strdup (_("Removed composer from selected files"));
553 }
554 }
555 else if (object == G_OBJECT (priv->orig_artist_entry))
556 {
557 string_to_set = gtk_entry_get_text (GTK_ENTRY (priv->orig_artist_entry));
558
559 for (l = etfilelist; l != NULL; l = g_list_next (l))
560 {
561 etfile = (ET_File *)l->data;
562 FileTag = et_file_tag_new ();
563 et_file_tag_copy_into (FileTag, etfile->FileTag->data);
564 et_file_tag_set_orig_artist (FileTag, string_to_set);
565 ET_Manage_Changes_Of_File_Data(etfile,NULL,FileTag);
566 }
567
568 if (!et_str_empty (string_to_set))
569 {
570 msg = g_strdup_printf (_("Selected files tagged with original artist ‘%s’"),
571 string_to_set);
572 }
573 else
574 {
575 msg = g_strdup (_("Removed original artist from selected files"));
576 }
577 }
578 else if (object == G_OBJECT (priv->copyright_entry))
579 {
580 string_to_set = gtk_entry_get_text (GTK_ENTRY (priv->copyright_entry));
581
582 for (l = etfilelist; l != NULL; l = g_list_next (l))
583 {
584 etfile = (ET_File *)l->data;
585 FileTag = et_file_tag_new ();
586 et_file_tag_copy_into (FileTag, etfile->FileTag->data);
587 et_file_tag_set_copyright (FileTag, string_to_set);
588 ET_Manage_Changes_Of_File_Data(etfile,NULL,FileTag);
589 }
590
591 if (!et_str_empty (string_to_set))
592 {
593 msg = g_strdup_printf (_("Selected files tagged with copyright ‘%s’"),
594 string_to_set);
595 }
596 else
597 {
598 msg = g_strdup (_("Removed copyright from selected files"));
599 }
600 }
601 else if (object == G_OBJECT (priv->url_entry))
602 {
603 string_to_set = gtk_entry_get_text (GTK_ENTRY( priv->url_entry));
604
605 for (l = etfilelist; l != NULL; l = g_list_next (l))
606 {
607 etfile = (ET_File *)l->data;
608 FileTag = et_file_tag_new ();
609 et_file_tag_copy_into (FileTag, etfile->FileTag->data);
610 et_file_tag_set_url (FileTag, string_to_set);
611 ET_Manage_Changes_Of_File_Data(etfile,NULL,FileTag);
612 }
613
614 if (!et_str_empty (string_to_set))
615 {
616 msg = g_strdup_printf (_("Selected files tagged with URL ‘%s’"),
617 string_to_set);
618 }
619 else
620 {
621 msg = g_strdup (_("Removed URL from selected files"));
622 }
623 }
624 else if (object == G_OBJECT (priv->encoded_by_entry))
625 {
626 string_to_set = gtk_entry_get_text (GTK_ENTRY (priv->encoded_by_entry));
627
628 for (l = etfilelist; l != NULL; l = g_list_next (l))
629 {
630 etfile = (ET_File *)l->data;
631 FileTag = et_file_tag_new ();
632 et_file_tag_copy_into (FileTag, etfile->FileTag->data);
633 et_file_tag_set_encoded_by (FileTag, string_to_set);
634 ET_Manage_Changes_Of_File_Data(etfile,NULL,FileTag);
635 }
636
637 if (!et_str_empty (string_to_set))
638 {
639 msg = g_strdup_printf (_("Selected files tagged with encoder name ‘%s’"),
640 string_to_set);
641 }
642 else
643 {
644 msg = g_strdup (_("Removed encoder name from selected files"));
645 }
646 }
647 else if (object == G_OBJECT (priv->apply_image_toolitem))
648 {
649 EtPicture *res = NULL, *pic, *prev_pic = NULL;
650 GtkTreeModel *model;
651 GtkTreeIter iter;
652
653 model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->images_view));
654
655 if (gtk_tree_model_get_iter_first(model, &iter))
656 {
657 do
658 {
659 gtk_tree_model_get (model, &iter, PICTURE_COLUMN_DATA, &pic,
660 -1);
661
662 if (!res)
663 res = pic;
664 else
665 prev_pic->next = pic;
666 prev_pic = pic;
667 } while (gtk_tree_model_iter_next(model, &iter));
668 }
669
670 for (l = etfilelist; l != NULL; l = g_list_next (l))
671 {
672 etfile = (ET_File *)l->data;
673 FileTag = et_file_tag_new ();
674 et_file_tag_copy_into (FileTag, etfile->FileTag->data);
675 et_file_tag_set_picture (FileTag, res);
676 ET_Manage_Changes_Of_File_Data(etfile,NULL,FileTag);
677 }
678 if (res)
679 {
680 msg = g_strdup (_("Selected files tagged with images"));
681 }
682 else
683 {
684 msg = g_strdup (_("Removed images from selected files"));
685 }
686
687 et_picture_free (res);
688 }
689
690 g_list_free(etfilelist);
691
692 /* Refresh the whole list (faster than file by file) to show changes. */
693 et_application_window_browser_refresh_list (window);
694
695 /* Display the current file (Needed when sequencing tracks) */
696 et_application_window_display_et_file (window, ETCore->ETFileDisplayed);
697
698 if (msg)
699 {
700 Log_Print(LOG_OK,"%s",msg);
701 et_application_window_status_bar_message (window, msg,TRUE);
702 g_free(msg);
703 }
704
705 /* To update state of Undo button */
706 et_application_window_update_actions (window);
707 }
708
709 static void
on_entry_icon_release(GtkEntry * entry,GtkEntryIconPosition icon_pos,GdkEvent * event,EtTagArea * self)710 on_entry_icon_release (GtkEntry *entry,
711 GtkEntryIconPosition icon_pos,
712 GdkEvent *event,
713 EtTagArea *self)
714 {
715 on_apply_to_selection (G_OBJECT (entry), self);
716 }
717
718 static void
Convert_P20_And_Underscore_Into_Spaces(GtkWidget * entry)719 Convert_P20_And_Underscore_Into_Spaces (GtkWidget *entry)
720 {
721 gchar *string = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
722
723 Scan_Convert_Underscore_Into_Space (string);
724 Scan_Convert_P20_Into_Space (string);
725 gtk_entry_set_text (GTK_ENTRY (entry), string);
726 g_free (string);
727 }
728
729 static void
Convert_Space_Into_Underscore(GtkWidget * entry)730 Convert_Space_Into_Underscore (GtkWidget *entry)
731 {
732 gchar *string = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
733
734 Scan_Convert_Space_Into_Underscore (string);
735 gtk_entry_set_text (GTK_ENTRY (entry), string);
736 g_free (string);
737 }
738
739 static void
Convert_All_Uppercase(GtkWidget * entry)740 Convert_All_Uppercase (GtkWidget *entry)
741 {
742 gchar *res;
743 const gchar *string = gtk_entry_get_text (GTK_ENTRY (entry));
744
745 res = Scan_Process_Fields_All_Uppercase (string);
746 gtk_entry_set_text (GTK_ENTRY (entry), res);
747 g_free (res);
748 }
749
750 static void
Convert_All_Lowercase(GtkWidget * entry)751 Convert_All_Lowercase (GtkWidget *entry)
752 {
753 gchar *res;
754 const gchar *string = gtk_entry_get_text (GTK_ENTRY (entry));
755
756 res = Scan_Process_Fields_All_Downcase (string);
757 gtk_entry_set_text (GTK_ENTRY (entry), res);
758 g_free (res);
759 }
760
761 static void
Convert_Letter_Uppercase(GtkWidget * entry)762 Convert_Letter_Uppercase (GtkWidget *entry)
763 {
764 gchar *res;
765 const gchar *string = gtk_entry_get_text (GTK_ENTRY (entry));
766
767 res = Scan_Process_Fields_Letter_Uppercase (string);
768 gtk_entry_set_text (GTK_ENTRY (entry), res);
769 g_free (res);
770 }
771
772 static void
Convert_First_Letters_Uppercase(GtkWidget * entry)773 Convert_First_Letters_Uppercase (GtkWidget *entry)
774 {
775 gchar *string;
776 gboolean uppercase_preps;
777 gboolean handle_roman;
778
779 string = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
780 uppercase_preps = g_settings_get_boolean (MainSettings,
781 "process-uppercase-prepositions");
782 handle_roman = g_settings_get_boolean (MainSettings,
783 "process-detect-roman-numerals");
784
785 Scan_Process_Fields_First_Letters_Uppercase (&string, uppercase_preps,
786 handle_roman);
787 gtk_entry_set_text (GTK_ENTRY (entry), string);
788 g_free (string);
789 }
790
791 static void
Convert_Remove_Space(GtkWidget * entry)792 Convert_Remove_Space (GtkWidget *entry)
793 {
794 gchar *string = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
795
796 Scan_Process_Fields_Remove_Space (string);
797 gtk_entry_set_text (GTK_ENTRY (entry), string);
798 g_free (string);
799 }
800
801 static void
Convert_Insert_Space(GtkWidget * entry)802 Convert_Insert_Space (GtkWidget *entry)
803 {
804 gchar *res;
805 const gchar *string = (gtk_entry_get_text (GTK_ENTRY (entry)));
806
807 res = Scan_Process_Fields_Insert_Space (string);
808 gtk_entry_set_text (GTK_ENTRY (entry), res);
809 g_free (res);
810 }
811
812 static void
Convert_Only_One_Space(GtkWidget * entry)813 Convert_Only_One_Space (GtkWidget *entry)
814 {
815 gchar *string = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
816
817 Scan_Process_Fields_Keep_One_Space (string);
818 gtk_entry_set_text (GTK_ENTRY (entry), string);
819 g_free (string);
820 }
821
822 static void
Convert_Remove_All_Text(GtkWidget * entry)823 Convert_Remove_All_Text (GtkWidget *entry)
824 {
825 gtk_entry_set_text (GTK_ENTRY (entry), "");
826 }
827
828 static void
on_apply_to_selection_menu_item(GObject * entry,GtkMenuItem * menu_item)829 on_apply_to_selection_menu_item (GObject *entry,
830 GtkMenuItem *menu_item)
831 {
832 EtTagArea *self;
833
834 self = g_object_get_data (G_OBJECT (menu_item), "tag-area");
835
836 on_apply_to_selection (entry, self);
837 }
838
839 /* TODO: Support populate-all and do not assume the widget is a GtkMenu.
840 * Popup menu attached to all entries of tag + filename + rename combobox.
841 * Displayed when pressing the right mouse button and contains functions to process ths strings.
842 */
843 void
on_entry_populate_popup(GtkEntry * entry,GtkWidget * menu,EtTagArea * self)844 on_entry_populate_popup (GtkEntry *entry,
845 GtkWidget *menu,
846 EtTagArea *self)
847 {
848 GtkWidget *menu_item;
849 GtkWidget *label;
850
851 /* Menu items */
852 menu_item = gtk_menu_item_new_with_label (_("Tag selected files with this field"));
853 label = gtk_bin_get_child (GTK_BIN (menu_item));
854 gtk_accel_label_set_accel (GTK_ACCEL_LABEL (label), GDK_KEY_Return,
855 GDK_CONTROL_MASK);
856 g_object_set_data (G_OBJECT (menu_item), "tag-area", self);
857 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
858 g_signal_connect_swapped (menu_item, "activate",
859 G_CALLBACK (on_apply_to_selection_menu_item),
860 G_OBJECT (entry));
861
862 /* Separator */
863 menu_item = gtk_menu_item_new ();
864 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
865
866 menu_item = gtk_menu_item_new_with_label (_("Convert ‘_’ and ‘%20’ to spaces"));
867 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
868 g_signal_connect_swapped (menu_item, "activate",
869 G_CALLBACK (Convert_P20_And_Underscore_Into_Spaces),
870 G_OBJECT (entry));
871
872 menu_item = gtk_menu_item_new_with_label (_("Convert spaces to underscores"));
873 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
874 g_signal_connect_swapped (menu_item, "activate",
875 G_CALLBACK (Convert_Space_Into_Underscore),
876 G_OBJECT (entry));
877
878 /* Separator */
879 menu_item = gtk_menu_item_new ();
880 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
881
882 menu_item = gtk_menu_item_new_with_label (_("All uppercase"));
883 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
884 g_signal_connect_swapped (menu_item, "activate",
885 G_CALLBACK (Convert_All_Uppercase),
886 G_OBJECT (entry));
887
888 menu_item = gtk_menu_item_new_with_label (_("All lowercase"));
889 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
890 g_signal_connect_swapped (menu_item, "activate",
891 G_CALLBACK (Convert_All_Lowercase),
892 G_OBJECT (entry));
893
894 menu_item = gtk_menu_item_new_with_label (_("First letter uppercase"));
895 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
896 g_signal_connect_swapped (menu_item, "activate",
897 G_CALLBACK (Convert_Letter_Uppercase),
898 G_OBJECT (entry));
899
900 menu_item = gtk_menu_item_new_with_label (_("First letter uppercase of each word"));
901 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
902 g_signal_connect_swapped (menu_item, "activate",
903 G_CALLBACK (Convert_First_Letters_Uppercase),
904 G_OBJECT (entry));
905
906 /* Separator */
907 menu_item = gtk_menu_item_new ();
908 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
909
910 menu_item = gtk_menu_item_new_with_label (_("Remove spaces"));
911 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
912 g_signal_connect_swapped (menu_item, "activate",
913 G_CALLBACK (Convert_Remove_Space),
914 G_OBJECT (entry));
915
916 menu_item = gtk_menu_item_new_with_label (_("Insert space before uppercase letter"));
917 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
918 g_signal_connect_swapped (menu_item, "activate",
919 G_CALLBACK (Convert_Insert_Space),
920 G_OBJECT (entry));
921
922 menu_item = gtk_menu_item_new_with_label (_("Remove duplicate spaces or underscores"));
923 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
924 g_signal_connect_swapped (menu_item, "activate",
925 G_CALLBACK (Convert_Only_One_Space),
926 G_OBJECT (entry));
927
928 menu_item = gtk_menu_item_new_with_label (_("Remove all text"));
929 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
930 g_signal_connect_swapped (menu_item, "activate",
931 G_CALLBACK (Convert_Remove_All_Text),
932 G_OBJECT (entry));
933
934 gtk_widget_show_all (menu);
935 }
936
937 /*
938 * et_tag_field_on_key_press_event:
939 * @entry: the tag entry field on which the event was generated
940 * @event: the generated event
941 * @user_data: user data set when the signal was connected
942 *
943 * Handle the Ctrl+Return combination being pressed in the tag field GtkEntrys
944 * and apply the tag to selected files.
945 *
946 * Returns: %TRUE if the event was handled, %FALSE if the event should
947 * propagate further
948 */
949 static gboolean
et_tag_field_on_key_press_event(GtkEntry * entry,GdkEventKey * event,gpointer user_data)950 et_tag_field_on_key_press_event (GtkEntry *entry, GdkEventKey *event,
951 gpointer user_data)
952 {
953 GdkModifierType modifiers = gtk_accelerator_get_default_mod_mask ();
954
955 switch (event->keyval)
956 {
957 case GDK_KEY_Return:
958 case GDK_KEY_KP_Enter:
959 case GDK_KEY_ISO_Enter:
960 if ((event->state & modifiers) == GDK_CONTROL_MASK)
961 {
962 on_apply_to_selection (G_OBJECT (entry),
963 ET_TAG_AREA (user_data));
964 }
965 return TRUE;
966 default:
967 return FALSE;
968 }
969 }
970
971 /*
972 * et_tag_field_connect_signals:
973 * @entry: the entry for which to connect signals
974 *
975 * Connect the GtkWidget::key-press-event and GtkEntry::icon-release signals
976 * of @entry to appropriate handlers for tag entry fields.
977 */
978 static void
et_tag_field_connect_signals(GtkEntry * entry,EtTagArea * self)979 et_tag_field_connect_signals (GtkEntry *entry,
980 EtTagArea *self)
981 {
982 g_signal_connect_after (entry, "key-press-event",
983 G_CALLBACK (et_tag_field_on_key_press_event),
984 self);
985 g_signal_connect (entry, "icon-release",
986 G_CALLBACK (on_entry_icon_release),
987 self);
988 g_signal_connect (entry, "populate-popup",
989 G_CALLBACK (on_entry_populate_popup), self);
990 }
991
992 /*
993 * Load the genres list to the combo, and sorts it
994 */
995 static void
populate_genre_combo(EtTagArea * self)996 populate_genre_combo (EtTagArea *self)
997 {
998 EtTagAreaPrivate *priv;
999 gsize i;
1000
1001 priv = et_tag_area_get_instance_private (self);
1002
1003 gtk_list_store_insert_with_values (priv->genre_combo_model, NULL,
1004 G_MAXINT, GENRE_COLUMN_GENRE, "", -1);
1005 gtk_list_store_insert_with_values (priv->genre_combo_model, NULL,
1006 G_MAXINT, GENRE_COLUMN_GENRE, "Unknown",
1007 -1);
1008
1009 for (i = 0; i <= GENRE_MAX; i++)
1010 {
1011 gtk_list_store_insert_with_values (priv->genre_combo_model, NULL,
1012 G_MAXINT, GENRE_COLUMN_GENRE,
1013 id3_genres[i], -1);
1014 }
1015 }
1016
1017 /*
1018 * Load the track numbers into the track combo list
1019 * We limit the preloaded values to 30 to avoid lost of time with lot of files...
1020 */
1021 static void
populate_track_combo(EtTagArea * self)1022 populate_track_combo (EtTagArea *self)
1023 {
1024 EtTagAreaPrivate *priv;
1025 /* Length limited to 30 (instead to the number of files)! */
1026 const gsize len = 30;
1027 gsize i;
1028 gchar *text;
1029
1030 priv = et_tag_area_get_instance_private (self);
1031
1032 /* Remove the entries in the list to avoid duplicates. */
1033 gtk_list_store_clear (priv->track_combo_model);
1034
1035 /* Create list of tracks. */
1036 for (i = 1; i <= len; i++)
1037 {
1038 text = et_track_number_to_string (i);
1039
1040 gtk_list_store_insert_with_values (priv->track_combo_model, NULL,
1041 G_MAXINT, TRACK_COLUMN_TRACK_NUMBER,
1042 text, -1);
1043 g_free (text);
1044 }
1045 }
1046
1047 /*
1048 * Iter compare func: Sort alphabetically
1049 */
1050 static gint
tree_iter_alphabetical_sort(GtkTreeModel * model,GtkTreeIter * a,GtkTreeIter * b,gpointer data)1051 tree_iter_alphabetical_sort (GtkTreeModel *model,
1052 GtkTreeIter *a,
1053 GtkTreeIter *b,
1054 gpointer data)
1055 {
1056 gchar *text1, *text1_folded;
1057 gchar *text2, *text2_folded;
1058 gint ret;
1059
1060 gtk_tree_model_get (model, a, GENRE_COLUMN_GENRE, &text1, -1);
1061 gtk_tree_model_get (model, b, GENRE_COLUMN_GENRE, &text2, -1);
1062
1063 if (text1 == text2)
1064 {
1065 g_free (text1);
1066 g_free (text2);
1067 return 0;
1068 }
1069
1070 if (text1 == NULL)
1071 {
1072 g_free (text2);
1073 return -1;
1074 }
1075
1076 if (text2 == NULL)
1077 {
1078 g_free (text1);
1079 return 1;
1080 }
1081
1082 text1_folded = g_utf8_casefold (text1, -1);
1083 text2_folded = g_utf8_casefold (text2, -1);
1084 ret = g_utf8_collate (text1_folded, text2_folded);
1085
1086 g_free (text1);
1087 g_free (text2);
1088 g_free (text1_folded);
1089 g_free (text2_folded);
1090
1091 return ret;
1092 }
1093
1094 /*
1095 * To insert only digits in an entry. If the text contains only digits: returns it,
1096 * else only first digits.
1097 */
1098 static void
Insert_Only_Digit(GtkEditable * editable,const gchar * inserted_text,gint length,gint * position,gpointer data)1099 Insert_Only_Digit (GtkEditable *editable,
1100 const gchar *inserted_text,
1101 gint length,
1102 gint *position,
1103 gpointer data)
1104 {
1105 int i = 1; // Ignore first character
1106 int j = 1;
1107 gchar *result;
1108
1109 if (length<=0 || !inserted_text)
1110 return;
1111
1112 if (!g_ascii_isdigit (inserted_text[0]) && inserted_text[0] != '-')
1113 {
1114 g_signal_stop_emission_by_name(G_OBJECT(editable),"insert_text");
1115 return;
1116 } else if (length == 1)
1117 {
1118 // We already checked the first digit...
1119 return;
1120 }
1121
1122 g_signal_stop_emission_by_name(G_OBJECT(editable),"insert_text");
1123 result = g_malloc0(length+1);
1124 result[0] = inserted_text[0];
1125
1126 // Check the rest, if any...
1127 for (i = 1; i < length; i++)
1128 {
1129 if (g_ascii_isdigit (inserted_text[i]))
1130 {
1131 result[j++] = inserted_text[i];
1132 }
1133 }
1134 // Null terminate for the benefit of glib/gtk
1135 result[j] = '\0';
1136
1137 if (result[0] == '\0')
1138 {
1139 g_free(result);
1140 return;
1141 }
1142
1143 g_signal_handlers_block_by_func(G_OBJECT(editable),G_CALLBACK(Insert_Only_Digit),data);
1144 gtk_editable_insert_text(editable, result, j, position);
1145 g_signal_handlers_unblock_by_func(G_OBJECT(editable),G_CALLBACK(Insert_Only_Digit),data);
1146 g_free(result);
1147 }
1148
1149 /*
1150 * Parse and auto complete date entry if you don't type the 4 digits.
1151 */
1152 #include <stdlib.h>
1153 static void
Parse_Date(EtTagArea * self)1154 Parse_Date (EtTagArea *self)
1155 {
1156 EtTagAreaPrivate *priv;
1157 const gchar *year;
1158 gchar *current_year;
1159
1160 priv = et_tag_area_get_instance_private (self);
1161
1162 /* Early return. */
1163 if (!g_settings_get_boolean (MainSettings, "tag-date-autocomplete"))
1164 {
1165 return;
1166 }
1167
1168 /* Get the info entered by user */
1169 year = gtk_entry_get_text (GTK_ENTRY (priv->year_entry));
1170
1171 if (!et_str_empty (year) && strlen (year) < 4)
1172 {
1173 GDateTime *dt;
1174 gchar *tmp, *tmp1;
1175
1176 dt = g_date_time_new_now_local ();
1177 current_year = g_date_time_format (dt, "%Y");
1178 g_date_time_unref (dt);
1179
1180 tmp = ¤t_year[4-strlen(year)];
1181
1182 if (atoi (year) <= atoi (tmp))
1183 {
1184 sprintf (current_year, "%d", atoi (current_year) - atoi (tmp));
1185 tmp1 = g_strdup_printf ("%d", atoi (current_year) + atoi (year));
1186 gtk_entry_set_text (GTK_ENTRY (priv->year_entry), tmp1);
1187 g_free (tmp1);
1188 }
1189 else
1190 {
1191 sprintf (current_year, "%d", atoi (current_year) - atoi (tmp)
1192 - (strlen (year) <= 0 ? 1 : strlen (year) <= 1 ? 10 : // pow(10,strlen(year)) returns 99 instead of 100 under Win32...
1193 strlen (year) <= 2 ? 100 : strlen (year) <= 3 ? 1000 : 0));
1194 tmp1 = g_strdup_printf ("%d", atoi (current_year) + atoi (year));
1195 gtk_entry_set_text (GTK_ENTRY (priv->year_entry), tmp1);
1196 g_free (tmp1);
1197 }
1198
1199 g_free (current_year);
1200 }
1201 }
1202
1203 static gboolean
on_year_entry_focus_out_event(GtkWidget * widget,GdkEvent * event,gpointer user_data)1204 on_year_entry_focus_out_event (GtkWidget *widget,
1205 GdkEvent *event,
1206 gpointer user_data)
1207 {
1208 Parse_Date (ET_TAG_AREA (user_data));
1209
1210 return GDK_EVENT_PROPAGATE;
1211 }
1212
1213 static void
on_year_entry_activate(GtkEntry * entry,gpointer user_data)1214 on_year_entry_activate (GtkEntry *entry,
1215 gpointer user_data)
1216 {
1217 Parse_Date (ET_TAG_AREA (user_data));
1218 }
1219
1220 static void
on_picture_view_selection_changed(GtkTreeSelection * selection,gpointer user_data)1221 on_picture_view_selection_changed (GtkTreeSelection *selection,
1222 gpointer user_data)
1223 {
1224 EtTagArea *self;
1225 EtTagAreaPrivate *priv;
1226
1227 self = ET_TAG_AREA (user_data);
1228 priv = et_tag_area_get_instance_private (self);
1229
1230 if (gtk_tree_selection_count_selected_rows (GTK_TREE_SELECTION (selection)) >= 1)
1231 {
1232 gtk_widget_set_sensitive (GTK_WIDGET (priv->remove_image_toolitem),
1233 TRUE);
1234 gtk_widget_set_sensitive (GTK_WIDGET (priv->save_image_toolitem),
1235 TRUE);
1236 gtk_widget_set_sensitive (GTK_WIDGET (priv->image_properties_toolitem),
1237 TRUE);
1238 }
1239 else
1240 {
1241 gtk_widget_set_sensitive (GTK_WIDGET (priv->remove_image_toolitem),
1242 FALSE);
1243 gtk_widget_set_sensitive (GTK_WIDGET (priv->save_image_toolitem),
1244 FALSE);
1245 gtk_widget_set_sensitive (GTK_WIDGET (priv->image_properties_toolitem),
1246 FALSE);
1247 }
1248 }
1249
1250 static void
PictureEntry_Clear(EtTagArea * self)1251 PictureEntry_Clear (EtTagArea *self)
1252 {
1253 EtTagAreaPrivate *priv;
1254
1255 priv = et_tag_area_get_instance_private (self);
1256
1257 gtk_list_store_clear (priv->images_model);
1258 }
1259
1260 static void
PictureEntry_Update(EtTagArea * self,EtPicture * pic,gboolean select_it)1261 PictureEntry_Update (EtTagArea *self,
1262 EtPicture *pic,
1263 gboolean select_it)
1264 {
1265 EtTagAreaPrivate *priv;
1266 GdkPixbufLoader *loader = 0;
1267 GError *error = NULL;
1268
1269 g_return_if_fail (pic != NULL);
1270
1271 priv = et_tag_area_get_instance_private (self);
1272
1273 if (g_bytes_get_size (pic->bytes) == 0)
1274 {
1275 goto next;
1276 }
1277
1278 loader = gdk_pixbuf_loader_new ();
1279
1280 if (loader)
1281 {
1282 if (gdk_pixbuf_loader_write_bytes (loader, pic->bytes, &error))
1283 {
1284 GtkTreeSelection *selection;
1285 GdkPixbuf *pixbuf;
1286
1287 if (!gdk_pixbuf_loader_close(loader, &error))
1288 {
1289 Log_Print (LOG_ERROR, _("Error parsing image data ‘%s’"),
1290 error->message);
1291 g_error_free (error);
1292 }
1293
1294 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->images_view));
1295
1296 pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
1297 if (pixbuf)
1298 {
1299 GtkTreeIter iter1;
1300 gint scale_factor;
1301 GdkPixbuf *scaled_pixbuf;
1302 cairo_surface_t *surface;
1303 GdkWindow *view_window;
1304 gint scaled_pixbuf_width;
1305 gint scaled_pixbuf_height;
1306 gchar *pic_info;
1307
1308 g_object_ref(pixbuf);
1309 g_object_unref(loader);
1310
1311 // Keep aspect ratio of the picture
1312 pic->width = gdk_pixbuf_get_width(pixbuf);
1313 pic->height = gdk_pixbuf_get_height(pixbuf);
1314 /* TODO: Connect to notify:scale-factor and update when the
1315 * scale changes. */
1316 scale_factor = gtk_widget_get_scale_factor (priv->images_view);
1317
1318 if (pic->width > pic->height)
1319 {
1320 scaled_pixbuf_width = 96 * scale_factor;
1321 scaled_pixbuf_height = 96 * scale_factor * pic->height
1322 / pic->width;
1323 }else
1324 {
1325 scaled_pixbuf_width = 96 * scale_factor * pic->width
1326 / pic->height;
1327 scaled_pixbuf_height = 96 * scale_factor;
1328 }
1329
1330 scaled_pixbuf = gdk_pixbuf_scale_simple (pixbuf,
1331 scaled_pixbuf_width,
1332 scaled_pixbuf_height,
1333 GDK_INTERP_BILINEAR);
1334 g_object_unref (pixbuf);
1335
1336 /* This ties the model to the view, so if the model is to be
1337 * shared in the future, the surface should be per-view. */
1338 view_window = gtk_widget_get_window (priv->images_view);
1339 surface = gdk_cairo_surface_create_from_pixbuf (scaled_pixbuf,
1340 scale_factor,
1341 view_window);
1342 pic_info = et_picture_format_info (pic,
1343 ETCore->ETFileDisplayed->ETFileDescription->TagType);
1344 gtk_list_store_insert_with_values (priv->images_model, &iter1,
1345 G_MAXINT,
1346 PICTURE_COLUMN_SURFACE,
1347 surface,
1348 PICTURE_COLUMN_TEXT,
1349 pic_info,
1350 PICTURE_COLUMN_DATA,
1351 pic, -1);
1352 g_free(pic_info);
1353
1354 if (select_it)
1355 gtk_tree_selection_select_iter(selection, &iter1);
1356 g_object_unref(scaled_pixbuf);
1357 }else
1358 {
1359 GtkWidget *msgdialog;
1360
1361 g_object_unref(loader);
1362
1363 Log_Print (LOG_ERROR, "%s",
1364 _("Cannot display the image because not enough data has been read to determine how to create the image buffer"));
1365
1366 msgdialog = gtk_message_dialog_new(GTK_WINDOW(MainWindow),
1367 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
1368 GTK_MESSAGE_ERROR,
1369 GTK_BUTTONS_CLOSE,
1370 "%s",
1371 _("Cannot display the image"));
1372 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (msgdialog),
1373 _("Not enough data has been read to determine how to create the image buffer."));
1374 gtk_window_set_title (GTK_WINDOW (msgdialog),
1375 _("Load Image File"));
1376 gtk_dialog_run(GTK_DIALOG(msgdialog));
1377 gtk_widget_destroy(msgdialog);
1378 }
1379 }
1380 else
1381 {
1382 Log_Print (LOG_ERROR, _("Error parsing image data ‘%s’"),
1383 error->message);
1384 g_error_free (error);
1385 }
1386 }
1387
1388 next:
1389 /* Do also for next picture. */
1390 if (pic->next)
1391 {
1392 PictureEntry_Update (self, pic->next, select_it);
1393 }
1394
1395 return;
1396 }
1397
1398
1399 /*
1400 * load_picture_from_file:
1401 * @file: the image file to load
1402 * @self: the #EtTagArea
1403 *
1404 * Load the image file @file and update the images tree model.
1405 */
1406 static void
load_picture_from_file(GFile * file,EtTagArea * self)1407 load_picture_from_file (GFile *file,
1408 EtTagArea *self)
1409 {
1410 GBytes *bytes;
1411 const gchar *filename_utf8;
1412 GFileInfo *info;
1413 GError *error = NULL;
1414
1415 info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
1416 G_FILE_QUERY_INFO_NONE, NULL, &error);
1417
1418 if (!info)
1419 {
1420 Log_Print (LOG_ERROR, _("Image file not loaded ‘%s’"), error->message);
1421 g_error_free (error);
1422 return;
1423 }
1424
1425 filename_utf8 = g_file_info_get_display_name (info);
1426 bytes = et_picture_load_file_data (file, &error);
1427
1428 if (!bytes)
1429 {
1430 GtkWidget *msgdialog;
1431
1432 /* Picture file not opened */
1433 msgdialog = gtk_message_dialog_new (GTK_WINDOW (MainWindow),
1434 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
1435 GTK_MESSAGE_ERROR,
1436 GTK_BUTTONS_CLOSE,
1437 _("Cannot open file ‘%s’"),
1438 filename_utf8);
1439 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG(msgdialog),
1440 "%s", error->message);
1441 gtk_window_set_title (GTK_WINDOW (msgdialog), _("Image File Error"));
1442 gtk_dialog_run (GTK_DIALOG (msgdialog));
1443 gtk_widget_destroy (msgdialog);
1444
1445 Log_Print (LOG_ERROR, _("Image file not loaded ‘%s’"),
1446 error->message);
1447 g_error_free (error);
1448 return;
1449 }
1450 else
1451 {
1452 Log_Print (LOG_OK, _("Image file loaded"));
1453 }
1454
1455 if (filename_utf8)
1456 {
1457 EtPicture *pic;
1458 EtPictureType type;
1459 const gchar *description;
1460
1461 // Behaviour following the tag type...
1462 switch (ETCore->ETFileDisplayed->ETFileDescription->TagType)
1463 {
1464 // Only one picture supported for MP4
1465 case MP4_TAG:
1466 description = "";
1467 type = ET_PICTURE_TYPE_FRONT_COVER;
1468 break;
1469
1470 // Other tag types
1471 case ID3_TAG:
1472 case OGG_TAG:
1473 case OPUS_TAG:
1474 case APE_TAG:
1475 case FLAC_TAG:
1476 case WAVPACK_TAG:
1477 description = filename_utf8;
1478
1479 if (g_settings_get_boolean (MainSettings,
1480 "tag-image-type-automatic"))
1481 {
1482 type = et_picture_type_from_filename (description);
1483 }
1484 else
1485 {
1486 type = ET_PICTURE_TYPE_FRONT_COVER;
1487 }
1488 break;
1489
1490 case UNKNOWN_TAG:
1491 default:
1492 g_assert_not_reached ();
1493 }
1494
1495 pic = et_picture_new (type, description, 0, 0, bytes);
1496
1497 PictureEntry_Update (self, pic, TRUE);
1498
1499 et_picture_free (pic);
1500 }
1501
1502 g_bytes_unref (bytes);
1503 g_object_unref (info);
1504 }
1505
1506 /*
1507 * To add a picture in the list -> call a FileSelectionWindow
1508 */
1509 static void
on_picture_add_button_clicked(GObject * object,gpointer user_data)1510 on_picture_add_button_clicked (GObject *object,
1511 gpointer user_data)
1512 {
1513 EtTagArea *self;
1514 EtTagAreaPrivate *priv;
1515 GtkWidget *FileSelectionWindow;
1516 GtkFileFilter *filter;
1517 GtkWindow *parent_window;
1518 gchar *init_dir;
1519 gint response;
1520
1521 self = ET_TAG_AREA (user_data);
1522 priv = et_tag_area_get_instance_private (self);
1523
1524 g_return_if_fail (ETCore->ETFileDisplayed);
1525
1526 parent_window = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (object)));
1527
1528 if (!gtk_widget_is_toplevel (GTK_WIDGET (parent_window)))
1529 {
1530 g_warning("Could not get parent window\n");
1531 return;
1532 }
1533
1534
1535 FileSelectionWindow = gtk_file_chooser_dialog_new (_("Add Images"),
1536 parent_window,
1537 GTK_FILE_CHOOSER_ACTION_OPEN,
1538 _("_Cancel"),
1539 GTK_RESPONSE_CANCEL,
1540 _("_Open"),
1541 GTK_RESPONSE_OK, NULL);
1542
1543 /* "All Files" filter. */
1544 filter = gtk_file_filter_new ();
1545 gtk_file_filter_set_name (filter, _("All Files"));
1546 gtk_file_filter_add_pattern (filter, "*");
1547 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (FileSelectionWindow),
1548 filter);
1549
1550 /* "PNG and JPEG" filter. */
1551 filter = gtk_file_filter_new ();
1552 gtk_file_filter_set_name (filter, _("PNG and JPEG"));
1553 gtk_file_filter_add_mime_type (filter, "image/jpeg");
1554 gtk_file_filter_add_mime_type (filter, "image/png");
1555 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (FileSelectionWindow),
1556 filter);
1557 /* Make this filter the default. */
1558 gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (FileSelectionWindow),
1559 filter);
1560
1561 // Behaviour following the tag type...
1562 if (ETCore->ETFileDisplayed->ETFileDescription->TagType == MP4_TAG)
1563 {
1564 /* Only one file can be selected. */
1565 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (FileSelectionWindow),
1566 FALSE);
1567 }
1568 else
1569 {
1570 /* Other tag types .*/
1571 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (FileSelectionWindow),
1572 TRUE);
1573 }
1574
1575 gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (FileSelectionWindow),
1576 FALSE);
1577
1578 /* Starting directory (the same as the current file). */
1579 init_dir = g_path_get_dirname (((File_Name *)((GList *)ETCore->ETFileDisplayed->FileNameCur)->data)->value);
1580 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (FileSelectionWindow),
1581 init_dir);
1582 g_free (init_dir);
1583
1584 response = gtk_dialog_run (GTK_DIALOG (FileSelectionWindow));
1585
1586 if (response == GTK_RESPONSE_OK)
1587 {
1588 GtkTreeSelection *selection;
1589 GSList *list;
1590
1591 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->images_view));
1592 gtk_tree_selection_unselect_all (selection);
1593
1594 list = gtk_file_chooser_get_files (GTK_FILE_CHOOSER (FileSelectionWindow));
1595 g_slist_foreach (list, (GFunc) load_picture_from_file, self);
1596 g_slist_free_full (list, g_object_unref);
1597 }
1598
1599 et_application_window_update_et_file_from_ui (ET_APPLICATION_WINDOW (MainWindow));
1600 et_application_window_display_et_file (ET_APPLICATION_WINDOW (MainWindow),
1601 ETCore->ETFileDisplayed);
1602
1603 gtk_widget_destroy(FileSelectionWindow);
1604 }
1605
1606
1607 /*
1608 * Open the window to select and type the picture properties
1609 */
1610 static void
on_picture_properties_button_clicked(GObject * object,gpointer user_data)1611 on_picture_properties_button_clicked (GObject *object,
1612 gpointer user_data)
1613 {
1614 EtTagArea *self;
1615 EtTagAreaPrivate *priv;
1616 GtkWidget *type, *desc;
1617 GtkTreeSelection *selection;
1618 GtkListStore *store;
1619 GtkTreeIter type_iter_to_select, iter;
1620 GtkTreeModel *model;
1621 GtkWindow *parent_window = NULL;
1622 GList *selection_list = NULL;
1623 GList *l;
1624 gint selection_nbr, selection_i = 1;
1625 gint response;
1626 EtPictureType pic_type;
1627
1628 self = ET_TAG_AREA (user_data);
1629 priv = et_tag_area_get_instance_private (self);
1630
1631 parent_window = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (object)));
1632
1633 if (!gtk_widget_is_toplevel (GTK_WIDGET (parent_window)))
1634 {
1635 g_warning ("Could not get parent window");
1636 return;
1637 }
1638
1639 model = GTK_TREE_MODEL (priv->images_model);
1640 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->images_view));
1641 selection_list = gtk_tree_selection_get_selected_rows (selection, NULL);
1642 selection_nbr = gtk_tree_selection_count_selected_rows (GTK_TREE_SELECTION (selection));
1643
1644 for (l = selection_list; l != NULL; l = g_list_next (l))
1645 {
1646 GtkWidget *PictureTypesWindow;
1647 GtkTreePath *path = l->data;
1648 EtPicture *pic = NULL;
1649 GtkTreeSelection *selectiontype;
1650 gchar *title;
1651 GtkTreePath *rowPath;
1652 gboolean valid;
1653 GtkBuilder *builder;
1654
1655 /* Get corresponding picture. */
1656 valid = gtk_tree_model_get_iter (model, &iter, path);
1657
1658 if (valid)
1659 {
1660 gtk_tree_model_get (model, &iter, PICTURE_COLUMN_DATA, &pic, -1);
1661 }
1662 else
1663 {
1664 g_warning ("Iter not found in picture model");
1665 break;
1666 }
1667
1668 builder = gtk_builder_new_from_resource ("/org/gnome/EasyTAG/image_properties_dialog.ui");
1669
1670 title = g_strdup_printf (_("Image Properties %d/%d"), selection_i++,
1671 selection_nbr);
1672 PictureTypesWindow = GTK_WIDGET (gtk_builder_get_object (builder,
1673 "image_properties_dialog"));
1674 gtk_window_set_title (GTK_WINDOW (PictureTypesWindow), title);
1675 g_free (title);
1676 gtk_window_set_transient_for (GTK_WINDOW (PictureTypesWindow),
1677 parent_window);
1678
1679 gtk_dialog_set_default_response (GTK_DIALOG (PictureTypesWindow),
1680 GTK_RESPONSE_ACCEPT);
1681
1682 store = gtk_list_store_new (PICTURE_TYPE_COLUMN_COUNT, G_TYPE_STRING,
1683 G_TYPE_INT);
1684 type = GTK_WIDGET (gtk_builder_get_object (builder, "types_view"));
1685 gtk_tree_view_set_model (GTK_TREE_VIEW (type), GTK_TREE_MODEL (store));
1686 g_object_unref (store);
1687
1688 /* Behaviour following the tag type. */
1689 if (ETCore->ETFileDisplayed->ETFileDescription->TagType == MP4_TAG)
1690 {
1691 /* Load picture type (only Front Cover!). */
1692 GtkTreeIter itertype;
1693
1694 gtk_list_store_insert_with_values (store, &itertype,
1695 G_MAXINT,
1696 PICTURE_TYPE_COLUMN_TEXT,
1697 _(Picture_Type_String (ET_PICTURE_TYPE_FRONT_COVER)),
1698 PICTURE_TYPE_COLUMN_TYPE_CODE,
1699 ET_PICTURE_TYPE_FRONT_COVER,
1700 -1);
1701 /* Line to select by default. */
1702 type_iter_to_select = itertype;
1703 }
1704 else
1705 /* Other tag types. */
1706 {
1707 /* Load pictures types. */
1708 for (pic_type = ET_PICTURE_TYPE_OTHER; pic_type < ET_PICTURE_TYPE_UNDEFINED; pic_type++)
1709 {
1710 GtkTreeIter itertype;
1711
1712 gtk_list_store_insert_with_values (store, &itertype,
1713 G_MAXINT,
1714 PICTURE_TYPE_COLUMN_TEXT,
1715 _(Picture_Type_String (pic_type)),
1716 PICTURE_TYPE_COLUMN_TYPE_CODE,
1717 pic_type, -1);
1718 /* Line to select by default. */
1719 if (pic->type == pic_type)
1720 {
1721 type_iter_to_select = itertype;
1722 }
1723 }
1724 }
1725
1726 /* Select the line by default. */
1727 selectiontype = gtk_tree_view_get_selection (GTK_TREE_VIEW (type));
1728 gtk_tree_selection_select_iter (selectiontype, &type_iter_to_select);
1729
1730 /* Set visible the current selected line. */
1731 rowPath = gtk_tree_model_get_path (GTK_TREE_MODEL (store),
1732 &type_iter_to_select);
1733 gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (type), rowPath, NULL,
1734 FALSE, 0, 0);
1735 gtk_tree_path_free (rowPath);
1736
1737 /* Entry for the description. */
1738 desc = GTK_WIDGET (gtk_builder_get_object (builder,
1739 "description_entry"));
1740
1741 g_object_unref (builder);
1742
1743 if (pic->description)
1744 {
1745 gchar *tmp = Try_To_Validate_Utf8_String (pic->description);
1746 gtk_entry_set_text (GTK_ENTRY (desc), tmp);
1747 g_free (tmp);
1748 }
1749
1750 /* Behaviour following the tag type. */
1751 if (ETCore->ETFileDisplayed->ETFileDescription->TagType == MP4_TAG)
1752 {
1753 gtk_widget_set_sensitive (GTK_WIDGET (desc), FALSE);
1754 }
1755
1756 gtk_widget_show_all (PictureTypesWindow);
1757
1758 response = gtk_dialog_run (GTK_DIALOG (PictureTypesWindow));
1759
1760 if (response == GTK_RESPONSE_ACCEPT)
1761 {
1762 GtkTreeModel *modeltype;
1763 GtkTreeIter itertype;
1764
1765 modeltype = gtk_tree_view_get_model (GTK_TREE_VIEW (type));
1766 selectiontype = gtk_tree_view_get_selection (GTK_TREE_VIEW (type));
1767
1768 if (gtk_tree_selection_get_selected (selectiontype, &modeltype,
1769 &itertype))
1770 {
1771 gchar *buffer, *pic_info;
1772 gint t;
1773
1774 gtk_tree_model_get (modeltype, &itertype,
1775 PICTURE_TYPE_COLUMN_TYPE_CODE, &t, -1);
1776 pic->type = t;
1777
1778 buffer = g_strdup (gtk_entry_get_text (GTK_ENTRY (desc)));
1779 g_strstrip (buffer);
1780
1781 g_free (pic->description);
1782
1783 /* If the entry was empty, buffer will be the empty string "".
1784 * This can be safely passed to the underlying
1785 * FLAC__metadata_object_picture_set_description(). See
1786 * https://bugs.launchpad.net/ubuntu/+source/easytag/+bug/558804
1787 * and https://bugzilla.redhat.com/show_bug.cgi?id=559828 for
1788 * downstream bugs when 0 was passed instead. */
1789 pic->description = buffer;
1790
1791 /* Update value in the PictureEntryView. */
1792 pic_info = et_picture_format_info (pic,
1793 ETCore->ETFileDisplayed->ETFileDescription->TagType);
1794 gtk_list_store_set (GTK_LIST_STORE (model), &iter,
1795 PICTURE_COLUMN_TEXT, pic_info,
1796 PICTURE_COLUMN_DATA, pic, -1);
1797 g_free (pic_info);
1798 }
1799 }
1800
1801 gtk_widget_destroy (PictureTypesWindow);
1802 et_picture_free (pic);
1803 }
1804
1805 g_list_free_full (selection_list, (GDestroyNotify)gtk_tree_path_free);
1806 }
1807
1808 static void
on_picture_save_button_clicked(GObject * object,gpointer user_data)1809 on_picture_save_button_clicked (GObject *object,
1810 gpointer user_data)
1811 {
1812 EtTagArea *self;
1813 EtTagAreaPrivate *priv;
1814 GtkWidget *FileSelectionWindow;
1815 GtkFileFilter *filter;
1816 GtkWindow *parent_window = NULL;
1817 static gchar *init_dir = NULL;
1818
1819 GtkTreeSelection *selection;
1820 GList *selection_list = NULL;
1821 GList *l;
1822 GtkTreeModel *model;
1823 gint selection_nbr, selection_i = 1;
1824
1825 self = ET_TAG_AREA (user_data);
1826 priv = et_tag_area_get_instance_private (self);
1827
1828 parent_window = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(object)));
1829 if (!gtk_widget_is_toplevel(GTK_WIDGET(parent_window)))
1830 {
1831 g_warning("Could not get parent window\n");
1832 return;
1833 }
1834
1835 model = GTK_TREE_MODEL (priv->images_model);
1836 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->images_view));
1837 selection_list = gtk_tree_selection_get_selected_rows (selection, NULL);
1838 selection_nbr = gtk_tree_selection_count_selected_rows (GTK_TREE_SELECTION (selection));
1839
1840 for (l = selection_list; l != NULL; l = g_list_next (l))
1841 {
1842 GtkTreePath *path = l->data;
1843 GtkTreeIter iter;
1844 EtPicture *pic;
1845 gchar *title;
1846 gboolean valid;
1847 gint response;
1848
1849 // Get corresponding picture
1850 valid = gtk_tree_model_get_iter (model, &iter, path);
1851
1852 if (valid)
1853 {
1854 gtk_tree_model_get (model, &iter, PICTURE_COLUMN_DATA, &pic, -1);
1855 }
1856 else
1857 {
1858 g_warning ("Iter not found in picture model");
1859 break;
1860 }
1861
1862 title = g_strdup_printf (_("Save Image %d/%d"), selection_i++,
1863 selection_nbr);
1864 FileSelectionWindow = gtk_file_chooser_dialog_new (title,
1865 parent_window,
1866 GTK_FILE_CHOOSER_ACTION_SAVE,
1867 _("_Cancel"),
1868 GTK_RESPONSE_CANCEL,
1869 _("_Save"),
1870 GTK_RESPONSE_OK,
1871 NULL);
1872 g_free(title);
1873
1874 /* "All Files" filter. */
1875 filter = gtk_file_filter_new ();
1876 gtk_file_filter_set_name (filter, _("All Files"));
1877 gtk_file_filter_add_pattern (filter, "*");
1878 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (FileSelectionWindow),
1879 filter);
1880
1881 /* "PNG and JPEG" filter. */
1882 filter = gtk_file_filter_new ();
1883 gtk_file_filter_set_name (filter, _("PNG and JPEG"));
1884 gtk_file_filter_add_mime_type (filter, "image/jpeg");
1885 gtk_file_filter_add_mime_type (filter, "image/png");
1886 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (FileSelectionWindow),
1887 filter);
1888 /* Make this filter the default. */
1889 gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (FileSelectionWindow),
1890 filter);
1891
1892 // Set the default folder if defined
1893 if (init_dir)
1894 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(FileSelectionWindow),init_dir);
1895
1896 /* Suggest a filename to the user. */
1897 if (!et_str_empty (pic->description))
1898 {
1899 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(FileSelectionWindow), pic->description); //filename in UTF8
1900 }else
1901 {
1902 gchar *image_name = NULL;
1903 switch (Picture_Format_From_Data (pic))
1904 {
1905 case PICTURE_FORMAT_JPEG :
1906 image_name = g_strdup("image_name.jpg");
1907 break;
1908 case PICTURE_FORMAT_PNG :
1909 image_name = g_strdup("image_name.png");
1910 break;
1911 case PICTURE_FORMAT_GIF:
1912 image_name = g_strdup ("image_name.gif");
1913 break;
1914 case PICTURE_FORMAT_UNKNOWN:
1915 default:
1916 image_name = g_strdup("image_name.ext");
1917 break;
1918 }
1919 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(FileSelectionWindow), image_name); //filename in UTF8
1920 g_free(image_name);
1921 }
1922
1923 gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (FileSelectionWindow),
1924 TRUE);
1925 gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (FileSelectionWindow),
1926 FALSE);
1927
1928 response = gtk_dialog_run(GTK_DIALOG(FileSelectionWindow));
1929 if (response == GTK_RESPONSE_OK)
1930 {
1931 GFile *file;
1932 GError *error = NULL;
1933
1934 // Save the directory selected for initialize next time
1935 g_free(init_dir);
1936 init_dir = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(FileSelectionWindow));
1937
1938 file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (FileSelectionWindow));
1939
1940 if (!et_picture_save_file_data (pic, file, &error))
1941 {
1942 Log_Print (LOG_ERROR, _("Image file not saved ‘%s’"),
1943 error->message);
1944 g_error_free (error);
1945 }
1946
1947 g_object_unref (file);
1948 }
1949 gtk_widget_destroy(FileSelectionWindow);
1950 }
1951
1952 g_list_free_full (selection_list, (GDestroyNotify)gtk_tree_path_free);
1953 }
1954
1955
1956 /*
1957 * If double clicking the PictureEntryView :
1958 * - over a selected row : opens properties window
1959 * - over an empty area : open the adding window
1960 */
1961 static gboolean
on_picture_view_button_pressed(GtkTreeView * treeview,GdkEventButton * event,gpointer user_data)1962 on_picture_view_button_pressed (GtkTreeView *treeview,
1963 GdkEventButton *event,
1964 gpointer user_data)
1965 {
1966 EtTagArea *self;
1967 EtTagAreaPrivate *priv;
1968
1969 self = ET_TAG_AREA (user_data);
1970 priv = et_tag_area_get_instance_private (self);
1971
1972 if (event->type == GDK_BUTTON_PRESS && event->button == GDK_BUTTON_PRIMARY)
1973 {
1974 if (event->window == gtk_tree_view_get_bin_window (treeview))
1975 {
1976 if (!gtk_tree_view_get_path_at_pos (treeview, event->x, event->y,
1977 NULL, NULL, NULL, NULL))
1978 {
1979 gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (treeview));
1980 }
1981 }
1982 }
1983
1984 if (event->type == GDK_2BUTTON_PRESS
1985 && event->button == GDK_BUTTON_PRIMARY)
1986 {
1987 GtkTreeSelection *selection;
1988
1989 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->images_view));
1990
1991 if (gtk_tree_selection_count_selected_rows (selection) >= 1)
1992 {
1993 on_picture_properties_button_clicked (G_OBJECT (priv->image_properties_toolitem),
1994 self);
1995 }
1996 else
1997 {
1998 on_picture_add_button_clicked (G_OBJECT (priv->add_image_toolitem),
1999 self);
2000 }
2001
2002 return GDK_EVENT_STOP;
2003 }
2004
2005 return GDK_EVENT_PROPAGATE;
2006 }
2007
2008 static void
on_picture_view_drag_data(GtkWidget * widget,GdkDragContext * dc,gint x,gint y,GtkSelectionData * selection_data,guint info,guint t,gpointer user_data)2009 on_picture_view_drag_data (GtkWidget *widget, GdkDragContext *dc,
2010 gint x, gint y, GtkSelectionData *selection_data,
2011 guint info, guint t, gpointer user_data)
2012 {
2013 EtTagArea *self;
2014 EtTagAreaPrivate *priv;
2015 GtkTreeSelection *selection;
2016 gchar **uri_list, **uri;
2017
2018 gtk_drag_finish(dc, TRUE, FALSE, t);
2019
2020 if (info != TARGET_URI_LIST || !selection_data)
2021 return;
2022
2023 self = ET_TAG_AREA (user_data);
2024 priv = et_tag_area_get_instance_private (self);
2025
2026 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->images_view));
2027 gtk_tree_selection_unselect_all(selection);
2028
2029 uri = uri_list = g_strsplit ((const gchar *)gtk_selection_data_get_data (selection_data),
2030 "\r\n", 0);
2031
2032 while (!et_str_empty (*uri))
2033 {
2034 GFile *file = g_file_new_for_uri (*uri);
2035
2036 load_picture_from_file (file, self);
2037
2038 g_object_unref (file);
2039 uri++;
2040 }
2041
2042 g_strfreev (uri_list);
2043 }
2044
2045 static void
on_picture_clear_button_clicked(GObject * object,gpointer user_data)2046 on_picture_clear_button_clicked (GObject *object,
2047 gpointer user_data)
2048 {
2049 EtTagArea *self;
2050 EtTagAreaPrivate *priv;
2051 GList *paths, *refs = NULL;
2052 GList *l;
2053 GtkTreeSelection *selection;
2054 GtkTreeModel *model;
2055 GtkTreeIter iter;
2056
2057 self = ET_TAG_AREA (user_data);
2058 priv = et_tag_area_get_instance_private (self);
2059
2060 model = GTK_TREE_MODEL (priv->images_model);
2061 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->images_view));
2062 paths = gtk_tree_selection_get_selected_rows (selection, NULL);
2063
2064 /* List of items to delete. */
2065 for (l = paths; l != NULL; l = g_list_next (l))
2066 {
2067 refs = g_list_prepend (refs, gtk_tree_row_reference_new (model,
2068 l->data));
2069 }
2070
2071 g_list_free_full (paths, (GDestroyNotify)gtk_tree_path_free);
2072
2073 for (l = refs; l != NULL; l = g_list_next (l))
2074 {
2075 GtkTreePath *path = gtk_tree_row_reference_get_path (l->data);
2076
2077 if (gtk_tree_model_get_iter (model, &iter, path))
2078 {
2079 gtk_list_store_remove (priv->images_model, &iter);
2080 }
2081
2082 gtk_tree_path_free(path);
2083 gtk_tree_row_reference_free (l->data);
2084 }
2085
2086 et_application_window_update_et_file_from_ui (ET_APPLICATION_WINDOW (MainWindow));
2087
2088 if (ETCore->ETFileDisplayed)
2089 {
2090 et_application_window_display_et_file (ET_APPLICATION_WINDOW (MainWindow),
2091 ETCore->ETFileDisplayed);
2092 }
2093
2094 g_list_free (refs);
2095 }
2096
2097
2098 /*
2099 * Key press into picture entry
2100 * - Delete = delete selected picture files
2101 */
2102 static gboolean
on_picture_view_key_pressed(GtkTreeView * treeview,GdkEvent * event,gpointer user_data)2103 on_picture_view_key_pressed (GtkTreeView *treeview,
2104 GdkEvent *event,
2105 gpointer user_data)
2106 {
2107 EtTagArea *self;
2108 EtTagAreaPrivate *priv;
2109 GdkEventKey *kevent;
2110
2111 self = ET_TAG_AREA (user_data);
2112 priv = et_tag_area_get_instance_private (self);
2113
2114 kevent = (GdkEventKey *)event;
2115
2116 if (event && event->type == GDK_KEY_PRESS)
2117 {
2118 switch (kevent->keyval)
2119 {
2120 case GDK_KEY_Delete:
2121 on_picture_clear_button_clicked (G_OBJECT (priv->remove_image_toolitem),
2122 self);
2123 return GDK_EVENT_STOP;
2124 default:
2125 /* Ignore all other keypresses. */
2126 break;
2127 }
2128 }
2129
2130 return GDK_EVENT_PROPAGATE;
2131 }
2132 static void
create_tag_area(EtTagArea * self)2133 create_tag_area (EtTagArea *self)
2134 {
2135 EtTagAreaPrivate *priv;
2136 GList *focus_chain = NULL;
2137 GtkEntryCompletion *completion;
2138
2139 /* For Picture. Ignore const string warning. */
2140 static const GtkTargetEntry drops[] = { { (gchar *)"text/uri-list", 0,
2141 TARGET_URI_LIST } };
2142
2143 priv = et_tag_area_get_instance_private (self);
2144
2145 /* Page for common tag fields. */
2146 et_tag_field_connect_signals (GTK_ENTRY (priv->title_entry), self);
2147 et_tag_field_connect_signals (GTK_ENTRY (priv->artist_entry), self);
2148 et_tag_field_connect_signals (GTK_ENTRY (priv->album_artist_entry), self);
2149 et_tag_field_connect_signals (GTK_ENTRY (priv->album_entry), self);
2150 /* FIXME should allow to type only something like : 1/3. */
2151 et_tag_field_connect_signals (GTK_ENTRY (priv->disc_number_entry), self);
2152 /* Year */
2153 et_tag_field_connect_signals (GTK_ENTRY (priv->year_entry), self);
2154
2155 /* Track and Track total */
2156 populate_track_combo (self);
2157
2158 gtk_entry_set_width_chars (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (priv->track_combo_entry))),
2159 2);
2160 g_signal_connect (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (priv->track_combo_entry))),
2161 "insert-text", G_CALLBACK (Insert_Only_Digit), NULL);
2162
2163 et_tag_field_connect_signals (GTK_ENTRY (priv->track_total_entry), self);
2164
2165 /* Genre */
2166 completion = gtk_entry_completion_new ();
2167 gtk_entry_set_icon_from_icon_name (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (priv->genre_combo_entry))),
2168 GTK_ENTRY_ICON_SECONDARY, "insert-text");
2169 gtk_entry_set_completion (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (priv->genre_combo_entry))),
2170 completion);
2171 g_object_unref (completion);
2172 gtk_entry_completion_set_model (completion,
2173 GTK_TREE_MODEL (priv->genre_combo_model));
2174 gtk_entry_completion_set_text_column (completion, 0);
2175 gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (priv->genre_combo_model),
2176 GENRE_COLUMN_GENRE,
2177 tree_iter_alphabetical_sort, NULL, NULL);
2178 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (priv->genre_combo_model),
2179 GENRE_COLUMN_GENRE,
2180 GTK_SORT_ASCENDING);
2181 populate_genre_combo (self);
2182
2183 et_tag_field_connect_signals (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (priv->genre_combo_entry))), self);
2184 gtk_entry_set_icon_tooltip_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (priv->genre_combo_entry))),
2185 GTK_ENTRY_ICON_SECONDARY,
2186 _("Tag selected files with this genre"));
2187
2188 et_tag_field_connect_signals (GTK_ENTRY (priv->comment_entry), self);
2189 et_tag_field_connect_signals (GTK_ENTRY (priv->composer_entry), self);
2190 /* Translators: Original Artist / Performer. Please try to keep this string
2191 * as short as possible, as it must fit into a narrow column. */
2192 et_tag_field_connect_signals (GTK_ENTRY (priv->orig_artist_entry), self);
2193 et_tag_field_connect_signals (GTK_ENTRY (priv->copyright_entry), self);
2194 et_tag_field_connect_signals (GTK_ENTRY (priv->url_entry), self);
2195 et_tag_field_connect_signals (GTK_ENTRY (priv->encoded_by_entry), self);
2196
2197 /* Set focus chain. */
2198 /* TODO: Use focus-chain GtkBuilder element in GTK+ 3.16. */
2199 focus_chain = g_list_prepend (focus_chain, priv->title_entry);
2200 focus_chain = g_list_prepend (focus_chain, priv->artist_entry);
2201 focus_chain = g_list_prepend (focus_chain, priv->album_artist_entry);
2202 focus_chain = g_list_prepend (focus_chain, priv->album_entry);
2203 focus_chain = g_list_prepend (focus_chain, priv->disc_number_entry);
2204 focus_chain = g_list_prepend (focus_chain, priv->year_entry);
2205 focus_chain = g_list_prepend (focus_chain, priv->track_combo_entry);
2206 focus_chain = g_list_prepend (focus_chain, priv->track_total_entry);
2207 focus_chain = g_list_prepend (focus_chain, priv->genre_combo_entry);
2208 focus_chain = g_list_prepend (focus_chain, priv->comment_entry);
2209 focus_chain = g_list_prepend (focus_chain, priv->composer_entry);
2210 focus_chain = g_list_prepend (focus_chain, priv->orig_artist_entry);
2211 focus_chain = g_list_prepend (focus_chain, priv->copyright_entry);
2212 focus_chain = g_list_prepend (focus_chain, priv->url_entry);
2213 focus_chain = g_list_prepend (focus_chain, priv->encoded_by_entry);
2214 /* More efficient than using g_list_append(), which must traverse the
2215 * whole list. */
2216 focus_chain = g_list_reverse (focus_chain);
2217 gtk_container_set_focus_chain (GTK_CONTAINER (priv->common_grid),
2218 focus_chain);
2219 g_list_free (focus_chain);
2220
2221 /* Activate Drag'n'Drop for the priv->images_view. */
2222 gtk_drag_dest_set (GTK_WIDGET (priv->images_view),
2223 GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
2224 drops, sizeof(drops) / sizeof(GtkTargetEntry),
2225 GDK_ACTION_COPY);
2226
2227 /* Activate Drag'n'Drop for the add_image_toolitem. */
2228 gtk_drag_dest_set (GTK_WIDGET (priv->add_image_toolitem),
2229 GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
2230 drops, sizeof(drops) / sizeof(GtkTargetEntry),
2231 GDK_ACTION_COPY);
2232 }
2233
2234 static void
et_tag_area_init(EtTagArea * self)2235 et_tag_area_init (EtTagArea *self)
2236 {
2237 /* Ensure that the boxed type is registered before using it in
2238 * GtkBuilder. */
2239 et_picture_get_type ();
2240
2241 gtk_widget_init_template (GTK_WIDGET (self));
2242 create_tag_area (self);
2243 }
2244
2245 static void
et_tag_area_class_init(EtTagAreaClass * klass)2246 et_tag_area_class_init (EtTagAreaClass *klass)
2247 {
2248 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
2249
2250 gtk_widget_class_set_template_from_resource (widget_class,
2251 "/org/gnome/EasyTAG/tag_area.ui");
2252 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2253 tag_label);
2254 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2255 tag_notebook);
2256 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2257 title_label);
2258 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2259 common_grid);
2260 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2261 title_entry);
2262 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2263 artist_label);
2264 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2265 artist_entry);
2266 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2267 album_artist_label);
2268 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2269 album_artist_entry);
2270 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2271 album_label);
2272 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2273 album_entry);
2274 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2275 disc_number_label);
2276 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2277 disc_number_entry);
2278 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2279 year_label);
2280 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2281 year_entry);
2282 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2283 track_label);
2284 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2285 track_combo_entry);
2286 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2287 track_total_entry);
2288 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2289 genre_label);
2290 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2291 genre_combo_entry);
2292 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2293 comment_label);
2294 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2295 comment_entry);
2296 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2297 composer_label);
2298 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2299 composer_entry);
2300 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2301 orig_artist_label);
2302 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2303 orig_artist_entry);
2304 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2305 copyright_label);
2306 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2307 copyright_entry);
2308 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2309 url_label);
2310 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2311 url_entry);
2312 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2313 encoded_by_label);
2314 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2315 encoded_by_entry);
2316 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2317 genre_combo_model);
2318 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2319 track_combo_model);
2320 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2321 images_view);
2322 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2323 add_image_toolitem);
2324 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2325 apply_image_toolitem);
2326 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2327 remove_image_toolitem);
2328 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2329 save_image_toolitem);
2330 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2331 image_properties_toolitem);
2332 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2333 images_grid);
2334 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2335 images_model);
2336 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2337 track_number_button);
2338 gtk_widget_class_bind_template_child_private (widget_class, EtTagArea,
2339 track_sequence_button);
2340 gtk_widget_class_bind_template_callback (widget_class,
2341 on_picture_add_button_clicked);
2342 gtk_widget_class_bind_template_callback (widget_class,
2343 on_picture_clear_button_clicked);
2344 gtk_widget_class_bind_template_callback (widget_class,
2345 on_picture_save_button_clicked);
2346 gtk_widget_class_bind_template_callback (widget_class,
2347 on_picture_properties_button_clicked);
2348 gtk_widget_class_bind_template_callback (widget_class,
2349 on_apply_to_selection);
2350 gtk_widget_class_bind_template_callback (widget_class,
2351 on_picture_view_button_pressed);
2352 gtk_widget_class_bind_template_callback (widget_class,
2353 on_picture_view_drag_data);
2354 gtk_widget_class_bind_template_callback (widget_class,
2355 on_picture_view_key_pressed);
2356 gtk_widget_class_bind_template_callback (widget_class,
2357 on_picture_view_selection_changed);
2358 gtk_widget_class_bind_template_callback (widget_class,
2359 on_year_entry_activate);
2360 gtk_widget_class_bind_template_callback (widget_class,
2361 on_year_entry_focus_out_event);
2362 gtk_widget_class_bind_template_callback (widget_class,
2363 Insert_Only_Digit);
2364 }
2365
2366 /*
2367 * et_tag_area_new:
2368 *
2369 * Create a new EtTagArea instance.
2370 *
2371 * Returns: a new #EtTagArea
2372 */
2373 GtkWidget *
et_tag_area_new(void)2374 et_tag_area_new (void)
2375 {
2376 return g_object_new (ET_TYPE_TAG_AREA, NULL);
2377 }
2378
2379 static void
et_tag_area_hide_images_tab(EtTagArea * self)2380 et_tag_area_hide_images_tab (EtTagArea *self)
2381 {
2382 EtTagAreaPrivate *priv;
2383
2384 priv = et_tag_area_get_instance_private (self);
2385
2386 gtk_widget_hide (priv->images_grid);
2387 }
2388
2389 static void
et_tag_area_show_images_tab(EtTagArea * self)2390 et_tag_area_show_images_tab (EtTagArea *self)
2391 {
2392 EtTagAreaPrivate *priv;
2393
2394 priv = et_tag_area_get_instance_private (self);
2395
2396 gtk_widget_show (priv->images_grid);
2397 }
2398
2399 /*
2400 * et_tag_area_update_controls:
2401 *
2402 * Update the visibility of entry fields depending on the type of file.
2403 */
2404 void
et_tag_area_update_controls(EtTagArea * self,const ET_File * ETFile)2405 et_tag_area_update_controls (EtTagArea *self,
2406 const ET_File *ETFile)
2407 {
2408 EtTagAreaPrivate *priv;
2409
2410 g_return_if_fail (ET_TAG_AREA (self));
2411
2412 priv = et_tag_area_get_instance_private (self);
2413
2414 /* Common controls for all tags. */
2415 gtk_widget_show (priv->title_label);
2416 gtk_widget_show (priv->title_entry);
2417 gtk_widget_show (priv->artist_label);
2418 gtk_widget_show (priv->artist_entry);
2419 gtk_widget_show (priv->album_artist_label);
2420 gtk_widget_show (priv->album_artist_entry);
2421 gtk_widget_show (priv->album_label);
2422 gtk_widget_show (priv->album_entry);
2423 gtk_widget_show (priv->year_label);
2424 gtk_widget_show (priv->year_entry);
2425 gtk_widget_show (priv->track_label);
2426 gtk_widget_show (priv->track_combo_entry);
2427 gtk_widget_show (priv->track_total_entry);
2428 gtk_widget_show (priv->track_sequence_button);
2429 gtk_widget_show (priv->track_number_button);
2430 gtk_widget_show (priv->genre_label);
2431 gtk_widget_show (priv->genre_combo_entry);
2432 gtk_widget_show (priv->comment_label);
2433 gtk_widget_show (priv->comment_entry);
2434
2435 /* Special controls to display or not! */
2436 switch (ETFile->ETFileDescription->TagType)
2437 {
2438 case ID3_TAG:
2439 if (!g_settings_get_boolean (MainSettings, "id3v2-enabled"))
2440 {
2441 /* ID3v1 : Hide specifics ID3v2 fields if not activated! */
2442 gtk_widget_hide (priv->disc_number_label);
2443 gtk_widget_hide (priv->disc_number_entry);
2444 gtk_widget_hide (priv->composer_label);
2445 gtk_widget_hide (priv->composer_entry);
2446 gtk_widget_hide (priv->orig_artist_label);
2447 gtk_widget_hide (priv->orig_artist_entry);
2448 gtk_widget_hide (priv->copyright_label);
2449 gtk_widget_hide (priv->copyright_entry);
2450 gtk_widget_hide (priv->url_label);
2451 gtk_widget_hide (priv->url_entry);
2452 gtk_widget_hide (priv->encoded_by_label);
2453 gtk_widget_hide (priv->encoded_by_entry);
2454 et_tag_area_hide_images_tab (self);
2455 }
2456 else
2457 {
2458 gtk_widget_show (priv->disc_number_label);
2459 gtk_widget_show (priv->disc_number_entry);
2460 gtk_widget_show (priv->composer_label);
2461 gtk_widget_show (priv->composer_entry);
2462 gtk_widget_show (priv->orig_artist_label);
2463 gtk_widget_show (priv->orig_artist_entry);
2464 gtk_widget_show (priv->copyright_label);
2465 gtk_widget_show (priv->copyright_entry);
2466 gtk_widget_show (priv->url_label);
2467 gtk_widget_show (priv->url_entry);
2468 gtk_widget_show (priv->encoded_by_label);
2469 gtk_widget_show (priv->encoded_by_entry);
2470 et_tag_area_show_images_tab (self);
2471 }
2472 break;
2473
2474 #ifdef ENABLE_OGG
2475 case OGG_TAG:
2476 gtk_widget_show (priv->disc_number_label);
2477 gtk_widget_show (priv->disc_number_entry);
2478 gtk_widget_show (priv->composer_label);
2479 gtk_widget_show (priv->composer_entry);
2480 gtk_widget_show (priv->orig_artist_label);
2481 gtk_widget_show (priv->orig_artist_entry);
2482 gtk_widget_show (priv->copyright_label);
2483 gtk_widget_show (priv->copyright_entry);
2484 gtk_widget_show (priv->url_label);
2485 gtk_widget_show (priv->url_entry);
2486 gtk_widget_show (priv->encoded_by_label);
2487 gtk_widget_show (priv->encoded_by_entry);
2488 et_tag_area_show_images_tab (self);
2489 break;
2490 #endif
2491
2492 #ifdef ENABLE_OPUS
2493 case OPUS_TAG:
2494 gtk_widget_show (priv->disc_number_label);
2495 gtk_widget_show (priv->disc_number_entry);
2496 gtk_widget_show (priv->composer_label);
2497 gtk_widget_show (priv->composer_entry);
2498 gtk_widget_show (priv->orig_artist_label);
2499 gtk_widget_show (priv->orig_artist_entry);
2500 gtk_widget_show (priv->copyright_label);
2501 gtk_widget_show (priv->copyright_entry);
2502 gtk_widget_show (priv->url_label);
2503 gtk_widget_show (priv->url_entry);
2504 gtk_widget_show (priv->encoded_by_label);
2505 gtk_widget_show (priv->encoded_by_entry);
2506 et_tag_area_show_images_tab (self);
2507 break;
2508 #endif
2509
2510 #ifdef ENABLE_FLAC
2511 case FLAC_TAG:
2512 gtk_widget_show (priv->disc_number_label);
2513 gtk_widget_show (priv->disc_number_entry);
2514 gtk_widget_show (priv->composer_label);
2515 gtk_widget_show (priv->composer_entry);
2516 gtk_widget_show (priv->orig_artist_label);
2517 gtk_widget_show (priv->orig_artist_entry);
2518 gtk_widget_show (priv->copyright_label);
2519 gtk_widget_show (priv->copyright_entry);
2520 gtk_widget_show (priv->url_label);
2521 gtk_widget_show (priv->url_entry);
2522 gtk_widget_show (priv->encoded_by_label);
2523 gtk_widget_show (priv->encoded_by_entry);
2524 et_tag_area_show_images_tab (self);
2525 break;
2526 #endif
2527
2528 case APE_TAG:
2529 gtk_widget_show (priv->disc_number_label);
2530 gtk_widget_show (priv->disc_number_entry);
2531 gtk_widget_show (priv->composer_label);
2532 gtk_widget_show (priv->composer_entry);
2533 gtk_widget_show (priv->orig_artist_label);
2534 gtk_widget_show (priv->orig_artist_entry);
2535 gtk_widget_show (priv->copyright_label);
2536 gtk_widget_show (priv->copyright_entry);
2537 gtk_widget_show (priv->url_label);
2538 gtk_widget_show (priv->url_entry);
2539 gtk_widget_show (priv->encoded_by_label);
2540 gtk_widget_show (priv->encoded_by_entry);
2541 et_tag_area_show_images_tab (self);
2542 break;
2543
2544 #ifdef ENABLE_MP4
2545 case MP4_TAG:
2546 gtk_widget_show (priv->disc_number_label);
2547 gtk_widget_show (priv->disc_number_entry);
2548 gtk_widget_show (priv->composer_label);
2549 gtk_widget_show (priv->composer_entry);
2550 gtk_widget_hide (priv->orig_artist_label);
2551 gtk_widget_hide (priv->orig_artist_entry);
2552 gtk_widget_show (priv->copyright_label);
2553 gtk_widget_show (priv->copyright_entry);
2554 gtk_widget_hide (priv->url_label);
2555 gtk_widget_hide (priv->url_entry);
2556 gtk_widget_show (priv->encoded_by_label);
2557 gtk_widget_show (priv->encoded_by_entry);
2558 et_tag_area_show_images_tab (self);
2559 break;
2560 #endif
2561
2562 #ifdef ENABLE_WAVPACK
2563 case WAVPACK_TAG:
2564 gtk_widget_show (priv->disc_number_label);
2565 gtk_widget_show (priv->disc_number_entry);
2566 gtk_widget_show (priv->composer_label);
2567 gtk_widget_show (priv->composer_entry);
2568 gtk_widget_show (priv->orig_artist_label);
2569 gtk_widget_show (priv->orig_artist_entry);
2570 gtk_widget_show (priv->copyright_label);
2571 gtk_widget_show (priv->copyright_entry);
2572 gtk_widget_show (priv->url_label);
2573 gtk_widget_show (priv->url_entry);
2574 gtk_widget_show (priv->encoded_by_label);
2575 gtk_widget_show (priv->encoded_by_entry);
2576 et_tag_area_hide_images_tab (self);
2577 break;
2578 #endif /* ENABLE_WAVPACK */
2579
2580 #ifndef ENABLE_OGG
2581 case OGG_TAG:
2582 #endif
2583 #ifndef ENABLE_FLAC
2584 case FLAC_TAG:
2585 #endif
2586 #ifndef ENABLE_MP4
2587 case MP4_TAG:
2588 #endif
2589 #ifndef ENABLE_WAVPACK
2590 case WAVPACK_TAG:
2591 #endif
2592 #ifndef ENABLE_OPUS
2593 case OPUS_TAG:
2594 #endif
2595 case UNKNOWN_TAG:
2596 default:
2597 gtk_widget_hide (priv->disc_number_label);
2598 gtk_widget_hide (priv->disc_number_entry);
2599 gtk_widget_hide (priv->composer_label);
2600 gtk_widget_hide (priv->composer_entry);
2601 gtk_widget_hide (priv->orig_artist_label);
2602 gtk_widget_hide (priv->orig_artist_entry);
2603 gtk_widget_hide (priv->copyright_label);
2604 gtk_widget_hide (priv->copyright_entry);
2605 gtk_widget_hide (priv->url_label);
2606 gtk_widget_hide (priv->url_entry);
2607 gtk_widget_hide (priv->encoded_by_label);
2608 gtk_widget_hide (priv->encoded_by_entry);
2609 et_tag_area_hide_images_tab (self);
2610 break;
2611 }
2612 }
2613
2614 void
et_tag_area_clear(EtTagArea * self)2615 et_tag_area_clear (EtTagArea *self)
2616 {
2617 EtTagAreaPrivate *priv;
2618
2619 g_return_if_fail (ET_TAG_AREA (self));
2620
2621 priv = et_tag_area_get_instance_private (self);
2622
2623 gtk_entry_set_text (GTK_ENTRY (priv->title_entry), "");
2624 gtk_entry_set_text (GTK_ENTRY (priv->artist_entry), "");
2625 gtk_entry_set_text (GTK_ENTRY (priv->album_artist_entry), "");
2626 gtk_entry_set_text (GTK_ENTRY (priv->album_entry), "");
2627 gtk_entry_set_text (GTK_ENTRY (priv->disc_number_entry), "");
2628 gtk_entry_set_text (GTK_ENTRY (priv->year_entry), "");
2629 gtk_entry_set_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (priv->track_combo_entry))),
2630 "");
2631 gtk_entry_set_text (GTK_ENTRY (priv->track_total_entry), "");
2632 gtk_entry_set_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (priv->genre_combo_entry))),
2633 "");
2634 gtk_entry_set_text (GTK_ENTRY (priv->comment_entry), "");
2635 gtk_entry_set_text (GTK_ENTRY (priv->composer_entry), "");
2636 gtk_entry_set_text (GTK_ENTRY (priv->orig_artist_entry), "");
2637 gtk_entry_set_text (GTK_ENTRY (priv->copyright_entry), "");
2638 gtk_entry_set_text (GTK_ENTRY (priv->url_entry), "");
2639 gtk_entry_set_text (GTK_ENTRY (priv->encoded_by_entry), "");
2640 PictureEntry_Clear (self);
2641 }
2642
2643 void
et_tag_area_title_grab_focus(EtTagArea * self)2644 et_tag_area_title_grab_focus (EtTagArea *self)
2645 {
2646 EtTagAreaPrivate *priv;
2647
2648 g_return_if_fail (ET_TAG_AREA (self));
2649
2650 priv = et_tag_area_get_instance_private (self);
2651
2652 gtk_widget_grab_focus (priv->title_entry);
2653 }
2654
2655 /*
2656 * et_tag_area_create_file_tag:
2657 *
2658 * Create a new File_Tag structure and poopulate it with values from the UI.
2659 */
2660 File_Tag *
et_tag_area_create_file_tag(EtTagArea * self)2661 et_tag_area_create_file_tag (EtTagArea *self)
2662 {
2663 EtTagAreaPrivate *priv;
2664 gchar *buffer;
2665 File_Tag *FileTag;
2666
2667 g_return_val_if_fail (ET_TAG_AREA (self), NULL);
2668
2669 priv = et_tag_area_get_instance_private (self);
2670
2671 /* Save tag data and generate undo for tag. */
2672 FileTag = et_file_tag_new ();
2673
2674 /* Title */
2675 buffer = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->title_entry)));
2676 g_strstrip (buffer);
2677
2678 if (*buffer)
2679 {
2680 FileTag->title = buffer;
2681 }
2682 else
2683 {
2684 FileTag->title = NULL;
2685 g_free (buffer);
2686 }
2687
2688 /* Artist */
2689 buffer = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->artist_entry)));
2690 g_strstrip (buffer);
2691
2692 if (*buffer)
2693 {
2694 FileTag->artist = buffer;
2695 }
2696 else
2697 {
2698 FileTag->artist = NULL;
2699 g_free (buffer);
2700 }
2701
2702 /* Album Artist */
2703 buffer = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->album_artist_entry)));
2704 g_strstrip (buffer);
2705
2706 if (*buffer)
2707 {
2708 FileTag->album_artist = buffer;
2709 }
2710 else
2711 {
2712 FileTag->album_artist = NULL;
2713 g_free (buffer);
2714 }
2715
2716 /* Album */
2717 buffer = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->album_entry)));
2718 g_strstrip (buffer);
2719
2720 if (*buffer)
2721 {
2722 FileTag->album = buffer;
2723 }
2724 else
2725 {
2726 FileTag->album = NULL;
2727 g_free (buffer);
2728 }
2729
2730 /* Disc number and total number of discs. */
2731 buffer = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->disc_number_entry)));
2732 g_strstrip (buffer);
2733
2734 if (*buffer)
2735 {
2736 gchar *separator;
2737
2738 separator = strchr (buffer, '/');
2739
2740 if (separator && *(separator + 1))
2741 {
2742 /* Copy before the separator for the disc number, beyond the
2743 * separator for the total number of discs. */
2744 FileTag->disc_number = g_strndup (buffer, separator - buffer);
2745 FileTag->disc_total = g_strdup (separator + 1);
2746 g_free (buffer);
2747 }
2748 else
2749 {
2750 FileTag->disc_number = buffer;
2751 FileTag->disc_total = NULL;
2752 }
2753 }
2754 else
2755 {
2756 FileTag->disc_number = NULL;
2757 FileTag->disc_total = NULL;
2758 g_free (buffer);
2759 }
2760
2761 /* Year */
2762 buffer = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->year_entry)));
2763 g_strstrip (buffer);
2764
2765 if (*buffer)
2766 {
2767 FileTag->year = buffer;
2768 }
2769 else
2770 {
2771 FileTag->year = NULL;
2772 g_free (buffer);
2773 }
2774
2775 /* Track */
2776 buffer = g_strdup (gtk_entry_get_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (priv->track_combo_entry)))));
2777 g_strstrip (buffer);
2778
2779 if (*buffer)
2780 {
2781 FileTag->track = et_track_number_to_string (atoi (buffer));
2782 g_free (buffer);
2783 }
2784 else
2785 {
2786 FileTag->track = NULL;
2787 g_free (buffer);
2788 }
2789
2790 /* Track Total */
2791 buffer = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->track_total_entry)));
2792 g_strstrip (buffer);
2793
2794 if (*buffer)
2795 {
2796 FileTag->track_total = et_track_number_to_string (atoi (buffer));
2797 g_free (buffer);
2798 }
2799 else
2800 {
2801 FileTag->track_total = NULL;
2802 g_free (buffer);
2803 }
2804
2805 /* Genre */
2806 buffer = g_strdup (gtk_entry_get_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (priv->genre_combo_entry)))));
2807 g_strstrip (buffer);
2808
2809 if (*buffer)
2810 {
2811 FileTag->genre = buffer;
2812 }
2813 else
2814 {
2815 FileTag->genre = NULL;
2816 g_free (buffer);
2817 }
2818
2819 /* Comment */
2820 buffer = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->comment_entry)));
2821 g_strstrip (buffer);
2822
2823 if (*buffer)
2824 {
2825 FileTag->comment = buffer;
2826 }
2827 else
2828 {
2829 FileTag->comment = NULL;
2830 g_free (buffer);
2831 }
2832
2833 /* Composer */
2834 buffer = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->composer_entry)));
2835 g_strstrip (buffer);
2836
2837 if (*buffer)
2838 {
2839 FileTag->composer = buffer;
2840 }
2841 else
2842 {
2843 FileTag->composer = NULL;
2844 g_free (buffer);
2845 }
2846
2847 /* Original Artist */
2848 buffer = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->orig_artist_entry)));
2849 g_strstrip (buffer);
2850
2851 if (*buffer)
2852 {
2853 FileTag->orig_artist = buffer;
2854 }
2855 else
2856 {
2857 FileTag->orig_artist = NULL;
2858 g_free (buffer);
2859 }
2860
2861 /* Copyright */
2862 buffer = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->copyright_entry)));
2863 g_strstrip (buffer);
2864
2865 if (*buffer)
2866 {
2867 FileTag->copyright = buffer;
2868 }
2869 else
2870 {
2871 FileTag->copyright = NULL;
2872 g_free (buffer);
2873 }
2874
2875 /* URL */
2876 buffer = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->url_entry)));
2877 g_strstrip (buffer);
2878
2879 if (*buffer)
2880 {
2881 FileTag->url = buffer;
2882 }
2883 else
2884 {
2885 FileTag->url = NULL;
2886 g_free (buffer);
2887 }
2888
2889 /* Encoded by */
2890 buffer = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->encoded_by_entry)));
2891 g_strstrip (buffer);
2892
2893 if (*buffer)
2894 {
2895 FileTag->encoded_by = buffer;
2896 }
2897 else
2898 {
2899 FileTag->encoded_by = NULL;
2900 g_free (buffer);
2901 }
2902
2903 /* Picture */
2904 {
2905 EtPicture *pic, *prev_pic = NULL;
2906 GtkTreeModel *model;
2907 GtkTreeIter iter;
2908
2909 et_file_tag_set_picture (FileTag, NULL);
2910
2911 model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->images_view));
2912
2913 if (gtk_tree_model_get_iter_first (model, &iter))
2914 {
2915 do
2916 {
2917 gtk_tree_model_get (model, &iter, PICTURE_COLUMN_DATA, &pic,
2918 -1);
2919
2920 if (!FileTag->picture)
2921 {
2922 FileTag->picture = pic;
2923 }
2924 else
2925 {
2926 prev_pic->next = pic;
2927 }
2928
2929 prev_pic = pic;
2930 } while (gtk_tree_model_iter_next (model, &iter));
2931 }
2932 }
2933
2934 return FileTag;
2935 }
2936
2937 gboolean
et_tag_area_display_et_file(EtTagArea * self,const ET_File * ETFile)2938 et_tag_area_display_et_file (EtTagArea *self,
2939 const ET_File *ETFile)
2940 {
2941 EtTagAreaPrivate *priv;
2942 File_Tag *FileTag = NULL;
2943
2944 g_return_val_if_fail (ET_TAG_AREA (self), FALSE);
2945
2946 if (!ETFile || !ETFile->FileTag)
2947 {
2948 et_tag_area_clear (self);
2949 //Tag_Area_Set_Sensitive(FALSE);
2950 return FALSE;
2951 }
2952
2953 priv = et_tag_area_get_instance_private (self);
2954
2955 switch (ETFile->ETFileDescription->TagType)
2956 {
2957 #ifdef ENABLE_MP3
2958 case ID3_TAG:
2959 gtk_label_set_text (GTK_LABEL (priv->tag_label), _("ID3 Tag"));
2960 break;
2961 #endif
2962 #ifdef ENABLE_OGG
2963 case OGG_TAG:
2964 gtk_label_set_text (GTK_LABEL (priv->tag_label), _("Ogg Vorbis Tag"));
2965 break;
2966 #endif
2967 #ifdef ENABLE_FLAC
2968 case FLAC_TAG:
2969 gtk_label_set_text (GTK_LABEL (priv->tag_label), _("FLAC Vorbis Tag"));
2970 break;
2971 #endif
2972 case APE_TAG:
2973 gtk_label_set_text (GTK_LABEL (priv->tag_label), _("APE Tag"));
2974 break;
2975 #ifdef ENABLE_MP4
2976 case MP4_TAG:
2977 gtk_label_set_text (GTK_LABEL (priv->tag_label), _("MP4/M4A/AAC Tag"));
2978 break;
2979 #endif
2980 #ifdef ENABLE_WAVPACK
2981 case WAVPACK_TAG:
2982 gtk_label_set_text (GTK_LABEL (priv->tag_label), _("Wavpack Tag"));
2983 break;
2984 #endif
2985 #ifdef ENABLE_OPUS
2986 case OPUS_TAG:
2987 gtk_label_set_text (GTK_LABEL (priv->tag_label), _("Opus Tag"));
2988 break;
2989 #endif
2990 #ifndef ENABLE_MP3
2991 case ID3_TAG:
2992 #endif
2993 #ifndef ENABLE_OGG
2994 case OGG_TAG:
2995 #endif
2996 #ifndef ENABLE_FLAC
2997 case FLAC_TAG:
2998 #endif
2999 #ifndef ENABLE_MP4
3000 case MP4_TAG:
3001 #endif
3002 #ifndef ENABLE_WAVPACK
3003 case WAVPACK_TAG:
3004 #endif
3005 #ifndef ENABLE_OPUS
3006 case OPUS_TAG:
3007 #endif
3008 case UNKNOWN_TAG:
3009 default:
3010 gtk_label_set_text (GTK_LABEL (priv->tag_label), _("Tag"));
3011 /* FIXME: Translatable string. */
3012 Log_Print (LOG_ERROR,
3013 "FileTag: Undefined tag type %d for file %s.",
3014 (gint)ETFile->ETFileDescription->TagType,
3015 ((File_Name *)((GList *)ETFile->FileNameCur)->data)->value_utf8);
3016 break;
3017 }
3018
3019 //Tag_Area_Set_Sensitive(TRUE); // Causes displaying problem when saving files
3020
3021 FileTag = (File_Tag *)(ETFile->FileTag->data);
3022
3023 /* Show title */
3024 if (FileTag && FileTag->title)
3025 {
3026 gchar *tmp = Try_To_Validate_Utf8_String (FileTag->title);
3027 gtk_entry_set_text (GTK_ENTRY (priv->title_entry), tmp);
3028 g_free (tmp);
3029 }
3030 else
3031 {
3032 gtk_entry_set_text (GTK_ENTRY (priv->title_entry), "");
3033 }
3034
3035 /* Show artist */
3036 if (FileTag && FileTag->artist)
3037 {
3038 gchar *tmp = Try_To_Validate_Utf8_String (FileTag->artist);
3039 gtk_entry_set_text (GTK_ENTRY (priv->artist_entry), tmp);
3040 g_free (tmp);
3041 }
3042 else
3043 {
3044 gtk_entry_set_text (GTK_ENTRY (priv->artist_entry), "");
3045 }
3046
3047 /* Show album artist */
3048 if (FileTag && FileTag->album_artist)
3049 {
3050 gchar *tmp = Try_To_Validate_Utf8_String (FileTag->album_artist);
3051 gtk_entry_set_text (GTK_ENTRY (priv->album_artist_entry), tmp);
3052 g_free (tmp);
3053 }
3054 else
3055 {
3056 gtk_entry_set_text (GTK_ENTRY (priv->album_artist_entry), "");
3057 }
3058
3059 /* Show album */
3060 if (FileTag && FileTag->album)
3061 {
3062 gchar *tmp = Try_To_Validate_Utf8_String (FileTag->album);
3063 gtk_entry_set_text (GTK_ENTRY (priv->album_entry), tmp);
3064 g_free (tmp);
3065 }
3066 else
3067 {
3068 gtk_entry_set_text (GTK_ENTRY (priv->album_entry),"");
3069 }
3070
3071 /* Show disc number and number of discs. */
3072 if (FileTag && FileTag->disc_number)
3073 {
3074 gchar *tmp;
3075
3076 if (FileTag->disc_total)
3077 {
3078 gchar *total;
3079
3080 total = g_strjoin ("/", FileTag->disc_number, FileTag->disc_total,
3081 NULL);
3082 tmp = Try_To_Validate_Utf8_String (total);
3083 g_free (total);
3084 }
3085 else
3086 {
3087 tmp = Try_To_Validate_Utf8_String (FileTag->disc_number);
3088 }
3089
3090 gtk_entry_set_text (GTK_ENTRY (priv->disc_number_entry), tmp);
3091 g_free (tmp);
3092 }
3093 else
3094 {
3095 gtk_entry_set_text (GTK_ENTRY (priv->disc_number_entry), "");
3096 }
3097
3098 /* Show year */
3099 if (FileTag && FileTag->year)
3100 {
3101 gchar *tmp = Try_To_Validate_Utf8_String (FileTag->year);
3102 gtk_entry_set_text (GTK_ENTRY (priv->year_entry), tmp);
3103 g_free (tmp);
3104 }
3105 else
3106 {
3107 gtk_entry_set_text (GTK_ENTRY (priv->year_entry), "");
3108 }
3109
3110 /* Show track */
3111 if (FileTag && FileTag->track)
3112 {
3113 gchar *tmp = Try_To_Validate_Utf8_String (FileTag->track);
3114 gtk_entry_set_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (priv->track_combo_entry))),
3115 tmp);
3116 g_free (tmp);
3117 }
3118 else
3119 {
3120 gtk_entry_set_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (priv->track_combo_entry))),
3121 "");
3122 }
3123
3124 /* Show number of tracks on the album */
3125 if (FileTag && FileTag->track_total)
3126 {
3127 gchar *tmp = Try_To_Validate_Utf8_String (FileTag->track_total);
3128 gtk_entry_set_text (GTK_ENTRY (priv->track_total_entry), tmp);
3129 g_free (tmp);
3130 }
3131 else
3132 {
3133 gtk_entry_set_text (GTK_ENTRY (priv->track_total_entry),
3134 "");
3135 }
3136
3137 /* Show genre */
3138 if (FileTag && FileTag->genre)
3139 {
3140 gchar *tmp = Try_To_Validate_Utf8_String (FileTag->genre);
3141 gtk_entry_set_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (priv->genre_combo_entry))),
3142 tmp);
3143 g_free (tmp);
3144 }
3145 else
3146 {
3147 gtk_entry_set_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (priv->genre_combo_entry))),
3148 "");
3149 }
3150
3151 /* Show comment */
3152 if (FileTag && FileTag->comment)
3153 {
3154 gchar *tmp = Try_To_Validate_Utf8_String (FileTag->comment);
3155 gtk_entry_set_text (GTK_ENTRY (priv->comment_entry), tmp);
3156 g_free (tmp);
3157 }
3158 else
3159 {
3160 gtk_entry_set_text (GTK_ENTRY (priv->comment_entry),
3161 "");
3162 }
3163
3164 /* Show composer */
3165 if (FileTag && FileTag->composer)
3166 {
3167 gchar *tmp = Try_To_Validate_Utf8_String (FileTag->composer);
3168 gtk_entry_set_text (GTK_ENTRY (priv->composer_entry), tmp);
3169 g_free (tmp);
3170 }
3171 else
3172 {
3173 gtk_entry_set_text (GTK_ENTRY (priv->composer_entry), "");
3174 }
3175
3176 /* Show original artist */
3177 if (FileTag && FileTag->orig_artist)
3178 {
3179 gchar *tmp = Try_To_Validate_Utf8_String (FileTag->orig_artist);
3180 gtk_entry_set_text (GTK_ENTRY (priv->orig_artist_entry), tmp);
3181 g_free (tmp);
3182 }
3183 else
3184 {
3185 gtk_entry_set_text (GTK_ENTRY (priv->orig_artist_entry),
3186 "");
3187 }
3188
3189 /* Show copyright */
3190 if (FileTag && FileTag->copyright)
3191 {
3192 gchar *tmp = Try_To_Validate_Utf8_String (FileTag->copyright);
3193 gtk_entry_set_text (GTK_ENTRY (priv->copyright_entry), tmp);
3194 g_free (tmp);
3195 }
3196 else
3197 {
3198 gtk_entry_set_text (GTK_ENTRY (priv->copyright_entry), "");
3199 }
3200
3201 /* Show URL */
3202 if (FileTag && FileTag->url)
3203 {
3204 gchar *tmp = Try_To_Validate_Utf8_String (FileTag->url);
3205 gtk_entry_set_text (GTK_ENTRY (priv->url_entry), tmp);
3206 g_free (tmp);
3207 }
3208 else
3209 {
3210 gtk_entry_set_text (GTK_ENTRY (priv->url_entry), "");
3211 }
3212
3213 /* Show Encoded by */
3214 if (FileTag && FileTag->encoded_by)
3215 {
3216 gchar *tmp = Try_To_Validate_Utf8_String (FileTag->encoded_by);
3217 gtk_entry_set_text (GTK_ENTRY (priv->encoded_by_entry), tmp);
3218 g_free (tmp);
3219 }
3220 else
3221 {
3222 gtk_entry_set_text (GTK_ENTRY (priv->encoded_by_entry), "");
3223 }
3224
3225 /* Show picture */
3226 PictureEntry_Clear (self);
3227
3228 if (FileTag && FileTag->picture)
3229 {
3230 EtPicture *pic;
3231 guint nbr_pic = 0;
3232 GtkWidget *page;
3233 gchar *string;
3234
3235 PictureEntry_Update (self, FileTag->picture, FALSE);
3236
3237 // Count the number of items
3238 for (pic = FileTag->picture; pic != NULL; pic = pic->next)
3239 {
3240 nbr_pic++;
3241 }
3242
3243 /* Get page "Images" of the notebook. */
3244 page = gtk_notebook_get_nth_page (GTK_NOTEBOOK (priv->tag_notebook), 1);
3245 string = g_strdup_printf (_("Images (%u)"), nbr_pic);
3246 /* Update the notebook tab. */
3247 gtk_notebook_set_tab_label_text (GTK_NOTEBOOK (priv->tag_notebook), page,
3248 string);
3249 /* Update the notebook menu. */
3250 gtk_notebook_set_menu_label_text (GTK_NOTEBOOK (priv->tag_notebook), page,
3251 string);
3252 g_free (string);
3253
3254 }
3255 else
3256 {
3257 GtkWidget *page;
3258
3259 /* Get page "Images" of the notebook. */
3260 page = gtk_notebook_get_nth_page (GTK_NOTEBOOK (priv->tag_notebook),
3261 1);
3262 /* Update the notebook tab. */
3263 gtk_notebook_set_tab_label_text (GTK_NOTEBOOK (priv->tag_notebook),
3264 page, _("Images"));
3265 /* Update the notebook menu. */
3266 gtk_notebook_set_menu_label_text (GTK_NOTEBOOK (priv->tag_notebook),
3267 page, _("Images"));
3268 }
3269
3270 return TRUE;
3271 }
3272
3273 gboolean
et_tag_area_select_all_if_focused(EtTagArea * self,GtkWidget * focused)3274 et_tag_area_select_all_if_focused (EtTagArea *self,
3275 GtkWidget *focused)
3276 {
3277 EtTagAreaPrivate *priv;
3278
3279 g_return_val_if_fail (ET_TAG_AREA (self), FALSE);
3280
3281 priv = et_tag_area_get_instance_private (self);
3282
3283 if (focused == priv->images_view)
3284 {
3285 GtkTreeSelection *selection;
3286
3287 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->images_view));
3288 gtk_tree_selection_select_all (selection);
3289 return TRUE;
3290 }
3291
3292 return FALSE;
3293 }
3294
3295 gboolean
et_tag_area_unselect_all_if_focused(EtTagArea * self,GtkWidget * focused)3296 et_tag_area_unselect_all_if_focused (EtTagArea *self,
3297 GtkWidget *focused)
3298 {
3299 EtTagAreaPrivate *priv;
3300
3301 g_return_val_if_fail (ET_TAG_AREA (self), FALSE);
3302
3303 priv = et_tag_area_get_instance_private (self);
3304
3305 if (focused == priv->images_view)
3306 {
3307 GtkTreeSelection *selection;
3308
3309 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->images_view));
3310 gtk_tree_selection_unselect_all (selection);
3311 return TRUE;
3312 }
3313
3314 return FALSE;
3315 }
3316