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 "file_area.h"
22
23 #include <glib/gi18n.h>
24
25 #include "charset.h"
26 #include "et_core.h"
27 #include "log.h"
28 #include "setting.h"
29 #include "tag_area.h"
30
31 typedef struct
32 {
33 GtkWidget *file_label;
34
35 GtkWidget *index_label;
36 GtkWidget *name_entry;
37
38 GtkWidget *header_grid;
39
40 GtkWidget *version_label;
41 GtkWidget *version_value_label;
42 GtkWidget *bitrate_label;
43 GtkWidget *bitrate_value_label;
44 GtkWidget *samplerate_label;
45 GtkWidget *samplerate_value_label;
46 GtkWidget *mode_label;
47 GtkWidget *mode_value_label;
48 GtkWidget *size_label;
49 GtkWidget *size_value_label;
50 GtkWidget *duration_label;
51 GtkWidget *duration_value_label;
52 } EtFileAreaPrivate;
53
G_DEFINE_TYPE_WITH_PRIVATE(EtFileArea,et_file_area,GTK_TYPE_BIN)54 G_DEFINE_TYPE_WITH_PRIVATE (EtFileArea, et_file_area, GTK_TYPE_BIN)
55
56 static void
57 on_file_show_header_changed (EtFileArea *self,
58 const gchar *key,
59 GSettings *settings)
60 {
61 EtFileAreaPrivate *priv;
62
63 priv = et_file_area_get_instance_private (self);
64
65 if (g_settings_get_boolean (settings, key))
66 {
67 gtk_widget_show (priv->header_grid);
68 }
69 else
70 {
71 gtk_widget_hide (priv->header_grid);
72 }
73 }
74
75 static void
et_file_area_init(EtFileArea * self)76 et_file_area_init (EtFileArea *self)
77 {
78 gtk_widget_init_template (GTK_WIDGET (self));
79
80 g_signal_connect_swapped (MainSettings, "changed::file-show-header",
81 G_CALLBACK (on_file_show_header_changed), self);
82 on_file_show_header_changed (self, "file-show-header", MainSettings);
83 }
84
85 static void
et_file_area_class_init(EtFileAreaClass * klass)86 et_file_area_class_init (EtFileAreaClass *klass)
87 {
88 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
89
90 gtk_widget_class_set_template_from_resource (widget_class,
91 "/org/gnome/EasyTAG/file_area.ui");
92 gtk_widget_class_bind_template_child_private (widget_class, EtFileArea,
93 file_label);
94 gtk_widget_class_bind_template_child_private (widget_class, EtFileArea,
95 index_label);
96 gtk_widget_class_bind_template_child_private (widget_class, EtFileArea,
97 name_entry);
98 gtk_widget_class_bind_template_child_private (widget_class, EtFileArea,
99 header_grid);
100 gtk_widget_class_bind_template_child_private (widget_class, EtFileArea,
101 version_label);
102 gtk_widget_class_bind_template_child_private (widget_class, EtFileArea,
103 version_value_label);
104 gtk_widget_class_bind_template_child_private (widget_class, EtFileArea,
105 bitrate_label);
106 gtk_widget_class_bind_template_child_private (widget_class, EtFileArea,
107 bitrate_value_label);
108 gtk_widget_class_bind_template_child_private (widget_class, EtFileArea,
109 samplerate_label);
110 gtk_widget_class_bind_template_child_private (widget_class, EtFileArea,
111 samplerate_value_label);
112 gtk_widget_class_bind_template_child_private (widget_class, EtFileArea,
113 mode_label);
114 gtk_widget_class_bind_template_child_private (widget_class, EtFileArea,
115 mode_value_label);
116 gtk_widget_class_bind_template_child_private (widget_class, EtFileArea,
117 size_label);
118 gtk_widget_class_bind_template_child_private (widget_class, EtFileArea,
119 size_value_label);
120 gtk_widget_class_bind_template_child_private (widget_class, EtFileArea,
121 duration_label);
122 gtk_widget_class_bind_template_child_private (widget_class, EtFileArea,
123 duration_value_label);
124 gtk_widget_class_bind_template_callback (widget_class,
125 on_entry_populate_popup);
126 }
127
128 /*
129 * et_file_area_new:
130 *
131 * Create a new EtFileArea instance.
132 *
133 * Returns: a new #EtFileArea
134 */
135 GtkWidget *
et_file_area_new(void)136 et_file_area_new (void)
137 {
138 return g_object_new (ET_TYPE_FILE_AREA, NULL);
139 }
140
141 void
et_file_area_clear(EtFileArea * self)142 et_file_area_clear (EtFileArea *self)
143 {
144 EtFileAreaPrivate *priv;
145 EtFileHeaderFields fields;
146 gchar *empty_str;
147
148 g_return_if_fail (ET_FILE_AREA (self));
149
150 priv = et_file_area_get_instance_private (self);
151
152 empty_str = g_strdup ("");
153
154 /* Default values are MPEG data. */
155 fields.description = _("File");
156 fields.version_label = _("Encoder:");
157 fields.version = empty_str;
158 fields.bitrate = empty_str;
159 fields.samplerate = empty_str;
160 fields.mode_label = _("Mode:");
161 fields.mode = empty_str;
162 fields.size = empty_str;
163 fields.duration = empty_str;
164
165 et_file_area_set_header_fields (self, &fields);
166
167 gtk_entry_set_text (GTK_ENTRY (priv->name_entry), empty_str);
168 gtk_label_set_text (GTK_LABEL (priv->index_label), "0/0:");
169
170 g_free (empty_str);
171 }
172
173 void
et_file_area_set_header_fields(EtFileArea * self,EtFileHeaderFields * fields)174 et_file_area_set_header_fields (EtFileArea *self,
175 EtFileHeaderFields *fields)
176 {
177 EtFileAreaPrivate *priv;
178
179 g_return_if_fail (ET_FILE_AREA (self));
180 g_return_if_fail (fields != NULL);
181
182 priv = et_file_area_get_instance_private (self);
183
184 gtk_label_set_text (GTK_LABEL (priv->file_label), fields->description);
185 gtk_label_set_text (GTK_LABEL (priv->version_label),
186 fields->version_label);
187 gtk_label_set_text (GTK_LABEL (priv->version_value_label),
188 fields->version);
189 gtk_label_set_text (GTK_LABEL (priv->bitrate_value_label),
190 fields->bitrate);
191 gtk_label_set_text (GTK_LABEL (priv->samplerate_value_label),
192 fields->samplerate);
193 gtk_label_set_text (GTK_LABEL (priv->mode_label), fields->mode_label);
194 gtk_label_set_text (GTK_LABEL (priv->mode_value_label), fields->mode);
195 gtk_label_set_text (GTK_LABEL (priv->size_value_label), fields->size);
196 gtk_label_set_text (GTK_LABEL (priv->duration_value_label),
197 fields->duration);
198 }
199
200 /* Toggle visibility of the small status icon if filename is read-only or not
201 * found. Show the position of the current file in the list, by using the index
202 * and list length. */
203 void
et_file_area_set_file_fields(EtFileArea * self,const ET_File * ETFile)204 et_file_area_set_file_fields (EtFileArea *self,
205 const ET_File *ETFile)
206 {
207 EtFileAreaPrivate *priv;
208 GFile *file;
209 gchar *text;
210 const gchar *cur_filename;
211 gchar *basename_utf8;
212 gchar *pos;
213 GFileInfo *info;
214 GError *error = NULL;
215
216 g_return_if_fail (ET_FILE_AREA (self));
217 g_return_if_fail (ETFile != NULL);
218
219 priv = et_file_area_get_instance_private (self);
220
221 cur_filename = ((File_Name *)((GList *)ETFile->FileNameCur)->data)->value;
222
223 file = g_file_new_for_path (cur_filename);
224
225 info = g_file_query_info (file, G_FILE_ATTRIBUTE_ACCESS_CAN_READ ","
226 G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE,
227 G_FILE_QUERY_INFO_NONE, NULL, &error);
228
229 /* Show/hide 'AccessStatusIcon' */
230 if (!info)
231 {
232 if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
233 {
234 /* No such file or directory. */
235 GIcon *emblem_icon;
236
237 emblem_icon = g_themed_icon_new ("emblem-unreadable");
238
239 gtk_entry_set_icon_from_gicon (GTK_ENTRY (priv->name_entry),
240 GTK_ENTRY_ICON_SECONDARY,
241 emblem_icon);
242 gtk_entry_set_icon_tooltip_text (GTK_ENTRY (priv->name_entry),
243 GTK_ENTRY_ICON_SECONDARY,
244 _("File not found"));
245 g_object_unref (emblem_icon);
246 }
247 else
248 {
249 Log_Print (LOG_ERROR, _("Cannot query file information ‘%s’"),
250 error->message);
251 g_error_free (error);
252 g_object_unref (file);
253 return;
254 }
255 }
256 else
257 {
258 gboolean readable, writable;
259
260 readable = g_file_info_get_attribute_boolean (info,
261 G_FILE_ATTRIBUTE_ACCESS_CAN_READ);
262 writable = g_file_info_get_attribute_boolean (info,
263 G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE);
264
265 if (readable && writable)
266 {
267 /* User has all necessary permissions. */
268 gtk_entry_set_icon_from_gicon (GTK_ENTRY (priv->name_entry),
269 GTK_ENTRY_ICON_SECONDARY, NULL);
270 }
271 else if (!writable)
272 {
273 /* Read only file or permission denied. */
274 GIcon *emblem_icon;
275
276 emblem_icon = g_themed_icon_new ("emblem-readonly");
277
278 gtk_entry_set_icon_from_gicon (GTK_ENTRY (priv->name_entry),
279 GTK_ENTRY_ICON_SECONDARY,
280 emblem_icon);
281 gtk_entry_set_icon_tooltip_text (GTK_ENTRY (priv->name_entry),
282 GTK_ENTRY_ICON_SECONDARY,
283 _("Read-only file"));
284 g_object_unref (emblem_icon);
285
286 }
287 else
288 {
289 /* Otherwise unreadable. */
290 GIcon *emblem_icon;
291
292 emblem_icon = g_themed_icon_new ("emblem-unreadable");
293
294 gtk_entry_set_icon_from_gicon (GTK_ENTRY (priv->name_entry),
295 GTK_ENTRY_ICON_SECONDARY,
296 emblem_icon);
297 gtk_entry_set_icon_tooltip_text (GTK_ENTRY (priv->name_entry),
298 GTK_ENTRY_ICON_SECONDARY,
299 _("File not found"));
300 g_object_unref (emblem_icon);
301 }
302
303 g_object_unref (info);
304 }
305
306
307 /* Set new filename into name_entry. This matches the GFile edit name. */
308 basename_utf8 = g_filename_display_basename (((File_Name *)((GList *)ETFile->FileNameNew)->data)->value);
309
310 /* Remove the extension. */
311 if ((pos = strrchr (basename_utf8, '.')) != NULL)
312 {
313 *pos = 0;
314 }
315
316 gtk_entry_set_text (GTK_ENTRY (priv->name_entry), basename_utf8);
317 g_free (basename_utf8);
318
319 /* Show position of current file in list */
320 text = g_strdup_printf ("%u/%u:", ETFile->IndexKey,
321 ETCore->ETFileDisplayedList_Length);
322 gtk_label_set_text (GTK_LABEL (priv->index_label), text);
323 g_object_unref (file);
324 g_free (text);
325 }
326
327 const gchar *
et_file_area_get_filename(EtFileArea * self)328 et_file_area_get_filename (EtFileArea *self)
329 {
330 EtFileAreaPrivate *priv;
331
332 g_return_val_if_fail (ET_FILE_AREA (self), NULL);
333
334 priv = et_file_area_get_instance_private (self);
335
336 return gtk_entry_get_text (GTK_ENTRY (priv->name_entry));
337 }
338