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 "application_window.h"
22
23 #include <glib/gi18n.h>
24
25 #include "browser.h"
26 #include "cddb_dialog.h"
27 #include "charset.h"
28 #include "easytag.h"
29 #include "file_area.h"
30 #include "file_list.h"
31 #ifdef ENABLE_FLAC
32 #include "flac_header.h"
33 #endif
34 #include "load_files_dialog.h"
35 #include "log.h"
36 #include "misc.h"
37 #ifdef ENABLE_MP4
38 #include "mp4_header.h"
39 #endif
40 #include "mpeg_header.h"
41 #include "monkeyaudio_header.h"
42 #include "musepack_header.h"
43 #ifdef ENABLE_OGG
44 #include "ogg_header.h"
45 #endif
46 #ifdef ENABLE_OPUS
47 #include "opus_header.h"
48 #endif
49 #include "picture.h"
50 #include "playlist_dialog.h"
51 #include "preferences_dialog.h"
52 #include "progress_bar.h"
53 #include "search_dialog.h"
54 #include "scan.h"
55 #include "scan_dialog.h"
56 #include "setting.h"
57 #include "status_bar.h"
58 #include "tag_area.h"
59 #ifdef ENABLE_WAVPACK
60 #include "wavpack_header.h"
61 #endif
62
63 typedef struct
64 {
65 GtkWidget *browser;
66
67 GtkWidget *file_area;
68 GtkWidget *log_area;
69 GtkWidget *tag_area;
70 GtkWidget *progress_bar;
71 GtkWidget *status_bar;
72
73 GtkWidget *cddb_dialog;
74 GtkWidget *load_files_dialog;
75 GtkWidget *playlist_dialog;
76 GtkWidget *preferences_dialog;
77 GtkWidget *scan_dialog;
78 GtkWidget *search_dialog;
79
80 GtkWidget *hpaned;
81 GtkWidget *vpaned;
82
83 GdkCursor *cursor;
84
85 gboolean is_maximized;
86 gint height;
87 gint width;
88 gint paned_position;
89 } EtApplicationWindowPrivate;
90
G_DEFINE_TYPE_WITH_PRIVATE(EtApplicationWindow,et_application_window,GTK_TYPE_APPLICATION_WINDOW)91 G_DEFINE_TYPE_WITH_PRIVATE (EtApplicationWindow, et_application_window, GTK_TYPE_APPLICATION_WINDOW)
92
93 /* Used to force to hide the msgbox when deleting file */
94 static gboolean SF_HideMsgbox_Delete_File;
95 /* To remember which button was pressed when deleting file */
96 static gint SF_ButtonPressed_Delete_File;
97
98 static gboolean
99 on_main_window_delete_event (GtkWidget *window,
100 GdkEvent *event,
101 gpointer user_data)
102 {
103 et_application_window_quit (ET_APPLICATION_WINDOW (window));
104
105 /* Handled the event, so stop propagation. */
106 return GDK_EVENT_STOP;
107 }
108
109 static void
save_state(EtApplicationWindow * self)110 save_state (EtApplicationWindow *self)
111 {
112 EtApplicationWindowPrivate *priv;
113 gchar *path;
114 GKeyFile *keyfile;
115 gchar *buffer;
116 gsize length;
117 GError *error = NULL;
118
119 priv = et_application_window_get_instance_private (self);
120 keyfile = g_key_file_new ();
121 path = g_build_filename (g_get_user_cache_dir (), PACKAGE_TARNAME,
122 "state", NULL);
123
124 /* Try to preserve comments by loading an existing keyfile. */
125 if (!g_key_file_load_from_file (keyfile, path, G_KEY_FILE_KEEP_COMMENTS,
126 &error))
127 {
128 g_debug ("Error loading window state during saving: %s",
129 error->message);
130 g_clear_error (&error);
131 }
132
133 g_key_file_set_integer (keyfile, "EtApplicationWindow", "width",
134 priv->width);
135 g_key_file_set_integer (keyfile, "EtApplicationWindow", "height",
136 priv->height);
137 g_key_file_set_boolean (keyfile, "EtApplicationWindow", "is_maximized",
138 priv->is_maximized);
139
140 if (priv->is_maximized)
141 {
142 gint width;
143
144 /* Calculate the paned position based on the unmaximized window state,
145 * as that is the state at which the window starts. */
146 gtk_window_get_size (GTK_WINDOW (self), &width, NULL);
147 priv->paned_position -= (width - priv->width);
148 }
149
150 g_key_file_set_integer (keyfile, "EtApplicationWindow", "paned_position",
151 priv->paned_position);
152
153 /* TODO; Use g_key_file_save_to_file() in GLib 2.40. */
154 buffer = g_key_file_to_data (keyfile, &length, NULL);
155
156 if (!g_file_set_contents (path, buffer, length, &error))
157 {
158 g_warning ("Error saving window state: %s", error->message);
159 g_error_free (error);
160 }
161
162 g_free (buffer);
163 g_free (path);
164 g_key_file_free (keyfile);
165 }
166
167 static void
restore_state(EtApplicationWindow * self)168 restore_state (EtApplicationWindow *self)
169 {
170 EtApplicationWindowPrivate *priv;
171 GtkWindow *window;
172 GKeyFile *keyfile;
173 gchar *path;
174 GError *error = NULL;
175
176 priv = et_application_window_get_instance_private (self);
177 window = GTK_WINDOW (self);
178
179 keyfile = g_key_file_new ();
180 path = g_build_filename (g_get_user_cache_dir (), PACKAGE_TARNAME,
181 "state", NULL);
182
183 if (!g_key_file_load_from_file (keyfile, path, G_KEY_FILE_KEEP_COMMENTS,
184 &error))
185 {
186 g_debug ("Error loading window state: %s", error->message);
187 g_error_free (error);
188 g_key_file_free (keyfile);
189 g_free (path);
190 return;
191 }
192
193 g_free (path);
194
195 /* Ignore errors, as the default values are fine. */
196 priv->width = g_key_file_get_integer (keyfile, "EtApplicationWindow",
197 "width", NULL);
198 priv->height = g_key_file_get_integer (keyfile, "EtApplicationWindow",
199 "height", NULL);
200 priv->is_maximized = g_key_file_get_boolean (keyfile,
201 "EtApplicationWindow",
202 "is_maximized", NULL);
203 priv->paned_position = g_key_file_get_integer (keyfile,
204 "EtApplicationWindow",
205 "paned_position", NULL);
206
207 gtk_window_set_default_size (window, priv->width, priv->height);
208
209 /* Only set the unmaximized position, as the maximized position should only
210 * be set after the window manager has maximized the window. */
211 gtk_paned_set_position (GTK_PANED (priv->hpaned), priv->paned_position);
212
213 if (priv->is_maximized)
214 {
215 gtk_window_maximize (window);
216 }
217
218 g_key_file_free (keyfile);
219 }
220
221 static gboolean
on_configure_event(GtkWidget * window,GdkEvent * event,gpointer user_data)222 on_configure_event (GtkWidget *window,
223 GdkEvent *event,
224 gpointer user_data)
225 {
226 EtApplicationWindow *self;
227 EtApplicationWindowPrivate *priv;
228 GdkEventConfigure *configure_event;
229
230 self = ET_APPLICATION_WINDOW (window);
231 priv = et_application_window_get_instance_private (self);
232 configure_event = (GdkEventConfigure *)event;
233
234 if (!priv->is_maximized)
235 {
236 priv->width = configure_event->width;
237 priv->height = configure_event->height;
238 }
239
240 return GDK_EVENT_PROPAGATE;
241 }
242
243 static gboolean
on_window_state_event(GtkWidget * window,GdkEvent * event,gpointer user_data)244 on_window_state_event (GtkWidget *window,
245 GdkEvent *event,
246 gpointer user_data)
247 {
248 EtApplicationWindow *self;
249 EtApplicationWindowPrivate *priv;
250 GdkEventWindowState *state_event;
251
252 self = ET_APPLICATION_WINDOW (window);
253 priv = et_application_window_get_instance_private (self);
254 state_event = (GdkEventWindowState *)event;
255
256 if (state_event->changed_mask & GDK_WINDOW_STATE_MAXIMIZED)
257 {
258 priv->is_maximized = (state_event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
259 }
260
261 return GDK_EVENT_PROPAGATE;
262 }
263
264 static void
on_paned_notify_position(EtApplicationWindow * self,GParamSpec * pspec,gpointer user_data)265 on_paned_notify_position (EtApplicationWindow *self,
266 GParamSpec *pspec,
267 gpointer user_data)
268 {
269 EtApplicationWindowPrivate *priv;
270
271 priv = et_application_window_get_instance_private (self);
272
273 priv->paned_position = gtk_paned_get_position (GTK_PANED (priv->hpaned));
274 }
275
276 File_Tag *
et_application_window_tag_area_create_file_tag(EtApplicationWindow * self)277 et_application_window_tag_area_create_file_tag (EtApplicationWindow *self)
278 {
279 EtApplicationWindowPrivate *priv;
280
281 g_return_val_if_fail (ET_APPLICATION_WINDOW (self), NULL);
282
283 priv = et_application_window_get_instance_private (self);
284
285 return et_tag_area_create_file_tag (ET_TAG_AREA (priv->tag_area));
286 }
287
288 gboolean
et_application_window_tag_area_display_et_file(EtApplicationWindow * self,const ET_File * ETFile)289 et_application_window_tag_area_display_et_file (EtApplicationWindow *self,
290 const ET_File *ETFile)
291 {
292 EtApplicationWindowPrivate *priv;
293
294 g_return_val_if_fail (ET_APPLICATION_WINDOW (self), FALSE);
295
296 priv = et_application_window_get_instance_private (self);
297
298 return et_tag_area_display_et_file (ET_TAG_AREA (priv->tag_area), ETFile);
299 }
300
301 /* Clear the entries of tag area. */
302 void
et_application_window_tag_area_clear(EtApplicationWindow * self)303 et_application_window_tag_area_clear (EtApplicationWindow *self)
304 {
305 EtApplicationWindowPrivate *priv;
306
307 g_return_if_fail (ET_APPLICATION_WINDOW (self));
308
309 priv = et_application_window_get_instance_private (self);
310
311 et_tag_area_clear (ET_TAG_AREA (priv->tag_area));
312 }
313
314 static void
et_application_window_show_cddb_dialog(EtApplicationWindow * self)315 et_application_window_show_cddb_dialog (EtApplicationWindow *self)
316 {
317 EtApplicationWindowPrivate *priv;
318
319 priv = et_application_window_get_instance_private (self);
320
321 if (priv->cddb_dialog)
322 {
323 gtk_widget_show (priv->cddb_dialog);
324 }
325 else
326 {
327 priv->cddb_dialog = GTK_WIDGET (et_cddb_dialog_new ());
328 gtk_widget_show_all (priv->cddb_dialog);
329 }
330 }
331
332 /*
333 * Delete the file ETFile
334 */
335 static gint
delete_file(ET_File * ETFile,gboolean multiple_files,GError ** error)336 delete_file (ET_File *ETFile, gboolean multiple_files, GError **error)
337 {
338 GtkWidget *msgdialog;
339 GtkWidget *msgdialog_check_button = NULL;
340 const gchar *cur_filename;
341 const gchar *cur_filename_utf8;
342 gchar *basename_utf8;
343 gint response;
344 gint stop_loop;
345
346 g_return_val_if_fail (ETFile != NULL, FALSE);
347 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
348
349 /* Filename of the file to delete. */
350 cur_filename = ((File_Name *)(ETFile->FileNameCur)->data)->value;
351 cur_filename_utf8 = ((File_Name *)(ETFile->FileNameCur)->data)->value_utf8;
352 basename_utf8 = g_path_get_basename (cur_filename_utf8);
353
354 /*
355 * Remove the file
356 */
357 if (g_settings_get_boolean (MainSettings, "confirm-delete-file")
358 && !SF_HideMsgbox_Delete_File)
359 {
360 if (multiple_files)
361 {
362 GtkWidget *message_area;
363 msgdialog = gtk_message_dialog_new(GTK_WINDOW(MainWindow),
364 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
365 GTK_MESSAGE_QUESTION,
366 GTK_BUTTONS_NONE,
367 _("Do you really want to delete the file ‘%s’?"),
368 basename_utf8);
369 message_area = gtk_message_dialog_get_message_area(GTK_MESSAGE_DIALOG(msgdialog));
370 msgdialog_check_button = gtk_check_button_new_with_label(_("Repeat action for the remaining files"));
371 gtk_container_add(GTK_CONTAINER(message_area),msgdialog_check_button);
372 gtk_dialog_add_buttons (GTK_DIALOG (msgdialog), _("_Skip"),
373 GTK_RESPONSE_NO, _("_Cancel"),
374 GTK_RESPONSE_CANCEL, _("_Delete"),
375 GTK_RESPONSE_YES, NULL);
376 gtk_window_set_title(GTK_WINDOW(msgdialog),_("Delete File"));
377 //GTK_TOGGLE_BUTTON(msgbox_check_button)->active = TRUE; // Checked by default
378 }else
379 {
380 msgdialog = gtk_message_dialog_new(GTK_WINDOW(MainWindow),
381 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
382 GTK_MESSAGE_QUESTION,
383 GTK_BUTTONS_NONE,
384 _("Do you really want to delete the file ‘%s’?"),
385 basename_utf8);
386 gtk_window_set_title(GTK_WINDOW(msgdialog),_("Delete File"));
387 gtk_dialog_add_buttons (GTK_DIALOG (msgdialog), _("_Cancel"),
388 GTK_RESPONSE_NO, _("_Delete"),
389 GTK_RESPONSE_YES, NULL);
390 }
391 gtk_dialog_set_default_response (GTK_DIALOG (msgdialog),
392 GTK_RESPONSE_YES);
393 SF_ButtonPressed_Delete_File = response = gtk_dialog_run(GTK_DIALOG(msgdialog));
394 if (msgdialog_check_button && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(msgdialog_check_button)))
395 SF_HideMsgbox_Delete_File = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(msgdialog_check_button));
396 gtk_widget_destroy(msgdialog);
397 }else
398 {
399 if (SF_HideMsgbox_Delete_File)
400 response = SF_ButtonPressed_Delete_File;
401 else
402 response = GTK_RESPONSE_YES;
403 }
404
405 switch (response)
406 {
407 case GTK_RESPONSE_YES:
408 {
409 GFile *cur_file = g_file_new_for_path (cur_filename);
410
411 if (g_file_delete (cur_file, NULL, error))
412 {
413 gchar *msg = g_strdup_printf(_("File ‘%s’ deleted"), basename_utf8);
414 et_application_window_status_bar_message (ET_APPLICATION_WINDOW (MainWindow),
415 msg, FALSE);
416 g_free(msg);
417 g_free(basename_utf8);
418 g_object_unref (cur_file);
419 g_assert (error == NULL || *error == NULL);
420 return 1;
421 }
422
423 /* Error in deleting file. */
424 g_assert (error == NULL || *error != NULL);
425 break;
426 }
427 case GTK_RESPONSE_NO:
428 break;
429 case GTK_RESPONSE_CANCEL:
430 case GTK_RESPONSE_DELETE_EVENT:
431 stop_loop = -1;
432 g_free(basename_utf8);
433 return stop_loop;
434 break;
435 default:
436 g_assert_not_reached ();
437 break;
438 }
439
440 g_free(basename_utf8);
441 return 0;
442 }
443
444 static void
on_open_with(GSimpleAction * action,GVariant * variant,gpointer user_data)445 on_open_with (GSimpleAction *action,
446 GVariant *variant,
447 gpointer user_data)
448 {
449 EtApplicationWindowPrivate *priv;
450 EtApplicationWindow *self = ET_APPLICATION_WINDOW (user_data);
451
452 priv = et_application_window_get_instance_private (self);
453
454 et_browser_show_open_files_with_dialog (ET_BROWSER (priv->browser));
455 }
456
457 static void
on_run_player(GSimpleAction * action,GVariant * variant,gpointer user_data)458 on_run_player (GSimpleAction *action,
459 GVariant *variant,
460 gpointer user_data)
461 {
462 EtApplicationWindowPrivate *priv;
463 EtApplicationWindow *self = ET_APPLICATION_WINDOW (user_data);
464
465 priv = et_application_window_get_instance_private (self);
466
467 et_browser_run_player_for_selection (ET_BROWSER (priv->browser));
468 }
469
470 static void
on_invert_selection(GSimpleAction * action,GVariant * variant,gpointer user_data)471 on_invert_selection (GSimpleAction *action,
472 GVariant *variant,
473 gpointer user_data)
474 {
475 EtApplicationWindowPrivate *priv;
476 EtApplicationWindow *self = ET_APPLICATION_WINDOW (user_data);
477
478 priv = et_application_window_get_instance_private (self);
479
480 et_application_window_update_et_file_from_ui (self);
481
482 et_browser_invert_selection (ET_BROWSER (priv->browser));
483 et_application_window_update_actions (self);
484 }
485
486 static void
on_delete(GSimpleAction * action,GVariant * variant,gpointer user_data)487 on_delete (GSimpleAction *action,
488 GVariant *variant,
489 gpointer user_data)
490 {
491 EtApplicationWindow *self;
492 EtApplicationWindowPrivate *priv;
493 GList *selfilelist;
494 GList *rowreflist = NULL;
495 GList *l;
496 gint progress_bar_index;
497 gint saving_answer;
498 gint nb_files_to_delete;
499 gint nb_files_deleted = 0;
500 gchar *msg;
501 gchar progress_bar_text[30];
502 double fraction;
503 GtkTreeModel *treemodel;
504 GtkTreeRowReference *rowref;
505 GtkTreeSelection *selection;
506 GError *error = NULL;
507
508 g_return_if_fail (ETCore->ETFileDisplayedList != NULL);
509
510 self = ET_APPLICATION_WINDOW (user_data);
511 priv = et_application_window_get_instance_private (self);
512
513 et_application_window_update_et_file_from_ui (self);
514
515 /* Number of files to save */
516 selection = et_application_window_browser_get_selection (self);
517 nb_files_to_delete = gtk_tree_selection_count_selected_rows (selection);
518
519 /* Initialize status bar */
520 et_application_window_progress_set_fraction (self, 0.0);
521 progress_bar_index = 0;
522 g_snprintf(progress_bar_text, 30, "%d/%d", progress_bar_index, nb_files_to_delete);
523 et_application_window_progress_set_text (self, progress_bar_text);
524
525 /* Set to unsensitive all command buttons (except Quit button) */
526 et_application_window_disable_command_actions (self);
527 et_application_window_browser_set_sensitive (self, FALSE);
528 et_application_window_tag_area_set_sensitive (self, FALSE);
529 et_application_window_file_area_set_sensitive (self, FALSE);
530
531 /* Show msgbox (if needed) to ask confirmation */
532 SF_HideMsgbox_Delete_File = 0;
533
534 selfilelist = gtk_tree_selection_get_selected_rows (selection, &treemodel);
535
536 for (l = selfilelist; l != NULL; l = g_list_next (l))
537 {
538 rowref = gtk_tree_row_reference_new (treemodel, l->data);
539 rowreflist = g_list_prepend (rowreflist, rowref);
540 }
541
542 g_list_free_full (selfilelist, (GDestroyNotify)gtk_tree_path_free);
543 rowreflist = g_list_reverse (rowreflist);
544
545 for (l = rowreflist; l != NULL; l = g_list_next (l))
546 {
547 GtkTreePath *path;
548 ET_File *ETFile;
549
550 path = gtk_tree_row_reference_get_path (l->data);
551 ETFile = et_browser_get_et_file_from_path (ET_BROWSER (priv->browser),
552 path);
553 gtk_tree_path_free (path);
554
555 et_application_window_display_et_file (self, ETFile);
556 et_application_window_browser_select_file_by_et_file (self, ETFile,
557 FALSE);
558 fraction = (++progress_bar_index) / (double) nb_files_to_delete;
559 et_application_window_progress_set_fraction (self, fraction);
560 g_snprintf (progress_bar_text, 30, "%d/%d", progress_bar_index,
561 nb_files_to_delete);
562 et_application_window_progress_set_text (self, progress_bar_text);
563 /* FIXME: Needed to refresh status bar */
564 while (gtk_events_pending ())
565 {
566 gtk_main_iteration ();
567 }
568
569 saving_answer = delete_file (ETFile,
570 nb_files_to_delete > 1 ? TRUE : FALSE,
571 &error);
572
573 switch (saving_answer)
574 {
575 case 1:
576 nb_files_deleted += saving_answer;
577 /* Remove file in the browser (corresponding line in the
578 * clist). */
579 et_browser_remove_file (ET_BROWSER (priv->browser), ETFile);
580 /* Remove file from file list. */
581 ET_Remove_File_From_File_List (ETFile);
582 break;
583 case 0:
584 /* Distinguish between the file being skipped, and there being
585 * an error during deletion. */
586 if (error)
587 {
588 Log_Print (LOG_ERROR, _("Cannot delete file ‘%s’"),
589 error->message);
590 g_clear_error (&error);
591 }
592 break;
593 case -1:
594 /* Stop deleting files + reinit progress bar. */
595 et_application_window_progress_set_fraction (self, 0.0);
596 /* To update state of command buttons. */
597 et_application_window_update_actions (self);
598 et_application_window_browser_set_sensitive (self, TRUE);
599 et_application_window_tag_area_set_sensitive (self, TRUE);
600 et_application_window_file_area_set_sensitive (self, TRUE);
601
602 return; /*We stop all actions. */
603 default:
604 g_assert_not_reached ();
605 break;
606 }
607 }
608
609 g_list_free_full (rowreflist, (GDestroyNotify)gtk_tree_row_reference_free);
610
611 if (nb_files_deleted < nb_files_to_delete)
612 msg = g_strdup (_("Some files were not deleted"));
613 else
614 msg = g_strdup (_("All files have been deleted"));
615
616 /* It's important to displayed the new item, as it'll check the changes in et_browser_toggle_display_mode. */
617 if (ETCore->ETFileDisplayed)
618 {
619 et_application_window_display_et_file (self, ETCore->ETFileDisplayed);
620 }
621 /*else if (ET_Displayed_File_List_Current())
622 ET_Display_File_Data_To_UI((ET_File *)ET_Displayed_File_List_Current()->data);*/
623
624 /* Load list... */
625 et_browser_load_file_list (ET_BROWSER (priv->browser),
626 ETCore->ETFileDisplayedList, NULL);
627 /* Rebuild the list... */
628 /*et_browser_toggle_display_mode (ET_BROWSER (priv->browser));*/
629
630 /* To update state of command buttons */
631 et_application_window_update_actions (self);
632 et_application_window_browser_set_sensitive (self, TRUE);
633 et_application_window_tag_area_set_sensitive (self, TRUE);
634 et_application_window_file_area_set_sensitive (self, TRUE);
635
636 et_application_window_progress_set_text (self, "");
637 et_application_window_progress_set_fraction (self, 0.0);
638 et_application_window_status_bar_message (self, msg, TRUE);
639 g_free (msg);
640
641 return;
642 }
643
644 static void
on_undo_file_changes(GSimpleAction * action,GVariant * variant,gpointer user_data)645 on_undo_file_changes (GSimpleAction *action,
646 GVariant *variant,
647 gpointer user_data)
648 {
649 EtApplicationWindow *self;
650 EtApplicationWindowPrivate *priv;
651 GList *selfilelist = NULL;
652 GList *l;
653 gboolean state = FALSE;
654 ET_File *etfile;
655 GtkTreeSelection *selection;
656
657 g_return_if_fail (ETCore->ETFileDisplayedList != NULL);
658
659 self = ET_APPLICATION_WINDOW (user_data);
660 priv = et_application_window_get_instance_private (self);
661
662 et_application_window_update_et_file_from_ui (self);
663
664 selection = et_application_window_browser_get_selection (self);
665 selfilelist = gtk_tree_selection_get_selected_rows(selection, NULL);
666
667 for (l = selfilelist; l != NULL; l = g_list_next (l))
668 {
669 etfile = et_browser_get_et_file_from_path (ET_BROWSER (priv->browser),
670 l->data);
671 state |= ET_Undo_File_Data(etfile);
672 }
673
674 g_list_free_full (selfilelist, (GDestroyNotify)gtk_tree_path_free);
675
676 /* Refresh the whole list (faster than file by file) to show changes. */
677 et_application_window_browser_refresh_list (self);
678
679 /* Display the current file */
680 et_application_window_display_et_file (self, ETCore->ETFileDisplayed);
681 et_application_window_update_actions (self);
682
683 //ET_Debug_Print_File_List(ETCore->ETFileList,__FILE__,__LINE__,__FUNCTION__);
684 }
685
686 static void
on_redo_file_changes(GSimpleAction * action,GVariant * variant,gpointer user_data)687 on_redo_file_changes (GSimpleAction *action,
688 GVariant *variant,
689 gpointer user_data)
690 {
691 EtApplicationWindow *self;
692 EtApplicationWindowPrivate *priv;
693 GList *selfilelist = NULL;
694 GList *l;
695 gboolean state = FALSE;
696 ET_File *etfile;
697 GtkTreeSelection *selection;
698
699 g_return_if_fail (ETCore->ETFileDisplayedList != NULL);
700
701 self = ET_APPLICATION_WINDOW (user_data);
702 priv = et_application_window_get_instance_private (self);
703
704 et_application_window_update_et_file_from_ui (self);
705
706 selection = et_application_window_browser_get_selection (ET_APPLICATION_WINDOW (user_data));
707 selfilelist = gtk_tree_selection_get_selected_rows(selection, NULL);
708
709 for (l = selfilelist; l != NULL; l = g_list_next (l))
710 {
711 etfile = et_browser_get_et_file_from_path (ET_BROWSER (priv->browser),
712 l->data);
713 state |= ET_Redo_File_Data(etfile);
714 }
715
716 g_list_free_full (selfilelist, (GDestroyNotify)gtk_tree_path_free);
717
718 /* Refresh the whole list (faster than file by file) to show changes. */
719 et_application_window_browser_refresh_list (ET_APPLICATION_WINDOW (user_data));
720
721 /* Display the current file */
722 et_application_window_display_et_file (self, ETCore->ETFileDisplayed);
723 et_application_window_update_actions (self);
724 }
725
726 static void
on_save(GSimpleAction * action,GVariant * variant,gpointer user_data)727 on_save (GSimpleAction *action,
728 GVariant *variant,
729 gpointer user_data)
730 {
731 Action_Save_Selected_Files ();
732 }
733
734 static void
on_save_force(GSimpleAction * action,GVariant * variant,gpointer user_data)735 on_save_force (GSimpleAction *action,
736 GVariant *variant,
737 gpointer user_data)
738 {
739 Action_Force_Saving_Selected_Files ();
740 }
741
742 static void
on_find(GSimpleAction * action,GVariant * variant,gpointer user_data)743 on_find (GSimpleAction *action,
744 GVariant *variant,
745 gpointer user_data)
746 {
747 EtApplicationWindow *self;
748 EtApplicationWindowPrivate *priv;
749
750 self = ET_APPLICATION_WINDOW (user_data);
751 priv = et_application_window_get_instance_private (self);
752
753 if (priv->search_dialog)
754 {
755 gtk_widget_show (priv->search_dialog);
756 }
757 else
758 {
759 priv->search_dialog = GTK_WIDGET (et_search_dialog_new (GTK_WINDOW (self)));
760 gtk_widget_show_all (priv->search_dialog);
761 }
762 }
763
764 static void
on_select_all(GSimpleAction * action,GVariant * variant,gpointer user_data)765 on_select_all (GSimpleAction *action,
766 GVariant *variant,
767 gpointer user_data)
768 {
769 EtApplicationWindow *self;
770 EtApplicationWindowPrivate *priv;
771 GtkWidget *focused;
772
773 self = ET_APPLICATION_WINDOW (user_data);
774 priv = et_application_window_get_instance_private (self);
775
776 /* Use the currently-focused widget and "select all" as appropriate.
777 * https://bugzilla.gnome.org/show_bug.cgi?id=697515 */
778 focused = gtk_window_get_focus (GTK_WINDOW (user_data));
779
780 if (GTK_IS_EDITABLE (focused))
781 {
782 gtk_editable_select_region (GTK_EDITABLE (focused), 0, -1);
783 }
784 else if (!et_tag_area_select_all_if_focused (ET_TAG_AREA (priv->tag_area),
785 focused))
786 /* Assume that other widgets should select all in the file view. */
787 {
788 et_application_window_update_et_file_from_ui (self);
789
790 et_browser_select_all (ET_BROWSER (priv->browser));
791 et_application_window_update_actions (self);
792 }
793 }
794
795 static void
on_unselect_all(GSimpleAction * action,GVariant * variant,gpointer user_data)796 on_unselect_all (GSimpleAction *action,
797 GVariant *variant,
798 gpointer user_data)
799 {
800 EtApplicationWindow *self;
801 EtApplicationWindowPrivate *priv;
802 GtkWidget *focused;
803
804 self = ET_APPLICATION_WINDOW (user_data);
805 priv = et_application_window_get_instance_private (self);
806
807 focused = gtk_window_get_focus (GTK_WINDOW (user_data));
808
809 if (GTK_IS_EDITABLE (focused))
810 {
811 GtkEditable *editable;
812 gint pos;
813
814 editable = GTK_EDITABLE (focused);
815 pos = gtk_editable_get_position (editable);
816 gtk_editable_select_region (editable, 0, 0);
817 gtk_editable_set_position (editable, pos);
818 }
819 else if (!et_tag_area_unselect_all_if_focused (ET_TAG_AREA (priv->tag_area),
820 focused))
821 /* Assume that other widgets should unselect all in the file view. */
822 {
823 et_application_window_update_et_file_from_ui (self);
824
825 et_browser_unselect_all (ET_BROWSER (priv->browser));
826
827 ETCore->ETFileDisplayed = NULL;
828 }
829 }
830
831 static void
on_undo_last_changes(GSimpleAction * action,GVariant * variant,gpointer user_data)832 on_undo_last_changes (GSimpleAction *action,
833 GVariant *variant,
834 gpointer user_data)
835 {
836 EtApplicationWindow *self;
837 ET_File *ETFile;
838
839 self = ET_APPLICATION_WINDOW (user_data);
840
841 g_return_if_fail (ETCore->ETFileList != NULL);
842
843 et_application_window_update_et_file_from_ui (self);
844
845 ETFile = ET_Undo_History_File_Data ();
846
847 if (ETFile)
848 {
849 et_application_window_display_et_file (self, ETFile);
850 et_application_window_browser_select_file_by_et_file (self, ETFile,
851 TRUE);
852 et_application_window_browser_refresh_file_in_list (self, ETFile);
853 }
854
855 et_application_window_update_actions (self);
856 }
857
858 static void
on_redo_last_changes(GSimpleAction * action,GVariant * variant,gpointer user_data)859 on_redo_last_changes (GSimpleAction *action,
860 GVariant *variant,
861 gpointer user_data)
862 {
863 EtApplicationWindow *self;
864 ET_File *ETFile;
865
866 self = ET_APPLICATION_WINDOW (user_data);
867
868 g_return_if_fail (ETCore->ETFileDisplayedList != NULL);
869
870 et_application_window_update_et_file_from_ui (self);
871
872 ETFile = ET_Redo_History_File_Data ();
873
874 if (ETFile)
875 {
876 et_application_window_display_et_file (self, ETFile);
877 et_application_window_browser_select_file_by_et_file (self, ETFile,
878 TRUE);
879 et_application_window_browser_refresh_file_in_list (self, ETFile);
880 }
881
882 et_application_window_update_actions (self);
883 }
884
885 static void
on_remove_tags(GSimpleAction * action,GVariant * variant,gpointer user_data)886 on_remove_tags (GSimpleAction *action,
887 GVariant *variant,
888 gpointer user_data)
889 {
890 EtApplicationWindow *self;
891 EtApplicationWindowPrivate *priv;
892 GList *selfilelist = NULL;
893 GList *l;
894 ET_File *etfile;
895 File_Tag *FileTag;
896 gint progress_bar_index;
897 gint selectcount;
898 double fraction;
899 GtkTreeSelection *selection;
900
901 g_return_if_fail (ETCore->ETFileDisplayedList != NULL);
902
903 self = ET_APPLICATION_WINDOW (user_data);
904 priv = et_application_window_get_instance_private (self);
905
906 et_application_window_update_et_file_from_ui (self);
907
908 /* Initialize status bar */
909 et_application_window_progress_set_fraction (self, 0.0);
910 selection = et_application_window_browser_get_selection (self);
911 selectcount = gtk_tree_selection_count_selected_rows (selection);
912 progress_bar_index = 0;
913
914 selfilelist = gtk_tree_selection_get_selected_rows (selection, NULL);
915
916 for (l = selfilelist; l != NULL; l = g_list_next (l))
917 {
918 etfile = et_browser_get_et_file_from_path (ET_BROWSER (priv->browser),
919 l->data);
920 FileTag = et_file_tag_new ();
921 ET_Manage_Changes_Of_File_Data (etfile, NULL, FileTag);
922
923 fraction = (++progress_bar_index) / (double) selectcount;
924 et_application_window_progress_set_fraction (self, fraction);
925 /* Needed to refresh status bar */
926 while (gtk_events_pending ())
927 {
928 gtk_main_iteration ();
929 }
930 }
931
932 g_list_free_full (selfilelist, (GDestroyNotify)gtk_tree_path_free);
933
934 /* Refresh the whole list (faster than file by file) to show changes. */
935 et_application_window_browser_refresh_list (self);
936
937 /* Display the current file */
938 et_application_window_display_et_file (self, ETCore->ETFileDisplayed);
939 et_application_window_update_actions (self);
940
941 et_application_window_progress_set_fraction (self, 0.0);
942 et_application_window_status_bar_message (self,
943 _("All tags have been removed"),
944 TRUE);
945 }
946
947 static void
on_preferences(GSimpleAction * action,GVariant * variant,gpointer user_data)948 on_preferences (GSimpleAction *action,
949 GVariant *variant,
950 gpointer user_data)
951 {
952 EtApplicationWindow *self;
953 EtApplicationWindowPrivate *priv;
954
955 self = ET_APPLICATION_WINDOW (user_data);
956 priv = et_application_window_get_instance_private (self);
957
958 if (priv->preferences_dialog)
959 {
960 gtk_widget_show (priv->preferences_dialog);
961 }
962 else
963 {
964 priv->preferences_dialog = GTK_WIDGET (et_preferences_dialog_new (GTK_WINDOW (self)));
965 gtk_widget_show_all (priv->preferences_dialog);
966 }
967 }
968
969 static void
on_action_toggle(GSimpleAction * action,GVariant * variant,gpointer user_data)970 on_action_toggle (GSimpleAction *action,
971 GVariant *variant,
972 gpointer user_data)
973 {
974 GVariant *state;
975
976 /* Toggle the current state. */
977 state = g_action_get_state (G_ACTION (action));
978 g_action_change_state (G_ACTION (action),
979 g_variant_new_boolean (!g_variant_get_boolean (state)));
980 g_variant_unref (state);
981 }
982
983 static void
on_action_radio(GSimpleAction * action,GVariant * variant,gpointer user_data)984 on_action_radio (GSimpleAction *action,
985 GVariant *variant,
986 gpointer user_data)
987 {
988 /* Set the action state to the just-activated state. */
989 g_action_change_state (G_ACTION (action), variant);
990 }
991
992 static void
on_scanner_change(GSimpleAction * action,GVariant * variant,gpointer user_data)993 on_scanner_change (GSimpleAction *action,
994 GVariant *variant,
995 gpointer user_data)
996 {
997 EtApplicationWindow *self;
998 EtApplicationWindowPrivate *priv;
999 gboolean active;
1000
1001 self = ET_APPLICATION_WINDOW (user_data);
1002 priv = et_application_window_get_instance_private (self);
1003 active = g_variant_get_boolean (variant);
1004
1005 if (!active)
1006 {
1007 if (priv->scan_dialog)
1008 {
1009 gtk_widget_hide (priv->scan_dialog);
1010 }
1011 else
1012 {
1013 return;
1014 }
1015 }
1016 else
1017 {
1018 if (priv->scan_dialog)
1019 {
1020 gtk_widget_show (priv->scan_dialog);
1021 }
1022 else
1023 {
1024 priv->scan_dialog = GTK_WIDGET (et_scan_dialog_new (GTK_WINDOW (self)));
1025 gtk_widget_show (priv->scan_dialog);
1026 }
1027 }
1028
1029 g_simple_action_set_state (action, variant);
1030 }
1031
1032 static void
on_file_artist_view_change(GSimpleAction * action,GVariant * variant,gpointer user_data)1033 on_file_artist_view_change (GSimpleAction *action,
1034 GVariant *variant,
1035 gpointer user_data)
1036 {
1037 EtApplicationWindow *self;
1038 EtApplicationWindowPrivate *priv;
1039 const gchar *state;
1040
1041 self = ET_APPLICATION_WINDOW (user_data);
1042 priv = et_application_window_get_instance_private (self);
1043 state = g_variant_get_string (variant, NULL);
1044
1045 g_return_if_fail (ETCore->ETFileDisplayedList != NULL);
1046
1047 et_application_window_update_et_file_from_ui (self);
1048
1049 if (strcmp (state, "file") == 0)
1050 {
1051 et_browser_set_display_mode (ET_BROWSER (priv->browser),
1052 ET_BROWSER_MODE_FILE);
1053 }
1054 else if (strcmp (state, "artist") == 0)
1055 {
1056 et_browser_set_display_mode (ET_BROWSER (priv->browser),
1057 ET_BROWSER_MODE_ARTIST);
1058 }
1059 else
1060 {
1061 g_assert_not_reached ();
1062 }
1063
1064 g_simple_action_set_state (action, variant);
1065
1066 et_application_window_update_actions (ET_APPLICATION_WINDOW (user_data));
1067 }
1068
1069 static void
on_collapse_tree(GSimpleAction * action,GVariant * variant,gpointer user_data)1070 on_collapse_tree (GSimpleAction *action,
1071 GVariant *variant,
1072 gpointer user_data)
1073 {
1074 EtApplicationWindowPrivate *priv;
1075 EtApplicationWindow *self = ET_APPLICATION_WINDOW (user_data);
1076
1077 priv = et_application_window_get_instance_private (self);
1078
1079 et_browser_collapse (ET_BROWSER (priv->browser));
1080 }
1081
1082 static void
on_reload_tree(GSimpleAction * action,GVariant * variant,gpointer user_data)1083 on_reload_tree (GSimpleAction *action,
1084 GVariant *variant,
1085 gpointer user_data)
1086 {
1087 EtApplicationWindowPrivate *priv;
1088 EtApplicationWindow *self = ET_APPLICATION_WINDOW (user_data);
1089
1090 priv = et_application_window_get_instance_private (self);
1091
1092 et_browser_reload (ET_BROWSER (priv->browser));
1093 }
1094
1095 static void
on_reload_directory(GSimpleAction * action,GVariant * variant,gpointer user_data)1096 on_reload_directory (GSimpleAction *action,
1097 GVariant *variant,
1098 gpointer user_data)
1099 {
1100 EtApplicationWindowPrivate *priv;
1101 EtApplicationWindow *self = ET_APPLICATION_WINDOW (user_data);
1102
1103 priv = et_application_window_get_instance_private (self);
1104
1105 et_browser_reload_directory (ET_BROWSER (priv->browser));
1106 }
1107
1108 static void
on_set_default_path(GSimpleAction * action,GVariant * variant,gpointer user_data)1109 on_set_default_path (GSimpleAction *action,
1110 GVariant *variant,
1111 gpointer user_data)
1112 {
1113 EtApplicationWindow *self;
1114 EtApplicationWindowPrivate *priv;
1115
1116 self = ET_APPLICATION_WINDOW (user_data);
1117 priv = et_application_window_get_instance_private (self);
1118
1119 et_browser_set_current_path_default (ET_BROWSER (priv->browser));
1120 }
1121
1122 static void
on_rename_directory(GSimpleAction * action,GVariant * variant,gpointer user_data)1123 on_rename_directory (GSimpleAction *action,
1124 GVariant *variant,
1125 gpointer user_data)
1126 {
1127 EtApplicationWindow *self;
1128 EtApplicationWindowPrivate *priv;
1129
1130 self = ET_APPLICATION_WINDOW (user_data);
1131 priv = et_application_window_get_instance_private (self);
1132
1133 et_browser_show_rename_directory_dialog (ET_BROWSER (priv->browser));
1134 }
1135
1136 static void
on_browse_directory(GSimpleAction * action,GVariant * variant,gpointer user_data)1137 on_browse_directory (GSimpleAction *action,
1138 GVariant *variant,
1139 gpointer user_data)
1140 {
1141 EtApplicationWindow *self;
1142 EtApplicationWindowPrivate *priv;
1143
1144 self = ET_APPLICATION_WINDOW (user_data);
1145 priv = et_application_window_get_instance_private (self);
1146
1147 et_browser_show_open_directory_with_dialog (ET_BROWSER (priv->browser));
1148 }
1149
1150 static void
on_show_cddb(GSimpleAction * action,GVariant * variant,gpointer user_data)1151 on_show_cddb (GSimpleAction *action,
1152 GVariant *variant,
1153 gpointer user_data)
1154 {
1155 EtApplicationWindow *self;
1156
1157 self = ET_APPLICATION_WINDOW (user_data);
1158
1159 et_application_window_show_cddb_dialog (self);
1160 }
1161
1162 static void
on_show_load_filenames(GSimpleAction * action,GVariant * variant,gpointer user_data)1163 on_show_load_filenames (GSimpleAction *action,
1164 GVariant *variant,
1165 gpointer user_data)
1166 {
1167 EtApplicationWindowPrivate *priv;
1168 EtApplicationWindow *self;
1169
1170 self = ET_APPLICATION_WINDOW (user_data);
1171 priv = et_application_window_get_instance_private (self);
1172
1173 if (priv->load_files_dialog)
1174 {
1175 gtk_widget_show (priv->load_files_dialog);
1176 }
1177 else
1178 {
1179 priv->load_files_dialog = GTK_WIDGET (et_load_files_dialog_new (GTK_WINDOW (self)));
1180 gtk_widget_show_all (priv->load_files_dialog);
1181 }
1182 }
1183
1184 static void
on_show_playlist(GSimpleAction * action,GVariant * variant,gpointer user_data)1185 on_show_playlist (GSimpleAction *action,
1186 GVariant *variant,
1187 gpointer user_data)
1188 {
1189 EtApplicationWindowPrivate *priv;
1190 EtApplicationWindow *self;
1191
1192 self = ET_APPLICATION_WINDOW (user_data);
1193 priv = et_application_window_get_instance_private (self);
1194
1195 if (priv->playlist_dialog)
1196 {
1197 gtk_widget_show (priv->playlist_dialog);
1198 }
1199 else
1200 {
1201 priv->playlist_dialog = GTK_WIDGET (et_playlist_dialog_new (GTK_WINDOW (self)));
1202 gtk_widget_show_all (priv->playlist_dialog);
1203 }
1204 }
1205
1206 static void
on_go_home(GSimpleAction * action,GVariant * variant,gpointer user_data)1207 on_go_home (GSimpleAction *action,
1208 GVariant *variant,
1209 gpointer user_data)
1210 {
1211 EtApplicationWindowPrivate *priv;
1212 EtApplicationWindow *self;
1213
1214 self = ET_APPLICATION_WINDOW (user_data);
1215 priv = et_application_window_get_instance_private (self);
1216
1217 et_browser_go_home (ET_BROWSER (priv->browser));
1218 }
1219
1220 static void
on_go_desktop(GSimpleAction * action,GVariant * variant,gpointer user_data)1221 on_go_desktop (GSimpleAction *action,
1222 GVariant *variant,
1223 gpointer user_data)
1224 {
1225 EtApplicationWindowPrivate *priv;
1226 EtApplicationWindow *self;
1227
1228 self = ET_APPLICATION_WINDOW (user_data);
1229 priv = et_application_window_get_instance_private (self);
1230
1231 et_browser_go_desktop (ET_BROWSER (priv->browser));
1232 }
1233
1234 static void
on_go_documents(GSimpleAction * action,GVariant * variant,gpointer user_data)1235 on_go_documents (GSimpleAction *action,
1236 GVariant *variant,
1237 gpointer user_data)
1238 {
1239 EtApplicationWindowPrivate *priv;
1240 EtApplicationWindow *self;
1241
1242 self = ET_APPLICATION_WINDOW (user_data);
1243 priv = et_application_window_get_instance_private (self);
1244
1245 et_browser_go_documents (ET_BROWSER (priv->browser));
1246 }
1247
1248 static void
on_go_downloads(GSimpleAction * action,GVariant * variant,gpointer user_data)1249 on_go_downloads (GSimpleAction *action,
1250 GVariant *variant,
1251 gpointer user_data)
1252 {
1253 EtApplicationWindowPrivate *priv;
1254 EtApplicationWindow *self;
1255
1256 self = ET_APPLICATION_WINDOW (user_data);
1257 priv = et_application_window_get_instance_private (self);
1258
1259 et_browser_go_downloads (ET_BROWSER (priv->browser));
1260 }
1261
1262 static void
on_go_music(GSimpleAction * action,GVariant * variant,gpointer user_data)1263 on_go_music (GSimpleAction *action,
1264 GVariant *variant,
1265 gpointer user_data)
1266 {
1267 EtApplicationWindowPrivate *priv;
1268 EtApplicationWindow *self;
1269
1270 self = ET_APPLICATION_WINDOW (user_data);
1271 priv = et_application_window_get_instance_private (self);
1272
1273 et_browser_go_music (ET_BROWSER (priv->browser));
1274 }
1275
1276 static void
on_go_parent(GSimpleAction * action,GVariant * variant,gpointer user_data)1277 on_go_parent (GSimpleAction *action,
1278 GVariant *variant,
1279 gpointer user_data)
1280 {
1281 EtApplicationWindowPrivate *priv;
1282 EtApplicationWindow *self;
1283
1284 self = ET_APPLICATION_WINDOW (user_data);
1285 priv = et_application_window_get_instance_private (self);
1286
1287 et_browser_go_parent (ET_BROWSER (priv->browser));
1288 }
1289
1290 static void
on_go_default(GSimpleAction * action,GVariant * variant,gpointer user_data)1291 on_go_default (GSimpleAction *action,
1292 GVariant *variant,
1293 gpointer user_data)
1294 {
1295 EtApplicationWindowPrivate *priv;
1296 EtApplicationWindow *self;
1297
1298 self = ET_APPLICATION_WINDOW (user_data);
1299 priv = et_application_window_get_instance_private (self);
1300
1301 et_browser_load_default_dir (ET_BROWSER (priv->browser));
1302 }
1303
1304 static void
update_ui_for_et_file(EtApplicationWindow * self,ET_File * et_file)1305 update_ui_for_et_file (EtApplicationWindow *self,
1306 ET_File *et_file)
1307 {
1308 EtApplicationWindowPrivate *priv;
1309
1310 priv = et_application_window_get_instance_private (self);
1311
1312 if (et_file)
1313 {
1314 /* To avoid the last line still selected. */
1315 et_browser_unselect_all (ET_BROWSER (priv->browser));
1316 et_application_window_browser_select_file_by_et_file (self, et_file,
1317 TRUE);
1318 et_application_window_display_et_file (self, et_file);
1319 }
1320
1321 et_application_window_update_actions (self);
1322 et_application_window_scan_dialog_update_previews (self);
1323
1324 if (!g_settings_get_boolean (MainSettings, "tag-preserve-focus"))
1325 {
1326 et_tag_area_title_grab_focus (ET_TAG_AREA (priv->tag_area));
1327 }
1328 }
1329
1330 static void
on_go_first(GSimpleAction * action,GVariant * variant,gpointer user_data)1331 on_go_first (GSimpleAction *action,
1332 GVariant *variant,
1333 gpointer user_data)
1334 {
1335 EtApplicationWindow *self;
1336 GList *etfilelist;
1337
1338 self = ET_APPLICATION_WINDOW (user_data);
1339
1340 g_return_if_fail (ETCore->ETFileDisplayedList);
1341
1342 et_application_window_update_et_file_from_ui (self);
1343
1344 /* Go to the first item of the list */
1345 etfilelist = ET_Displayed_File_List_First ();
1346
1347 update_ui_for_et_file (self, etfilelist ? (ET_File *)etfilelist->data
1348 : NULL);
1349 }
1350
1351 static void
on_go_previous(GSimpleAction * action,GVariant * variant,gpointer user_data)1352 on_go_previous (GSimpleAction *action,
1353 GVariant *variant,
1354 gpointer user_data)
1355 {
1356 EtApplicationWindow *self;
1357 GList *etfilelist;
1358
1359 self = ET_APPLICATION_WINDOW (user_data);
1360
1361 g_return_if_fail (ETCore->ETFileDisplayedList
1362 && ETCore->ETFileDisplayedList->prev);
1363
1364 et_application_window_update_et_file_from_ui (self);
1365
1366 /* Go to the prev item of the list */
1367 etfilelist = ET_Displayed_File_List_Previous ();
1368
1369 update_ui_for_et_file (self, etfilelist ? (ET_File *)etfilelist->data
1370 : NULL);
1371 }
1372
1373 static void
on_go_next(GSimpleAction * action,GVariant * variant,gpointer user_data)1374 on_go_next (GSimpleAction *action,
1375 GVariant *variant,
1376 gpointer user_data)
1377 {
1378 EtApplicationWindow *self;
1379 GList *etfilelist;
1380
1381 self = ET_APPLICATION_WINDOW (user_data);
1382
1383 g_return_if_fail (ETCore->ETFileDisplayedList
1384 && ETCore->ETFileDisplayedList->next);
1385
1386 et_application_window_update_et_file_from_ui (self);
1387
1388 /* Go to the next item of the list */
1389 etfilelist = ET_Displayed_File_List_Next ();
1390
1391 update_ui_for_et_file (self, etfilelist ? (ET_File *)etfilelist->data
1392 : NULL);
1393 }
1394
1395 static void
on_go_last(GSimpleAction * action,GVariant * variant,gpointer user_data)1396 on_go_last (GSimpleAction *action,
1397 GVariant *variant,
1398 gpointer user_data)
1399 {
1400 EtApplicationWindow *self;
1401 GList *etfilelist;
1402
1403 self = ET_APPLICATION_WINDOW (user_data);
1404
1405 g_return_if_fail (ETCore->ETFileDisplayedList
1406 && ETCore->ETFileDisplayedList->next);
1407
1408 et_application_window_update_et_file_from_ui (self);
1409
1410 /* Go to the last item of the list */
1411 etfilelist = ET_Displayed_File_List_Last ();
1412
1413 update_ui_for_et_file (self, etfilelist ? (ET_File *)etfilelist->data
1414 : NULL);
1415 }
1416
1417 static void
on_show_cddb_selection(GSimpleAction * action,GVariant * variant,gpointer user_data)1418 on_show_cddb_selection (GSimpleAction *action,
1419 GVariant *variant,
1420 gpointer user_data)
1421 {
1422 EtApplicationWindowPrivate *priv;
1423 EtApplicationWindow *self = ET_APPLICATION_WINDOW (user_data);
1424
1425 priv = et_application_window_get_instance_private (self);
1426
1427 et_application_window_show_cddb_dialog (self);
1428 et_cddb_dialog_search_from_selection (ET_CDDB_DIALOG (priv->cddb_dialog));
1429 }
1430
1431 static void
on_clear_log(GSimpleAction * action,GVariant * variant,gpointer user_data)1432 on_clear_log (GSimpleAction *action,
1433 GVariant *variant,
1434 gpointer user_data)
1435 {
1436 EtApplicationWindowPrivate *priv;
1437 EtApplicationWindow *self = ET_APPLICATION_WINDOW (user_data);
1438
1439 priv = et_application_window_get_instance_private (self);
1440
1441 et_log_area_clear (ET_LOG_AREA (priv->log_area));
1442 }
1443
1444 static void
on_run_player_album(GSimpleAction * action,GVariant * variant,gpointer user_data)1445 on_run_player_album (GSimpleAction *action,
1446 GVariant *variant,
1447 gpointer user_data)
1448 {
1449 EtApplicationWindowPrivate *priv;
1450 EtApplicationWindow *self = ET_APPLICATION_WINDOW (user_data);
1451
1452 priv = et_application_window_get_instance_private (self);
1453
1454 et_browser_run_player_for_album_list (ET_BROWSER (priv->browser));
1455 }
1456
1457 static void
on_run_player_artist(GSimpleAction * action,GVariant * variant,gpointer user_data)1458 on_run_player_artist (GSimpleAction *action,
1459 GVariant *variant,
1460 gpointer user_data)
1461 {
1462 EtApplicationWindowPrivate *priv;
1463 EtApplicationWindow *self = ET_APPLICATION_WINDOW (user_data);
1464
1465 priv = et_application_window_get_instance_private (self);
1466
1467 et_browser_run_player_for_artist_list (ET_BROWSER (priv->browser));
1468 }
1469
1470 static gboolean
run_audio_player_using_directory(GError ** error)1471 run_audio_player_using_directory (GError **error)
1472 {
1473 GList *l;
1474 GList *file_list = NULL;
1475 gboolean res;
1476
1477 for (l = ETCore->ETFileList; l != NULL; l = g_list_next (l))
1478 {
1479 ET_File *etfile = (ET_File *)l->data;
1480 const gchar *path = ((File_Name *)etfile->FileNameCur->data)->value;
1481 file_list = g_list_prepend (file_list, g_file_new_for_path (path));
1482 }
1483
1484 file_list = g_list_reverse (file_list);
1485
1486 res = et_run_audio_player (file_list, error);
1487
1488 g_list_free_full (file_list, g_object_unref);
1489
1490 return res;
1491 }
1492
1493 static void
on_run_player_directory(GSimpleAction * action,GVariant * variant,gpointer user_data)1494 on_run_player_directory (GSimpleAction *action,
1495 GVariant *variant,
1496 gpointer user_data)
1497 {
1498 GError *error = NULL;
1499
1500 if (!run_audio_player_using_directory (&error))
1501 {
1502 Log_Print (LOG_ERROR, _("Failed to launch program ‘%s’"),
1503 error->message);
1504 g_error_free (error);
1505 }
1506 }
1507
1508 static void
on_stop(GSimpleAction * action,GVariant * variant,gpointer user_data)1509 on_stop (GSimpleAction *action,
1510 GVariant *variant,
1511 gpointer user_data)
1512 {
1513 Action_Main_Stop_Button_Pressed ();
1514 }
1515
1516 static const GActionEntry actions[] =
1517 {
1518 /* File menu. */
1519 { "open-with", on_open_with },
1520 { "run-player", on_run_player },
1521 { "invert-selection", on_invert_selection },
1522 { "delete", on_delete },
1523 { "undo-file-changes", on_undo_file_changes },
1524 { "redo-file-changes", on_redo_file_changes },
1525 { "save", on_save },
1526 { "save-force", on_save_force },
1527 /* Edit menu. */
1528 { "find", on_find },
1529 { "select-all", on_select_all },
1530 { "unselect-all", on_unselect_all },
1531 { "undo-last-changes", on_undo_last_changes },
1532 { "redo-last-changes", on_redo_last_changes },
1533 { "remove-tags", on_remove_tags },
1534 { "preferences", on_preferences },
1535 /* View menu. */
1536 { "scanner", on_action_toggle, NULL, "false", on_scanner_change },
1537 /* { "scan-mode", on_action_radio, NULL, "false", on_scan_mode_change },
1538 * Created from GSetting. */
1539 /* { "sort-mode", on_action_radio, "s", "'ascending-filename'",
1540 * on_sort_mode_change }, Created from GSetting */
1541 { "file-artist-view", on_action_radio, "s", "'file'",
1542 on_file_artist_view_change },
1543 { "collapse-tree", on_collapse_tree },
1544 { "reload-tree", on_reload_tree },
1545 { "reload-directory", on_reload_directory },
1546 /* { "browse-show-hidden", on_action_toggle, NULL, "true",
1547 on_browse_show_hidden_change }, Created from GSetting. */
1548 /* Browser menu. */
1549 { "set-default-path", on_set_default_path },
1550 { "rename-directory", on_rename_directory },
1551 { "browse-directory", on_browse_directory },
1552 /* { "browse-subdir", on_browse_subdir }, Created from GSetting. */
1553 /* Miscellaneous menu. */
1554 { "show-cddb", on_show_cddb },
1555 { "show-load-filenames", on_show_load_filenames },
1556 { "show-playlist", on_show_playlist },
1557 /* Go menu. */
1558 { "go-home", on_go_home },
1559 { "go-desktop", on_go_desktop },
1560 { "go-documents", on_go_documents },
1561 { "go-downloads", on_go_downloads },
1562 { "go-music", on_go_music },
1563 { "go-parent", on_go_parent },
1564 { "go-default", on_go_default },
1565 { "go-first", on_go_first },
1566 { "go-previous", on_go_previous },
1567 { "go-next", on_go_next },
1568 { "go-last", on_go_last },
1569 /* Popup menus. */
1570 { "show-cddb-selection", on_show_cddb_selection },
1571 { "clear-log", on_clear_log },
1572 { "run-player-album", on_run_player_album },
1573 { "run-player-artist", on_run_player_artist },
1574 { "run-player-directory", on_run_player_directory },
1575 /* Toolbar. */
1576 { "stop", on_stop }
1577 };
1578
1579 static void
et_application_window_dispose(GObject * object)1580 et_application_window_dispose (GObject *object)
1581 {
1582 EtApplicationWindow *self;
1583 EtApplicationWindowPrivate *priv;
1584
1585 self = ET_APPLICATION_WINDOW (object);
1586 priv = et_application_window_get_instance_private (self);
1587
1588 save_state (self);
1589
1590 if (ETCore)
1591 {
1592 ET_Core_Free ();
1593 }
1594
1595 if (priv->cddb_dialog)
1596 {
1597 gtk_widget_destroy (priv->cddb_dialog);
1598 priv->cddb_dialog = NULL;
1599 }
1600
1601 if (priv->load_files_dialog)
1602 {
1603 gtk_widget_destroy (priv->load_files_dialog);
1604 priv->load_files_dialog = NULL;
1605 }
1606
1607 if (priv->playlist_dialog)
1608 {
1609 gtk_widget_destroy (priv->playlist_dialog);
1610 priv->playlist_dialog = NULL;
1611 }
1612
1613 if (priv->preferences_dialog)
1614 {
1615 gtk_widget_destroy (priv->preferences_dialog);
1616 priv->preferences_dialog = NULL;
1617 }
1618
1619 if (priv->scan_dialog)
1620 {
1621 gtk_widget_destroy (priv->scan_dialog);
1622 priv->scan_dialog = NULL;
1623 }
1624
1625 if (priv->search_dialog)
1626 {
1627 gtk_widget_destroy (priv->search_dialog);
1628 priv->search_dialog = NULL;
1629 }
1630
1631 if (priv->cursor)
1632 {
1633 g_object_unref (priv->cursor);
1634 priv->cursor = NULL;
1635 }
1636
1637 G_OBJECT_CLASS (et_application_window_parent_class)->dispose (object);
1638 }
1639
1640 static void
et_application_window_init(EtApplicationWindow * self)1641 et_application_window_init (EtApplicationWindow *self)
1642 {
1643 EtApplicationWindowPrivate *priv;
1644 GAction *action;
1645 GtkWindow *window;
1646 GtkWidget *main_vbox;
1647 GtkWidget *hbox;
1648 GtkWidget *grid;
1649
1650 priv = et_application_window_get_instance_private (self);
1651
1652 g_action_map_add_action_entries (G_ACTION_MAP (self), actions,
1653 G_N_ELEMENTS (actions), self);
1654
1655 action = g_settings_create_action (MainSettings, "browse-show-hidden");
1656 g_action_map_add_action (G_ACTION_MAP (self), action);
1657 g_object_unref (action);
1658 action = g_settings_create_action (MainSettings, "browse-subdir");
1659 g_action_map_add_action (G_ACTION_MAP (self), action);
1660 g_object_unref (action);
1661 action = g_settings_create_action (MainSettings, "scan-mode");
1662 g_action_map_add_action (G_ACTION_MAP (self), action);
1663 g_object_unref (action);
1664 action = g_settings_create_action (MainSettings, "sort-mode");
1665 g_action_map_add_action (G_ACTION_MAP (self), action);
1666 g_object_unref (action);
1667
1668 window = GTK_WINDOW (self);
1669
1670 gtk_window_set_icon_name (window, PACKAGE_TARNAME);
1671 gtk_window_set_title (window, _(PACKAGE_NAME));
1672
1673 g_signal_connect (self, "configure-event",
1674 G_CALLBACK (on_configure_event), NULL);
1675 g_signal_connect (self, "delete-event",
1676 G_CALLBACK (on_main_window_delete_event), NULL);
1677 g_signal_connect (self, "window-state-event",
1678 G_CALLBACK (on_window_state_event), NULL);
1679
1680 /* Mainvbox for Menu bar + Tool bar + "Browser Area & FileArea & TagArea" + Log Area + "Status bar & Progress bar" */
1681 main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
1682 gtk_container_add (GTK_CONTAINER (self), main_vbox);
1683
1684 /* Menu bar and tool bar. */
1685 {
1686 GtkBuilder *builder;
1687 GtkWidget *toolbar;
1688
1689 builder = gtk_builder_new_from_resource ("/org/gnome/EasyTAG/toolbar.ui");
1690
1691 toolbar = GTK_WIDGET (gtk_builder_get_object (builder, "main_toolbar"));
1692 gtk_box_pack_start (GTK_BOX (main_vbox), toolbar, FALSE, FALSE, 0);
1693
1694 g_object_unref (builder);
1695 }
1696
1697 /* The two panes: BrowserArea on the left, FileArea+TagArea on the right */
1698 priv->hpaned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
1699
1700 /* Browser (Tree + File list + Entry) */
1701 priv->browser = GTK_WIDGET (et_browser_new ());
1702 gtk_paned_pack1 (GTK_PANED (priv->hpaned), priv->browser, TRUE, TRUE);
1703
1704 /* Vertical box for FileArea + TagArea */
1705 grid = gtk_grid_new ();
1706 gtk_orientable_set_orientation (GTK_ORIENTABLE (grid),
1707 GTK_ORIENTATION_VERTICAL);
1708 gtk_paned_pack2 (GTK_PANED (priv->hpaned), grid, FALSE, FALSE);
1709
1710 /* File */
1711 priv->file_area = et_file_area_new ();
1712 gtk_container_add (GTK_CONTAINER (grid), priv->file_area);
1713
1714 /* Tag */
1715 priv->tag_area = et_tag_area_new ();
1716 gtk_container_add (GTK_CONTAINER (grid), priv->tag_area);
1717
1718 /* Update the stored paned position whenever it is changed (after configure
1719 * and windows state events have been processed). */
1720 g_signal_connect_swapped (priv->hpaned, "notify::position",
1721 G_CALLBACK (on_paned_notify_position), self);
1722 restore_state (self);
1723
1724 /* Vertical pane for Browser Area + FileArea + TagArea */
1725 priv->vpaned = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
1726 gtk_box_pack_start (GTK_BOX (main_vbox), priv->vpaned, TRUE, TRUE, 0);
1727 gtk_paned_pack1 (GTK_PANED (priv->vpaned), priv->hpaned, TRUE,
1728 FALSE);
1729
1730
1731 /* Log */
1732 priv->log_area = et_log_area_new ();
1733 gtk_paned_pack2 (GTK_PANED (priv->vpaned), priv->log_area, FALSE, FALSE);
1734
1735 /* Horizontal box for Status bar + Progress bar */
1736 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
1737 gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
1738 gtk_widget_show (hbox);
1739
1740 /* Status bar */
1741 priv->status_bar = et_status_bar_new ();
1742 gtk_box_pack_start (GTK_BOX (hbox), priv->status_bar, TRUE, TRUE, 0);
1743
1744 /* Progress bar */
1745 priv->progress_bar = et_progress_bar_new ();
1746 gtk_box_pack_end (GTK_BOX (hbox), priv->progress_bar, FALSE, FALSE, 0);
1747
1748 gtk_widget_show_all (GTK_WIDGET (main_vbox));
1749
1750 /* Bind the setting after the log area has been shown, to avoid
1751 * force-enabling the visibility on startup. */
1752 g_settings_bind (MainSettings, "log-show", priv->log_area, "visible",
1753 G_SETTINGS_BIND_DEFAULT);
1754 }
1755
1756 static void
et_application_window_class_init(EtApplicationWindowClass * klass)1757 et_application_window_class_init (EtApplicationWindowClass *klass)
1758 {
1759 G_OBJECT_CLASS (klass)->dispose = et_application_window_dispose;
1760 }
1761
1762 /*
1763 * et_application_window_new:
1764 *
1765 * Create a new EtApplicationWindow instance.
1766 *
1767 * Returns: a new #EtApplicationWindow
1768 */
1769 EtApplicationWindow *
et_application_window_new(GtkApplication * application)1770 et_application_window_new (GtkApplication *application)
1771 {
1772 g_return_val_if_fail (GTK_IS_APPLICATION (application), NULL);
1773
1774 return g_object_new (ET_TYPE_APPLICATION_WINDOW, "application",
1775 application, NULL);
1776 }
1777
1778 void
et_application_window_scan_dialog_update_previews(EtApplicationWindow * self)1779 et_application_window_scan_dialog_update_previews (EtApplicationWindow *self)
1780 {
1781 EtApplicationWindowPrivate *priv;
1782
1783 g_return_if_fail (self != NULL);
1784
1785 priv = et_application_window_get_instance_private (self);
1786
1787 if (priv->scan_dialog)
1788 {
1789 et_scan_dialog_update_previews (ET_SCAN_DIALOG (priv->scan_dialog));
1790 }
1791 }
1792
1793 void
et_application_window_progress_set_fraction(EtApplicationWindow * self,gdouble fraction)1794 et_application_window_progress_set_fraction (EtApplicationWindow *self,
1795 gdouble fraction)
1796 {
1797 EtApplicationWindowPrivate *priv;
1798
1799 g_return_if_fail (ET_APPLICATION_WINDOW (self));
1800
1801 priv = et_application_window_get_instance_private (self);
1802
1803 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (priv->progress_bar),
1804 fraction);
1805 }
1806
1807 void
et_application_window_progress_set_text(EtApplicationWindow * self,const gchar * text)1808 et_application_window_progress_set_text (EtApplicationWindow *self,
1809 const gchar *text)
1810 {
1811 EtApplicationWindowPrivate *priv;
1812
1813 g_return_if_fail (ET_APPLICATION_WINDOW (self));
1814
1815 priv = et_application_window_get_instance_private (self);
1816
1817 gtk_progress_bar_set_text (GTK_PROGRESS_BAR (priv->progress_bar), text);
1818 }
1819
1820 void
et_application_window_status_bar_message(EtApplicationWindow * self,const gchar * message,gboolean with_timer)1821 et_application_window_status_bar_message (EtApplicationWindow *self,
1822 const gchar *message,
1823 gboolean with_timer)
1824 {
1825 EtApplicationWindowPrivate *priv;
1826
1827 g_return_if_fail (ET_APPLICATION_WINDOW (self));
1828
1829 priv = et_application_window_get_instance_private (self);
1830
1831 et_status_bar_message (ET_STATUS_BAR (priv->status_bar), message,
1832 with_timer);
1833 }
1834
1835 GtkWidget *
et_application_window_get_log_area(EtApplicationWindow * self)1836 et_application_window_get_log_area (EtApplicationWindow *self)
1837 {
1838 EtApplicationWindowPrivate *priv;
1839
1840 g_return_val_if_fail (self != NULL, NULL);
1841
1842 priv = et_application_window_get_instance_private (self);
1843
1844 return priv->log_area;
1845 }
1846
1847 void
et_application_window_show_preferences_dialog_scanner(EtApplicationWindow * self)1848 et_application_window_show_preferences_dialog_scanner (EtApplicationWindow *self)
1849 {
1850 EtApplicationWindowPrivate *priv;
1851
1852 g_return_if_fail (ET_APPLICATION_WINDOW (self));
1853
1854 priv = et_application_window_get_instance_private (self);
1855
1856 if (!priv->preferences_dialog)
1857 {
1858 priv->preferences_dialog = GTK_WIDGET (et_preferences_dialog_new (GTK_WINDOW (self)));
1859 }
1860
1861 et_preferences_dialog_show_scanner (ET_PREFERENCES_DIALOG (priv->preferences_dialog));
1862 }
1863
1864 void
et_application_window_browser_toggle_display_mode(EtApplicationWindow * self)1865 et_application_window_browser_toggle_display_mode (EtApplicationWindow *self)
1866 {
1867 EtApplicationWindowPrivate *priv;
1868 GVariant *variant;
1869
1870 priv = et_application_window_get_instance_private (self);
1871
1872 variant = g_action_group_get_action_state (G_ACTION_GROUP (self),
1873 "file-artist-view");
1874
1875 if (strcmp (g_variant_get_string (variant, NULL), "file") == 0)
1876 {
1877 et_browser_set_display_mode (ET_BROWSER (priv->browser),
1878 ET_BROWSER_MODE_FILE);
1879 }
1880 else if (strcmp (g_variant_get_string (variant, NULL), "artist") == 0)
1881 {
1882 et_browser_set_display_mode (ET_BROWSER (priv->browser),
1883 ET_BROWSER_MODE_ARTIST);
1884 }
1885 else
1886 {
1887 g_assert_not_reached ();
1888 }
1889
1890 g_variant_unref (variant);
1891 }
1892
1893 void
et_application_window_browser_set_sensitive(EtApplicationWindow * self,gboolean sensitive)1894 et_application_window_browser_set_sensitive (EtApplicationWindow *self,
1895 gboolean sensitive)
1896 {
1897 EtApplicationWindowPrivate *priv;
1898
1899 g_return_if_fail (ET_APPLICATION_WINDOW (self));
1900
1901 priv = et_application_window_get_instance_private (self);
1902
1903 g_return_if_fail (priv->browser != NULL);
1904
1905 et_browser_set_sensitive (ET_BROWSER (priv->browser), sensitive);
1906 }
1907
1908 void
et_application_window_browser_clear(EtApplicationWindow * self)1909 et_application_window_browser_clear (EtApplicationWindow *self)
1910 {
1911 EtApplicationWindowPrivate *priv;
1912
1913 g_return_if_fail (ET_APPLICATION_WINDOW (self));
1914
1915 priv = et_application_window_get_instance_private (self);
1916
1917 g_return_if_fail (priv->browser != NULL);
1918
1919 et_browser_clear (ET_BROWSER (priv->browser));
1920 }
1921
1922 void
et_application_window_browser_clear_album_model(EtApplicationWindow * self)1923 et_application_window_browser_clear_album_model (EtApplicationWindow *self)
1924 {
1925 EtApplicationWindowPrivate *priv;
1926
1927 g_return_if_fail (ET_APPLICATION_WINDOW (self));
1928
1929 priv = et_application_window_get_instance_private (self);
1930
1931 g_return_if_fail (priv->browser != NULL);
1932
1933 et_browser_clear_album_model (ET_BROWSER (priv->browser));
1934 }
1935
1936 void
et_application_window_browser_clear_artist_model(EtApplicationWindow * self)1937 et_application_window_browser_clear_artist_model (EtApplicationWindow *self)
1938 {
1939 EtApplicationWindowPrivate *priv;
1940
1941 g_return_if_fail (ET_APPLICATION_WINDOW (self));
1942
1943 priv = et_application_window_get_instance_private (self);
1944
1945 g_return_if_fail (priv->browser != NULL);
1946
1947 et_browser_clear_artist_model (ET_BROWSER (priv->browser));
1948 }
1949
1950 void
et_application_window_select_dir(EtApplicationWindow * self,GFile * file)1951 et_application_window_select_dir (EtApplicationWindow *self,
1952 GFile *file)
1953 {
1954 EtApplicationWindowPrivate *priv;
1955
1956 priv = et_application_window_get_instance_private (self);
1957
1958 et_browser_select_dir (ET_BROWSER (priv->browser), file);
1959 }
1960
1961 /*
1962 * Select a file in the "main list" using the ETFile address of each item.
1963 */
1964 void
et_application_window_select_file_by_et_file(EtApplicationWindow * self,ET_File * ETFile)1965 et_application_window_select_file_by_et_file (EtApplicationWindow *self,
1966 ET_File *ETFile)
1967 {
1968 if (!ETCore->ETFileDisplayedList)
1969 return;
1970
1971 et_application_window_update_et_file_from_ui (self);
1972
1973 /* Display the item */
1974 et_application_window_browser_select_file_by_et_file (self, ETFile, TRUE);
1975 /* Just to update 'ETFileDisplayedList'. */
1976 ET_Displayed_File_List_By_Etfile (ETFile);
1977 et_application_window_display_et_file (self, ETFile);
1978
1979 et_application_window_update_actions (self);
1980 et_application_window_scan_dialog_update_previews (self);
1981 }
1982
1983 /*
1984 * Save displayed filename into list if it had been changed. Generates also an history list for undo/redo.
1985 * - ETFile : the current etfile that we want to save,
1986 * - FileName : where is 'temporary' saved the new filename.
1987 *
1988 * Note : it builds new filename (with path) from strings encoded into file system
1989 * encoding, not UTF-8 (it preserves file system encoding of parent directories).
1990 */
1991 static void
et_application_window_update_file_name_from_ui(EtApplicationWindow * self,const ET_File * ETFile,File_Name * FileName)1992 et_application_window_update_file_name_from_ui (EtApplicationWindow *self,
1993 const ET_File *ETFile,
1994 File_Name *FileName)
1995 {
1996 gchar *filename_new = NULL;
1997 gchar *dirname = NULL;
1998 gchar *filename;
1999 const gchar *filename_utf8;
2000 gchar *extension;
2001
2002 g_return_if_fail (ETFile != NULL && FileName != NULL);
2003
2004 filename_utf8 = et_application_window_file_area_get_filename (self);
2005 filename = filename_from_display (filename_utf8);
2006
2007 if (!filename)
2008 {
2009 /* If conversion fails... */
2010 GtkWidget *msgdialog;
2011 gchar *filename_escaped_utf8 = g_strescape(filename_utf8, NULL);
2012 msgdialog = gtk_message_dialog_new (GTK_WINDOW (self),
2013 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
2014 GTK_MESSAGE_ERROR,
2015 GTK_BUTTONS_CLOSE,
2016 _("Could not convert filename ‘%s’ to system filename encoding"),
2017 filename_escaped_utf8);
2018 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (msgdialog),
2019 _("Try setting the environment variable G_FILENAME_ENCODING."));
2020 gtk_window_set_title (GTK_WINDOW (msgdialog),
2021 _("Filename translation"));
2022
2023 gtk_dialog_run (GTK_DIALOG (msgdialog));
2024 gtk_widget_destroy (msgdialog);
2025 g_free (filename_escaped_utf8);
2026 return;
2027 }
2028
2029 /* Get the current path to the file. */
2030 dirname = g_path_get_dirname (((File_Name *)ETFile->FileNameNew->data)->value);
2031
2032 /* Convert filename extension (lower or upper). */
2033 extension = ET_File_Format_File_Extension (ETFile);
2034
2035 // Check length of filename (limit ~255 characters)
2036 //ET_File_Name_Check_Length(ETFile,filename);
2037
2038 /* Filename (in file system encoding!). */
2039 if (!et_str_empty (filename))
2040 {
2041 /* Regenerate the new filename (without path). */
2042 filename_new = g_strconcat (filename, extension, NULL);
2043 }
2044 else
2045 {
2046 /* Keep the 'last' filename (if a 'blank' filename was entered in the
2047 * fileentry for example). */
2048 filename_new = g_path_get_basename (((File_Name *)ETFile->FileNameNew->data)->value);
2049 }
2050
2051 g_free (filename);
2052 g_free (extension);
2053
2054 et_file_name_set_from_components (FileName, filename_new, dirname,
2055 g_settings_get_boolean (MainSettings,
2056 "rename-replace-illegal-chars"));
2057
2058 g_free (filename_new);
2059 g_free (dirname);
2060 return;
2061 }
2062
2063 void
et_application_window_update_et_file_from_ui(EtApplicationWindow * self)2064 et_application_window_update_et_file_from_ui (EtApplicationWindow *self)
2065 {
2066 const ET_File_Description *description;
2067 ET_File *et_file;
2068 File_Name *FileName;
2069 File_Tag *FileTag;
2070 const gchar *cur_filename_utf8;
2071
2072 if (!ETCore->ETFileDisplayed)
2073 {
2074 return;
2075 }
2076
2077 et_file = ETCore->ETFileDisplayed;
2078
2079 g_return_if_fail (et_file != NULL && et_file->FileNameCur != NULL
2080 && et_file->FileNameCur->data != NULL);
2081
2082 /* Save the current displayed data */
2083 cur_filename_utf8 = ((File_Name *)((GList *)et_file->FileNameCur)->data)->value_utf8;
2084 description = et_file->ETFileDescription;
2085
2086 /* Save filename and generate undo for filename. */
2087 FileName = et_file_name_new ();
2088 et_application_window_update_file_name_from_ui (self, et_file, FileName);
2089
2090 switch (description->TagType)
2091 {
2092 #ifdef ENABLE_MP3
2093 case ID3_TAG:
2094 #endif
2095 #ifdef ENABLE_OGG
2096 case OGG_TAG:
2097 #endif
2098 #ifdef ENABLE_FLAC
2099 case FLAC_TAG:
2100 #endif
2101 #ifdef ENABLE_MP4
2102 case MP4_TAG:
2103 #endif
2104 #ifdef ENABLE_WAVPACK
2105 case WAVPACK_TAG:
2106 #endif
2107 #ifdef ENABLE_OPUS
2108 case OPUS_TAG:
2109 #endif
2110 case APE_TAG:
2111 FileTag = et_application_window_tag_area_create_file_tag (self);
2112 et_file_tag_copy_other_into (et_file->FileTag->data, FileTag);
2113 break;
2114 #ifndef ENABLE_MP3
2115 case ID3_TAG:
2116 #endif
2117 #ifndef ENABLE_OGG
2118 case OGG_TAG:
2119 #endif
2120 #ifndef ENABLE_FLAC
2121 case FLAC_TAG:
2122 #endif
2123 #ifndef ENABLE_MP4
2124 case MP4_TAG:
2125 #endif
2126 #ifndef ENABLE_WAVPACK
2127 case WAVPACK_TAG:
2128 #endif
2129 #ifndef ENABLE_OPUS
2130 case OPUS_TAG:
2131 #endif
2132 case UNKNOWN_TAG:
2133 default:
2134 FileTag = et_file_tag_new ();
2135 Log_Print (LOG_ERROR,
2136 "FileTag: Undefined tag type %d for file %s.",
2137 (gint)description->TagType, cur_filename_utf8);
2138 break;
2139 }
2140
2141 /*
2142 * Generate undo for the file and the main undo list.
2143 * If no changes detected, FileName and FileTag item are deleted.
2144 */
2145 ET_Manage_Changes_Of_File_Data (et_file, FileName, FileTag);
2146
2147 /* Refresh file into browser list */
2148 et_application_window_browser_refresh_file_in_list (self, et_file);
2149 }
2150
2151 static void
et_file_header_fields_free(EtFileHeaderFields * fields)2152 et_file_header_fields_free (EtFileHeaderFields *fields)
2153 {
2154 g_free (fields->version);
2155 g_free (fields->bitrate);
2156 g_free (fields->samplerate);
2157 g_free (fields->mode);
2158 g_free (fields->size);
2159 g_free (fields->duration);
2160 g_slice_free (EtFileHeaderFields, fields);
2161 }
2162
2163 static void
et_application_window_display_file_name(EtApplicationWindow * self,const ET_File * ETFile)2164 et_application_window_display_file_name (EtApplicationWindow *self,
2165 const ET_File *ETFile)
2166 {
2167 const gchar *new_filename_utf8;
2168 gchar *dirname_utf8;
2169 gchar *text;
2170
2171 g_return_if_fail (ETFile != NULL);
2172
2173 new_filename_utf8 = ((File_Name *)((GList *)ETFile->FileNameNew)->data)->value_utf8;
2174
2175 /*
2176 * Set the path to the file into BrowserEntry (dirbrowser)
2177 */
2178 dirname_utf8 = g_path_get_dirname (new_filename_utf8);
2179 et_application_window_browser_entry_set_text (self, dirname_utf8);
2180
2181 // And refresh the number of files in this directory
2182 text = g_strdup_printf (ngettext ("One file", "%u files",
2183 et_file_list_get_n_files_in_path (ETCore->ETFileList,
2184 dirname_utf8)),
2185 et_file_list_get_n_files_in_path (ETCore->ETFileList,
2186 dirname_utf8));
2187 et_application_window_browser_label_set_text (self, text);
2188 g_free(dirname_utf8);
2189 g_free(text);
2190 }
2191
2192 /*
2193 * "Default" way to display File Info to the user interface.
2194 */
2195 static EtFileHeaderFields *
et_header_fields_new_from_unknown(const ET_File * ETFile)2196 et_header_fields_new_from_unknown (const ET_File *ETFile)
2197 {
2198 EtFileHeaderFields *fields;
2199 ET_File_Info *info;
2200 gchar *time = NULL;
2201 gchar *time1 = NULL;
2202 gchar *size = NULL;
2203 gchar *size1 = NULL;
2204
2205 info = ETFile->ETFileInfo;
2206 fields = g_slice_new (EtFileHeaderFields);
2207
2208 fields->description = _("File");
2209
2210 /* MPEG, Layer versions */
2211 fields->version = g_strdup_printf ("%d, Layer %" G_GSIZE_FORMAT,
2212 info->version, info->layer);
2213
2214 /* Bitrate */
2215 fields->bitrate = g_strdup_printf (_("%d kb/s"), info->bitrate);
2216
2217 /* Samplerate */
2218 fields->samplerate = g_strdup_printf (_("%d Hz"), info->samplerate);
2219
2220 /* Mode */
2221 fields->mode = g_strdup_printf ("%d", info->mode);
2222
2223 /* Size */
2224 size = g_format_size (info->size);
2225 size1 = g_format_size (ETCore->ETFileDisplayedList_TotalSize);
2226 fields->size = g_strdup_printf ("%s (%s)", size, size1);
2227 g_free (size);
2228 g_free (size1);
2229
2230 /* Duration */
2231 time = Convert_Duration (info->duration);
2232 time1 = Convert_Duration (ETCore->ETFileDisplayedList_TotalDuration);
2233 fields->duration = g_strdup_printf ("%s (%s)", time, time1);
2234 g_free (time);
2235 g_free (time1);
2236
2237 return fields;
2238 }
2239
2240 /*
2241 * Display information of the file (Position + Header + Tag) to the user interface.
2242 * Before doing it, it saves data of the file currently displayed
2243 */
2244 void
et_application_window_display_et_file(EtApplicationWindow * self,ET_File * ETFile)2245 et_application_window_display_et_file (EtApplicationWindow *self,
2246 ET_File *ETFile)
2247 {
2248 const ET_File_Description *description;
2249 const gchar *cur_filename_utf8;
2250 gchar *msg;
2251 EtFileHeaderFields *fields;
2252
2253 g_return_if_fail (ETFile != NULL &&
2254 ((GList *)ETFile->FileNameCur)->data != NULL);
2255 /* For the case where ETFile is an "empty" structure. */
2256
2257 cur_filename_utf8 = ((File_Name *)((GList *)ETFile->FileNameCur)->data)->value_utf8;
2258 description = ETFile->ETFileDescription;
2259
2260 /* Save the current displayed file */
2261 ETCore->ETFileDisplayed = ETFile;
2262
2263 /* Display position in list + show/hide icon if file writable/read_only (cur_filename) */
2264 et_application_window_file_area_set_file_fields (self, ETFile);
2265
2266 /* Display filename (and his path) (value in FileNameNew) */
2267 et_application_window_display_file_name (self, ETFile);
2268
2269 /* Display tag data */
2270 et_application_window_tag_area_display_et_file (self, ETFile);
2271
2272 /* Display controls in tag area */
2273 et_application_window_tag_area_display_controls (self, ETFile);
2274
2275 /* Display file data, header data and file type */
2276 switch (description->FileType)
2277 {
2278 #if defined ENABLE_MP3 && defined ENABLE_ID3LIB
2279 case MP3_FILE:
2280 case MP2_FILE:
2281 fields = et_mpeg_header_display_file_info_to_ui (ETFile);
2282 et_application_window_file_area_set_header_fields (self, fields);
2283 et_mpeg_file_header_fields_free (fields);
2284 break;
2285 #endif
2286 #ifdef ENABLE_OGG
2287 case OGG_FILE:
2288 fields = et_ogg_header_display_file_info_to_ui (ETFile);
2289 et_application_window_file_area_set_header_fields (self, fields);
2290 et_ogg_file_header_fields_free (fields);
2291 break;
2292 #endif
2293 #ifdef ENABLE_SPEEX
2294 case SPEEX_FILE:
2295 fields = et_ogg_header_display_file_info_to_ui (ETFile);
2296 et_application_window_file_area_set_header_fields (self, fields);
2297 et_ogg_file_header_fields_free (fields);
2298 break;
2299 #endif
2300 #ifdef ENABLE_FLAC
2301 case FLAC_FILE:
2302 fields = et_flac_header_display_file_info_to_ui (ETFile);
2303 et_application_window_file_area_set_header_fields (self, fields);
2304 et_flac_file_header_fields_free (fields);
2305 break;
2306 #endif
2307 case MPC_FILE:
2308 fields = et_mpc_header_display_file_info_to_ui (ETFile);
2309 et_application_window_file_area_set_header_fields (self, fields);
2310 et_mpc_file_header_fields_free (fields);
2311 break;
2312 case MAC_FILE:
2313 fields = et_mac_header_display_file_info_to_ui (ETFile);
2314 et_application_window_file_area_set_header_fields (self, fields);
2315 et_mac_file_header_fields_free (fields);
2316 break;
2317 #ifdef ENABLE_MP4
2318 case MP4_FILE:
2319 fields = et_mp4_header_display_file_info_to_ui (ETFile);
2320 et_application_window_file_area_set_header_fields (self, fields);
2321 et_mp4_file_header_fields_free (fields);
2322 break;
2323 #endif
2324 #ifdef ENABLE_WAVPACK
2325 case WAVPACK_FILE:
2326 fields = et_wavpack_header_display_file_info_to_ui (ETFile);
2327 et_application_window_file_area_set_header_fields (self, fields);
2328 et_wavpack_file_header_fields_free (fields);
2329 break;
2330 #endif
2331 #ifdef ENABLE_OPUS
2332 case OPUS_FILE:
2333 fields = et_opus_header_display_file_info_to_ui (ETFile);
2334 et_application_window_file_area_set_header_fields (self, fields);
2335 et_opus_file_header_fields_free (fields);
2336 break;
2337 #endif
2338 case OFR_FILE:
2339 #if !defined ENABLE_MP3 && !defined ENABLE_ID3LIB
2340 case MP3_FILE:
2341 case MP2_FILE:
2342 #endif
2343 #ifndef ENABLE_OGG
2344 case OGG_FILE:
2345 #endif
2346 #ifndef ENABLE_SPEEX
2347 case SPEEX_FILE:
2348 #endif
2349 #ifndef ENABLE_FLAC
2350 case FLAC_FILE:
2351 #endif
2352 #ifndef ENABLE_MP4
2353 case MP4_FILE:
2354 #endif
2355 #ifndef ENABLE_WAVPACK
2356 case WAVPACK_FILE:
2357 #endif
2358 #ifndef ENABLE_OPUS
2359 case OPUS_FILE:
2360 #endif
2361 case UNKNOWN_FILE:
2362 default:
2363 /* Default displaying. */
2364 fields = et_header_fields_new_from_unknown (ETFile);
2365 et_application_window_file_area_set_header_fields (self, fields);
2366 et_file_header_fields_free (fields);
2367 Log_Print (LOG_ERROR,
2368 "ETFileInfo: Undefined file type %d for file %s.",
2369 (gint)description->FileType, cur_filename_utf8);
2370 break;
2371 }
2372
2373 msg = g_strdup_printf (_("File: ‘%s’"), cur_filename_utf8);
2374 et_application_window_status_bar_message (self, msg, FALSE);
2375 g_free (msg);
2376 }
2377
2378 GFile *
et_application_window_get_current_path(EtApplicationWindow * self)2379 et_application_window_get_current_path (EtApplicationWindow *self)
2380 {
2381 EtApplicationWindowPrivate *priv;
2382
2383 g_return_val_if_fail (ET_APPLICATION_WINDOW (self), NULL);
2384
2385 priv = et_application_window_get_instance_private (self);
2386
2387 return et_browser_get_current_path (ET_BROWSER (priv->browser));
2388 }
2389
2390 GtkWidget *
et_application_window_get_scan_dialog(EtApplicationWindow * self)2391 et_application_window_get_scan_dialog (EtApplicationWindow *self)
2392 {
2393 EtApplicationWindowPrivate *priv;
2394
2395 g_return_val_if_fail (self != NULL, NULL);
2396
2397 priv = et_application_window_get_instance_private (self);
2398
2399 return priv->scan_dialog;
2400 }
2401
2402 void
et_application_window_apply_changes(EtApplicationWindow * self)2403 et_application_window_apply_changes (EtApplicationWindow *self)
2404 {
2405 EtApplicationWindowPrivate *priv;
2406
2407 g_return_if_fail (ET_APPLICATION_WINDOW (self));
2408
2409 priv = et_application_window_get_instance_private (self);
2410
2411 if (priv->scan_dialog)
2412 {
2413 et_scan_dialog_apply_changes (ET_SCAN_DIALOG (priv->scan_dialog));
2414 }
2415
2416 if (priv->search_dialog)
2417 {
2418 et_search_dialog_apply_changes (ET_SEARCH_DIALOG (priv->search_dialog));
2419 }
2420 }
2421
2422 /*
2423 * Disable (FALSE) / Enable (TRUE) all user widgets in the tag area
2424 */
2425 void
et_application_window_tag_area_set_sensitive(EtApplicationWindow * self,gboolean sensitive)2426 et_application_window_tag_area_set_sensitive (EtApplicationWindow *self,
2427 gboolean sensitive)
2428 {
2429 EtApplicationWindowPrivate *priv;
2430
2431 g_return_if_fail (ET_APPLICATION_WINDOW (self));
2432
2433 priv = et_application_window_get_instance_private (self);
2434
2435 g_return_if_fail (priv->tag_area != NULL);
2436
2437 /* TAG Area (entries + buttons). */
2438 gtk_widget_set_sensitive (gtk_bin_get_child (GTK_BIN (priv->tag_area)),
2439 sensitive);
2440 }
2441
2442 void
et_application_window_file_area_clear(EtApplicationWindow * self)2443 et_application_window_file_area_clear (EtApplicationWindow *self)
2444 {
2445 EtApplicationWindowPrivate *priv;
2446
2447 g_return_if_fail (ET_APPLICATION_WINDOW (self));
2448
2449 priv = et_application_window_get_instance_private (self);
2450
2451 et_file_area_clear (ET_FILE_AREA (priv->file_area));
2452 }
2453
2454 const gchar *
et_application_window_file_area_get_filename(EtApplicationWindow * self)2455 et_application_window_file_area_get_filename (EtApplicationWindow *self)
2456 {
2457 EtApplicationWindowPrivate *priv;
2458
2459 g_return_val_if_fail (ET_APPLICATION_WINDOW (self), NULL);
2460
2461 priv = et_application_window_get_instance_private (self);
2462
2463 return et_file_area_get_filename (ET_FILE_AREA (priv->file_area));
2464 }
2465
2466 void
et_application_window_file_area_set_file_fields(EtApplicationWindow * self,const ET_File * ETFile)2467 et_application_window_file_area_set_file_fields (EtApplicationWindow *self,
2468 const ET_File *ETFile)
2469 {
2470 EtApplicationWindowPrivate *priv;
2471
2472 g_return_if_fail (ET_APPLICATION_WINDOW (self));
2473
2474 priv = et_application_window_get_instance_private (self);
2475
2476 et_file_area_set_file_fields (ET_FILE_AREA (priv->file_area), ETFile);
2477 }
2478
2479 void
et_application_window_file_area_set_header_fields(EtApplicationWindow * self,EtFileHeaderFields * fields)2480 et_application_window_file_area_set_header_fields (EtApplicationWindow *self,
2481 EtFileHeaderFields *fields)
2482 {
2483 EtApplicationWindowPrivate *priv;
2484
2485 g_return_if_fail (ET_APPLICATION_WINDOW (self));
2486
2487 priv = et_application_window_get_instance_private (self);
2488
2489 et_file_area_set_header_fields (ET_FILE_AREA (priv->file_area), fields);
2490 }
2491
2492 /*
2493 * Disable (FALSE) / Enable (TRUE) all user widgets in the file area
2494 */
2495 void
et_application_window_file_area_set_sensitive(EtApplicationWindow * self,gboolean sensitive)2496 et_application_window_file_area_set_sensitive (EtApplicationWindow *self,
2497 gboolean sensitive)
2498 {
2499 EtApplicationWindowPrivate *priv;
2500
2501 g_return_if_fail (ET_APPLICATION_WINDOW (self));
2502
2503 priv = et_application_window_get_instance_private (self);
2504
2505 g_return_if_fail (priv->file_area != NULL);
2506
2507 /* File Area. */
2508 gtk_widget_set_sensitive (gtk_bin_get_child (GTK_BIN (priv->file_area)),
2509 sensitive);
2510 }
2511
2512 static void
set_action_state(EtApplicationWindow * self,const gchar * action_name,gboolean enabled)2513 set_action_state (EtApplicationWindow *self,
2514 const gchar *action_name,
2515 gboolean enabled)
2516 {
2517 GSimpleAction *action;
2518
2519 action = G_SIMPLE_ACTION (g_action_map_lookup_action (G_ACTION_MAP (self),
2520 action_name));
2521
2522 if (action == NULL)
2523 {
2524 g_error ("Unable to find action '%s' in application window",
2525 action_name);
2526 }
2527
2528 g_simple_action_set_enabled (action, enabled);
2529 }
2530
2531 /* et_application_window_disable_command_actions:
2532 * Disable buttons when saving files (do not disable Quit button).
2533 */
2534 void
et_application_window_disable_command_actions(EtApplicationWindow * self)2535 et_application_window_disable_command_actions (EtApplicationWindow *self)
2536 {
2537 GtkDialog *dialog;
2538
2539 dialog = GTK_DIALOG (et_application_window_get_scan_dialog (self));
2540
2541 /* Scanner Window */
2542 if (dialog)
2543 {
2544 gtk_dialog_set_response_sensitive (dialog, GTK_RESPONSE_APPLY, FALSE);
2545 }
2546
2547 /* "File" menu commands */
2548 set_action_state (self, "open-with", FALSE);
2549 set_action_state (self, "invert-selection", FALSE);
2550 set_action_state (self, "delete", FALSE);
2551 set_action_state (self, "go-first", FALSE);
2552 set_action_state (self, "go-previous", FALSE);
2553 set_action_state (self, "go-next", FALSE);
2554 set_action_state (self, "go-last", FALSE);
2555 set_action_state (self, "remove-tags", FALSE);
2556 set_action_state (self, "undo-file-changes", FALSE);
2557 set_action_state (self, "redo-file-changes", FALSE);
2558 set_action_state (self, "save", FALSE);
2559 set_action_state (self, "save-force", FALSE);
2560 set_action_state (self, "undo-last-changes", FALSE);
2561 set_action_state (self, "redo-last-changes", FALSE);
2562
2563 /* FIXME: "Scanner" menu commands */
2564 /*set_action_state (self, "scan-mode", FALSE);*/
2565 }
2566
2567
2568 /* et_application_window_update_actions:
2569 * Set to sensitive/unsensitive the state of each button into
2570 * the commands area and menu items in function of state of the "main list".
2571 */
2572 void
et_application_window_update_actions(EtApplicationWindow * self)2573 et_application_window_update_actions (EtApplicationWindow *self)
2574 {
2575 GtkDialog *dialog;
2576
2577 dialog = GTK_DIALOG (et_application_window_get_scan_dialog (self));
2578
2579 if (!ETCore->ETFileDisplayedList)
2580 {
2581 /* No file found */
2582
2583 /* File and Tag frames */
2584 et_application_window_file_area_set_sensitive (self, FALSE);
2585 et_application_window_tag_area_set_sensitive (self, FALSE);
2586
2587 /* Tool bar buttons (the others are covered by the menu) */
2588 set_action_state (self, "stop", FALSE);
2589
2590 /* Scanner Window */
2591 if (dialog)
2592 {
2593 gtk_dialog_set_response_sensitive (dialog, GTK_RESPONSE_APPLY,
2594 FALSE);
2595 }
2596
2597 /* Menu commands */
2598 set_action_state (self, "open-with", FALSE);
2599 set_action_state (self, "invert-selection", FALSE);
2600 set_action_state (self, "delete", FALSE);
2601 /* FIXME: set_action_state (self, "sort-mode", FALSE); */
2602 set_action_state (self, "go-previous", FALSE);
2603 set_action_state (self, "go-next", FALSE);
2604 set_action_state (self, "go-first", FALSE);
2605 set_action_state (self, "go-last", FALSE);
2606 set_action_state (self, "remove-tags", FALSE);
2607 set_action_state (self, "undo-file-changes", FALSE);
2608 set_action_state (self, "redo-file-changes", FALSE);
2609 set_action_state (self, "save", FALSE);
2610 set_action_state (self, "save-force", FALSE);
2611 set_action_state (self, "undo-last-changes", FALSE);
2612 set_action_state (self, "redo-last-changes", FALSE);
2613 set_action_state (self, "find", FALSE);
2614 set_action_state (self, "show-load-filenames", FALSE);
2615 set_action_state (self, "show-playlist", FALSE);
2616 set_action_state (self, "run-player", FALSE);
2617 /* FIXME set_action_state (self, "scan-mode", FALSE);*/
2618 set_action_state (self, "file-artist-view", FALSE);
2619
2620 return;
2621 }else
2622 {
2623 GList *selfilelist = NULL;
2624 ET_File *etfile;
2625 gboolean has_undo = FALSE;
2626 gboolean has_redo = FALSE;
2627 //gboolean has_to_save = FALSE;
2628 GtkTreeSelection *selection;
2629
2630 /* File and Tag frames */
2631 et_application_window_file_area_set_sensitive (self, TRUE);
2632 et_application_window_tag_area_set_sensitive (self, TRUE);
2633
2634 /* Tool bar buttons */
2635 set_action_state (self, "stop", FALSE);
2636
2637 /* Scanner Window */
2638 if (dialog)
2639 {
2640 gtk_dialog_set_response_sensitive (dialog, GTK_RESPONSE_APPLY,
2641 TRUE);
2642 }
2643
2644 /* Commands into menu */
2645 set_action_state (self, "open-with", TRUE);
2646 set_action_state (self, "invert-selection", TRUE);
2647 set_action_state (self, "delete", TRUE);
2648 /* FIXME set_action_state (self, "sort-mode", TRUE); */
2649 set_action_state (self, "remove-tags", TRUE);
2650 set_action_state (self, "find", TRUE);
2651 set_action_state (self, "show-load-filenames", TRUE);
2652 set_action_state (self, "show-playlist", TRUE);
2653 set_action_state (self, "run-player", TRUE);
2654 /* FIXME set_action_state (self, "scan-mode", TRUE); */
2655 set_action_state (self, "file-artist-view", TRUE);
2656
2657 /* Check if one of the selected files has undo or redo data */
2658 {
2659 GList *l;
2660
2661 selection = et_application_window_browser_get_selection (self);
2662 selfilelist = gtk_tree_selection_get_selected_rows(selection, NULL);
2663
2664 for (l = selfilelist; l != NULL; l = g_list_next (l))
2665 {
2666 etfile = et_application_window_browser_get_et_file_from_path (self,
2667 l->data);
2668 has_undo |= ET_File_Data_Has_Undo_Data(etfile);
2669 has_redo |= ET_File_Data_Has_Redo_Data(etfile);
2670 /* has_to_save |= et_file_check_saved (etfile); */
2671 if ((has_undo && has_redo /*&& has_to_save*/) || !l->next) // Useless to check the other files
2672 break;
2673 }
2674
2675 g_list_free_full (selfilelist, (GDestroyNotify)gtk_tree_path_free);
2676 }
2677
2678 /* Enable undo commands if there are undo data */
2679 if (has_undo)
2680 {
2681 set_action_state (self, "undo-file-changes", TRUE);
2682 }
2683 else
2684 {
2685 set_action_state (self, "undo-file-changes", FALSE);
2686 }
2687
2688 /* Enable redo commands if there are redo data */
2689 if (has_redo)
2690 {
2691 set_action_state (self, "redo-file-changes", TRUE);
2692 }
2693 else
2694 {
2695 set_action_state (self, "redo-file-changes", FALSE);
2696 }
2697
2698 /* Enable save file command if file has been changed */
2699 // Desactivated because problem with only one file in the list, as we can't change the selected file => can't mark file as changed
2700 /*if (has_to_save)
2701 ui_widget_set_sensitive(MENU_FILE, AM_SAVE, FALSE);
2702 else*/
2703 set_action_state (self, "save", TRUE);
2704
2705 set_action_state (self, "save-force", TRUE);
2706
2707 /* Enable undo command if there are data into main undo list (history list) */
2708 if (et_history_list_has_undo (ETCore->ETHistoryFileList))
2709 {
2710 set_action_state (self, "undo-last-changes", TRUE);
2711 }
2712 else
2713 {
2714 set_action_state (self, "undo-last-changes", FALSE);
2715 }
2716
2717 /* Enable redo commands if there are data into main redo list (history list) */
2718 if (et_history_list_has_redo (ETCore->ETHistoryFileList))
2719 {
2720 set_action_state (self, "redo-last-changes", TRUE);
2721 }
2722 else
2723 {
2724 set_action_state (self, "redo-last-changes", FALSE);
2725 }
2726
2727 {
2728 GVariant *variant;
2729 const gchar *state;
2730
2731 variant = g_action_group_get_action_state (G_ACTION_GROUP (self),
2732 "file-artist-view");
2733
2734 state = g_variant_get_string (variant, NULL);
2735
2736 if (strcmp (state, "artist") == 0)
2737 {
2738 set_action_state (self, "collapse-tree", FALSE);
2739 set_action_state (self, "reload-tree", FALSE);
2740 }
2741 else if (strcmp (state, "file") == 0)
2742 {
2743 set_action_state (self, "collapse-tree", TRUE);
2744 set_action_state (self, "reload-tree", TRUE);
2745 }
2746 else
2747 {
2748 g_assert_not_reached ();
2749 }
2750
2751 g_variant_unref (variant);
2752 }
2753 }
2754
2755 if (!ETCore->ETFileDisplayedList->prev) /* Is it the 1st item ? */
2756 {
2757 set_action_state (self, "go-previous", FALSE);
2758 set_action_state (self, "go-first", FALSE);
2759 }
2760 else
2761 {
2762 set_action_state (self, "go-previous", TRUE);
2763 set_action_state (self, "go-first", TRUE);
2764 }
2765
2766 if (!ETCore->ETFileDisplayedList->next) /* Is it the last item ? */
2767 {
2768 set_action_state (self, "go-next", FALSE);
2769 set_action_state (self, "go-last", FALSE);
2770 }
2771 else
2772 {
2773 set_action_state (self, "go-next", TRUE);
2774 set_action_state (self, "go-last", TRUE);
2775 }
2776 }
2777
2778 void
et_application_window_set_busy_cursor(EtApplicationWindow * self)2779 et_application_window_set_busy_cursor (EtApplicationWindow *self)
2780 {
2781 EtApplicationWindowPrivate *priv;
2782
2783 g_return_if_fail (ET_APPLICATION_WINDOW (self));
2784
2785 priv = et_application_window_get_instance_private (self);
2786
2787 if (!priv->cursor)
2788 {
2789 priv->cursor = gdk_cursor_new_for_display (gdk_window_get_display (gtk_widget_get_window (GTK_WIDGET (self))),
2790 GDK_WATCH);
2791
2792 }
2793
2794 gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (self)),
2795 priv->cursor);
2796 }
2797
2798 void
et_application_window_set_normal_cursor(EtApplicationWindow * self)2799 et_application_window_set_normal_cursor (EtApplicationWindow *self)
2800 {
2801 g_return_if_fail (ET_APPLICATION_WINDOW (self));
2802
2803 /* Back to standard cursor */
2804 gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (self)), NULL);
2805 }
2806
2807 /*
2808 * Display controls according the kind of tag... (Hide some controls if not available for a tag type)
2809 */
2810 void
et_application_window_tag_area_display_controls(EtApplicationWindow * self,const ET_File * ETFile)2811 et_application_window_tag_area_display_controls (EtApplicationWindow *self,
2812 const ET_File *ETFile)
2813 {
2814 EtApplicationWindowPrivate *priv;
2815
2816 g_return_if_fail (ET_APPLICATION_WINDOW (self));
2817 g_return_if_fail (ETFile != NULL && ETFile->ETFileDescription != NULL);
2818
2819 priv = et_application_window_get_instance_private (self);
2820
2821 et_tag_area_update_controls (ET_TAG_AREA (priv->tag_area), ETFile);
2822 }
2823
2824 void
et_application_window_browser_entry_set_text(EtApplicationWindow * self,const gchar * text)2825 et_application_window_browser_entry_set_text (EtApplicationWindow *self,
2826 const gchar *text)
2827 {
2828 EtApplicationWindowPrivate *priv;
2829
2830 priv = et_application_window_get_instance_private (self);
2831
2832 et_browser_entry_set_text (ET_BROWSER (priv->browser), text);
2833 }
2834
2835 void
et_application_window_browser_label_set_text(EtApplicationWindow * self,const gchar * text)2836 et_application_window_browser_label_set_text (EtApplicationWindow *self,
2837 const gchar *text)
2838 {
2839 EtApplicationWindowPrivate *priv;
2840
2841 priv = et_application_window_get_instance_private (self);
2842
2843 et_browser_label_set_text (ET_BROWSER (priv->browser), text);
2844 }
2845
2846 ET_File *
et_application_window_browser_get_et_file_from_path(EtApplicationWindow * self,GtkTreePath * path)2847 et_application_window_browser_get_et_file_from_path (EtApplicationWindow *self,
2848 GtkTreePath *path)
2849 {
2850 EtApplicationWindowPrivate *priv;
2851
2852 priv = et_application_window_get_instance_private (self);
2853
2854 return et_browser_get_et_file_from_path (ET_BROWSER (priv->browser), path);
2855 }
2856
2857 ET_File *
et_application_window_browser_get_et_file_from_iter(EtApplicationWindow * self,GtkTreeIter * iter)2858 et_application_window_browser_get_et_file_from_iter (EtApplicationWindow *self,
2859 GtkTreeIter *iter)
2860 {
2861 EtApplicationWindowPrivate *priv;
2862
2863 priv = et_application_window_get_instance_private (self);
2864
2865 return et_browser_get_et_file_from_iter (ET_BROWSER (priv->browser), iter);
2866 }
2867
2868 GtkTreeSelection *
et_application_window_browser_get_selection(EtApplicationWindow * self)2869 et_application_window_browser_get_selection (EtApplicationWindow *self)
2870 {
2871 EtApplicationWindowPrivate *priv;
2872
2873 priv = et_application_window_get_instance_private (self);
2874
2875 return et_browser_get_selection (ET_BROWSER (priv->browser));
2876 }
2877
2878 GtkTreeViewColumn *
et_application_window_browser_get_column_for_column_id(EtApplicationWindow * self,gint column_id)2879 et_application_window_browser_get_column_for_column_id (EtApplicationWindow *self,
2880 gint column_id)
2881 {
2882 EtApplicationWindowPrivate *priv;
2883
2884 priv = et_application_window_get_instance_private (self);
2885
2886 return et_browser_get_column_for_column_id (ET_BROWSER (priv->browser),
2887 column_id);
2888 }
2889
2890 GtkSortType
et_application_window_browser_get_sort_order_for_column_id(EtApplicationWindow * self,gint column_id)2891 et_application_window_browser_get_sort_order_for_column_id (EtApplicationWindow *self,
2892 gint column_id)
2893 {
2894 EtApplicationWindowPrivate *priv;
2895
2896 priv = et_application_window_get_instance_private (self);
2897
2898 return et_browser_get_sort_order_for_column_id (ET_BROWSER (priv->browser),
2899 column_id);
2900 }
2901
2902 void
et_application_window_browser_select_file_by_iter_string(EtApplicationWindow * self,const gchar * iter_string,gboolean select)2903 et_application_window_browser_select_file_by_iter_string (EtApplicationWindow *self,
2904 const gchar *iter_string,
2905 gboolean select)
2906 {
2907 EtApplicationWindowPrivate *priv;
2908
2909 priv = et_application_window_get_instance_private (self);
2910
2911 et_browser_select_file_by_iter_string (ET_BROWSER (priv->browser),
2912 iter_string, select);
2913 }
2914
2915 void
et_application_window_browser_select_file_by_et_file(EtApplicationWindow * self,const ET_File * file,gboolean select)2916 et_application_window_browser_select_file_by_et_file (EtApplicationWindow *self,
2917 const ET_File *file,
2918 gboolean select)
2919 {
2920 EtApplicationWindowPrivate *priv;
2921
2922 priv = et_application_window_get_instance_private (self);
2923
2924 return et_browser_select_file_by_et_file (ET_BROWSER (priv->browser), file,
2925 select);
2926 }
2927
2928 GtkTreePath *
et_application_window_browser_select_file_by_et_file2(EtApplicationWindow * self,const ET_File * file,gboolean select,GtkTreePath * start_path)2929 et_application_window_browser_select_file_by_et_file2 (EtApplicationWindow *self,
2930 const ET_File *file,
2931 gboolean select,
2932 GtkTreePath *start_path)
2933 {
2934 EtApplicationWindowPrivate *priv;
2935
2936 priv = et_application_window_get_instance_private (self);
2937
2938 return et_browser_select_file_by_et_file2 (ET_BROWSER (priv->browser),
2939 file, select, start_path);
2940 }
2941
2942 ET_File *
et_application_window_browser_select_file_by_dlm(EtApplicationWindow * self,const gchar * string,gboolean select)2943 et_application_window_browser_select_file_by_dlm (EtApplicationWindow *self,
2944 const gchar *string,
2945 gboolean select)
2946 {
2947 EtApplicationWindowPrivate *priv;
2948
2949 priv = et_application_window_get_instance_private (self);
2950
2951 return et_browser_select_file_by_dlm (ET_BROWSER (priv->browser), string,
2952 select);
2953 }
2954
2955 void
et_application_window_browser_unselect_all(EtApplicationWindow * self)2956 et_application_window_browser_unselect_all (EtApplicationWindow *self)
2957 {
2958 EtApplicationWindowPrivate *priv;
2959
2960 priv = et_application_window_get_instance_private (self);
2961
2962 et_application_window_update_et_file_from_ui (self);
2963
2964 et_browser_unselect_all (ET_BROWSER (priv->browser));
2965 ETCore->ETFileDisplayed = NULL;
2966 }
2967
2968 void
et_application_window_browser_refresh_list(EtApplicationWindow * self)2969 et_application_window_browser_refresh_list (EtApplicationWindow *self)
2970 {
2971 EtApplicationWindowPrivate *priv;
2972
2973 g_return_if_fail (ET_APPLICATION_WINDOW (self));
2974
2975 priv = et_application_window_get_instance_private (self);
2976
2977 et_browser_refresh_list (ET_BROWSER (priv->browser));
2978 }
2979
2980 void
et_application_window_browser_refresh_file_in_list(EtApplicationWindow * self,const ET_File * file)2981 et_application_window_browser_refresh_file_in_list (EtApplicationWindow *self,
2982 const ET_File *file)
2983 {
2984 EtApplicationWindowPrivate *priv;
2985
2986 g_return_if_fail (ET_APPLICATION_WINDOW (self));
2987
2988 priv = et_application_window_get_instance_private (self);
2989
2990 et_browser_refresh_file_in_list (ET_BROWSER (priv->browser), file);
2991 }
2992
2993 static void
quit_confirmed(EtApplicationWindow * self)2994 quit_confirmed (EtApplicationWindow *self)
2995 {
2996 /* Save the configuration when exiting. */
2997 et_application_window_apply_changes (self);
2998
2999 /* Quit EasyTAG. */
3000 Log_Print (LOG_OK, _("Normal exit"));
3001
3002 gtk_widget_destroy (GTK_WIDGET (self));
3003 }
3004
3005 static void
save_and_quit(EtApplicationWindow * self)3006 save_and_quit (EtApplicationWindow *self)
3007 {
3008 /* Save modified tags */
3009 if (Save_All_Files_With_Answer (FALSE) == -1)
3010 return;
3011
3012 quit_confirmed (self);
3013 }
3014
3015 void
et_application_window_quit(EtApplicationWindow * self)3016 et_application_window_quit (EtApplicationWindow *self)
3017 {
3018 GtkWidget *msgbox;
3019 gint response;
3020
3021 /* If you change the displayed data and quit immediately */
3022 et_application_window_update_et_file_from_ui (self);
3023
3024 /* Check if all files have been saved before exit */
3025 if (g_settings_get_boolean (MainSettings, "confirm-when-unsaved-files")
3026 && et_file_list_check_all_saved (ETCore->ETFileList) != TRUE)
3027 {
3028 /* Some files haven't been saved */
3029 msgbox = gtk_message_dialog_new (GTK_WINDOW (self),
3030 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
3031 GTK_MESSAGE_QUESTION,
3032 GTK_BUTTONS_NONE,
3033 "%s",
3034 _("Some files have been modified but not saved"));
3035 gtk_dialog_add_buttons (GTK_DIALOG (msgbox), _("_Discard"),
3036 GTK_RESPONSE_NO, _("_Cancel"),
3037 GTK_RESPONSE_CANCEL, _("_Save"),
3038 GTK_RESPONSE_YES, NULL);
3039 gtk_dialog_set_default_response (GTK_DIALOG (msgbox),
3040 GTK_RESPONSE_YES);
3041 gtk_window_set_title (GTK_WINDOW (msgbox), _("Quit"));
3042 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (msgbox),
3043 "%s",
3044 _("Do you want to save them before quitting?"));
3045 response = gtk_dialog_run (GTK_DIALOG (msgbox));
3046 gtk_widget_destroy (msgbox);
3047
3048 switch (response)
3049 {
3050 case GTK_RESPONSE_YES:
3051 save_and_quit (self);
3052 break;
3053 case GTK_RESPONSE_NO:
3054 quit_confirmed (self);
3055 break;
3056 case GTK_RESPONSE_CANCEL:
3057 case GTK_RESPONSE_DELETE_EVENT:
3058 return;
3059 break;
3060 default:
3061 g_assert_not_reached ();
3062 break;
3063 }
3064
3065 }
3066 else
3067 {
3068 quit_confirmed (self);
3069 }
3070 }
3071