1 /* $Id$ */
2 /*-
3  * Copyright (c) 2006 Jannis Pohlmann <jannis@xfce.org>
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
18  * MA 02111-1307 USA.
19  */
20 
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 
25 #ifdef HAVE_MEMORY_H
26 #include <memory.h>
27 #endif
28 #ifdef HAVE_STRING_H
29 #include <string.h>
30 #endif
31 
32 #include <taglib/tag_c.h>
33 
34 #include <exo/exo.h>
35 
36 #include <tag-renamer.h>
37 #include <audio-tags-page.h>
38 #include <media-tags-provider.h>
39 
40 
41 
42 static GType tag_renamer_format_type;
43 
44 
45 
46 GType
tag_renamer_format_get_type(void)47 tag_renamer_format_get_type (void)
48 {
49   return tag_renamer_format_type;
50 }
51 
52 
53 
54 void
tag_renamer_register_enum_types(ThunarxProviderPlugin * plugin)55 tag_renamer_register_enum_types (ThunarxProviderPlugin *plugin)
56 {
57   static const GEnumValue tag_renamer_format_values[] =
58   {
59     { TAG_RENAMER_FORMAT_TITLE,                  "TAG_RENAMER_FORMAT_TITLE",                  N_ ("Title"),  },
60     { TAG_RENAMER_FORMAT_ARTIST_TITLE,           "TAG_RENAMER_FORMAT_ARTIST_TITLE",           N_ ("Artist - Title"), },
61     { TAG_RENAMER_FORMAT_TRACK_TITLE,            "TAG_RENAMER_FORMAT_TRACK_TITLE",            N_ ("Track - Title"), },
62     { TAG_RENAMER_FORMAT_TRACK_ARTIST_TITLE,     "TAG_RENAMER_FORMAT_TRACK_ARTIST_TITLE",     N_ ("Track - Artist - Title"), },
63     { TAG_RENAMER_FORMAT_TRACK_DOT_TITLE,        "TAG_RENAMER_FORMAT_TRACK_DOT_TITLE",        N_ ("Track. Title"), },
64     { TAG_RENAMER_FORMAT_TRACK_DOT_ARTIST_TITLE, "TAG_RENAMER_FORMAT_TRACK_DOT_ARTIST_TITLE", N_ ("Track. Artist - Title"), },
65     { TAG_RENAMER_FORMAT_ARTIST_TRACK_TITLE,     "TAG_RENAMER_FORMAT_ARTIST_TRACK_TITLE",     N_ ("Artist - Track - Title"), },
66     { TAG_RENAMER_FORMAT_SEPARATOR,              "TAG_RENAMER_FORMAT_SEPARATOR",              " ", },
67     { TAG_RENAMER_FORMAT_CUSTOM,                 "TAG_RENAMER_FORMAT_CUSTOM",                 N_ ("Custom"), },
68     { 0,                                         NULL,                                        NULL, },
69   };
70 
71   tag_renamer_format_type = thunarx_provider_plugin_register_enum (plugin, "TagRenamerFormat", tag_renamer_format_values);
72 }
73 
74 
75 
76 enum
77 {
78   COLUMN_TEXT,
79   COLUMN_NUMBER,
80   N_COLUMNS
81 };
82 
83 
84 
85 /* Property identifiers */
86 enum
87 {
88   PROP_0,
89   PROP_FORMAT,
90   PROP_TEXT,
91   PROP_REPLACE_SPACES,
92   PROP_LOWERCASE,
93 };
94 
95 
96 
97 static void      tag_renamer_finalize              (GObject         *object);
98 static void      tag_renamer_get_property          (GObject         *object,
99                                                     guint            prop_id,
100                                                     GValue          *value,
101                                                     GParamSpec      *pspec);
102 static void      tag_renamer_set_property          (GObject         *object,
103                                                     guint            prop_id,
104                                                     const GValue    *value,
105                                                     GParamSpec      *pspec);
106 static gchar    *tag_renamer_process               (ThunarxRenamer  *renamer,
107                                                     ThunarxFileInfo *file,
108                                                     const gchar     *text,
109                                                     guint            index);
110 static GList    *tag_renamer_get_menu_items        (ThunarxRenamer  *renamer,
111                                                     GtkWindow       *window,
112                                                     GList           *files);
113 static void      tag_renamer_help_clicked          (GtkWidget       *button);
114 static gboolean  tag_renamer_combo_separator_func  (GtkTreeModel    *model,
115                                                     GtkTreeIter     *iter,
116                                                     gpointer         user_data);
117 static void      tag_renamer_combo_changed         (GtkComboBox     *combo_box,
118                                                     GtkWidget       *entry);
119 static void      tag_renamer_edit_tags_activated   (ThunarxMenuItem *item,
120                                                     ThunarxFileInfo *file);
121 
122 
123 
124 struct _TagRenamerClass
125 {
126   ThunarxRenamerClass __parent__;
127 };
128 
129 struct _TagRenamer
130 {
131   ThunarxRenamer __parent__;
132 
133   /* Properties */
134   TagRenamerFormat  format;
135   gchar            *text;
136   gboolean          replace_spaces;
137   gboolean          lowercase;
138 };
139 
140 
141 
142 THUNARX_DEFINE_TYPE (TagRenamer, tag_renamer, THUNARX_TYPE_RENAMER);
143 
144 
145 
146 static void
tag_renamer_class_init(TagRenamerClass * klass)147 tag_renamer_class_init (TagRenamerClass *klass)
148 {
149   ThunarxRenamerClass *thunarxrenamer_class;
150   GObjectClass        *gobject_class;
151 
152   gobject_class = G_OBJECT_CLASS (klass);
153   gobject_class->finalize = tag_renamer_finalize;
154   gobject_class->get_property = tag_renamer_get_property;
155   gobject_class->set_property = tag_renamer_set_property;
156 
157   thunarxrenamer_class = THUNARX_RENAMER_CLASS (klass);
158   thunarxrenamer_class->process = tag_renamer_process;
159   thunarxrenamer_class->get_menu_items = tag_renamer_get_menu_items;
160 
161   /**
162    * TagRenamer:format:
163    *
164    * Naming format used for renaming the selected files.
165    **/
166   g_object_class_install_property (gobject_class,
167                                    PROP_FORMAT,
168                                    g_param_spec_enum ("format",
169                                                       "format",
170                                                       "format",
171                                                       TYPE_TAG_RENAMER_FORMAT,
172                                                       TAG_RENAMER_FORMAT_TRACK_TITLE,
173                                                       G_PARAM_READWRITE));
174 
175   /**
176    * TagRenamer:text:
177    *
178    * Custom format from the user.
179    **/
180   g_object_class_install_property (gobject_class,
181                                    PROP_TEXT,
182                                    g_param_spec_string ("text",
183                                                         "text",
184                                                         "text",
185                                                         NULL,
186                                                         G_PARAM_READWRITE));
187 
188   /**
189    * TagRenamer:replace-spaces:
190    *
191    * Whether spaces should be replaced with _ or not
192    **/
193   g_object_class_install_property (gobject_class,
194                                    PROP_REPLACE_SPACES,
195                                    g_param_spec_boolean ("replace-spaces",
196                                                          "replace-spaces",
197                                                          "replace-spaces",
198                                                          FALSE,
199                                                          G_PARAM_READWRITE));
200 
201   /**
202    * TagRenamer:lowercase:
203    *
204    * Whether all chars will be converted to lowercase.
205    **/
206   g_object_class_install_property (gobject_class,
207                                    PROP_LOWERCASE,
208                                    g_param_spec_boolean ("lowercase",
209                                                          "lowercase",
210                                                          "lowercase",
211                                                          FALSE,
212                                                          G_PARAM_READWRITE));
213 
214 }
215 
216 
217 
218 static void
tag_renamer_init(TagRenamer * tag_renamer)219 tag_renamer_init (TagRenamer *tag_renamer)
220 {
221   AtkRelationSet  *relations;
222   AtkRelation     *relation;
223   AtkObject       *object;
224   GtkWidget       *grid;
225   GtkWidget       *label;
226   GtkWidget       *combo;
227   GtkWidget       *image;
228   GtkWidget       *button;
229   GtkWidget       *entry;
230   GEnumClass      *klass;
231   GtkListStore    *store;
232   GtkCellRenderer *cell;
233   GtkTreeIter      iter;
234   guint            n;
235 
236   grid = gtk_grid_new ();
237   gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
238   gtk_grid_set_column_spacing (GTK_GRID (grid), 12);
239   gtk_box_pack_start (GTK_BOX (tag_renamer), grid, FALSE, FALSE, 0);
240   gtk_widget_show (grid);
241 
242   /* Custom format */
243   label = gtk_label_new_with_mnemonic (_("Cust_om format:"));
244   gtk_label_set_xalign (GTK_LABEL (label), 1.0f);
245   gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1);
246   gtk_widget_show (label);
247 
248   entry = gtk_entry_new ();
249   gtk_widget_set_hexpand (entry, TRUE);
250   gtk_grid_attach (GTK_GRID (grid), entry, 1, 1, 1, 1);
251   exo_mutual_binding_new (G_OBJECT (entry), "text", G_OBJECT (tag_renamer), "text");
252   gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);
253   gtk_widget_show (entry);
254 
255   button = gtk_button_new ();
256   gtk_grid_attach (GTK_GRID (grid), button, 2, 1, 1, 1);
257   g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (tag_renamer_help_clicked), NULL);
258   gtk_widget_show (button);
259 
260   image = gtk_image_new_from_icon_name ("dialog-information", GTK_ICON_SIZE_MENU);
261   gtk_container_add (GTK_CONTAINER (button), image);
262   gtk_widget_show (image);
263 
264   /* Set Atk label relation for the entry */
265   object = gtk_widget_get_accessible (entry);
266   relations = atk_object_ref_relation_set (gtk_widget_get_accessible (label));
267   relation = atk_relation_new (&object, 1, ATK_RELATION_LABEL_FOR);
268   atk_relation_set_add (relations, relation);
269   g_object_unref (G_OBJECT (relation));
270 
271   /* Format label */
272   label = gtk_label_new_with_mnemonic (_("_Format:"));
273   gtk_label_set_xalign (GTK_LABEL (label), 1.0f);
274   gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
275   gtk_widget_show (label);
276 
277   /* Create combo box store */
278   store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_INT);
279 
280   /* Format combo box */
281   combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (store));
282   gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (combo), tag_renamer_combo_separator_func, NULL, NULL);
283   g_signal_connect (G_OBJECT (combo), "changed", G_CALLBACK (tag_renamer_combo_changed), entry);
284 
285   /* Text renderer for the combo box */
286   cell = gtk_cell_renderer_text_new ();
287   gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE);
288   gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), cell, "text", COLUMN_TEXT, NULL);
289 
290   /* Insert items */
291   klass = g_type_class_ref (TYPE_TAG_RENAMER_FORMAT);
292   for (n = 0; n < klass->n_values; ++n)
293     {
294       gtk_list_store_append (store, &iter);
295       gtk_list_store_set (store, &iter, COLUMN_TEXT, _(klass->values[n].value_nick), COLUMN_NUMBER, n, -1);
296     }
297   g_type_class_unref (klass);
298   exo_mutual_binding_new (G_OBJECT (tag_renamer), "format", G_OBJECT (combo), "active");
299   gtk_widget_set_hexpand (combo, TRUE);
300   gtk_grid_attach (GTK_GRID (grid), combo, 1, 0, 2, 1);
301   gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
302   gtk_widget_show (combo);
303 
304   /* Release the store */
305   g_object_unref (G_OBJECT (store));
306 
307   /* Set Atk label relation for the combo box */
308   object = gtk_widget_get_accessible (combo);
309   relations = atk_object_ref_relation_set (gtk_widget_get_accessible (label));
310   relation = atk_relation_new (&object, 1, ATK_RELATION_LABEL_FOR);
311   atk_relation_set_add (relations, relation);
312   g_object_unref (G_OBJECT (relation));
313 
314   button = gtk_check_button_new_with_mnemonic (_("_Underscores"));
315   exo_mutual_binding_new (G_OBJECT (button), "active", G_OBJECT (tag_renamer), "replace-spaces");
316   gtk_widget_set_tooltip_text (GTK_WIDGET (button), _("Activating this option will replace all spaces in the target filename "
317         "with underscores."));
318   gtk_grid_attach (GTK_GRID (grid), button, 3, 0, 1, 1);
319   gtk_widget_show (button);
320 
321   button = gtk_check_button_new_with_mnemonic (_("_Lowercase"));
322   exo_mutual_binding_new (G_OBJECT (button), "active", G_OBJECT (tag_renamer), "lowercase");
323   gtk_widget_set_tooltip_text (GTK_WIDGET (button), _("If you activate this, the resulting filename will only contain lowercase letters."));
324   gtk_grid_attach (GTK_GRID (grid), button, 3, 1, 1, 1);
325   gtk_widget_show (button);
326 }
327 
328 
329 
330 
331 
332 static void
tag_renamer_finalize(GObject * object)333 tag_renamer_finalize (GObject *object)
334 {
335   TagRenamer *tag_renamer = TAG_RENAMER (object);
336 
337   /* Free string */
338   g_free (tag_renamer->text);
339 
340   (*G_OBJECT_CLASS (tag_renamer_parent_class)->finalize) (object);
341 }
342 
343 
344 
345 static void
tag_renamer_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)346 tag_renamer_get_property (GObject    *object,
347                           guint       prop_id,
348                           GValue     *value,
349                           GParamSpec *pspec)
350 {
351   TagRenamer *tag_renamer = TAG_RENAMER (object);
352 
353   switch (prop_id)
354     {
355     case PROP_FORMAT:
356       g_value_set_enum (value, tag_renamer_get_format (tag_renamer));
357       break;
358 
359     case PROP_TEXT:
360       g_value_set_string (value, tag_renamer_get_text (tag_renamer));
361       break;
362 
363     case PROP_REPLACE_SPACES:
364       g_value_set_boolean (value, tag_renamer_get_replace_spaces (tag_renamer));
365       break;
366 
367     case PROP_LOWERCASE:
368       g_value_set_boolean (value, tag_renamer_get_lowercase (tag_renamer));
369       break;
370 
371     default:
372       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
373       break;
374     }
375 }
376 
377 
378 
379 static void
tag_renamer_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)380 tag_renamer_set_property (GObject      *object,
381                           guint         prop_id,
382                           const GValue *value,
383                           GParamSpec   *pspec)
384 {
385   TagRenamer *tag_renamer = TAG_RENAMER (object);
386 
387   switch (prop_id)
388     {
389     case PROP_FORMAT:
390       tag_renamer_set_format (tag_renamer, g_value_get_enum (value));
391       break;
392 
393     case PROP_TEXT:
394       tag_renamer_set_text (tag_renamer, g_value_get_string (value));
395       break;
396 
397     case PROP_REPLACE_SPACES:
398       tag_renamer_set_replace_spaces (tag_renamer, g_value_get_boolean (value));
399       break;
400 
401     case PROP_LOWERCASE:
402       tag_renamer_set_lowercase (tag_renamer, g_value_get_boolean (value));
403       break;
404 
405     default:
406       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
407       break;
408     }
409 }
410 
411 
412 
413 static gchar *
tag_renamer_process_format(TagRenamer * tag_renamer,ThunarxFileInfo * file,const gchar * format)414 tag_renamer_process_format (TagRenamer      *tag_renamer,
415                             ThunarxFileInfo *file,
416                             const gchar     *format)
417 {
418   TagLib_File *taglib_file;
419   TagLib_Tag  *taglib_tag;
420   const gchar *value;
421   guint        integer;
422   gchar       *uri, *filename;
423   gchar       *string, *tmp;
424   GString     *result;
425   const gchar *p;
426 
427   /* Get the file uri, return on fail */
428   uri = thunarx_file_info_get_uri (file);
429   if (G_UNLIKELY (uri == NULL))
430     return NULL;
431 
432   /* Conver the uri into a filename, return on fail */
433   filename = g_filename_from_uri (uri, NULL, NULL);
434   g_free (uri);
435   if (G_UNLIKELY (filename == NULL))
436     return NULL;
437 
438   /* Load taglib file, return on fail */
439   taglib_file = taglib_file_new (filename);
440   g_free (filename);
441   if (G_UNLIKELY (taglib_file == NULL))
442     return NULL;
443 
444   /* Load tag info, return on fail */
445   taglib_tag = taglib_file_tag (taglib_file);
446   if (G_UNLIKELY (taglib_tag == NULL))
447     {
448       taglib_file_free (taglib_file);
449       return NULL;
450     }
451 
452   /* Create string with some size */
453   result = g_string_sized_new (512);
454 
455   /* walk the string */
456   for (p = format; *p != '\0'; ++p)
457     {
458       if (p[0] == '%' && p[1] != '\0')
459         {
460           switch (*++p)
461             {
462             case 'a':
463               /* Arist */
464               value = taglib_tag_artist (taglib_tag);
465               if (G_UNLIKELY (g_utf8_strlen (value, -1) == 0))
466                 value = _("Unknown Artist");
467               result = g_string_append (result, value);
468               break;
469 
470             case 't':
471               /* Title */
472               value = taglib_tag_title (taglib_tag);
473               if (G_UNLIKELY (g_utf8_strlen (value, -1) == 0))
474                 value = _("Unknown Title");
475               result = g_string_append (result, value);
476               break;
477 
478             case 'b':
479               /* Album */
480               value = taglib_tag_album (taglib_tag);
481               if (G_LIKELY (g_utf8_strlen (value, -1) > 0))
482                 result = g_string_append (result, value);
483               break;
484 
485             case 'g':
486               /* Genre */
487               value = taglib_tag_genre (taglib_tag);
488               if (G_LIKELY (g_utf8_strlen (value, -1) > 0))
489                 result = g_string_append (result, value);
490               break;
491 
492             case 'n':
493               /* Track Number */
494               integer = taglib_tag_track (taglib_tag);
495               g_string_append_printf (result, "%02d", integer);
496               break;
497 
498             case 'y':
499               /* Year */
500               integer = taglib_tag_year (taglib_tag);
501               if (G_LIKELY (integer > 0))
502                 g_string_append_printf (result, "%d", integer);
503               break;
504 
505             case 'c':
506               /* Comment */
507               value = taglib_tag_comment (taglib_tag);
508               if (G_LIKELY (g_utf8_strlen (value, -1) > 0))
509                 result = g_string_append (result, value);
510               break;
511 
512             case '%':
513               /* Percentage character */
514               result = g_string_append_c (result, '%');
515               break;
516             }
517         }
518       else
519         {
520           /* Append character */
521           result = g_string_append_c (result, *p);
522         }
523     }
524 
525   /* Free tag info strings */
526   taglib_tag_free_strings ();
527 
528   /* Cleanup */
529   taglib_file_free (taglib_file);
530 
531   /* Get the resulting string */
532   string = g_string_free (result, FALSE);
533 
534   /* Replace spaces if requested */
535   if (tag_renamer_get_replace_spaces (tag_renamer))
536     string = g_strdelimit (string, " ", '_');
537 
538   /* Convert to lowercase if requested */
539   if (tag_renamer_get_lowercase (tag_renamer))
540   {
541     tmp = g_utf8_strdown (string, -1);
542     g_free (string);
543     string = tmp;
544   }
545 
546   /* Replace slashes */
547   string = g_strdelimit (string, G_DIR_SEPARATOR_S, '_');
548 
549   /* Return the result */
550   return string;
551 }
552 
553 
554 
555 static gchar*
tag_renamer_process(ThunarxRenamer * renamer,ThunarxFileInfo * file,const gchar * text,guint idx)556 tag_renamer_process (ThunarxRenamer  *renamer,
557                      ThunarxFileInfo *file,
558                      const gchar     *text,
559                      guint            idx)
560 {
561   TagRenamer  *tag_renamer = TAG_RENAMER (renamer);
562   const gchar *format;
563 
564   switch (tag_renamer_get_format (tag_renamer))
565     {
566     case TAG_RENAMER_FORMAT_TRACK_DOT_TITLE:
567       format = "%n. %t";
568       break;
569 
570     case TAG_RENAMER_FORMAT_TRACK_DOT_ARTIST_TITLE:
571       format = "%n. %a - %t";
572       break;
573 
574     case TAG_RENAMER_FORMAT_TRACK_TITLE:
575       format = "%n - %t";
576       break;
577 
578     case TAG_RENAMER_FORMAT_TRACK_ARTIST_TITLE:
579       format = "%n - %a - %t";
580       break;
581 
582     case TAG_RENAMER_FORMAT_TITLE:
583       format = "%t";
584       break;
585 
586     case TAG_RENAMER_FORMAT_ARTIST_TITLE:
587       format = "%a - %t";
588       break;
589 
590     case TAG_RENAMER_FORMAT_ARTIST_TRACK_TITLE:
591       format = "%a - %n - %t";
592       break;
593 
594     default: /* Custom & separator */
595       format = tag_renamer_get_text (tag_renamer);
596       if (format == NULL || *format == '\0')
597         return g_strdup (text);
598       break;
599     }
600 
601   return tag_renamer_process_format (tag_renamer, file, format);;
602 }
603 
604 
605 
606 static GList*
tag_renamer_get_menu_items(ThunarxRenamer * renamer,GtkWindow * window,GList * files)607 tag_renamer_get_menu_items (ThunarxRenamer *renamer,
608                             GtkWindow      *window,
609                             GList          *files)
610 {
611   ThunarxMenuItem *item;
612   GList           *file;
613   GList           *items = NULL;
614   ThunarxFileInfo *info;
615 
616   if (g_list_length (files) != 1)
617     return NULL;
618 
619   file = g_list_first (files);
620 
621   if (G_UNLIKELY (file == NULL))
622     return NULL;
623 
624   info = THUNARX_FILE_INFO (file->data);
625 
626   if (G_LIKELY (media_tags_get_audio_file_supported (info)))
627     {
628       /* Edit tags action */
629       item = thunarx_menu_item_new ("edit-tags", _("Edit _Tags"), _("Edit ID3/OGG tags of this file."), "gtk-edit");
630       g_object_set_data_full (G_OBJECT (item), "window", g_object_ref (G_OBJECT (window)), (GDestroyNotify)g_object_unref);
631       g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (tag_renamer_edit_tags_activated), info);
632       items = g_list_prepend (items, item);
633     }
634 
635   return items;
636 }
637 
638 
639 
640 static void
tag_renamer_help_clicked(GtkWidget * button)641 tag_renamer_help_clicked (GtkWidget *button)
642 {
643   GtkWidget *dialog;
644 
645   /* Create dialog */
646   dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (button)),
647                                    GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
648                                    GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, _("Tag Help"));
649 
650   /* Format help text */
651   gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog),
652                                               "<tt>%%a = </tt>%s\n"
653                                               "<tt>%%t = </tt>%s\n"
654                                               "<tt>%%b = </tt>%s\n"
655                                               "<tt>%%g = </tt>%s\n"
656                                               "<tt>%%n = </tt>%s\n"
657                                               "<tt>%%y = </tt>%s\n"
658                                               "<tt>%%c = </tt>%s",
659                                               _("Artist"), _("Title"),
660                                               _("Album"), _("Genre"),
661                                               _("Track number"), _("Year"),
662                                               _("Comment"));
663 
664   /* Run and destroy */
665   gtk_dialog_run (GTK_DIALOG (dialog));
666   gtk_widget_destroy (dialog);
667 }
668 
669 
670 
671 static gboolean
tag_renamer_combo_separator_func(GtkTreeModel * model,GtkTreeIter * iter,gpointer user_data)672 tag_renamer_combo_separator_func (GtkTreeModel *model,
673                                   GtkTreeIter  *iter,
674                                   gpointer      user_data)
675 {
676   gint n;
677 
678   /* Get item number from model */
679   gtk_tree_model_get (model, iter, COLUMN_NUMBER, &n, -1);
680 
681   /* Return true if this is the separator item */
682   return (n == TAG_RENAMER_FORMAT_SEPARATOR);
683 }
684 
685 
686 
687 static void
tag_renamer_combo_changed(GtkComboBox * combo_box,GtkWidget * entry)688 tag_renamer_combo_changed (GtkComboBox *combo_box,
689                            GtkWidget   *entry)
690 {
691   GtkTreeModel *model;
692   GtkTreeIter   iter;
693   gint          n;
694 
695   /* Get the combo model and active iter*/
696   model = gtk_combo_box_get_model (combo_box);
697   gtk_combo_box_get_active_iter (combo_box, &iter);
698 
699   /* Get item number from model */
700   gtk_tree_model_get (model, &iter, COLUMN_NUMBER, &n, -1);
701 
702   /* Whether the entry is sensitive */
703   gtk_widget_set_sensitive (entry, (n == TAG_RENAMER_FORMAT_CUSTOM));
704 }
705 
706 
707 
708 /**
709  * tag_renamer_new:
710  *
711  * Allocates a new #TagRenamer instance.
712  *
713  * Return value: the newly allocated #TagRenamer.
714  **/
715 TagRenamer*
tag_renamer_new(void)716 tag_renamer_new (void)
717 {
718   return g_object_new (TYPE_TAG_RENAMER,
719                        "name", _("Audio Tags"),
720                        NULL);
721 }
722 
723 
724 
725 /**
726  * tag_renamer_get_format:
727  * @tag_renamer : a #TagRenamer.
728  *
729  * Returns the current #TagRenamerFormat
730  * for the @tag_renamer.
731  *
732  * Return value: the current naming format of @tag_renamer.
733  **/
734 TagRenamerFormat
tag_renamer_get_format(TagRenamer * tag_renamer)735 tag_renamer_get_format (TagRenamer *tag_renamer)
736 {
737   g_return_val_if_fail (IS_TAG_RENAMER (tag_renamer), TAG_RENAMER_FORMAT_TRACK_TITLE);
738   return tag_renamer->format;
739 }
740 
741 
742 
743 /**
744  * tag_renamer_set_format:
745  * @tag_renamer : a #TagRenamer.
746  * @format      : the new #TagRenamerFormat.
747  *
748  * Sets the #TagRenamerFormat of the @tag_renamer
749  * to the specified @format.
750  **/
751 void
tag_renamer_set_format(TagRenamer * tag_renamer,TagRenamerFormat format)752 tag_renamer_set_format (TagRenamer      *tag_renamer,
753                         TagRenamerFormat format)
754 {
755   g_return_if_fail (IS_TAG_RENAMER (tag_renamer));
756 
757   /* Check if we already use that format */
758   if (G_UNLIKELY (tag_renamer->format == format))
759     return;
760 
761   /* Apply the new format */
762   tag_renamer->format = format;
763 
764   /* Notify listeners */
765   g_object_notify (G_OBJECT (tag_renamer), "format");
766 
767   /* Emit the "changed" signal */
768   thunarx_renamer_changed (THUNARX_RENAMER (tag_renamer));
769 }
770 
771 
772 
773 const gchar *
tag_renamer_get_text(TagRenamer * tag_renamer)774 tag_renamer_get_text (TagRenamer *tag_renamer)
775 {
776   g_return_val_if_fail (IS_TAG_RENAMER (tag_renamer), NULL);
777   return tag_renamer->text;
778 }
779 
780 
781 
782 void
tag_renamer_set_text(TagRenamer * tag_renamer,const gchar * text)783 tag_renamer_set_text (TagRenamer  *tag_renamer,
784                       const gchar *text)
785 {
786   g_return_if_fail (IS_TAG_RENAMER (tag_renamer));
787 
788   /* check if we have a new text */
789   if (G_LIKELY (!exo_str_is_equal (tag_renamer->text, text)))
790     {
791       /* apply the new text */
792       g_free (tag_renamer->text);
793       tag_renamer->text = g_strdup (text);
794 
795       /* update the renamer */
796       thunarx_renamer_changed (THUNARX_RENAMER (tag_renamer));
797 
798       /* notify listeners */
799       g_object_notify (G_OBJECT (tag_renamer), "text");
800     }
801 }
802 
803 
804 
805 /**
806  * tag_renamer_get_replace_spaces:
807  * @tag_renamer : a #TagRenamer.
808  *
809  * Returns whether spaces are going to be replaced with underscores or not.
810  *
811  * Return value: whether spaces are going to be replaced or not.
812  **/
813 gboolean
tag_renamer_get_replace_spaces(TagRenamer * tag_renamer)814 tag_renamer_get_replace_spaces (TagRenamer *tag_renamer)
815 {
816   g_return_val_if_fail (IS_TAG_RENAMER (tag_renamer), FALSE);
817   return tag_renamer->replace_spaces;
818 }
819 
820 
821 
822 /**
823  * tag_renamer_set_replace_spaces:
824  * @tag_renamer : a #TagRenamer.
825  * @replace     : a boolean flag.
826  *
827  * Sets whether spaces are going to be replaced with underscores or not.
828  **/
829 void
tag_renamer_set_replace_spaces(TagRenamer * tag_renamer,gboolean replace)830 tag_renamer_set_replace_spaces (TagRenamer *tag_renamer,
831                                 gboolean    replace)
832 {
833   g_return_if_fail (IS_TAG_RENAMER (tag_renamer));
834 
835   /* Abort if flag is already set */
836   if (G_UNLIKELY (tag_renamer->replace_spaces == replace))
837     return;
838 
839   /* Apply the new setting */
840   tag_renamer->replace_spaces = replace;
841 
842   /* Notify listeners */
843   g_object_notify (G_OBJECT (tag_renamer), "replace-spaces");
844 
845   /* Emit the "changed" signal */
846   thunarx_renamer_changed (THUNARX_RENAMER (tag_renamer));
847 }
848 
849 
850 
851 /**
852  * tag_renamer_get_lowercase:
853  * @tag_renamer : a #TagRenamer.
854  *
855  * Returns whether the resulting filename will be completely lowercase.
856  *
857  * Return value: whether all letters will be lowercase.
858  **/
859 gboolean
tag_renamer_get_lowercase(TagRenamer * tag_renamer)860 tag_renamer_get_lowercase (TagRenamer *tag_renamer)
861 {
862   g_return_val_if_fail (IS_TAG_RENAMER (tag_renamer), FALSE);
863   return tag_renamer->lowercase;
864 }
865 
866 
867 
868 /**
869  * tag_renamer_set_lowercase:
870  * @tag_renamer : a #TagRenamer.
871  * @lowercase     : a boolean flag.
872  *
873  * Sets whether all letters are going to be converted to lowercase.
874  **/
875 void
tag_renamer_set_lowercase(TagRenamer * tag_renamer,gboolean lowercase)876 tag_renamer_set_lowercase (TagRenamer *tag_renamer,
877                            gboolean    lowercase)
878 {
879   g_return_if_fail (IS_TAG_RENAMER (tag_renamer));
880 
881   /* Abort if flag is already set */
882   if (G_UNLIKELY (tag_renamer->lowercase == lowercase))
883     return;
884 
885   /* Apply the new setting */
886   tag_renamer->lowercase = lowercase;
887 
888   /* Notify listeners */
889   g_object_notify (G_OBJECT (tag_renamer), "lowercase");
890 
891   /* Emit the "changed" signal */
892   thunarx_renamer_changed (THUNARX_RENAMER (tag_renamer));
893 }
894 
895 
896 
897 static void
tag_renamer_edit_tags_activated(ThunarxMenuItem * item,ThunarxFileInfo * file)898 tag_renamer_edit_tags_activated (ThunarxMenuItem *item,
899                                  ThunarxFileInfo *file)
900 {
901   GtkWindow *window;
902   GtkWidget *dialog;
903 
904   /* Determine the parent window */
905   window = g_object_get_data (G_OBJECT (item), "window");
906   if (G_UNLIKELY (window == NULL))
907     return;
908 
909   dialog = audio_tags_page_dialog_new (window, file);
910 
911   gtk_dialog_run (GTK_DIALOG (dialog));
912   gtk_widget_destroy (dialog);
913 }
914