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 = &current_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