[easytag/wip/application-window] Move scan dialog to EtScanDialog object WIP
- From: David King <davidk src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [easytag/wip/application-window] Move scan dialog to EtScanDialog object WIP
- Date: Wed, 1 Jan 2014 12:42:23 +0000 (UTC)
commit 509cad8d91e3c475400e7f12288ab22f162684d1
Author: David King <amigadave amigadave com>
Date: Sun Dec 29 23:15:26 2013 +0000
Move scan dialog to EtScanDialog object WIP
Makefile.am | 2 +
TODO | 4 -
src/application_window.c | 103 ++-
src/application_window.h | 4 +
src/bar.c | 14 +-
src/browser.c | 3 +-
src/cddb_dialog.c | 35 +-
src/easytag.c | 160 +--
src/easytag.h | 2 +-
src/load_files_dialog.c | 18 +-
src/misc.c | 1 -
src/playlist_dialog.c | 3 +-
src/preferences_dialog.c | 2 +-
src/scan.c | 3978 +---------------------------------------------
src/scan.h | 95 +-
src/scan_dialog.c | 3873 ++++++++++++++++++++++++++++++++++++++++++++
src/scan_dialog.h | 94 ++
src/search_dialog.c | 2 +-
src/setting.c | 21 +-
src/setting.h | 3 -
20 files changed, 4262 insertions(+), 4155 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 4672595..ccc7105 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -64,6 +64,7 @@ easytag_SOURCES = \
src/playlist_dialog.c \
src/preferences_dialog.c \
src/scan.c \
+ src/scan_dialog.c \
src/search_dialog.c \
src/setting.c \
src/vcedit.c \
@@ -107,6 +108,7 @@ easytag_headers = \
src/playlist_dialog.h \
src/preferences_dialog.h \
src/scan.h \
+ src/scan_dialog.h \
src/search_dialog.h \
src/setting.h \
src/ui_manager.h \
diff --git a/TODO b/TODO
index 16e1389..7f35978 100644
--- a/TODO
+++ b/TODO
@@ -4,9 +4,6 @@ TODO List
General tidying
---------------
-* Convert user guide to help in Mallard
-* Avoid using GdkWindow all over the place
-** Drop the window moving and size restoring code
* Use PNG icons and drop the XPM ones
* Use GProxyResolver for proxy settings
* Port configuration settings to use GSettings
@@ -14,7 +11,6 @@ General tidying
** Additionally, make I/O asynchronous
** Always use the GLib encoding for filenames (convert for display)
* Use g_spawn_async() or g_app_info_launch() to spawn processes
-* Instantiate windows on first use, not at startup
* GObjectification
* Avoid using gtk_events_pending(), use asynchronous operations instead
* Add a test suite
diff --git a/src/application_window.c b/src/application_window.c
index 3d3987a..9d855d5 100644
--- a/src/application_window.c
+++ b/src/application_window.c
@@ -36,6 +36,7 @@
#include "preferences_dialog.h"
#include "search_dialog.h"
#include "scan.h"
+#include "scan_dialog.h"
#include "setting.h"
/* TODO: Use G_DEFINE_TYPE_WITH_PRIVATE. */
@@ -52,6 +53,7 @@ struct _EtApplicationWindowPrivate
GtkWidget *load_files_dialog;
GtkWidget *playlist_dialog;
GtkWidget *preferences_dialog;
+ GtkWidget *scan_dialog;
GtkWidget *search_dialog;
/* Tag area labels. */
@@ -111,7 +113,7 @@ Convert_Space_Into_Underscore (GtkWidget *entry)
{
gchar *string = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
- Scan_Convert_Space_Into_Undescore (string);
+ Scan_Convert_Space_Into_Underscore (string);
gtk_entry_set_text (GTK_ENTRY (entry), string);
g_free (string);
}
@@ -149,9 +151,13 @@ Convert_Letter_Uppercase (GtkWidget *entry)
static void
Convert_First_Letters_Uppercase (GtkWidget *entry)
{
- gchar *string = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
+ EtScanDialog *dialog;
+ gchar *string;
+
+ string = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
+ dialog = ET_SCAN_DIALOG (et_application_window_get_scan_dialog (ET_APPLICATION_WINDOW (MainWindow)));
- Scan_Process_Fields_First_Letters_Uppercase (string);
+ Scan_Process_Fields_First_Letters_Uppercase (dialog, string);
gtk_entry_set_text (GTK_ENTRY (entry), string);
g_free (string);
}
@@ -1648,6 +1654,7 @@ et_application_window_finalize (GObject *object)
g_clear_object (&priv->load_files_dialog);
g_clear_object (&priv->playlist_dialog);
g_clear_object (&priv->preferences_dialog);
+ g_clear_object (&priv->scan_dialog);
g_clear_object (&priv->search_dialog);
G_OBJECT_CLASS (et_application_window_parent_class)->finalize (object);
@@ -1670,6 +1677,7 @@ et_application_window_init (EtApplicationWindow *self)
priv->load_files_dialog = NULL;
priv->playlist_dialog = NULL;
priv->preferences_dialog = NULL;
+ priv->scan_dialog = NULL;
priv->search_dialog = NULL;
window = GTK_WINDOW (self);
@@ -1966,6 +1974,95 @@ et_application_window_search_cddb_for_selection (G_GNUC_UNUSED GtkAction *action
et_cddb_dialog_search_from_selection (ET_CDDB_DIALOG (priv->cddb_dialog));
}
+GtkWidget *
+et_application_window_get_scan_dialog (EtApplicationWindow *self)
+{
+ EtApplicationWindowPrivate *priv;
+
+ g_return_val_if_fail (self != NULL, NULL);
+
+ priv = et_application_window_get_instance_private (self);
+
+ return priv->scan_dialog;
+}
+
+void
+et_application_window_show_scan_dialog (GtkAction *action, gpointer user_data)
+{
+ EtApplicationWindowPrivate *priv;
+ gboolean active;
+ EtApplicationWindow *self = ET_APPLICATION_WINDOW (user_data);
+
+ priv = et_application_window_get_instance_private (self);
+ active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
+
+ if (!active)
+ {
+ if (priv->scan_dialog)
+ {
+ gtk_widget_hide (priv->scan_dialog);
+ }
+ else
+ {
+ return;
+ }
+ }
+ else
+ {
+ if (priv->scan_dialog)
+ {
+ gtk_widget_show (priv->scan_dialog);
+ }
+ else
+ {
+ priv->scan_dialog = GTK_WIDGET (et_scan_dialog_new ());
+ }
+ }
+}
+
+/*
+ * Action when Scan button is pressed
+ */
+void
+et_application_window_scan_selected_files (G_GNUC_UNUSED GtkAction *action,
+ gpointer user_data)
+{
+ EtApplicationWindowPrivate *priv;
+ EtApplicationWindow *self = ET_APPLICATION_WINDOW (user_data);
+
+ priv = et_application_window_get_instance_private (self);
+
+ et_scan_dialog_scan_selected_files (ET_SCAN_DIALOG (priv->scan_dialog));
+}
+
+/*
+ * et_on_action_select_scan_mode:
+ * @action: the action on which the signal was emitted
+ * @current: the member of the action group which has just been activated
+ * @user_data: user data set when the signal handler was connected
+ *
+ * Select the current scanner mode and open the scanner window.
+ */
+void
+et_on_action_select_scan_mode (GtkRadioAction *action, GtkRadioAction *current,
+ gpointer user_data)
+{
+ EtApplicationWindowPrivate *priv;
+ EtApplicationWindow *self = ET_APPLICATION_WINDOW (user_data);
+ gint active_value;
+
+ priv = et_application_window_get_instance_private (self);
+
+ active_value = gtk_radio_action_get_current_value (action);
+
+ if (SCANNER_TYPE != active_value)
+ {
+ SCANNER_TYPE = active_value;
+ }
+
+ et_scan_dialog_open (ET_SCAN_DIALOG (priv->scan_dialog), SCANNER_TYPE);
+}
+
/*
* Disable (FALSE) / Enable (TRUE) all user widgets in the tag area
*/
diff --git a/src/application_window.h b/src/application_window.h
index 7d764f3..31b28ae 100644
--- a/src/application_window.h
+++ b/src/application_window.h
@@ -62,6 +62,10 @@ void et_application_window_show_preferences_dialog (GtkAction *action, gpointer
GtkWidget * et_application_window_get_cddb_dialog (EtApplicationWindow *self);
void et_application_window_show_cddb_dialog (GtkAction *action, gpointer user_data);
void et_application_window_search_cddb_for_selection (GtkAction *action, gpointer user_data);
+GtkWidget * et_application_window_get_scan_dialog (EtApplicationWindow *self);
+void et_application_window_show_scan_dialog (GtkAction *action, gpointer user_data);
+void et_application_window_scan_selected_files (GtkAction *action, gpointer user_data);
+void et_on_action_select_scan_mode (GtkRadioAction *action, GtkRadioAction *current, gpointer user_data);
void et_application_window_hide_log_area (EtApplicationWindow *self);
void et_application_window_show_log_area (EtApplicationWindow *self);
diff --git a/src/bar.c b/src/bar.c
index 0b55278..d6138d8 100644
--- a/src/bar.c
+++ b/src/bar.c
@@ -30,7 +30,7 @@
#include "preferences_dialog.h"
#include "setting.h"
#include "browser.h"
-#include "scan.h"
+#include "scan_dialog.h"
#include "cddb_dialog.h"
#include "log.h"
#include "misc.h"
@@ -223,7 +223,8 @@ Create_UI (GtkWindow *window, GtkWidget **ppmenubar, GtkWidget **pptoolbar)
{ AM_LAST, GTK_STOCK_GOTO_LAST, _("_Last File"), "<Primary>End",
_("Last file"), G_CALLBACK (Action_Select_Last_File) },
{ AM_SCAN_FILES, GTK_STOCK_APPLY, _("S_can Files"), NULL,
- _("Scan selected files"), G_CALLBACK (Action_Scan_Selected_Files) },
+ _("Scan selected files"),
+ G_CALLBACK (et_application_window_scan_selected_files) },
{ AM_REMOVE, GTK_STOCK_CLEAR, _("_Remove Tags"), "<Primary>E",
_("Remove tags"), G_CALLBACK (Action_Remove_Selected_Tags) },
{ AM_UNDO, GTK_STOCK_UNDO, _("_Undo Last Files Changes"), "<Primary>Z",
@@ -347,7 +348,8 @@ Create_UI (GtkWindow *window, GtkWidget **ppmenubar, GtkWidget **pptoolbar)
{ AM_BROWSER_HIDDEN_DIR, NULL, _("Show Hidden Directories"),
NULL, _("Show hidden directories"), G_CALLBACK(Browser_Tree_Rebuild),
BROWSE_HIDDEN_DIR },
#endif /* !G_OS_WIN32 */
{ AM_SCANNER_SHOW, "document-properties", _("_Show Scanner"), NULL,
- _("Show scanner"), G_CALLBACK (et_scan_show),
+ _("Show scanner"),
+ G_CALLBACK (et_application_window_show_scan_dialog),
OPEN_SCANNER_WINDOW_ON_STARTUP },
};
@@ -363,13 +365,13 @@ Create_UI (GtkWindow *window, GtkWidget **ppmenubar, GtkWidget **pptoolbar)
GtkRadioActionEntry scanner_mode_entries[] =
{
{ AM_SCANNER_FILL_TAG, "document-properties", _("_Fill Tags…"), NULL,
- _("Fill tags"), SCANNER_FILL_TAG },
+ _("Fill tags"), ET_SCAN_TYPE_FILL_TAG },
{ AM_SCANNER_RENAME_FILE, "document-properties",
_("_Rename Files and Directories…"), NULL,
- _("Rename files and directories"), SCANNER_RENAME_FILE },
+ _("Rename files and directories"), ET_SCAN_TYPE_RENAME_FILE },
{ AM_SCANNER_PROCESS_FIELDS, "document-properties",
_("_Process Fields…"), NULL, _("Process Fields"),
- SCANNER_PROCESS_FIELDS }
+ ET_SCAN_TYPE_PROCESS_FIELDS }
};
GError *error = NULL;
diff --git a/src/browser.c b/src/browser.c
index 94c2248..48bc2b8 100644
--- a/src/browser.c
+++ b/src/browser.c
@@ -1,4 +1,3 @@
-/* browser.c - 2000/04/28 */
/*
* EasyTAG - Tag editor for MP3 and Ogg Vorbis files
* Copyright (C) 2000-2003 Jerome Couderc <easytag gmail com>
@@ -43,7 +42,7 @@
#include "easytag.h"
#include "browser.h"
#include "et_core.h"
-#include "scan.h"
+#include "scan_dialog.h"
#include "bar.h"
#include "log.h"
#include "misc.h"
diff --git a/src/cddb_dialog.c b/src/cddb_dialog.c
index df5c73a..8c52349 100644
--- a/src/cddb_dialog.c
+++ b/src/cddb_dialog.c
@@ -39,11 +39,12 @@
#include <errno.h>
#include "gtk2_compat.h"
+#include "application_window.h"
#include "cddb_dialog.h"
#include "easytag.h"
#include "et_core.h"
#include "browser.h"
-#include "scan.h"
+#include "scan_dialog.h"
#include "log.h"
#include "misc.h"
#include "setting.h"
@@ -2600,11 +2601,20 @@ Cddb_Set_Track_Infos_To_File_List (EtCDDBDialog *self)
ET_Manage_Changes_Of_File_Data(*etfile,FileName,FileTag);
- // Then run current scanner if asked...
- if (ScannerWindow && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(CddbRunScanner)) )
- Scan_Select_Mode_And_Run_Scanner(*etfile);
+ /* Then run current scanner if requested. */
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (CddbRunScanner)))
+ {
+ EtScanDialog *dialog;
+
+ dialog = ET_SCAN_DIALOG (et_application_window_get_scan_dialog (ET_APPLICATION_WINDOW
(MainWindow)));
- } else if (cddbtrackalbum && file_iterlist && file_iterlist->data)
+ if (dialog)
+ {
+ Scan_Select_Mode_And_Run_Scanner (dialog, *etfile);
+ }
+ }
+ }
+ else if (cddbtrackalbum && file_iterlist && file_iterlist->data)
{
ET_File *etfile;
File_Name *FileName = NULL;
@@ -2688,9 +2698,18 @@ Cddb_Set_Track_Infos_To_File_List (EtCDDBDialog *self)
ET_Manage_Changes_Of_File_Data(etfile,FileName,FileTag);
- // Then run current scanner if asked...
- if (ScannerWindow && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(CddbRunScanner)) )
- Scan_Select_Mode_And_Run_Scanner(etfile);
+ /* Then run current scanner if requested. */
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (CddbRunScanner)))
+ {
+ EtScanDialog *dialog;
+
+ dialog = ET_SCAN_DIALOG (et_application_window_get_scan_dialog (ET_APPLICATION_WINDOW
(MainWindow)));
+
+ if (dialog)
+ {
+ Scan_Select_Mode_And_Run_Scanner (dialog, etfile);
+ }
+ }
}
if(!file_iterlist->next) break;
diff --git a/src/easytag.c b/src/easytag.c
index 6de1777..73cf47d 100644
--- a/src/easytag.c
+++ b/src/easytag.c
@@ -40,6 +40,7 @@
#include "gtk2_compat.h"
#include "easytag.h"
#include "application.h"
+#include "application_window.h"
#include "browser.h"
#include "log.h"
#include "misc.h"
@@ -47,7 +48,7 @@
#include "cddb_dialog.h"
#include "preferences_dialog.h"
#include "setting.h"
-#include "scan.h"
+#include "scan_dialog.h"
#include "mpeg_header.h"
#include "id3_tag.h"
#include "ogg_tag.h"
@@ -93,7 +94,6 @@ static gint SF_ButtonPressed_Delete_File;
static void Handle_Crash (gint signal_id);
#endif /* !G_OS_WIN32 */
-static void Disable_Command_Buttons (void);
static gboolean Write_File_Tag (ET_File *ETFile, gboolean hide_msgbox);
static gint Save_File (ET_File *ETFile, gboolean multiple_files,
gboolean force_saving_files);
@@ -172,7 +172,6 @@ common_init (GApplication *application)
Main_Stop_Button_Pressed = FALSE;
Init_Custom_Icons();
Init_Mouse_Cursor();
- Init_ScannerWindow();
BrowserEntryModel = NULL;
TrackEntryComboModel = NULL;
GenreComboModel = NULL;
@@ -588,8 +587,7 @@ void Action_Select_First_File (void)
}
Update_Command_Buttons_Sensivity();
- Scan_Rename_File_Generate_Preview();
- Scan_Fill_Tag_Generate_Preview();
+ et_scan_dialog_update_previews (ET_SCAN_DIALOG (et_application_window_get_scan_dialog
(ET_APPLICATION_WINDOW (MainWindow))));
if (SET_FOCUS_TO_FIRST_TAG_FIELD)
gtk_widget_grab_focus(GTK_WIDGET(TitleEntry));
@@ -622,8 +620,7 @@ void Action_Select_Prev_File (void)
// gdk_beep(); // Warm the user
Update_Command_Buttons_Sensivity();
- Scan_Rename_File_Generate_Preview();
- Scan_Fill_Tag_Generate_Preview();
+ et_scan_dialog_update_previews (ET_SCAN_DIALOG (et_application_window_get_scan_dialog
(ET_APPLICATION_WINDOW (MainWindow))));
if (SET_FOCUS_TO_FIRST_TAG_FIELD)
gtk_widget_grab_focus(GTK_WIDGET(TitleEntry));
@@ -656,8 +653,7 @@ void Action_Select_Next_File (void)
// gdk_beep(); // Warm the user
Update_Command_Buttons_Sensivity();
- Scan_Rename_File_Generate_Preview();
- Scan_Fill_Tag_Generate_Preview();
+ et_scan_dialog_update_previews (ET_SCAN_DIALOG (et_application_window_get_scan_dialog
(ET_APPLICATION_WINDOW (MainWindow))));
if (SET_FOCUS_TO_FIRST_TAG_FIELD)
gtk_widget_grab_focus(GTK_WIDGET(TitleEntry));
@@ -687,8 +683,7 @@ void Action_Select_Last_File (void)
}
Update_Command_Buttons_Sensivity();
- Scan_Rename_File_Generate_Preview();
- Scan_Fill_Tag_Generate_Preview();
+ et_scan_dialog_update_previews (ET_SCAN_DIALOG (et_application_window_get_scan_dialog
(ET_APPLICATION_WINDOW (MainWindow))));
if (SET_FOCUS_TO_FIRST_TAG_FIELD)
gtk_widget_grab_focus(GTK_WIDGET(TitleEntry));
@@ -712,89 +707,9 @@ void Action_Select_Nth_File_By_Etfile (ET_File *ETFile)
ET_Display_File_Data_To_UI(ETFile);
Update_Command_Buttons_Sensivity();
- Scan_Rename_File_Generate_Preview();
- Scan_Fill_Tag_Generate_Preview();
+ et_scan_dialog_update_previews (ET_SCAN_DIALOG (et_application_window_get_scan_dialog
(ET_APPLICATION_WINDOW (MainWindow))));
}
-
-/*
- * Action when Scan button is pressed
- */
-void Action_Scan_Selected_Files (void)
-{
- gint progress_bar_index;
- gint selectcount;
- gchar progress_bar_text[30];
- double fraction;
- GList *selfilelist = NULL;
- GList *l;
- ET_File *etfile;
- GtkTreeSelection *selection;
-
- g_return_if_fail (ETCore->ETFileDisplayedList != NULL ||
- BrowserList != NULL);
-
- /* Check if scanner window is opened */
- if (!ScannerWindow)
- {
- Open_ScannerWindow(SCANNER_TYPE);
- Statusbar_Message(_("Select Mode and Mask, and redo the same action"),TRUE);
- return;
- }
-
- /* Save the current displayed data */
- ET_Save_File_Data_From_UI(ETCore->ETFileDisplayed);
-
- /* Initialize status bar */
- selectcount =
gtk_tree_selection_count_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(BrowserList)));
- gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(ProgressBar),0);
- progress_bar_index = 0;
- g_snprintf(progress_bar_text, 30, "%d/%d", progress_bar_index, selectcount);
- gtk_progress_bar_set_text(GTK_PROGRESS_BAR(ProgressBar), progress_bar_text);
-
- /* Set to unsensitive all command buttons (except Quit button) */
- Disable_Command_Buttons();
-
- progress_bar_index = 0;
-
- selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(BrowserList));
- selfilelist = gtk_tree_selection_get_selected_rows(selection, NULL);
-
- for (l = selfilelist; l != NULL; l = g_list_next (l))
- {
- etfile = Browser_List_Get_ETFile_From_Path (l->data);
-
- // Run the current scanner
- Scan_Select_Mode_And_Run_Scanner(etfile);
-
- fraction = (++progress_bar_index) / (double) selectcount;
- gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(ProgressBar), fraction);
- g_snprintf(progress_bar_text, 30, "%d/%d", progress_bar_index, selectcount);
- gtk_progress_bar_set_text(GTK_PROGRESS_BAR(ProgressBar), progress_bar_text);
-
- /* Needed to refresh status bar */
- while (gtk_events_pending())
- gtk_main_iteration();
- }
-
- g_list_free_full (selfilelist, (GDestroyNotify)gtk_tree_path_free);
-
- // Refresh the whole list (faster than file by file) to show changes
- Browser_List_Refresh_Whole_List();
-
- /* Display the current file */
- ET_Display_File_Data_To_UI(ETCore->ETFileDisplayed);
-
- /* To update state of command buttons */
- Update_Command_Buttons_Sensivity();
-
- gtk_progress_bar_set_text(GTK_PROGRESS_BAR(ProgressBar), "");
- gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(ProgressBar), 0);
- Statusbar_Message(_("All tags have been scanned"),TRUE);
-}
-
-
-
/*
* Action when Remove button is pressed
*/
@@ -1956,31 +1871,6 @@ Action_Select_Browser_Style (void)
}
/*
- * et_on_action_select_scan_mode:
- * @action: the action on which the signal was emitted
- * @current: the member of the action group which has just been activated
- * @user_data: user data set when the signal handler was connected
- *
- * Select the current scanner mode and open the scanner window.
- */
-void
-et_on_action_select_scan_mode (GtkRadioAction *action, GtkRadioAction *current,
- gpointer user_data)
-{
- gint active_value;
-
- active_value = gtk_radio_action_get_current_value (action);
-
- if (SCANNER_TYPE != active_value)
- {
- SCANNER_TYPE = active_value;
- }
-
- Open_ScannerWindow (SCANNER_TYPE);
-}
-
-
-/*
* Scans the specified directory: and load files into a list.
* If the path doesn't exist, we free the previous loaded list of files.
*/
@@ -2376,12 +2266,15 @@ ui_widget_set_sensitive (const gchar *menu, const gchar *action, gboolean sensit
* Update_Command_Buttons_Sensivity: Set to sensitive/unsensitive the state of each button into
* the commands area and menu items in function of state of the "main list".
*/
-void Update_Command_Buttons_Sensivity (void)
+void
+Update_Command_Buttons_Sensivity (void)
{
EtApplicationWindow *window;
+ GtkDialog *dialog;
GtkAction *uiaction;
window = ET_APPLICATION_WINDOW (MainWindow);
+ dialog = GTK_DIALOG (et_application_window_get_scan_dialog (window));
if (!ETCore->ETFileDisplayedList)
{
@@ -2396,10 +2289,10 @@ void Update_Command_Buttons_Sensivity (void)
g_object_set(uiaction, "sensitive", FALSE, NULL);
/* Scanner Window */
- if (ScannerWindow)
+ if (dialog)
{
- gtk_dialog_set_response_sensitive (GTK_DIALOG (ScannerWindow),
- GTK_RESPONSE_APPLY, FALSE);
+ gtk_dialog_set_response_sensitive (dialog, GTK_RESPONSE_APPLY,
+ FALSE);
}
/* Menu commands */
@@ -2475,10 +2368,10 @@ void Update_Command_Buttons_Sensivity (void)
g_object_set(uiaction, "sensitive", FALSE, NULL);
/* Scanner Window */
- if (ScannerWindow)
+ if (dialog)
{
- gtk_dialog_set_response_sensitive (GTK_DIALOG (ScannerWindow),
- GTK_RESPONSE_APPLY, TRUE);
+ gtk_dialog_set_response_sensitive (dialog, GTK_RESPONSE_APPLY,
+ TRUE);
}
/* Commands into menu */
@@ -2603,14 +2496,17 @@ void Update_Command_Buttons_Sensivity (void)
/*
* Just to disable buttons when we are saving files (do not disable Quit button)
*/
-static void
+void
Disable_Command_Buttons (void)
{
+ GtkDialog *dialog;
+
+ dialog = GTK_DIALOG (et_application_window_get_scan_dialog (ET_APPLICATION_WINDOW (MainWindow)));
+
/* Scanner Window */
- if (ScannerWindow)
+ if (dialog)
{
- gtk_dialog_set_response_sensitive (GTK_DIALOG (ScannerWindow),
- GTK_RESPONSE_APPLY, FALSE);
+ gtk_dialog_set_response_sensitive (dialog, GTK_RESPONSE_APPLY, FALSE);
}
/* "File" menu commands */
@@ -2651,9 +2547,13 @@ Init_Load_Default_Dir (void)
ET_Core_Free();
ET_Core_Initialize();
- // Open the scanner window
+ /* FIXME: Open the scanner window. */
+ /*
if (OPEN_SCANNER_WINDOW_ON_STARTUP)
- Open_ScannerWindow(SCANNER_TYPE); // Open the last selected scanner
+ {
+ et_application_window_show_scan_dialog (ET_APPLICATION_WINDOW (MainWindow));
+ }
+ */
if (INIT_DIRECTORY)
{
diff --git a/src/easytag.h b/src/easytag.h
index 79bbd81..7322871 100644
--- a/src/easytag.h
+++ b/src/easytag.h
@@ -101,6 +101,7 @@ gboolean ReadingDirectory;
/**************
* Prototypes *
**************/
+void Disable_Command_Buttons (void);
void et_on_action_select_all (void);
void et_on_action_unselect_all (void);
void Action_Invert_Files_Selection (void);
@@ -111,7 +112,6 @@ void Action_Select_Last_File (void);
void Action_Select_Nth_File_By_Position (gulong num_item);
void Action_Select_Nth_File_By_Etfile (ET_File *ETFile);
-void Action_Scan_Selected_Files (void);
void Action_Remove_Selected_Tags (void);
gint Action_Undo_Selected_Files (void);
gint Action_Redo_Selected_File (void);
diff --git a/src/load_files_dialog.c b/src/load_files_dialog.c
index a012658..4e70cd6 100644
--- a/src/load_files_dialog.c
+++ b/src/load_files_dialog.c
@@ -23,6 +23,7 @@
#include <gdk/gdkkeysyms.h>
#include <glib/gi18n.h>
+#include "application_window.h"
#include "bar.h"
#include "browser.h"
#include "charset.h"
@@ -31,7 +32,7 @@
#include "log.h"
#include "misc.h"
#include "picture.h"
-#include "scan.h"
+#include "scan_dialog.h"
#include "setting.h"
/* TODO: Use G_DEFINE_TYPE_WITH_PRIVATE. */
@@ -136,9 +137,18 @@ Load_Filename_Set_Filenames (EtLoadFilesDialog *self)
g_free(filename_new_utf8);
- // Then run current scanner if asked...
- if (ScannerWindow &&
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->load_file_run_scanner)) )
- Scan_Select_Mode_And_Run_Scanner(ETFile);
+ /* Then run current scanner if requested. */
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->load_file_run_scanner)))
+ {
+ EtScanDialog *dialog;
+
+ dialog = ET_SCAN_DIALOG (et_application_window_get_scan_dialog (ET_APPLICATION_WINDOW
(MainWindow)));
+
+ if (dialog)
+ {
+ Scan_Select_Mode_And_Run_Scanner (dialog, ETFile);
+ }
+ }
}
g_free(list_text);
}
diff --git a/src/misc.c b/src/misc.c
index d319b62..0a49292 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -34,7 +34,6 @@
#include "setting.h"
#include "bar.h"
#include "preferences_dialog.h"
-#include "scan.h"
#include "genres.h"
#include "log.h"
#include "charset.h"
diff --git a/src/playlist_dialog.c b/src/playlist_dialog.c
index 1b03514..9e88fa9 100644
--- a/src/playlist_dialog.c
+++ b/src/playlist_dialog.c
@@ -31,6 +31,7 @@
#include "misc.h"
#include "picture.h"
#include "scan.h"
+#include "scan_dialog.h"
#include "setting.h"
/* TODO: Use G_DEFINE_TYPE_WITH_PRIVATE. */
@@ -446,7 +447,7 @@ write_button_clicked (EtPlaylistDialog *self)
}
if (RFS_CONVERT_SPACE_INTO_UNDERSCORE)
{
- Scan_Convert_Space_Into_Undescore(playlist_basename_utf8);
+ Scan_Convert_Space_Into_Underscore (playlist_basename_utf8);
}
if (RFS_REMOVE_SPACES)
{
diff --git a/src/preferences_dialog.c b/src/preferences_dialog.c
index 4924891..a6f8b34 100644
--- a/src/preferences_dialog.c
+++ b/src/preferences_dialog.c
@@ -35,7 +35,7 @@
#include "setting.h"
#include "bar.h"
#include "misc.h"
-#include "scan.h"
+#include "scan_dialog.h"
#include "easytag.h"
#include "browser.h"
#include "cddb_dialog.h"
diff --git a/src/scan.c b/src/scan.c
index 46e2941..44f069f 100644
--- a/src/scan.c
+++ b/src/scan.c
@@ -1,1640 +1,55 @@
-/*
- * EasyTAG - Tag editor for MP3 and Ogg Vorbis files
- * Copyright (C) 2000-2003 Jerome Couderc <easytag gmail com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-
#include "scan.h"
-#include <gtk/gtk.h>
#include <string.h>
-#include <stdlib.h>
-#include <gdk/gdkkeysyms.h>
-#include <config.h>
-#include <glib/gi18n.h>
-
-#include "application_window.h"
-#include "gtk2_compat.h"
-#include "easytag.h"
-#include "preferences_dialog.h"
-#include "setting.h"
-#include "id3_tag.h"
-#include "bar.h"
-#include "browser.h"
-#include "log.h"
-#include "misc.h"
-#include "et_core.h"
-#include "crc32.h"
-#include "charset.h"
-
-
-#define step(a,b) (b-a)+1
-
-
-/****************
- * Declarations *
- ****************/
-static GtkWidget *ScanTagMaskCombo = NULL;
-static GtkWidget *RenameFileMaskCombo = NULL;
-static GtkWidget *ScannerOptionCombo = NULL;
-static GtkWidget *RenameFilePrefixPathButton = NULL;
-
-static GtkWidget *ScanTagFrame;
-static GtkWidget *RenameFileFrame;
-static GtkWidget *ProcessFieldsFrame;
-static GtkWidget *FillTagPreviewLabel = NULL;
-static GtkWidget *RenameFilePreviewLabel = NULL;
-
-static GtkListStore *RenameFileListModel;
-static GtkListStore *ScanTagListModel;
-
-static GtkWidget *ProcessFileNameField;
-static GtkWidget *ProcessTitleField;
-static GtkWidget *ProcessArtistField;
-static GtkWidget *ProcessAlbumArtistField;
-static GtkWidget *ProcessAlbumField;
-static GtkWidget *ProcessGenreField;
-static GtkWidget *ProcessCommentField;
-static GtkWidget *ProcessComposerField;
-static GtkWidget *ProcessOrigArtistField;
-static GtkWidget *ProcessCopyrightField;
-static GtkWidget *ProcessURLField;
-static GtkWidget *ProcessEncodedByField;
-static GtkWidget *ProcessFieldsConvertIntoSpace = NULL;
-static GtkWidget *ProcessFieldsConvertSpace = NULL;
-static GtkWidget *ProcessFieldsConvert = NULL;
-static GtkWidget *ProcessFieldsConvertLabelTo;
-static GtkWidget *ProcessFieldsConvertTo = NULL;
-static GtkWidget *ProcessFieldsConvertFrom = NULL;
-static GtkWidget *ProcessFieldsAllUppercase = NULL;
-static GtkWidget *ProcessFieldsAllDowncase = NULL;
-static GtkWidget *ProcessFieldsFirstLetterUppercase = NULL;
-static GtkWidget *ProcessFieldsFirstLettersUppercase = NULL;
-static GtkWidget *ProcessFieldsDetectRomanNumerals = NULL;
-static GtkWidget *ProcessFieldsRemoveSpace = NULL;
-static GtkWidget *ProcessFieldsInsertSpace = NULL;
-static GtkWidget *ProcessFieldsOnlyOneSpace = NULL;
-
-static GtkWidget *LegendFrame = NULL;
-static GtkWidget *LegendButton = NULL;
-
-static GtkWidget *MaskEditorButton = NULL;
-static GtkWidget *MaskEditorFrame = NULL;
-static GtkWidget *MaskEditorVBox;
-static GtkWidget *MaskEditorHBox;
-static GtkWidget *MaskEditorScrollWindow;
-static GtkWidget *MaskEditorList;
-static GtkWidget *MaskEditorEntry;
-static GtkWidget *MaskEditorNewButton;
-static GtkWidget *MaskEditorCopyButton;
-static GtkWidget *MaskEditorAddButton;
-static GtkWidget *MaskEditorRemoveButton;
-static GtkWidget *MaskEditorUpButton;
-static GtkWidget *MaskEditorDownButton;
-static GtkWidget *MaskEditorSaveButton;
-
-static const guint BOX_SPACING = 6;
-
-/* Some predefined masks -- IMPORTANT: Null-terminate me! */
-static const gchar *Scan_Masks [] =
-{
- "%a - %b"G_DIR_SEPARATOR_S"%n - %t",
- "%a_-_%b"G_DIR_SEPARATOR_S"%n_-_%t",
- "%a - %b (%y)"G_DIR_SEPARATOR_S"%n - %a - %t",
- "%a_-_%b_(%y)"G_DIR_SEPARATOR_S"%n_-_%a_-_%t",
- "%a - %b (%y) - %g"G_DIR_SEPARATOR_S"%n - %a - %t",
- "%a_-_%b_(%y)_-_%g"G_DIR_SEPARATOR_S"%n_-_%a_-_%t",
- "%a - %b"G_DIR_SEPARATOR_S"%n. %t",
- "%a_-_%b"G_DIR_SEPARATOR_S"%n._%t",
- "%a-%b"G_DIR_SEPARATOR_S"%n-%t",
- "%b"G_DIR_SEPARATOR_S"%n. %a - %t",
- "%b"G_DIR_SEPARATOR_S"%n._%a_-_%t",
- "%b"G_DIR_SEPARATOR_S"%n - %a - %t",
- "%b"G_DIR_SEPARATOR_S"%n_-_%a_-_%t",
- "%b"G_DIR_SEPARATOR_S"%n-%a-%t",
- "%a-%b"G_DIR_SEPARATOR_S"%n-%t",
- "%a"G_DIR_SEPARATOR_S"%b"G_DIR_SEPARATOR_S"%n. %t",
- "%g"G_DIR_SEPARATOR_S"%a"G_DIR_SEPARATOR_S"%b"G_DIR_SEPARATOR_S"%t",
- "%a_-_%b-%n-%t-%y",
- "%a - %b"G_DIR_SEPARATOR_S"%n. %t(%c)",
- "%t",
- "Track%n",
- "Track%i %n",
- NULL
-};
-
-static const gchar *Rename_File_Masks [] =
-{
- "%n - %a - %t",
- "%n_-_%a_-_%t",
- "%n. %a - %t",
- "%n._%a_-_%t",
- "%a - %b"G_DIR_SEPARATOR_S"%n - %t",
- "%a_-_%b"G_DIR_SEPARATOR_S"%n_-_%t",
- "%a - %b (%y) - %g"G_DIR_SEPARATOR_S"%n - %t",
- "%a_-_%b_(%y)_-_%g"G_DIR_SEPARATOR_S"%n_-_%t",
- "%n - %t",
- "%n_-_%t",
- "%n. %t",
- "%n._%t",
- "%n - %a - %b - %t",
- "%n_-_%a_-_%b_-_%t",
- "%a - %b - %t",
- "%a_-_%b_-_%t",
- "%a - %b - %n - %t",
- "%a_-_%b_-_%n_-_%t",
- "%a - %t",
- "%a_-_%t",
- "Track %n",
- NULL
-};
-
-/**gchar *Rename_Directory_Masks [] =
-{
- "%a - %b",
- "%a_-_%b",
- "%a - %b (%y) - %g",
- "%a_-_%b_(%y)_-_%g",
- "VA - %b (%y)",
- "VA_-_%b_(%y)",
- NULL
-};**/
-
-
-static const gchar *Scanner_Option_Menu_Items [] =
-{
- N_("Fill Tag"),
- N_("Rename File and Directory"),
- N_("Process Fields")
-};
-
-typedef enum
-{
- UNKNOWN = 0, /* Default value when initialized */
- LEADING_SEPARATOR, /* characters before the first code */
- TRAILING_SEPARATOR, /* characters after the last code */
- SEPARATOR, /* item is a separator between two codes */
- DIRECTORY_SEPARATOR, /* item is a separator between two codes with character '/' (G_DIR_SEPARATOR) */
- FIELD, /* item contains text (not empty) of entry */
- EMPTY_FIELD /* item when entry contains no text */
-} Mask_Item_Type;
-
-
-
-/*
- * Used into Rename File Scanner
- */
-typedef struct _File_Mask_Item File_Mask_Item;
-struct _File_Mask_Item
-{
- Mask_Item_Type type;
- gchar *string;
-};
/*
- * Used into Scan Tag Scanner
+ * Function to replace underscore '_' by a space. No need to reallocate.
*/
-typedef struct _Scan_Mask_Item Scan_Mask_Item;
-struct _Scan_Mask_Item
-{
- gchar code; // The code of the mask without % (ex: %a => a)
- gchar *string; // The string found by the scanner for the code defined the line above
-};
-
-
-
-/**************
- * Prototypes *
- **************/
-static void Scan_Tag_With_Mask (ET_File *ETFile);
-static void ScannerWindow_Quit (void);
-static void Scan_Toggle_Legend_Button (void);
-static void Scan_Toggle_Mask_Editor_Button (void);
-static void Scan_Option_Button (void);
-static void entry_check_scan_tag_mask (GtkEntry *entry, gpointer user_data);
-
-static GList *Scan_Generate_New_Tag_From_Mask (ET_File *ETFile, gchar *mask);
-static void Scan_Rename_File_Prefix_Path (void);
-static void Scan_Free_File_Rename_List (GList *list);
-static void Scan_Free_File_Fill_Tag_List (GList *list);
-
-static gchar **Scan_Return_File_Tag_Field_From_Mask_Code (File_Tag *FileTag,
- gchar code);
-static void Scan_Process_Fields_Functions (gchar **string);
-
-static gint Scan_Word_Is_Roman_Numeral (const gchar *text);
-
-static void Process_Fields_Convert_Check_Button_Toggled (GtkWidget *object);
-static void Process_Fields_First_Letters_Check_Button_Toggled (GtkWidget *object);
-static void Select_Fields_Invert_Selection (void);
-static void Select_Fields_Select_Unselect_All (void);
-static void Select_Fields_Set_Sensitive (void);
-
-static void Mask_Editor_List_Row_Selected (GtkTreeSelection* selection,
- gpointer data);
-static void Mask_Editor_List_Set_Row_Visible (GtkTreeModel *treeModel,
- GtkTreeIter *rowIter);
-static void Mask_Editor_List_New (void);
-static void Mask_Editor_List_Duplicate (void);
-static void Mask_Editor_List_Add (void);
-static void Mask_Editor_List_Remove (void);
-static void Mask_Editor_List_Move_Up (void);
-static void Mask_Editor_List_Move_Down (void);
-static void Mask_Editor_List_Save_Button (void);
-static void Mask_Editor_Entry_Changed (void);
-static gboolean Mask_Editor_List_Key_Press (GtkWidget *widget,
- GdkEvent *event);
-
-static void Mask_Editor_Clean_Up_Masks_List (void);
-
-static void Scanner_Option_Menu_Activate_Item (GtkWidget *widget, gpointer data);
-
-static int roman2int (const char *str);
-static const char *int2roman (int num);
-static char *int2roman_r (int num, char * str, size_t len);
-
-static void Scan_Convert_Character (gchar **string);
-static GList *Scan_Generate_New_Tag_From_Mask (ET_File *ETFile, gchar *mask);
-static void Scan_Set_Scanner_Window_Init_Position (void);
-
-static void et_scan_on_response (GtkDialog *dialog, gint response_id,
- gpointer user_data);
-
-
-/*************
- * Functions *
- *************/
-
-void Init_ScannerWindow (void)
-{
- ScannerWindow = NULL;
- ScannerOptionCombo= NULL;
-}
-
-
-/*
- * Uses the filename and path to fill tag information
- * Note: mask and source are read from the right to the left
- */
-static void
-Scan_Tag_With_Mask (ET_File *ETFile)
-{
- GList *fill_tag_list = NULL;
- GList *l;
- gchar **dest = NULL;
- gchar *mask; // The 'mask' in the entry
- gchar *filename_utf8;
- File_Tag *FileTag;
-
- g_return_if_fail (ScannerWindow != NULL && ScanTagMaskCombo != NULL);
- g_return_if_fail (ETFile != NULL);
-
- mask = g_strdup(gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(ScanTagMaskCombo)))));
- if (!mask) return;
-
- // Create a new File_Tag item
- FileTag = ET_File_Tag_Item_New();
- ET_Copy_File_Tag_Item(ETFile,FileTag);
-
- // Process this mask with file
- fill_tag_list = Scan_Generate_New_Tag_From_Mask(ETFile,mask);
-
- for (l = fill_tag_list; l != NULL; l = g_list_next (l))
- {
- Scan_Mask_Item *mask_item = l->data;
-
- // Get the target entry for this code
- dest = Scan_Return_File_Tag_Field_From_Mask_Code(FileTag,mask_item->code);
-
- // We display the text affected to the code
- if ( dest && ( OVERWRITE_TAG_FIELD || *dest==NULL || strlen(*dest)==0 ) )
- ET_Set_Field_File_Tag_Item(dest,mask_item->string);
-
- }
-
- Scan_Free_File_Fill_Tag_List(fill_tag_list);
-
- // Set the default text to comment
- if (SET_DEFAULT_COMMENT && (OVERWRITE_TAG_FIELD || FileTag->comment==NULL || strlen(FileTag->comment)==0
) )
- ET_Set_Field_File_Tag_Item((void *)&FileTag->comment,DEFAULT_COMMENT);
-
- // Set CRC-32 value as default comment (for files with ID3 tag only ;-)
- if (SET_CRC32_COMMENT && (OVERWRITE_TAG_FIELD || FileTag->comment==NULL || strlen(FileTag->comment)==0 )
)
- {
- GError *error = NULL;
- guint32 crc32_value;
- gchar *buffer;
- ET_File_Description *ETFileDescription;
-
- ETFileDescription = ETFile->ETFileDescription;
- switch (ETFileDescription->TagType)
- {
- case ID3_TAG:
- if (crc32_file_with_ID3_tag (((File_Name *)((GList *)ETFile->FileNameNew)->data)->value,
- &crc32_value, &error))
- {
- buffer = g_strdup_printf ("%.8" G_GUINT32_FORMAT,
- crc32_value);
- ET_Set_Field_File_Tag_Item((void *)&FileTag->comment,buffer);
- g_free(buffer);
- }
- else
- {
- Log_Print (LOG_ERROR,
- _("Cannot calculate CRC value of file (%s)"),
- error->message);
- g_error_free (error);
- }
- break;
- default:
- break;
- }
- }
-
-
- // Save changes of the 'File_Tag' item
- ET_Manage_Changes_Of_File_Data(ETFile,NULL,FileTag);
-
- g_free(mask);
- Statusbar_Message(_("Tag successfully scanned"),TRUE);
- filename_utf8 = g_path_get_basename( ((File_Name *)ETFile->FileNameNew->data)->value_utf8 );
- Log_Print(LOG_OK,_("Tag successfully scanned: %s"),filename_utf8);
- g_free(filename_utf8);
-}
-
-static GList *
-Scan_Generate_New_Tag_From_Mask (ET_File *ETFile, gchar *mask)
+void
+Scan_Convert_Underscore_Into_Space (gchar *string)
{
- GList *fill_tag_list = NULL;
- gchar *filename_utf8;
gchar *tmp;
- gchar *buf;
- gchar *separator;
- gchar *string;
- gint len, i, loop=0;
- gchar **mask_splitted;
- gchar **file_splitted;
- guint mask_splitted_number;
- guint file_splitted_number;
- guint mask_splitted_index;
- guint file_splitted_index;
- Scan_Mask_Item *mask_item;
-
- g_return_val_if_fail (ETFile != NULL && mask != NULL, NULL);
-
- filename_utf8 = g_strdup(((File_Name *)((GList *)ETFile->FileNameNew)->data)->value_utf8);
- if (!filename_utf8) return NULL;
-
- // Remove extension of file (if found)
- tmp = strrchr(filename_utf8,'.');
- for (i=0; i<=(gint)ET_FILE_DESCRIPTION_SIZE; i++)
- {
- if ( strcasecmp(tmp,ETFileDescription[i].Extension)==0 )
- {
- *tmp = 0; //strrchr(source,'.') = 0;
- break;
- }
- }
-
- if (i==ET_FILE_DESCRIPTION_SIZE)
- {
- gchar *tmp1 = g_path_get_basename(filename_utf8);
- Log_Print(LOG_ERROR,_("Tag scanner: strange… the extension '%s' was not found in filename
'%s'"),tmp,tmp1);
- g_free(tmp1);
- }
-
- // Replace characters into mask and filename before parsing
- if (FTS_CONVERT_UNDERSCORE_AND_P20_INTO_SPACE)
- {
- Scan_Convert_Underscore_Into_Space(mask);
- Scan_Convert_Underscore_Into_Space(filename_utf8);
- Scan_Convert_P20_Into_Space(mask);
- Scan_Convert_P20_Into_Space(filename_utf8);
- }
- if (FTS_CONVERT_SPACE_INTO_UNDERSCORE)
- {
- Scan_Convert_Space_Into_Undescore(mask);
- Scan_Convert_Space_Into_Undescore(filename_utf8);
- }
-
-
- // Split the Scanner mask
- mask_splitted = g_strsplit(mask,G_DIR_SEPARATOR_S,0);
- // Get number of arguments into 'mask_splitted'
- for (mask_splitted_number=0;mask_splitted[mask_splitted_number];mask_splitted_number++);
-
- // Split the File Path
- file_splitted = g_strsplit(filename_utf8,G_DIR_SEPARATOR_S,0);
- // Get number of arguments into 'file_splitted'
- for (file_splitted_number=0;file_splitted[file_splitted_number];file_splitted_number++);
-
- // Set the starting position for each tab
- if (mask_splitted_number <= file_splitted_number)
- {
- mask_splitted_index = 0;
- file_splitted_index = file_splitted_number - mask_splitted_number;
- }else
- {
- mask_splitted_index = mask_splitted_number - file_splitted_number;
- file_splitted_index = 0;
- }
-
- loop = 0;
- while ( mask_splitted[mask_splitted_index]!= NULL && file_splitted[file_splitted_index]!=NULL )
- {
- gchar *mask_seq = mask_splitted[mask_splitted_index];
- gchar *file_seq = file_splitted[file_splitted_index];
- gchar *file_seq_utf8 = filename_to_display(file_seq);
-
- //g_print(">%d> seq '%s' '%s'\n",loop,mask_seq,file_seq);
- while ( mask_seq && strlen(mask_seq)>0 )
- {
-
- /*
- * Determine (first) code and destination
- */
- if ( (tmp=strchr(mask_seq,'%')) == NULL || strlen(tmp) < 2 )
- {
- break;
- }
-
- /*
- * Allocate a new iten for the fill_tag_list
- */
- mask_item = g_malloc0(sizeof(Scan_Mask_Item));
-
- // Get the code (used to determine the corresponding target entry)
- mask_item->code = tmp[1];
-
- /*
- * Delete text before the code
- */
- if ( (len = strlen(mask_seq) - strlen(tmp)) > 0 )
- {
- // Get this text in 'mask_seq'
- buf = g_strndup(mask_seq,len);
- // We remove it in 'mask_seq'
- mask_seq = mask_seq + len;
- // Find the same text at the begining of 'file_seq' ?
- if ( (strstr(file_seq,buf)) == file_seq )
- {
- file_seq = file_seq + len; // We remove it
- }else
- {
- Log_Print(LOG_ERROR,_("Scan Error: can't find separator '%s' within
'%s'"),buf,file_seq_utf8);
- }
- g_free(buf);
- }
-
- // Remove the current code into 'mask_seq'
- mask_seq = mask_seq + 2;
-
- /*
- * Determine separator between two code or trailing text (after code)
- */
- if ( mask_seq && strlen(mask_seq)>0 )
- {
- if ( (tmp=strchr(mask_seq,'%')) == NULL || strlen(tmp) < 2 )
- {
- // No more code found
- len = strlen(mask_seq);
- }else
- {
- len = strlen(mask_seq) - strlen(tmp);
- }
- separator = g_strndup(mask_seq,len);
-
- // Remove the current separator in 'mask_seq'
- mask_seq = mask_seq + len;
-
- // Try to find the separator in 'file_seq'
- if ( (tmp=strstr(file_seq,separator)) == NULL )
- {
- Log_Print(LOG_ERROR,_("Scan Error: can't find separator '%s' within
'%s'"),separator,file_seq_utf8);
- separator[0] = 0; // Needed to avoid error when calculting 'len' below
- }
-
- // Get the string affected to the code (or the corresponding entry field)
- len = strlen(file_seq) - (tmp!=NULL?strlen(tmp):0);
- string = g_strndup(file_seq,len);
-
- // Remove the current separator in 'file_seq'
- file_seq = file_seq + strlen(string) + strlen(separator);
- g_free(separator);
-
- // We get the text affected to the code
- mask_item->string = string;
- }else
- {
- // We display the remaining text, affected to the code (no more data in 'mask_seq')
- mask_item->string = g_strdup(file_seq);
- }
-
- // Add the filled mask_iten to the list
- fill_tag_list = g_list_append(fill_tag_list,mask_item);
- }
-
- g_free(file_seq_utf8);
-
- // Next sequences
- mask_splitted_index++;
- file_splitted_index++;
- loop++;
- }
-
- g_free(filename_utf8);
- g_strfreev(mask_splitted);
- g_strfreev(file_splitted);
- // The 'fill_tag_list' must be freed after use
- return fill_tag_list;
-}
-
-void Scan_Fill_Tag_Generate_Preview (void)
-{
- gchar *mask = NULL;
- gchar *preview_text = NULL;
- GList *fill_tag_list = NULL;
- GList *l;
-
- if (!ETCore->ETFileDisplayedList
- || !ScannerWindow || !RenameFileMaskCombo || !FillTagPreviewLabel
- || gtk_combo_box_get_active(GTK_COMBO_BOX(ScannerOptionCombo)) != SCANNER_FILL_TAG)
- return;
-
- mask = g_strdup(gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(ScanTagMaskCombo)))));
- if (!mask)
- return;
-
- preview_text = g_strdup("");
- fill_tag_list = Scan_Generate_New_Tag_From_Mask(ETCore->ETFileDisplayed,mask);
- for (l = fill_tag_list; l != NULL; l = g_list_next (l))
+ while ((tmp = strchr (string, '_')) != NULL)
{
- Scan_Mask_Item *mask_item = l->data;
- gchar *tmp_code = g_strdup_printf("%c",mask_item->code);
- gchar *tmp_string = g_markup_printf_escaped("%s",mask_item->string); // To avoid problem with
strings containing characters like '&'
- gchar *tmp_preview_text = preview_text;
-
- preview_text = g_strconcat(tmp_preview_text,"<b>","%",tmp_code," = ",
- "</b>","<i>",tmp_string,"</i>",NULL);
- g_free(tmp_code);
- g_free(tmp_string);
- g_free(tmp_preview_text);
-
- tmp_preview_text = preview_text;
- preview_text = g_strconcat(tmp_preview_text," || ",NULL);
- g_free(tmp_preview_text);
- }
-
- Scan_Free_File_Fill_Tag_List(fill_tag_list);
-
- if (GTK_IS_LABEL(FillTagPreviewLabel))
- {
- if (preview_text)
- {
- //gtk_label_set_text(GTK_LABEL(FillTagPreviewLabel),preview_text);
- gtk_label_set_markup(GTK_LABEL(FillTagPreviewLabel),preview_text);
- } else
- {
- gtk_label_set_text(GTK_LABEL(FillTagPreviewLabel),"");
- }
-
- // Force the window to be redrawed
- gtk_widget_queue_resize(ScannerWindow);
- }
-
- g_free(mask);
- g_free(preview_text);
-}
-
-static void
-Scan_Free_File_Fill_Tag_List (GList *list)
-{
- GList *l;
-
- list = g_list_first (list);
-
- for (l = list; l != NULL; l = g_list_next (l))
- {
- if (l->data)
- {
- g_free (((Scan_Mask_Item *)l->data)->string);
- g_free ((Scan_Mask_Item *)l->data);
- }
+ *tmp = ' ';
}
-
- g_list_free (list);
}
-
-
-/**************************
- * Scanner To Rename File *
- **************************/
/*
- * Uses tag information (displayed into tag entries) to rename file
- * Note: mask and source are read from the right to the left.
- * Note1: a mask code may be used severals times...
+ * Function to replace %20 by a space. No need to reallocate.
*/
-static void
-Scan_Rename_File_With_Mask (ET_File *ETFile)
+void
+Scan_Convert_P20_Into_Space (gchar *string)
{
- gchar *filename_generated_utf8 = NULL;
- gchar *filename_generated = NULL;
- gchar *filename_new_utf8 = NULL;
- gchar *mask = NULL;
- File_Name *FileName;
-
- g_return_if_fail (ScannerWindow != NULL || RenameFileMaskCombo != NULL ||
- ETFile != NULL);
-
- mask = g_strdup(gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(RenameFileMaskCombo)))));
- if (!mask) return;
-
- // Note : if the first character is '/', we have a path with the filename,
- // else we have only the filename. The both are in UTF-8.
- filename_generated_utf8 = Scan_Generate_New_Filename_From_Mask(ETFile,mask,FALSE);
- g_free(mask);
-
- if (!filename_generated_utf8)
- return;
- if (g_utf8_strlen(filename_generated_utf8,-1)<1)
- {
- g_free(filename_generated_utf8);
- return;
- }
+ gchar *tmp, *tmp1;
- // Convert filename to file-system encoding
- filename_generated = filename_from_display(filename_generated_utf8);
- if (!filename_generated)
+ while ((tmp = strstr (string, "%20")) != NULL)
{
- GtkWidget *msgdialog;
- msgdialog = gtk_message_dialog_new(GTK_WINDOW(ScannerWindow),
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR,
- GTK_BUTTONS_CLOSE,
- _("Could not convert filename '%s' into system filename encoding"),
- filename_generated_utf8);
- gtk_window_set_title(GTK_WINDOW(msgdialog),_("Filename translation"));
-
- gtk_dialog_run(GTK_DIALOG(msgdialog));
- gtk_widget_destroy(msgdialog);
- g_free(filename_generated_utf8);
- return;
+ tmp1 = tmp + 3;
+ *(tmp++) = ' ';
+ while (*tmp1)
+ *(tmp++) = *(tmp1++);
+ *tmp = '\0';
}
-
- /* Build the filename with the full path or relative to old path */
- filename_new_utf8 = ET_File_Name_Generate(ETFile,filename_generated_utf8);
- g_free(filename_generated);
- g_free(filename_generated_utf8);
-
- /* Set the new filename */
- // Create a new 'File_Name' item
- FileName = ET_File_Name_Item_New();
- // Save changes of the 'File_Name' item
- ET_Set_Filename_File_Name_Item(FileName,filename_new_utf8,NULL);
-
- ET_Manage_Changes_Of_File_Data(ETFile,FileName,NULL);
- g_free(filename_new_utf8);
-
- Statusbar_Message (_("New filename successfully scanned"),TRUE);
-
- filename_new_utf8 = g_path_get_basename(((File_Name *)ETFile->FileNameNew->data)->value_utf8);
- Log_Print (LOG_OK, _("New filename successfully scanned: %s"),
- filename_new_utf8);
- g_free(filename_new_utf8);
-
- return;
}
/*
- * Build the new filename using tag + mask
- * Used also to rename the directory (from the browser)
- * @param ETFile : the etfile to process
- * @param mask : the pattern to parse
- * @param no_dir_check_or_conversion : if FALSE, disable checking of a directory
- * in the mask, and don't convert "illegal" characters. This is used in the
- * function "Write_Playlist" for the content of the playlist.
- * Returns filename in UTF-8
+ * Function to replace space by '_'. No need to reallocate.
*/
-gchar *Scan_Generate_New_Filename_From_Mask (ET_File *ETFile, gchar *mask, gboolean
no_dir_check_or_conversion)
+void
+Scan_Convert_Space_Into_Underscore (gchar *string)
{
gchar *tmp;
- gchar **source = NULL;
- gchar *path_utf8_cur = NULL;
- gchar *filename_new_utf8 = NULL;
- gchar *filename_tmp = NULL;
- GList *rename_file_list = NULL;
- GList *l;
- File_Mask_Item *mask_item;
- File_Mask_Item *mask_item_prev;
- File_Mask_Item *mask_item_next;
- gint counter = 0;
-
- g_return_val_if_fail (ETFile != NULL && mask != NULL, NULL);
-
- /*
- * Check for a directory in the mask
- */
- if (!no_dir_check_or_conversion)
- {
- if (g_path_is_absolute(mask))
- {
- // Absolute directory
- }else if (strrchr(mask,G_DIR_SEPARATOR)!=NULL) // This is '/' on UNIX machines and '\' under Windows
- {
- // Relative path => set beginning of the path
- path_utf8_cur = g_path_get_dirname( ((File_Name *)ETFile->FileNameCur->data)->value_utf8 );
- }
- }
-
-
- /*
- * Parse the codes to generate a list (1rst item = 1rst code)
- */
- while ( mask!=NULL && (tmp=strrchr(mask,'%'))!=NULL && strlen(tmp)>1 )
- {
- // Mask contains some characters after the code ('%b__')
- if (strlen(tmp)>2)
- {
- mask_item = g_malloc0(sizeof(File_Mask_Item));
- if (counter)
- {
- if (strchr(tmp+2,G_DIR_SEPARATOR))
- mask_item->type = DIRECTORY_SEPARATOR;
- else
- mask_item->type = SEPARATOR;
- } else
- {
- mask_item->type = TRAILING_SEPARATOR;
- }
- mask_item->string = g_strdup(tmp+2);
- rename_file_list = g_list_prepend(rename_file_list,mask_item);
- }
-
- // Now, parses the code to get the corresponding string (from tag)
- source = Scan_Return_File_Tag_Field_From_Mask_Code((File_Tag *)ETFile->FileTag->data,tmp[1]);
- mask_item = g_malloc0(sizeof(File_Mask_Item));
- if (source && *source && strlen(*source)>0)
- {
- mask_item->type = FIELD;
- mask_item->string = g_strdup(*source);
-
- // Replace invalid characters for this field
- /* Do not replace characters in a playlist information field. */
- if (!no_dir_check_or_conversion)
- {
- ET_File_Name_Convert_Character(mask_item->string);
-
- if (RFS_CONVERT_UNDERSCORE_AND_P20_INTO_SPACE)
- {
- Scan_Convert_Underscore_Into_Space(mask_item->string);
- Scan_Convert_P20_Into_Space(mask_item->string);
- }
- if (RFS_CONVERT_SPACE_INTO_UNDERSCORE)
- {
- Scan_Convert_Space_Into_Undescore(mask_item->string);
- }
- if (RFS_REMOVE_SPACES)
- {
- Scan_Remove_Spaces(mask_item->string);
- }
- }
- }else
- {
- mask_item->type = EMPTY_FIELD;
- mask_item->string = NULL;
- }
- rename_file_list = g_list_prepend(rename_file_list,mask_item);
- *tmp = '\0'; // Cut parsed data of mask
- counter++; // To indicate that we made at least one loop to identifiate 'separator' or
'trailing_separator'
- }
-
- // It may have some characters before the last remaining code ('__%a')
- if (mask!=NULL && strlen(mask)>0)
- {
- mask_item = g_malloc0(sizeof(File_Mask_Item));
- mask_item->type = LEADING_SEPARATOR;
- mask_item->string = g_strdup(mask);
- rename_file_list = g_list_prepend(rename_file_list,mask_item);
- }
-
- if (!rename_file_list) return NULL;
-
- /*
- * For Debugging : display the "rename_file_list" list
- */
- /***{
- GList *list = g_list_first(rename_file_list);
- gint i = 0;
- g_print("## rename_file_list - start\n");
- while (list)
- {
- File_Mask_Item *mask_item = (File_Mask_Item *)list->data;
- Mask_Item_Type type = mask_item->type;
- gchar *string = mask_item->string;
-
- //g_print("item %d : \n",i++);
- //g_print(" - type :
'%s'\n",type==UNKNOWN?"UNKNOWN":type==LEADING_SEPARATOR?"LEADING_SEPARATOR":type==TRAILING_SEPARATOR?"TRAILING_SEPARATOR":type==SEPARATOR?"SEPARATOR":type==DIRECTORY_SEPARATOR?"DIRECTORY_SEPARATOR":type==FIELD?"FIELD":type==EMPTY_FIELD?"EMPTY_FIELD":"???");
- //g_print(" - string : '%s'\n",string);
- g_print("%d -> %s (%s) |
",i++,type==UNKNOWN?"UNKNOWN":type==LEADING_SEPARATOR?"LEADING_SEPARATOR":type==TRAILING_SEPARATOR?"TRAILING_SEPARATOR":type==SEPARATOR?"SEPARATOR":type==DIRECTORY_SEPARATOR?"DIRECTORY_SEPARATOR":type==FIELD?"FIELD":type==EMPTY_FIELD?"EMPTY_FIELD":"???",string);
-
- list = list->next;
- }
- g_print("\n## rename_file_list - end\n\n");
- }***/
-
- /*
- * Build the new filename with items placed into the list
- * (read the list from the end to the beginning)
- */
- filename_new_utf8 = g_strdup("");
-
- for (l = g_list_last (rename_file_list); l != NULL;
- l = g_list_previous (l))
- {
- File_Mask_Item *mask_item = l->data;
-
- if ( mask_item->type==TRAILING_SEPARATOR ) // Trailing characters of mask
- {
- // Doesn't write it if previous field is empty
- if (l->prev
- && ((File_Mask_Item *)l->prev->data)->type != EMPTY_FIELD)
- {
- filename_tmp = filename_new_utf8;
- filename_new_utf8 = g_strconcat(mask_item->string,filename_new_utf8,NULL);
- g_free(filename_tmp);
- }
- }else
- if ( mask_item->type==EMPTY_FIELD )
- // We don't concatenate the field value (empty) and the previous
- // separator (except leading separator) to the filename.
- // If the empty field is the 'first', we don't concatenate it, and the
- // next separator too.
- {
- if (l->prev)
- {
- // The empty field isn't the first.
- // If previous string is a separator, we don't use it, except if the next
- // string is a FIELD (not empty)
- mask_item_prev = l->prev->data;
- if ( mask_item_prev->type==SEPARATOR )
- {
- if (!(l->next
- && (mask_item_next = rename_file_list->next->data)
- && mask_item_next->type == FIELD))
- {
- l = l->prev;
- }
- }
- }else
- if (l->next && (mask_item_next = l->next->data)
- && mask_item_next->type == SEPARATOR)
- // We are at the 'beginning' of the mask (so empty field is the first)
- // and next field is a separator. As the separator may have been already added, we remove it
- {
- if ( filename_new_utf8 && mask_item_next->string &&
(strncmp(filename_new_utf8,mask_item_next->string,strlen(mask_item_next->string))==0) ) // To avoid crash if
filename_new_utf8 is 'empty'
- {
- filename_tmp = filename_new_utf8;
- filename_new_utf8 = g_strdup(filename_new_utf8+strlen(mask_item_next->string));
- g_free(filename_tmp);
- }
- }
-
- }else // SEPARATOR, FIELD, LEADING_SEPARATOR, DIRECTORY_SEPARATOR
- {
- filename_tmp = filename_new_utf8;
- filename_new_utf8 = g_strconcat(mask_item->string,filename_new_utf8,NULL);
- g_free(filename_tmp);
- }
- }
-
- // Free the list
- Scan_Free_File_Rename_List(rename_file_list);
-
-
- // Add current path if relative path entered
- if (path_utf8_cur)
- {
- filename_tmp = filename_new_utf8; // in UTF-8!
- filename_new_utf8 = g_strconcat(path_utf8_cur,G_DIR_SEPARATOR_S,filename_new_utf8,NULL);
- g_free(filename_tmp);
- g_free(path_utf8_cur);
- }
-
- return filename_new_utf8; // in UTF-8!
-}
-
-void Scan_Rename_File_Generate_Preview (void)
-{
- gchar *preview_text = NULL;
- gchar *mask = NULL;
-
- if (!ETCore->ETFileDisplayed
- || !ScannerWindow || !RenameFileMaskCombo || !RenameFilePreviewLabel)
- return;
-
- if (gtk_combo_box_get_active(GTK_COMBO_BOX(ScannerOptionCombo)) != SCANNER_RENAME_FILE)
- return;
-
- mask = g_strdup(gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(RenameFileMaskCombo)))));
- if (!mask)
- return;
-
- preview_text = Scan_Generate_New_Filename_From_Mask(ETCore->ETFileDisplayed,mask,FALSE);
-
- if (GTK_IS_LABEL(RenameFilePreviewLabel))
- {
- if (preview_text)
- {
- //gtk_label_set_text(GTK_LABEL(RenameFilePreviewLabel),preview_text);
- gchar *tmp_string = g_markup_printf_escaped("%s",preview_text); // To avoid problem with strings
containing characters like '&'
- gchar *str = g_strdup_printf("<i>%s</i>",tmp_string);
- gtk_label_set_markup(GTK_LABEL(RenameFilePreviewLabel),str);
- g_free(tmp_string);
- g_free(str);
- } else
- {
- gtk_label_set_text(GTK_LABEL(RenameFilePreviewLabel),"");
- }
-
- // Force the window to be redrawed
- gtk_widget_queue_resize(ScannerWindow);
- }
-
- g_free(mask);
- g_free(preview_text);
-}
-
-
-static void
-Scan_Free_File_Rename_List (GList *list)
-{
- GList *l;
-
- for (l = list; l != NULL; l = g_list_next (l))
- {
- if (l->data)
- {
- g_free (((File_Mask_Item *)l->data)->string);
- g_free ((File_Mask_Item *)l->data);
- }
- }
-
- g_list_free (list);
-}
-
-/*
- * Adds the current path of the file to the mask on the "Rename File Scanner" entry
- */
-static void
-Scan_Rename_File_Prefix_Path (void)
-{
- gint pos;
- gchar *path_tmp;
- const gchar *combo_text = NULL;
- gchar *combo_tmp;
- ET_File *ETFile = ETCore->ETFileDisplayed;
- gchar *filename_utf8_cur = ((File_Name *)ETFile->FileNameCur->data)->value_utf8;
- gchar *path_utf8_cur;
-
-
- // The path to prefix
- path_utf8_cur = g_path_get_dirname(filename_utf8_cur);
- // The current text in the combobox
- combo_text = gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(RenameFileMaskCombo))));
- /*if (!g_utf8_validate(combo_text, -1, NULL))
+ while ((tmp = strchr (string, ' ')) != NULL)
{
- combo_tmp = convert_to_utf8(combo_text);
- }else
- {
- combo_tmp = g_strdup(combo_text);
- }*/
- combo_tmp = Try_To_Validate_Utf8_String(combo_text);
-
- // If the path already exists we don't add it again
- // Use g_utf8_collate_key instead of strncmp
- if (combo_tmp && path_utf8_cur && strncmp(combo_tmp,path_utf8_cur,strlen(path_utf8_cur))!=0)
- {
- if (g_path_is_absolute(combo_tmp))
- {
- path_tmp = g_strdup(path_utf8_cur);
- } else
- {
- path_tmp = g_strconcat(path_utf8_cur,G_DIR_SEPARATOR_S,NULL);
- }
- pos = 0;
- gtk_editable_insert_text(GTK_EDITABLE(gtk_bin_get_child(GTK_BIN(RenameFileMaskCombo))),path_tmp, -1,
&pos);
- g_free(path_tmp);
- }
-
- g_free(path_utf8_cur);
-}
-
-
-/*******************************
- * Scanner To Rename Directory *
- *******************************/
-void Scan_Rename_Directory_Generate_Preview (void)
-{
- gchar *preview_text = NULL;
- gchar *mask = NULL;
-
- if (!ETCore->ETFileDisplayed
- || !RenameDirectoryWindow || !RenameDirectoryMaskCombo || !RenameDirectoryPreviewLabel)
- return;
-
- mask = g_strdup(gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(RenameDirectoryMaskCombo)))));
- if (!mask)
- return;
-
- preview_text = Scan_Generate_New_Filename_From_Mask(ETCore->ETFileDisplayed,mask,FALSE);
-
- if (GTK_IS_LABEL(RenameDirectoryPreviewLabel))
- {
- if (preview_text)
- {
- //gtk_label_set_text(GTK_LABEL(RenameFilePreviewLabel),preview_text);
- gchar *tmp_string = g_markup_printf_escaped("%s",preview_text); // To avoid problem with strings
containing characters like '&'
- gchar *str = g_strdup_printf("<i>%s</i>",tmp_string);
- gtk_label_set_markup(GTK_LABEL(RenameDirectoryPreviewLabel),str);
- g_free(tmp_string);
- g_free(str);
- } else
- {
- gtk_label_set_text(GTK_LABEL(RenameDirectoryPreviewLabel),"");
- }
-
- // Force the window to be redrawed else the preview label may be not placed correctly
- gtk_widget_queue_resize(RenameDirectoryWindow);
- }
-
- g_free(mask);
- g_free(preview_text);
-}
-
-gchar *Scan_Generate_New_Directory_Name_From_Mask (ET_File *ETFile, gchar *mask, gboolean
no_dir_check_or_conversion)
-{
- return Scan_Generate_New_Filename_From_Mask(ETFile,mask,no_dir_check_or_conversion);
-}
-
-
-
-/*****************************
- * Scanner To Process Fields *
- *****************************/
-/* See also functions : Convert_P20_And_Undescore_Into_Spaces, ... in easytag.c */
-static void
-Scan_Process_Fields (ET_File *ETFile)
-{
- File_Name *FileName = NULL;
- File_Tag *FileTag = NULL;
- File_Name *st_filename;
- File_Tag *st_filetag;
- gchar *filename_utf8;
- gchar *string;
-
- g_return_if_fail (ScannerWindow != NULL || ETFile != NULL);
-
- st_filename = (File_Name *)ETFile->FileNameNew->data;
- st_filetag = (File_Tag *)ETFile->FileTag->data;
-
- /* Process the filename */
- if (st_filename != NULL)
- {
- if (st_filename->value_utf8 && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFileNameField)))
- {
- gchar *string_utf8;
- gchar *pos;
-
- filename_utf8 = st_filename->value_utf8;
-
- if (!FileName)
- FileName = ET_File_Name_Item_New();
-
- string = g_path_get_basename(filename_utf8);
- // Remove the extension to set it to lower case (to avoid problem with undo)
- if ((pos=strrchr(string,'.'))!=NULL) *pos = 0;
-
- Scan_Process_Fields_Functions(&string);
-
- string_utf8 = ET_File_Name_Generate(ETFile,string);
- ET_Set_Filename_File_Name_Item(FileName,string_utf8,NULL);
- g_free(string_utf8);
- g_free(string);
- }
- }
-
- /* Process data of the tag */
- if (st_filetag != NULL)
- {
- // Title field
- if (st_filetag->title && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessTitleField)))
- {
- if (!FileTag)
- {
- FileTag = ET_File_Tag_Item_New();
- ET_Copy_File_Tag_Item(ETFile,FileTag);
- }
-
- string = g_strdup(st_filetag->title);
-
- Scan_Process_Fields_Functions(&string);
-
- ET_Set_Field_File_Tag_Item(&FileTag->title,string);
-
- g_free(string);
- }
-
- // Artist field
- if (st_filetag->artist && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessArtistField)))
- {
- if (!FileTag)
- {
- FileTag = ET_File_Tag_Item_New();
- ET_Copy_File_Tag_Item(ETFile,FileTag);
- }
-
- string = g_strdup(st_filetag->artist);
-
- Scan_Process_Fields_Functions(&string);
-
- ET_Set_Field_File_Tag_Item(&FileTag->artist,string);
-
- g_free(string);
- }
-
- // Album Artist field
- if (st_filetag->album_artist &&
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessAlbumArtistField)))
- {
- if (!FileTag)
- {
- FileTag = ET_File_Tag_Item_New();
- ET_Copy_File_Tag_Item(ETFile,FileTag);
- }
-
- string = g_strdup(st_filetag->album_artist);
-
- Scan_Process_Fields_Functions(&string);
-
- ET_Set_Field_File_Tag_Item(&FileTag->album_artist,string);
-
- g_free(string);
- }
- // Album field
- if (st_filetag->album && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessAlbumField)))
- {
- if (!FileTag)
- {
- FileTag = ET_File_Tag_Item_New();
- ET_Copy_File_Tag_Item(ETFile,FileTag);
- }
-
- string = g_strdup(st_filetag->album);
-
- Scan_Process_Fields_Functions(&string);
-
- ET_Set_Field_File_Tag_Item(&FileTag->album,string);
-
- g_free(string);
- }
-
- // Genre field
- if (st_filetag->genre && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessGenreField)))
- {
- if (!FileTag)
- {
- FileTag = ET_File_Tag_Item_New();
- ET_Copy_File_Tag_Item(ETFile,FileTag);
- }
-
- string = g_strdup(st_filetag->genre);
-
- Scan_Process_Fields_Functions(&string);
-
- ET_Set_Field_File_Tag_Item(&FileTag->genre,string);
-
- g_free(string);
- }
-
- // Comment field
- if (st_filetag->comment && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessCommentField)))
- {
- if (!FileTag)
- {
- FileTag = ET_File_Tag_Item_New();
- ET_Copy_File_Tag_Item(ETFile,FileTag);
- }
-
- string = g_strdup(st_filetag->comment);
-
- Scan_Process_Fields_Functions(&string);
-
- ET_Set_Field_File_Tag_Item(&FileTag->comment,string);
-
- g_free(string);
- }
-
- // Composer field
- if (st_filetag->composer && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessComposerField)))
- {
- if (!FileTag)
- {
- FileTag = ET_File_Tag_Item_New();
- ET_Copy_File_Tag_Item(ETFile,FileTag);
- }
-
- string = g_strdup(st_filetag->composer);
-
- Scan_Process_Fields_Functions(&string);
-
- ET_Set_Field_File_Tag_Item(&FileTag->composer,string);
-
- g_free(string);
- }
-
- // Original artist field
- if (st_filetag->orig_artist &&
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessOrigArtistField)))
- {
- if (!FileTag)
- {
- FileTag = ET_File_Tag_Item_New();
- ET_Copy_File_Tag_Item(ETFile,FileTag);
- }
-
- string = g_strdup(st_filetag->orig_artist);
-
- Scan_Process_Fields_Functions(&string);
-
- ET_Set_Field_File_Tag_Item(&FileTag->orig_artist,string);
-
- g_free(string);
- }
-
- // Copyright field
- if (st_filetag->copyright && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessCopyrightField)))
- {
- if (!FileTag)
- {
- FileTag = ET_File_Tag_Item_New();
- ET_Copy_File_Tag_Item(ETFile,FileTag);
- }
-
- string = g_strdup(st_filetag->copyright);
-
- Scan_Process_Fields_Functions(&string);
-
- ET_Set_Field_File_Tag_Item(&FileTag->copyright,string);
-
- g_free(string);
- }
-
- // URL field
- if (st_filetag->url && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessURLField)))
- {
- if (!FileTag)
- {
- FileTag = ET_File_Tag_Item_New();
- ET_Copy_File_Tag_Item(ETFile,FileTag);
- }
-
- string = g_strdup(st_filetag->url);
-
- Scan_Process_Fields_Functions(&string);
-
- ET_Set_Field_File_Tag_Item(&FileTag->url,string);
-
- g_free(string);
- }
-
- // 'Encoded by' field
- if (st_filetag->encoded_by && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessEncodedByField)))
- {
- if (!FileTag)
- {
- FileTag = ET_File_Tag_Item_New();
- ET_Copy_File_Tag_Item(ETFile,FileTag);
- }
-
- string = g_strdup(st_filetag->encoded_by);
-
- Scan_Process_Fields_Functions(&string);
-
- ET_Set_Field_File_Tag_Item(&FileTag->encoded_by,string);
-
- g_free(string);
- }
- }
-
- if (FileName && FileTag)
- {
- // Synchronize undo key of the both structures (used for the
- // undo functions, as they are generated as the same time)
- FileName->key = FileTag->key;
- }
- ET_Manage_Changes_Of_File_Data(ETFile,FileName,FileTag);
-
-}
-
-
-static void
-Scan_Process_Fields_Functions (gchar **string)
-{
- if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsConvertIntoSpace)))
- {
- Scan_Convert_Underscore_Into_Space(*string);
- Scan_Convert_P20_Into_Space(*string);
- }
-
- if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsConvertSpace)))
- Scan_Convert_Space_Into_Undescore(*string);
-
- if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsInsertSpace)))
- Scan_Process_Fields_Insert_Space(string);
-
- if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsOnlyOneSpace)))
- Scan_Process_Fields_Keep_One_Space(*string);
-
- if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsConvert)))
- Scan_Convert_Character(string);
-
- if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsAllUppercase)))
- Scan_Process_Fields_All_Uppercase(*string);
-
- if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsAllDowncase)))
- Scan_Process_Fields_All_Downcase(*string);
-
- if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsFirstLetterUppercase)))
- Scan_Process_Fields_Letter_Uppercase(*string);
-
- if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsFirstLettersUppercase)))
- Scan_Process_Fields_First_Letters_Uppercase(*string);
-
- if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsRemoveSpace)))
- Scan_Process_Fields_Remove_Space(*string);
-
-}
-
-void Scan_Process_Fields_All_Uppercase (gchar *string)
-{
- gchar *temp;
- gchar temp2[6]; // Must have at least 6 bytes of space
- gunichar c;
-
- for (temp = string; *temp; temp = g_utf8_next_char(temp))
- {
- c = g_utf8_get_char(temp);
- if (g_unichar_islower(c))
- strncpy(temp, temp2, g_unichar_to_utf8(g_unichar_toupper(c), temp2));
- }
-}
-
-void Scan_Process_Fields_All_Downcase (gchar *string)
-{
- gchar *temp;
- gchar temp2[6];
- gunichar c;
-
- for (temp = string; *temp; temp = g_utf8_next_char(temp))
- {
- c = g_utf8_get_char(temp);
- if (g_unichar_isupper(c))
- strncpy(temp, temp2, g_unichar_to_utf8(g_unichar_tolower(c), temp2));
- }
-}
-
-void Scan_Process_Fields_Letter_Uppercase (gchar *string)
-{
- gchar *temp;
- gchar temp2[6];
- gboolean set_to_upper_case = TRUE;
- gunichar c;
- gchar utf8_character[6];
- gchar *word, *word1, *word2;
-
- for (temp = string; *temp; temp = g_utf8_next_char(temp))
- {
- c = g_utf8_get_char(temp);
- if (set_to_upper_case && g_unichar_islower(c))
- strncpy(temp, temp2, g_unichar_to_utf8(g_unichar_toupper(c), temp2));
- else if (!set_to_upper_case && g_unichar_isupper(c))
- strncpy(temp, temp2, g_unichar_to_utf8(g_unichar_tolower(c), temp2));
- set_to_upper_case = FALSE; // After the first time, all will be down case
- }
-
- temp = string;
-
- // Uppercase again the word 'I' in english
- while ( temp )
- {
- word = temp; // Needed if there is only one word
- word1 = g_utf8_strchr(temp,-1,' ');
- word2 = g_utf8_strchr(temp,-1,'_');
-
- // Take the first string found (near beginning of string)
- if (word1 && word2)
- word = MIN(word1,word2);
- else if (word1)
- word = word1;
- else if (word2)
- word = word2;
- else
- // Last word of the string
- break;
-
- // Go to first character of the word (char. after ' ' or '_')
- word = word+1;
-
- // Set uppercase word 'I'
- if (g_ascii_strncasecmp("I ", word, strlen("I ")) == 0)
- {
- c = g_utf8_get_char(word);
- strncpy(word, utf8_character, g_unichar_to_utf8(g_unichar_toupper(c), utf8_character));
- }
-
- temp = word;
- }
-}
-
-/*
- * Function to set the first letter of each word to uppercase, according the "Chicago Manual of Style"
(http://www.docstyles.com/cmscrib.htm#Note2)
- * No needed to reallocate
- */
-void Scan_Process_Fields_First_Letters_Uppercase (gchar *string)
-{
-/**** DANIEL TEST *****
- gchar *iter;
- gchar utf8_character[6];
- gboolean set_to_upper_case = TRUE;
- gunichar c;
-
- for (iter = text; *iter; iter = g_utf8_next_char(iter))
- {
- c = g_utf8_get_char(iter);
- if (set_to_upper_case && g_unichar_islower(c))
- strncpy(iter, utf8_character, g_unichar_to_utf8(g_unichar_toupper(c), utf8_character));
- else if (!set_to_upper_case && g_unichar_isupper(c))
- strncpy(iter, utf8_character, g_unichar_to_utf8(g_unichar_tolower(c), utf8_character));
-
- set_to_upper_case = (g_unichar_isalpha(c)
- || c == (gunichar)'.'
- || c == (gunichar)'\''
- || c == (gunichar)'`') ? FALSE : TRUE;
- }
-****/
-/**** Barış Çiçek version ****/
- gchar *word, *word1, *word2, *temp;
- gint i, len;
- gchar utf8_character[6];
- gunichar c;
- gboolean set_to_upper_case, set_to_upper_case_tmp;
- // There have to be space at the end of words to seperate them from prefix
- // Chicago Manual of Style "Heading caps" Capitalization Rules (CMS 1993, 282)
(http://www.docstyles.com/cmscrib.htm#Note2)
- const gchar * exempt[] =
- {
- "a ", "a_",
- "against ", "against_",
- "an ", "an_",
- "and ", "and_",
- "at ", "at_",
- "between ", "between_",
- "but ", "but_",
- //"feat. ", "feat._", // Removed by Slash Bunny
- "for ", "for_",
- "in ", "in_",
- "nor ", "nor_",
- "of ", "of_",
- //"off ", "off_", // Removed by Slash Bunny
- "on ", "on_",
- "or ", "or_",
- //"over ", "over_", // Removed by Slash Bunny
- "so ", "so_",
- "the ", "the_",
- "to ", "to_",
- "with ", "with_",
- "yet ", "yet_",
- NULL
- };
-
- if (!PFS_DONT_UPPER_SOME_WORDS)
- {
- exempt[0] = NULL;
- }
- Scan_Process_Fields_All_Downcase(string);
-
- if (!g_utf8_validate(string,-1,NULL))
- {
- Log_Print(LOG_ERROR,"Scan_Process_Fields_First_Letters_Uppercase: Not a valid utf8! quiting");
- return;
- }
- // Removes trailing whitespace
- string = g_strchomp(string);
-
- temp = string;
-
- // If the word is a roman numeral, capitalize all of it
- if ((len = Scan_Word_Is_Roman_Numeral(temp)))
- {
- strncpy(string, g_utf8_strup(temp, len), len);
- } else
- {
- // Set first character to uppercase
- c = g_utf8_get_char(temp);
- strncpy(string, utf8_character, g_unichar_to_utf8(g_unichar_toupper(c), utf8_character));
- }
-
- // Uppercase first character of each word, except for 'exempt[]' words lists
- while ( temp )
- {
- word = temp; // Needed if there is only one word
- word1 = g_utf8_strchr(temp,-1,' ');
- word2 = g_utf8_strchr(temp,-1,'_');
-
- // Take the first string found (near beginning of string)
- if (word1 && word2)
- word = MIN(word1,word2);
- else if (word1)
- word = word1;
- else if (word2)
- word = word2;
- else
- {
- // Last word of the string: the first letter is always uppercase,
- // even if it's in the exempt list. This is a Chicago Manual of Style rule.
- // Last Word In String - Should Capitalize Regardless of Word (Chicago Manual of Style)
- c = g_utf8_get_char(word);
- strncpy(word, utf8_character, g_unichar_to_utf8(g_unichar_toupper(c), utf8_character));
- break;
- }
-
- // Go to first character of the word (char. after ' ' or '_')
- word = word+1;
-
- // If the word is a roman numeral, capitalize all of it
- if ((len = Scan_Word_Is_Roman_Numeral(word)))
- {
- strncpy(word, g_utf8_strup(word, len), len);
- } else
- {
- // Set uppercase the first character of this word
- c = g_utf8_get_char(word);
- strncpy(word, utf8_character, g_unichar_to_utf8(g_unichar_toupper(c), utf8_character));
-
- // Set lowercase the first character of this word if found in the exempt words list
- for (i=0; exempt[i]!=NULL; i++)
- {
- if (g_ascii_strncasecmp(exempt[i], word, strlen(exempt[i])) == 0)
- {
- c = g_utf8_get_char(word);
- strncpy(word, utf8_character, g_unichar_to_utf8(g_unichar_tolower(c), utf8_character));
- break;
- }
- }
- }
-
- temp = word;
- }
-
- // Uppercase letter placed after some characters like '(', '[', '{'
- set_to_upper_case = FALSE;
- for (temp = string; *temp; temp = g_utf8_next_char(temp))
- {
- c = g_utf8_get_char(temp);
- set_to_upper_case_tmp = ( c == (gunichar)'('
- || c == (gunichar)'['
- || c == (gunichar)'{'
- || c == (gunichar)'"'
- || c == (gunichar)':'
- || c == (gunichar)'.'
- || c == (gunichar)'`'
- || c == (gunichar)'-'
- ) ? TRUE : FALSE;
-
- if (set_to_upper_case && g_unichar_islower(c))
- strncpy(temp, utf8_character, g_unichar_to_utf8(g_unichar_toupper(c), utf8_character));
-
- set_to_upper_case = set_to_upper_case_tmp;
+ *tmp = '_';
}
-
}
-void Scan_Process_Fields_Remove_Space (gchar *string)
+void
+Scan_Process_Fields_Remove_Space (gchar *string)
{
gchar *tmp, *tmp1;
@@ -1654,7 +69,8 @@ void Scan_Process_Fields_Remove_Space (gchar *string)
* The function inserts a space before an uppercase letter
* It is needed to realloc the memory!
*/
-void Scan_Process_Fields_Insert_Space (gchar **string)
+void
+Scan_Process_Fields_Insert_Space (gchar **string)
{
gchar *iter;
gunichar c;
@@ -1686,10 +102,10 @@ void Scan_Process_Fields_Insert_Space (gchar **string)
}
/*
- * The function removes the duplicated spaces
- * No need to reallocate
+ * The function removes the duplicated spaces. No need to reallocate.
*/
-void Scan_Process_Fields_Keep_One_Space (gchar *string)
+void
+Scan_Process_Fields_Keep_One_Space (gchar *string)
{
gchar *tmp, *tmp1;
@@ -1710,40 +126,11 @@ void Scan_Process_Fields_Keep_One_Space (gchar *string)
}
/*
- * Function to replace underscore '_' by a space
- * No need to reallocate
- */
-void Scan_Convert_Underscore_Into_Space (gchar *string)
-{
- gchar *tmp;
-
- while ((tmp=strchr(string,'_'))!=NULL)
- *tmp = ' ';
-}
-
-/*
- * Function to replace %20 by a space
- * No need to reallocate
- */
-void Scan_Convert_P20_Into_Space (gchar *string)
-{
- gchar *tmp, *tmp1;
-
- while ((tmp=strstr(string,"%20"))!=NULL)
- {
- tmp1 = tmp + 3;
- *(tmp++) = ' ';
- while (*tmp1)
- *(tmp++) = *(tmp1++);
- *tmp = '\0';
- }
-}
-
-/*
* Function to remove spaces
* No need to reallocate
*/
-void Scan_Remove_Spaces (gchar *string)
+void
+Scan_Remove_Spaces (gchar *string)
{
int nextnotspace = 0, pos = 0;
@@ -1761,2289 +148,88 @@ void Scan_Remove_Spaces (gchar *string)
}
}
-/*
- * Function to replace space by '_'
- * No need to reallocate
- */
-void Scan_Convert_Space_Into_Undescore (gchar *string)
-{
- gchar *tmp;
-
- while ((tmp=strchr(string,' '))!=NULL)
- *tmp = '_';
-}
-
-/*
- * Replace something with something else ;)
- * Here use Regular Expression, to search and replace.
- */
-static void
-Scan_Convert_Character (gchar **string)
-{
- gchar *from;
- gchar *to;
- GRegex *regex;
- GError *regex_error = NULL;
- gchar *new_string;
-
- from = gtk_editable_get_chars (GTK_EDITABLE (ProcessFieldsConvertFrom), 0,
- -1);
- to = gtk_editable_get_chars (GTK_EDITABLE (ProcessFieldsConvertTo), 0, -1);
-
- regex = g_regex_new (from, 0, 0, ®ex_error);
- if (regex_error != NULL)
- {
- goto handle_error;
- }
-
- new_string = g_regex_replace (regex, *string, -1, 0, to, 0, ®ex_error);
- if (regex_error != NULL)
- {
- g_free (new_string);
- g_regex_unref (regex);
- goto handle_error;
- }
-
- /* Success. */
- g_regex_unref (regex);
- g_free (*string);
- *string = new_string;
-
-out:
- g_free (from);
- g_free (to);
- return;
-
-handle_error:
- Log_Print (LOG_ERROR, _("Error while processing fields: %s"),
- regex_error->message);
-
- g_error_free (regex_error);
-
- goto out;
-}
-
-/*
- * Quick roman numeral check (non-roman numerals may also return true)
- * Patch from Slash Bunny (2007.08.12)
- * (http://home.hiwaay.net/~lkseitz/math/roman/numerals.shtml)
- * I = 1 (one)
- * V = 5 (five)
- * X = 10 (ten)
- * L = 50 (fifty)
- * C = 100 (one hundred)
- * D = 500 (five hundred)
- * M = 1000 (one thousand)
- */
-static gint
-Scan_Word_Is_Roman_Numeral (const gchar *text)
-{
- const gchar *tmp;
- gint len;
- gchar *buf = NULL;
- gint rn_int;
- gchar *rn_char;
-
- if (!ScannerWindow
- || !ProcessFieldsDetectRomanNumerals
- || !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsDetectRomanNumerals)))
- return 0;
-
- tmp = text;
- len = 0;
-
- while (*tmp)
- {
- if (*tmp == (gunichar)'i'
- || *tmp == (gunichar)'v'
- || *tmp == (gunichar)'x'
- || *tmp == (gunichar)'l'
- || *tmp == (gunichar)'c'
- || *tmp == (gunichar)'d'
- || *tmp == (gunichar)'m')
- {
- // Found a roman numeral => continue
- tmp++;
- len++;
- } else if (*tmp == ' '
- || *tmp == '_'
- || *tmp == '.'
- || *tmp == ','
- || *tmp == '-')
- {
- // A separator was found => end of word
- // Check if it is a valid roman numeral
- goto roman_numeral_found;
-
- } else
- {
- return 0;
- }
- }
-
- // Found in last word of the string
-
-roman_numeral_found:
- // Check if it is a valid roman numeral
- buf = g_strndup(text,len);
- rn_int = roman2int(buf); // Convert the Roman numeral string to integer
-
- if (rn_int >= 0 )
- {
- // Some strings as "IIIII" or "CCCCC" are returned as valid, which is not correct...
- // Same problem with: IC MIC IM MIM IL CIL XM MXM VC MVC VM MVM VL MVL LC MLC LD MLD LM MLM MDM
- // So we convert it again to a string, and compare to the initial one.
- rn_char = (gchar *)int2roman(rn_int); // Convert the Roman numeral integer to string
- if (rn_char
- && strcasecmp(buf,rn_char)==0)
- {
- g_free(buf);
- g_free(rn_char);
- return len; // Roman numeral valid
- }else
- {
- g_free(buf);
- g_free(rn_char);
- return 0;
- }
- }else
- {
- g_free(buf);
- return 0;
- }
-}
-
-
-
-/*
- * Taken from :
- * Roman Numeral Conversion API (http://sourceforge.net/project/showfiles.php?group_id=211070)
- * Copyright (c) 2007 David M. Syzdek <roman-project syzdek net>
- */
-/* Convert Roman numeral from integer to string */
-static const char *
-int2roman (int num)
-{
- #define ROMAN_BUFF_LEN 512
-
- /* buffer for storing conversions */
- char roman_string[ROMAN_BUFF_LEN];
-
- /* wrap long2roman_r() with library buffer */
- char *result = int2roman_r(num, roman_string, ROMAN_BUFF_LEN);
-
- if (!result)
- return NULL;
- return g_strdup(roman_string);
-}
-
-static char *
-int2roman_r (int num, char * str, size_t len)
-{
- // local variables
- unsigned pos;
- unsigned u;
- unsigned dividend;
-
- g_return_val_if_fail (str != NULL, NULL);
-
- // verify that number is withing boundaries
- if ((num > 5000) || (num < 0))
- {
- return NULL;
- };
-
- // sets initial values
- pos = 0;
- memset(str, 0, len);
- len--;
-
- // checks for nullae
- if (!(num))
- {
- str[0] = 'N';
- return str;
- };
-
- // calculates sign
- if (num < 0)
- {
- num *= -1;
- if (1 > len)
- {
- return NULL;
- };
- str[pos] = '-';
- pos++;
- };
-
- // calculates thousands
- dividend = num/1000;
- if (dividend > (len-1))
- {
- return NULL;
- };
- for (u = 0; u < dividend; u++)
- str[pos+u] = 'M';
- num %= 1000;
- pos += u;
-
- // calculates hundreds
- dividend = num/100;
- if (dividend > (len-1-pos))
- {
- return NULL;
- };
- if (dividend == 9)
- {
- str[pos+0] = 'C';
- str[pos+1] = 'M';
- pos += 2;
- dividend = 0;
- };
- if (dividend >= 5)
- {
- str[pos] = 'D';
- dividend -= 5;
- pos++;
- };
- if (dividend == 4)
- {
- str[pos+0] = 'C';
- str[pos+1] = 'D';
- dividend -= 4;
- pos += 2;
- };
- for(u = 0; u < dividend; u++)
- str[pos+u] = 'C';
- pos += u;
- num %= 100;
-
- // calculates tens
- dividend = num/10;
- if (dividend > (len-1-pos))
- {
- return NULL;
- };
- if (dividend == 9)
- {
- str[pos+0] = 'X';
- str[pos+1] = 'C';
- dividend = 0;
- pos += 2;
- };
- if (dividend >= 5)
- {
- str[pos+0] = 'L';
- dividend -= 5;
- pos++;
- };
- if (dividend == 4)
- {
- str[pos+0] = 'X';
- str[pos+1] = 'L';
- pos += 2;
- dividend -= 4;
- };
- for (u = 0; u < dividend; u++)
- str[pos+u] = 'X';
- pos += u;
- num %= 10;
-
- // calculates ones
- dividend = num;
- if (dividend > (len-1-pos))
- {
- return NULL;
- };
- if (dividend == 9)
- {
- str[pos+0] = 'I';
- str[pos+1] = 'X';
- dividend = 0;
- pos += 2;
- };
- if (dividend >= 5)
- {
- str[pos+0] = 'V';
- dividend -= 5;
- pos++;
- };
- if (dividend == 4)
- {
- str[pos+0] = 'I';
- str[pos+1] = 'V';
- pos += 2;
- dividend -= 4;
- };
- for(u = 0; u < dividend; u++)
- str[pos+u] = 'I';
-
- /* ends function */
- return str;
-}
-
-/* Convert Roman numeral from string to integer */
-static int
-roman2int (const char *str)
-{
- // declares local vars
- int num;
- unsigned i;
- unsigned len;
- unsigned last;
- unsigned prevlast;
-
- // checks args
- if (!(str))
- {
- return(0);
- };
-
- // sets initial values
- num = 0;
- len = strlen(str);
- last = 1000;
- prevlast = 1000;
-
- // loops through characters
- for(i = 0; i < len; i++)
- {
- switch(str[i])
- {
- case 'n':
- case 'N':
- if (strlen(str) > 1)
- {
- return(-1);
- };
- return(0);
- break;
- case 'i':
- case 'I':
- num += 1;
- // prevent patterns like IXI
- if ((prevlast == 1) && (last != 1))
- {
- return(-1);
- };
- // prevent patterns like IIIII and VIIIII
- if ((!(num%5)) || (!(num%10)))
- {
- return(-1);
- };
- // rotates value into history
- prevlast = last;
- last = 1;
- break;
- case 'v':
- case 'V':
- num += 5;
- // tests for invalid syntax
- if ( ((last <= 5) && (last != 1)) || (prevlast <= 5) )
- {
- return(-1);
- }
- // applies subtraction method & rotates value into history
- if (last < 5)
- num -= (last * 2);
- prevlast = last;
- last = 5;
- break;
- case 'x':
- case 'X':
- num += 10;
- // tests for invalid syntax
- if ( ((prevlast < 10) && (last <= 10)) || ((last < 10) && (last != 1)) )
- {
- return(-1);
- };
- // prevent patterns like XXXXX and VXXXXX
- if ((!(num%50)) || (!(num%100)))
- {
- return(-1);
- };
- // applies subtraction method & rotates value into history
- if (last == 1)
- num -= (last * 2);
- prevlast = last;
- last = 10;
- break;
- case 'l':
- case 'L':
- num += 50;
- // tests for invalid syntax
- if ( ((last <= 50) && (last != 10)) || (prevlast <= 50) )
- {
- return(-1);
- }
- // applies subtraction method & rotates value into history
- if (last < 50)
- num -= (last * 2);
- prevlast = last;
- last = 50;
- break;
- case 'c':
- case 'C':
- num += 100;
- // tests for invalid syntax
- if ( ((prevlast < 100) && (last <= 100)) || ((last < 100) && (last != 10)) )
- {
- return(-1);
- };
- // prevent patterns like CCCCC and VCCCCC
- if ((!(num%500)) || (!(num%1000)))
- {
- return(-1);
- };
- // applies subtraction method & rotates value into history
- if (last == 10)
- num -= (last * 2);
- prevlast = last;
- last = 100;
- break;
- case 'd':
- case 'D':
- num += 500;
- // tests for invalid syntax
- if ( ((last <= 500) && (last != 100)) || (prevlast <= 500) )
- {
- return(-1);
- }
- // applies subtraction method & rotates value into history
- if (last < 500)
- num -= (last * 2);
- prevlast = last;
- last = 500;
- break;
- case 'm':
- case 'M':
- num += 1000;
- // tests for invalid syntax
- if ( ((prevlast < 1000) && (last <= 1000)) || ((last < 1000) && (last != 100)) )
- {
- return(-1);
- };
- // prevent patterns like MMMMM and VMMMMM
- if ((!(num%5000)) || (!(num%10000)))
- {
- return(-1);
- };
- // applies subtraction method & rotates value into history
- if (last == 100)
- num -= (last * 2);
- prevlast = last;
- last = 1000;
- break;
- default:
- return(-1);
- };
- };
-
- // ends function
- return(num);
-}
-
-
-
-/*
- * Return the field of a 'File_Tag' structure corresponding to the mask code
- */
-static gchar
-**Scan_Return_File_Tag_Field_From_Mask_Code (File_Tag *FileTag, gchar code)
-{
- switch (code)
- {
- case 't': /* Title */
- return &FileTag->title;
- case 'a': /* Artist */
- return &FileTag->artist;
- case 'b': /* Album */
- return &FileTag->album;
- case 'd': /* Disc Number */
- return &FileTag->disc_number;
- case 'x': /* Total number of discs. */
- return &FileTag->disc_total;
- case 'y': /* Year */
- return &FileTag->year;
- case 'n': /* Track */
- return &FileTag->track;
- case 'l': /* Track Total */
- return &FileTag->track_total;
- case 'g': /* Genre */
- return &FileTag->genre;
- case 'c': /* Comment */
- return &FileTag->comment;
- case 'p': /* Composer */
- return &FileTag->composer;
- case 'o': /* Orig. Artist */
- return &FileTag->orig_artist;
- case 'r': /* Copyright */
- return &FileTag->copyright;
- case 'u': /* URL */
- return &FileTag->url;
- case 'e': /* Encoded by */
- return &FileTag->encoded_by;
- case 'z': /* Album Artist */
- return &FileTag->album_artist;
- case 'i': /* Ignored */
- return NULL;
- default:
- Log_Print(LOG_ERROR,"Scanner: Invalid code '%%%c' found!",code);
- return NULL;
- }
-}
-
-
-
-/******************
- * Scanner Window *
- ******************/
-void Open_ScannerWindow (gint scanner_type)
-{
- GtkWidget *scan_button;
- GtkWidget *ScanVBox;
- GtkWidget *HBox1, *HBox2, *HBox4, *VBox, *hbox, *vbox;
- GtkWidget *Table;
- GtkWidget *Label;
- GtkWidget *Button;
- GIcon *new_folder;
- GtkWidget *Icon;
- GtkWidget *group;
- GtkWidget *process_fields_convert_none;
- GtkWidget *process_fields_case_none;
- GtkWidget *radio_space_none;
- GtkTreeViewColumn * column;
- GtkCellRenderer *renderer;
- GtkToggleAction *toggle_action;
-
- /* Check if already opened */
- if (ScannerWindow)
- {
- //gdk_window_show(ScannerWindow->window);
- gtk_window_present(GTK_WINDOW(ScannerWindow));
- if (ScannerOptionCombo)
- {
- gtk_combo_box_set_active(GTK_COMBO_BOX(ScannerOptionCombo), scanner_type);
- }
- return;
- }
-
- if ( scanner_type < SCANNER_FILL_TAG
- || scanner_type > SCANNER_PROCESS_FIELDS)
- scanner_type = SCANNER_FILL_TAG;
-
- /* The window */
- ScannerWindow = gtk_dialog_new_with_buttons (_("Tag and Filename Scan"),
- GTK_WINDOW (MainWindow),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_STOCK_CLOSE,
- GTK_RESPONSE_CLOSE, NULL);
-
- /* 'Scan selected files' button */
- scan_button = gtk_button_new_from_stock (GTK_STOCK_APPLY);
- /* TODO: Set related action to match AM_SCAN_FILES. */
- gtk_button_set_label (GTK_BUTTON (scan_button), _("Scan Files"));
- gtk_widget_set_can_default (scan_button, TRUE);
- gtk_dialog_add_action_widget (GTK_DIALOG (ScannerWindow), scan_button,
- GTK_RESPONSE_APPLY);
- gtk_dialog_set_default_response (GTK_DIALOG (ScannerWindow),
- GTK_RESPONSE_APPLY);
- gtk_widget_show (scan_button);
- gtk_widget_set_tooltip_text (scan_button, _("Scan selected files"));
-
- /* The response signal handles close, scan and the delete event. */
- g_signal_connect (G_OBJECT (ScannerWindow), "response",
- G_CALLBACK (et_scan_on_response), NULL);
-
- /* The init position is defined below, because the scanner window must be
- * shown before it can be moved. */
-
- /* The main vbox */
- ScanVBox = gtk_dialog_get_content_area (GTK_DIALOG (ScannerWindow));
- gtk_container_set_border_width (GTK_CONTAINER (ScannerWindow), 6);
- gtk_box_set_spacing (GTK_BOX (ScanVBox), 12);
-
- /*
- * The hbox for mode buttons + buttons + what to scan
- */
- HBox1 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,0);
- gtk_box_pack_start(GTK_BOX(ScanVBox),HBox1,FALSE,FALSE,0);
-
- /* Option Menu */
- Label = gtk_label_new(_("Scanner:"));
- gtk_box_pack_start(GTK_BOX(HBox1),Label,FALSE,FALSE,0);
-
- ScannerOptionCombo = gtk_combo_box_text_new();
- gtk_box_pack_start(GTK_BOX (HBox1), ScannerOptionCombo, TRUE, TRUE, 2);
- gtk_widget_set_size_request(ScannerOptionCombo, 160, -1);
-
- /* Option for Tag */
- gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(ScannerOptionCombo),
- _(Scanner_Option_Menu_Items[SCANNER_FILL_TAG]));
-
- /* Option for FileName */
- gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(ScannerOptionCombo),
- _(Scanner_Option_Menu_Items[SCANNER_RENAME_FILE]));
-
- /* Option for ProcessFields */
- gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(ScannerOptionCombo),
- _(Scanner_Option_Menu_Items[SCANNER_PROCESS_FIELDS]));
-
- /* Selection of the item made at the end of the function. */
- gtk_widget_set_tooltip_text (ScannerOptionCombo,
- _("Select the type of scanner to use"));
- g_signal_connect(G_OBJECT(ScannerOptionCombo), "changed", G_CALLBACK(Scanner_Option_Menu_Activate_Item),
NULL);
-
- /* Options button */
- Button = gtk_button_new();
- Icon = gtk_image_new_from_stock(GTK_STOCK_PREFERENCES, GTK_ICON_SIZE_BUTTON);
- gtk_container_add(GTK_CONTAINER(Button),Icon);
- gtk_box_pack_start(GTK_BOX(HBox1),Button,FALSE,FALSE,0);
- gtk_button_set_relief(GTK_BUTTON(Button),GTK_RELIEF_NONE);
- gtk_widget_set_tooltip_text(Button,_("Scanner Preferences"));
- g_signal_connect(G_OBJECT(Button),"clicked",G_CALLBACK(Scan_Option_Button),NULL);
-
- /* Mask Editor button */
- MaskEditorButton = gtk_toggle_button_new();
- Icon = gtk_image_new_from_stock("easytag-mask", GTK_ICON_SIZE_BUTTON);
- gtk_container_add(GTK_CONTAINER(MaskEditorButton),Icon);
- gtk_box_pack_start(GTK_BOX(HBox1),MaskEditorButton,FALSE,FALSE,0);
- gtk_button_set_relief(GTK_BUTTON(MaskEditorButton),GTK_RELIEF_NONE);
- gtk_widget_set_tooltip_text(MaskEditorButton,_("Show / Hide Masks Editor"));
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(MaskEditorButton),SCAN_MASK_EDITOR_BUTTON);
- g_signal_connect(G_OBJECT(MaskEditorButton),"toggled",G_CALLBACK(Scan_Toggle_Mask_Editor_Button),NULL);
-
- /* Legend button */
- LegendButton = gtk_toggle_button_new();
- Icon = gtk_image_new_from_stock(GTK_STOCK_HELP, GTK_ICON_SIZE_BUTTON);
- gtk_container_add(GTK_CONTAINER(LegendButton),Icon);
- gtk_box_pack_start(GTK_BOX(HBox1),LegendButton,FALSE,FALSE,0);
- gtk_button_set_relief(GTK_BUTTON(LegendButton),GTK_RELIEF_NONE);
- gtk_widget_set_tooltip_text(LegendButton,_("Show / Hide Legend"));
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(LegendButton),SCAN_LEGEND_BUTTON);
- g_signal_connect(G_OBJECT(LegendButton),"toggled",G_CALLBACK(Scan_Toggle_Legend_Button),NULL);
-
- /*
- * Frame for Scan Tag
- */
- ScanTagFrame = gtk_frame_new (_(Scanner_Option_Menu_Items[0]));
- gtk_box_pack_start(GTK_BOX(ScanVBox),ScanTagFrame,FALSE,FALSE,0);
-
- vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, BOX_SPACING);
- gtk_container_add(GTK_CONTAINER(ScanTagFrame),vbox);
- gtk_container_set_border_width(GTK_CONTAINER(vbox), 4);
- gtk_widget_show(vbox);
-
- /* The combo box + Status icon */
- HBox2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, BOX_SPACING);
- gtk_box_pack_start(GTK_BOX(vbox),HBox2,TRUE,TRUE,0);
-
- // Set up list model which is used both by the combobox and the editor
- ScanTagListModel = gtk_list_store_new(MASK_EDITOR_COUNT, G_TYPE_STRING);
-
- // The combo box to select the mask to apply
- ScanTagMaskCombo = gtk_combo_box_new_with_entry();
- gtk_combo_box_set_model(GTK_COMBO_BOX(ScanTagMaskCombo), GTK_TREE_MODEL(ScanTagListModel));
- g_object_unref (ScanTagListModel);
- gtk_combo_box_set_entry_text_column(GTK_COMBO_BOX(ScanTagMaskCombo), MASK_EDITOR_TEXT);
-
- gtk_box_pack_start(GTK_BOX(HBox2),ScanTagMaskCombo,TRUE,TRUE,2);
- gtk_widget_set_tooltip_text(GTK_WIDGET(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(ScanTagMaskCombo)))),
- _("Select or type in a mask using codes (see Legend) to parse "
- "filename and path. Used to fill in tag fields"));
- // Signal to generate preview (preview of the new tag values)
- g_signal_connect_swapped(G_OBJECT(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(ScanTagMaskCombo)))),"changed",
- G_CALLBACK(Scan_Fill_Tag_Generate_Preview),NULL);
-
- // Load masks into the combobox from a file
- Load_Scan_Tag_Masks_List(ScanTagListModel, MASK_EDITOR_TEXT, Scan_Masks);
- if (SCAN_TAG_DEFAULT_MASK)
- {
- Add_String_To_Combo_List(ScanTagListModel, SCAN_TAG_DEFAULT_MASK);
- gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(ScanTagMaskCombo))), SCAN_TAG_DEFAULT_MASK);
- }else
- {
- gtk_combo_box_set_active(GTK_COMBO_BOX(ScanTagMaskCombo), 0);
- }
-
- // Mask status icon
- // Signal connection to check if mask is correct into the mask entry
- g_signal_connect (gtk_bin_get_child (GTK_BIN (ScanTagMaskCombo)),
- "changed", G_CALLBACK (entry_check_scan_tag_mask),
- NULL);
-
- // Preview label
- FillTagPreviewLabel = gtk_label_new (_("Fill tag preview"));
- gtk_label_set_line_wrap(GTK_LABEL(FillTagPreviewLabel),TRUE);
- gtk_widget_show(FillTagPreviewLabel);
- gtk_box_pack_start(GTK_BOX(vbox),FillTagPreviewLabel,TRUE,TRUE,0);
-
- /*
- * Frame for Rename File
- */
- RenameFileFrame = gtk_frame_new (_(Scanner_Option_Menu_Items[1]));
- gtk_box_pack_start(GTK_BOX(ScanVBox),RenameFileFrame,FALSE,FALSE,0);
-
- vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL,4);
- gtk_container_add(GTK_CONTAINER(RenameFileFrame),vbox);
- gtk_container_set_border_width(GTK_CONTAINER(vbox), 4);
- gtk_widget_show(vbox);
-
- /* The button to prefix path + combo box + Status icon */
- HBox4 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,2);
- gtk_box_pack_start(GTK_BOX(vbox),HBox4,TRUE,TRUE,0);
-
- // Button to prefix path
- RenameFilePrefixPathButton = gtk_button_new();
- new_folder = g_themed_icon_new ("folder-new");
- /* TODO: On Win32, GTK_ICON_SIZE_BUTTON enlarges the combobox. */
- Icon = gtk_image_new_from_gicon (new_folder, GTK_ICON_SIZE_MENU);
- g_object_unref (new_folder);
- gtk_container_add(GTK_CONTAINER(RenameFilePrefixPathButton),Icon);
- gtk_box_pack_start(GTK_BOX(HBox4),RenameFilePrefixPathButton,FALSE,FALSE,0);
- gtk_button_set_relief(GTK_BUTTON(RenameFilePrefixPathButton),GTK_RELIEF_NONE);
-
g_signal_connect(G_OBJECT(RenameFilePrefixPathButton),"clicked",G_CALLBACK(Scan_Rename_File_Prefix_Path),NULL);
- gtk_widget_set_tooltip_text(RenameFilePrefixPathButton,_("Prefix mask with current path"));
-
- // Set up list model which is used both by the combobox and the editor
- RenameFileListModel = gtk_list_store_new(MASK_EDITOR_COUNT, G_TYPE_STRING);
-
- // The combo box to select the mask to apply
- RenameFileMaskCombo = gtk_combo_box_new_with_entry();
- gtk_combo_box_set_model(GTK_COMBO_BOX(RenameFileMaskCombo), GTK_TREE_MODEL(RenameFileListModel));
- g_object_unref (RenameFileListModel);
- gtk_combo_box_set_entry_text_column(GTK_COMBO_BOX(RenameFileMaskCombo), MASK_EDITOR_TEXT);
-
- gtk_box_pack_start(GTK_BOX(HBox4),RenameFileMaskCombo,TRUE,TRUE,2);
- gtk_container_set_border_width(GTK_CONTAINER(HBox4), 2);
- gtk_widget_set_tooltip_text(GTK_WIDGET(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(RenameFileMaskCombo)))),
- _("Select or type in a mask using codes (see Legend) to parse tag fields. "
- "Used to rename the file.\nUse / to make directories. If the first character "
- "is /, it's a absolute path, otherwise is relative to the old path."));
- // Signal to generate preview (preview of the new filename)
- g_signal_connect_swapped(G_OBJECT(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(RenameFileMaskCombo)))),"changed",
- G_CALLBACK(Scan_Rename_File_Generate_Preview),NULL);
-
- // Load masks into the combobox from a file
- Load_Rename_File_Masks_List(RenameFileListModel, MASK_EDITOR_TEXT, Rename_File_Masks);
- if (RENAME_FILE_DEFAULT_MASK)
- {
- Add_String_To_Combo_List(RenameFileListModel, RENAME_FILE_DEFAULT_MASK);
- gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(RenameFileMaskCombo))),
RENAME_FILE_DEFAULT_MASK);
- }else
- {
- gtk_combo_box_set_active(GTK_COMBO_BOX(RenameFileMaskCombo), 0);
- }
-
- // Mask status icon
- // Signal connection to check if mask is correct into the mask entry
- g_signal_connect (gtk_bin_get_child (GTK_BIN (RenameFileMaskCombo)),
- "changed", G_CALLBACK (entry_check_rename_file_mask),
- NULL);
-
- /* Preview label */
- RenameFilePreviewLabel = gtk_label_new (_("Rename file preview"));
- gtk_label_set_line_wrap(GTK_LABEL(RenameFilePreviewLabel),TRUE);
- gtk_widget_show(RenameFilePreviewLabel);
- gtk_box_pack_start(GTK_BOX(vbox),RenameFilePreviewLabel,TRUE,TRUE,0);
-
- /*
- * Frame for Processing Fields
- */
- ProcessFieldsFrame = gtk_frame_new (_(Scanner_Option_Menu_Items[2]));
- gtk_box_pack_start(GTK_BOX(ScanVBox),ProcessFieldsFrame,FALSE,FALSE,0);
-
- VBox = gtk_box_new (GTK_ORIENTATION_VERTICAL, BOX_SPACING);
- gtk_container_add(GTK_CONTAINER(ProcessFieldsFrame),VBox);
- gtk_container_set_border_width(GTK_CONTAINER(VBox), 4);
- gtk_widget_show(VBox);
-
- /* Group: select entry fields to process */
- hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,0);
- gtk_box_pack_start(GTK_BOX(VBox),hbox,FALSE,FALSE,2);
- Label = gtk_label_new(_("Select fields:"));
- gtk_box_pack_start (GTK_BOX (hbox), Label, FALSE, FALSE, 2);
- gtk_widget_set_tooltip_text (Label,
- _("The buttons on the right represent the "
- "fields which can be processed. Select "
- "those which interest you"));
- // Advice for Translators: set the first letter of filename translated
- ProcessFileNameField = gtk_toggle_button_new_with_label( _("F"));
- gtk_widget_set_tooltip_text (ProcessFileNameField,
- _("Process filename field"));
- // Advice for Translators: set the first letter of title translated
- ProcessTitleField = gtk_toggle_button_new_with_label( _("T"));
- gtk_widget_set_tooltip_text(ProcessTitleField, _("Process title field"));
- // Advice for Translators: set the first letter of artist translated
- ProcessArtistField = gtk_toggle_button_new_with_label( _("Ar"));
- gtk_widget_set_tooltip_text(ProcessArtistField, _("Process file artist field"));
- // Advice for Translators: set the first letter of album artist translated
- ProcessAlbumArtistField = gtk_toggle_button_new_with_label(_("AA"));
- gtk_widget_set_tooltip_text(ProcessAlbumArtistField, _("Process album artist field"));
- // Advice for Translators: set the first letter of album translated
- ProcessAlbumField = gtk_toggle_button_new_with_label( _("Al"));
- gtk_widget_set_tooltip_text(ProcessAlbumField, _("Process album field"));
- // Advice for Translators: set the first letter of genre translated
- ProcessGenreField = gtk_toggle_button_new_with_label( _("G"));
- gtk_widget_set_tooltip_text(ProcessGenreField, _("Process genre field"));
- // Advice for Translators: set the first letter of comment translated
- ProcessCommentField = gtk_toggle_button_new_with_label( _("Cm"));
- gtk_widget_set_tooltip_text(ProcessCommentField, _("Process comment field"));
- // Advice for Translators: set the first letter of composer translated
- ProcessComposerField = gtk_toggle_button_new_with_label( _("Cp"));
- gtk_widget_set_tooltip_text(ProcessComposerField, _("Process composer field"));
- // Advice for Translators: set the first letter of orig artist translated
- ProcessOrigArtistField = gtk_toggle_button_new_with_label( _("O"));
- gtk_widget_set_tooltip_text(ProcessOrigArtistField, _("Process original artist field"));
- // Advice for Translators: set the first letter of copyright translated
- ProcessCopyrightField = gtk_toggle_button_new_with_label( _("Cr"));
- gtk_widget_set_tooltip_text(ProcessCopyrightField, _("Process copyright field"));
- // Advice for Translators: set the first letter of URL translated
- ProcessURLField = gtk_toggle_button_new_with_label( _("U"));
- gtk_widget_set_tooltip_text(ProcessURLField, _("Process URL field"));
- // Advice for Translators: set the first letter of encoder name translated
- ProcessEncodedByField = gtk_toggle_button_new_with_label( _("E"));
- gtk_widget_set_tooltip_text(ProcessEncodedByField, _("Process encoder name field"));
- gtk_box_pack_start(GTK_BOX(hbox),ProcessFileNameField, TRUE,TRUE,2);
- gtk_box_pack_start(GTK_BOX(hbox),ProcessTitleField, TRUE,TRUE,2);
- gtk_box_pack_start(GTK_BOX(hbox),ProcessArtistField, TRUE,TRUE,2);
- gtk_box_pack_start(GTK_BOX(hbox),ProcessAlbumArtistField,TRUE,TRUE,2);
- gtk_box_pack_start(GTK_BOX(hbox),ProcessAlbumField, TRUE,TRUE,2);
- gtk_box_pack_start(GTK_BOX(hbox),ProcessGenreField, TRUE,TRUE,2);
- gtk_box_pack_start(GTK_BOX(hbox),ProcessCommentField, TRUE,TRUE,2);
- gtk_box_pack_start(GTK_BOX(hbox),ProcessComposerField, TRUE,TRUE,2);
- gtk_box_pack_start(GTK_BOX(hbox),ProcessOrigArtistField, TRUE,TRUE,2);
- gtk_box_pack_start(GTK_BOX(hbox),ProcessCopyrightField, TRUE,TRUE,2);
- gtk_box_pack_start(GTK_BOX(hbox),ProcessURLField, TRUE,TRUE,2);
- gtk_box_pack_start(GTK_BOX(hbox),ProcessEncodedByField, TRUE,TRUE,2);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessFileNameField), PROCESS_FILENAME_FIELD);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessTitleField), PROCESS_TITLE_FIELD);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessArtistField), PROCESS_ARTIST_FIELD);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessAlbumArtistField),PROCESS_ALBUM_ARTIST_FIELD);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessAlbumField), PROCESS_ALBUM_FIELD);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessGenreField), PROCESS_GENRE_FIELD);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessCommentField), PROCESS_COMMENT_FIELD);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessComposerField), PROCESS_COMPOSER_FIELD);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessOrigArtistField), PROCESS_ORIG_ARTIST_FIELD);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessCopyrightField), PROCESS_COPYRIGHT_FIELD);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessURLField), PROCESS_URL_FIELD);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessEncodedByField), PROCESS_ENCODED_BY_FIELD);
- g_signal_connect(G_OBJECT(ProcessFileNameField),
"toggled",G_CALLBACK(Select_Fields_Set_Sensitive),NULL);
- g_signal_connect(G_OBJECT(ProcessTitleField),
"toggled",G_CALLBACK(Select_Fields_Set_Sensitive),NULL);
- g_signal_connect(G_OBJECT(ProcessArtistField),
"toggled",G_CALLBACK(Select_Fields_Set_Sensitive),NULL);
-
g_signal_connect(G_OBJECT(ProcessAlbumArtistField),"toggled",G_CALLBACK(Select_Fields_Set_Sensitive),NULL);
- g_signal_connect(G_OBJECT(ProcessAlbumField),
"toggled",G_CALLBACK(Select_Fields_Set_Sensitive),NULL);
- g_signal_connect(G_OBJECT(ProcessGenreField),
"toggled",G_CALLBACK(Select_Fields_Set_Sensitive),NULL);
- g_signal_connect(G_OBJECT(ProcessCommentField),
"toggled",G_CALLBACK(Select_Fields_Set_Sensitive),NULL);
- g_signal_connect(G_OBJECT(ProcessComposerField),
"toggled",G_CALLBACK(Select_Fields_Set_Sensitive),NULL);
- g_signal_connect(G_OBJECT(ProcessOrigArtistField),
"toggled",G_CALLBACK(Select_Fields_Set_Sensitive),NULL);
- g_signal_connect(G_OBJECT(ProcessCopyrightField),
"toggled",G_CALLBACK(Select_Fields_Set_Sensitive),NULL);
- g_signal_connect(G_OBJECT(ProcessURLField),
"toggled",G_CALLBACK(Select_Fields_Set_Sensitive),NULL);
- g_signal_connect(G_OBJECT(ProcessEncodedByField),
"toggled",G_CALLBACK(Select_Fields_Set_Sensitive),NULL);
- /* The small buttons */
- Button = gtk_button_new();
- g_signal_connect(G_OBJECT(Button),"clicked",G_CALLBACK(Select_Fields_Invert_Selection),NULL);
- gtk_box_pack_end (GTK_BOX(hbox), Button, FALSE, FALSE, 0);
- Icon = gtk_image_new_from_stock ("easytag-invert-selection",
- GTK_ICON_SIZE_BUTTON);
- gtk_container_add(GTK_CONTAINER(Button),Icon);
- gtk_widget_set_tooltip_text (Button, _("Invert selection"));
- Button = gtk_button_new();
- g_signal_connect(G_OBJECT(Button),"clicked",G_CALLBACK(Select_Fields_Select_Unselect_All),NULL);
- gtk_box_pack_end (GTK_BOX(hbox), Button, FALSE, FALSE, 0);
- Icon = gtk_image_new_from_icon_name ("edit-select-all",
- GTK_ICON_SIZE_BUTTON);
- gtk_container_add(GTK_CONTAINER(Button),Icon);
- gtk_widget_set_tooltip_text (Button, _("Select/Unselect all"));
-
- /* Group: character conversion */
- group = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
- gtk_box_pack_start (GTK_BOX (VBox), group, FALSE, FALSE, 0);
- ProcessFieldsConvertIntoSpace = gtk_radio_button_new_with_label_from_widget (NULL, _("Convert '_' and
'%20' to spaces"));
- ProcessFieldsConvertSpace = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON
(ProcessFieldsConvertIntoSpace),
- _("Convert ' ' to '_'"));
- gtk_box_pack_start (GTK_BOX (group), ProcessFieldsConvertIntoSpace, FALSE,
- FALSE, 0);
- gtk_box_pack_start (GTK_BOX (group), ProcessFieldsConvertSpace, FALSE,
- FALSE, 0);
- hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,2);
- gtk_box_pack_start (GTK_BOX (group), hbox, FALSE, FALSE, 0);
- ProcessFieldsConvert = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON
(ProcessFieldsConvertIntoSpace),
- _("Convert:"));
- ProcessFieldsConvertTo = gtk_entry_new();
- ProcessFieldsConvertLabelTo = gtk_label_new(_("to: ")); // A "space" at the end to allow another
translation for "to :" (needed in French!)
- ProcessFieldsConvertFrom = gtk_entry_new();
- //gtk_entry_set_max_length(GTK_ENTRY(ProcessFieldsConvertTo), 1); // Now, it isn't limited to one
character
- //gtk_entry_set_max_length(GTK_ENTRY(ProcessFieldsConvertFrom), 1);
- gtk_widget_set_size_request(ProcessFieldsConvertTo,120,-1);
- gtk_widget_set_size_request(ProcessFieldsConvertFrom,120,-1);
- process_fields_convert_none = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON
(ProcessFieldsConvertIntoSpace),
- _("Do not convert"));
- gtk_box_pack_start(GTK_BOX(hbox),ProcessFieldsConvert, FALSE,FALSE,0);
- gtk_box_pack_start(GTK_BOX(hbox),ProcessFieldsConvertFrom, FALSE,FALSE,0);
- gtk_box_pack_start(GTK_BOX(hbox),ProcessFieldsConvertLabelTo,FALSE,FALSE,0);
- gtk_box_pack_start(GTK_BOX(hbox),ProcessFieldsConvertTo, FALSE,FALSE,0);
- gtk_box_pack_start (GTK_BOX (group), process_fields_convert_none, FALSE,
- FALSE, 0);
- if (PROCESS_FIELDS_CONVERT_FROM)
- gtk_entry_set_text(GTK_ENTRY(ProcessFieldsConvertFrom),PROCESS_FIELDS_CONVERT_FROM);
- if (PROCESS_FIELDS_CONVERT_TO)
- gtk_entry_set_text(GTK_ENTRY(ProcessFieldsConvertTo),PROCESS_FIELDS_CONVERT_TO);
- /* Toggled signals */
- g_signal_connect(G_OBJECT(ProcessFieldsConvert),
"toggled",G_CALLBACK(Process_Fields_Convert_Check_Button_Toggled),NULL);
- /* Set check buttons to init value */
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessFieldsConvertIntoSpace),PF_CONVERT_INTO_SPACE);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessFieldsConvertSpace),PF_CONVERT_SPACE);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessFieldsConvert),PF_CONVERT);
- /* Tooltips */
- gtk_widget_set_tooltip_text(ProcessFieldsConvertIntoSpace,
- _("The underscore character or the string '%20' are replaced by one space. "
- "Example, before: 'Text%20In%20An_Entry', after: 'Text In An Entry'."));
- gtk_widget_set_tooltip_text(ProcessFieldsConvertSpace,
- _("The space character is replaced by one underscore character. "
- "Example, before: 'Text In An Entry', after: 'Text_In_An_Entry'."));
- gtk_widget_set_tooltip_text(ProcessFieldsConvert,
- _("Replace a string by another one. Note that the search is case sensitive."));
-
- hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,0);
-
- /* Group: capitalize, ... */
- group = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
- gtk_box_pack_start (GTK_BOX (VBox), group, FALSE, FALSE, 0);
- ProcessFieldsAllUppercase = gtk_radio_button_new_with_label_from_widget (NULL, _("Capitalize all"));
- ProcessFieldsAllDowncase = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON
(ProcessFieldsAllUppercase),
- _("Lowercase all"));
- ProcessFieldsFirstLetterUppercase = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON
(ProcessFieldsAllUppercase),
- _("Capitalize first
letter"));
- ProcessFieldsFirstLettersUppercase = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON
(ProcessFieldsAllUppercase),
- _("Capitalize the
first letter of each word"));
- ProcessFieldsDetectRomanNumerals = gtk_check_button_new_with_label(_("Detect Roman numerals"));
- process_fields_case_none = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON
(ProcessFieldsAllUppercase),
- _("Do not change
capitalization"));
- gtk_box_pack_start (GTK_BOX (group), ProcessFieldsAllUppercase, FALSE,
- FALSE, 0);
- gtk_box_pack_start (GTK_BOX (group),ProcessFieldsAllDowncase, FALSE, FALSE,
- 0);
- gtk_box_pack_start (GTK_BOX (group),ProcessFieldsFirstLetterUppercase,
- FALSE, FALSE, 0);
- gtk_box_pack_start (GTK_BOX (group), hbox, FALSE, FALSE, 0);
- gtk_box_pack_start(GTK_BOX(hbox),ProcessFieldsFirstLettersUppercase,FALSE,FALSE,0);
- gtk_box_pack_start(GTK_BOX(hbox),ProcessFieldsDetectRomanNumerals,FALSE,FALSE,0);
- gtk_box_pack_start (GTK_BOX (group), process_fields_case_none, FALSE,
- FALSE, 0);
- /* Toggled signals */
-
g_signal_connect(G_OBJECT(ProcessFieldsFirstLettersUppercase),"toggled",G_CALLBACK(Process_Fields_First_Letters_Check_Button_Toggled),NULL);
- /* Set check buttons to init value */
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessFieldsAllUppercase),PF_CONVERT_ALL_UPPERCASE);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessFieldsAllDowncase),PF_CONVERT_ALL_DOWNCASE);
-
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessFieldsFirstLetterUppercase),PF_CONVERT_FIRST_LETTER_UPPERCASE);
-
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessFieldsFirstLettersUppercase),PF_CONVERT_FIRST_LETTERS_UPPERCASE);
-
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessFieldsDetectRomanNumerals),PF_DETECT_ROMAN_NUMERALS);
- /* Tooltips */
- gtk_widget_set_tooltip_text(ProcessFieldsAllUppercase,
- _("Convert all words in all fields to upper case. "
- "Example, before: 'Text IN AN entry', after: 'TEXT IN AN ENTRY'."));
- gtk_widget_set_tooltip_text(ProcessFieldsAllDowncase,
- _("Convert all words in all fields to lower case. "
- "Example, before: 'TEXT IN an entry', after: 'text in an entry'."));
- gtk_widget_set_tooltip_text(ProcessFieldsFirstLetterUppercase,
- _("Convert the initial of the first word in all fields to upper case. "
- "Example, before: 'text IN An ENTRY', after: 'Text in an entry'."));
- gtk_widget_set_tooltip_text(ProcessFieldsFirstLettersUppercase,
- _("Convert the initial of each word in all fields to upper case. "
- "Example, before: 'Text in an ENTRY', after: 'Text In An Entry'."));
- gtk_widget_set_tooltip_text(ProcessFieldsDetectRomanNumerals,
- _("Force to convert to upper case the Roman numerals. "
- "Example, before: 'ix. text in an entry', after: 'IX. Text In An Entry'."));
-
- /* Group: insert/remove spaces */
- group = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
- gtk_box_pack_start (GTK_BOX (VBox), group, FALSE, FALSE, 0);
- ProcessFieldsRemoveSpace = gtk_radio_button_new_with_label_from_widget (NULL, _("Remove spaces"));
- ProcessFieldsInsertSpace = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON
(ProcessFieldsRemoveSpace),
- _("Insert a space before
uppercase letters"));
- ProcessFieldsOnlyOneSpace = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON
(ProcessFieldsRemoveSpace),
- _("Remove duplicate spaces and
underscores"));
- radio_space_none = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON
(ProcessFieldsRemoveSpace),
- _("Do not change word separators"));
- gtk_box_pack_start (GTK_BOX (group), ProcessFieldsRemoveSpace, FALSE,
- FALSE, 0);
- gtk_box_pack_start (GTK_BOX (group), ProcessFieldsInsertSpace, FALSE,
- FALSE, 0);
- gtk_box_pack_start (GTK_BOX (group), ProcessFieldsOnlyOneSpace, FALSE,
- FALSE, 0);
- gtk_box_pack_start (GTK_BOX (group), radio_space_none, FALSE, FALSE, 0);
- /* Set check buttons to init value */
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessFieldsRemoveSpace),PF_REMOVE_SPACE);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessFieldsInsertSpace),PF_INSERT_SPACE);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessFieldsOnlyOneSpace),PF_ONLY_ONE_SPACE);
- /* Tooltips */
- gtk_widget_set_tooltip_text(ProcessFieldsRemoveSpace,
- _("All spaces between words are removed. "
- "Example, before: 'Text In An Entry', after: 'TextInAnEntry'."));
- gtk_widget_set_tooltip_text(ProcessFieldsInsertSpace,
- _("A space is inserted before each upper case letter. "
- "Example, before: 'TextInAnEntry', after: 'Text In An Entry'."));
- gtk_widget_set_tooltip_text(ProcessFieldsOnlyOneSpace,
- _("Duplicate spaces and underscores are removed. "
- "Example, before: 'Text__In__An Entry', after: 'Text_In_An Entry'."));
- Select_Fields_Set_Sensitive();
-
- /*
- * Frame to display codes legend
- */
- LegendFrame = gtk_frame_new (_("Legend"));
- gtk_box_pack_start(GTK_BOX(ScanVBox),LegendFrame,FALSE,FALSE,0);
- /* Legend labels */
- Table = et_grid_new (3, 6);
- gtk_container_add(GTK_CONTAINER(LegendFrame),Table);
- gtk_container_set_border_width(GTK_CONTAINER(Table),4);
- Label = gtk_label_new(_("%a: artist"));
- et_grid_attach_margins (GTK_GRID (Table), Label, 0, 0, 1, 1, 6, 0);
- gtk_misc_set_alignment(GTK_MISC(Label),0,0.5);
- Label = gtk_label_new(_("%z: album artist"));
- et_grid_attach_margins (GTK_GRID (Table), Label, 0, 1, 1, 1, 6, 0);
- gtk_misc_set_alignment(GTK_MISC(Label),0,0.5);
- Label = gtk_label_new(_("%b: album"));
- et_grid_attach_margins (GTK_GRID (Table), Label, 0, 2, 1, 1, 6, 0);
- gtk_misc_set_alignment(GTK_MISC(Label),0,0.5);
- Label = gtk_label_new(_("%c: comment"));
- et_grid_attach_margins (GTK_GRID (Table), Label, 0, 3, 1, 1, 6, 0);
- gtk_misc_set_alignment(GTK_MISC(Label),0,0.5);
- Label = gtk_label_new(_("%p: composer"));
- et_grid_attach_margins (GTK_GRID (Table), Label, 0, 4, 1, 1, 6, 0);
- gtk_misc_set_alignment(GTK_MISC(Label),0,0.5);
- Label = gtk_label_new(_("%r: copyright"));
- et_grid_attach_margins (GTK_GRID (Table), Label, 0, 5, 1, 1, 6, 0);
- gtk_misc_set_alignment(GTK_MISC(Label),0,0.5);
- Label = gtk_label_new(_("%d: disc number"));
- et_grid_attach_margins (GTK_GRID (Table), Label, 1, 0, 1, 1, 6, 0);
- gtk_misc_set_alignment(GTK_MISC(Label),0,0.5);
- Label = gtk_label_new(_("%e: encoded by"));
- et_grid_attach_margins (GTK_GRID (Table), Label, 1, 1, 1, 1, 6, 0);
- gtk_misc_set_alignment(GTK_MISC(Label),0,0.5);
- Label = gtk_label_new(_("%g: genre"));
- et_grid_attach_margins (GTK_GRID (Table), Label, 1, 2, 1, 1, 6, 0);
- gtk_misc_set_alignment(GTK_MISC(Label),0,0.5);
- Label = gtk_label_new(_("%i: ignored"));
- et_grid_attach_margins (GTK_GRID (Table), Label, 1, 3, 1, 1, 6, 0);
- gtk_misc_set_alignment(GTK_MISC(Label),0,0.5);
- Label = gtk_label_new(_("%l: number of tracks"));
- et_grid_attach_margins (GTK_GRID (Table), Label, 1, 4, 1, 1, 6, 0);
- gtk_misc_set_alignment(GTK_MISC(Label),0,0.5);
- Label = gtk_label_new(_("%o: orig. artist"));
- et_grid_attach_margins (GTK_GRID (Table), Label, 1, 5, 1, 1, 6, 0);
- gtk_misc_set_alignment(GTK_MISC(Label),0,0.5);
- Label = gtk_label_new(_("%n: track"));
- et_grid_attach_margins (GTK_GRID (Table), Label, 2, 0, 1, 1, 6, 0);
- gtk_misc_set_alignment(GTK_MISC(Label),0,0.5);
- Label = gtk_label_new(_("%t: title"));
- et_grid_attach_margins (GTK_GRID (Table), Label, 2, 1, 1, 1, 6, 0);
- gtk_misc_set_alignment(GTK_MISC(Label),0,0.5);
- Label = gtk_label_new(_("%u: URL"));
- et_grid_attach_margins (GTK_GRID (Table), Label, 2, 2, 1, 1, 6, 0);
- gtk_misc_set_alignment(GTK_MISC(Label),0,0.5);
- Label = gtk_label_new (_("%x: number of discs"));
- et_grid_attach_margins (GTK_GRID (Table), Label, 2, 3, 1, 1, 6, 0);
- gtk_misc_set_alignment (GTK_MISC (Label), 0, 0.5);
- Label = gtk_label_new(_("%y: year"));
- et_grid_attach_margins (GTK_GRID (Table), Label, 2, 4, 1, 1, 6, 0);
- gtk_misc_set_alignment(GTK_MISC(Label),0,0.5);
-
- /*
- * Masks Editor
- */
- MaskEditorFrame = gtk_frame_new (_("Mask Editor"));
- gtk_box_pack_start(GTK_BOX(ScanVBox),MaskEditorFrame,FALSE,FALSE,0);
- MaskEditorHBox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,4);
- gtk_container_add(GTK_CONTAINER(MaskEditorFrame),MaskEditorHBox);
- gtk_container_set_border_width(GTK_CONTAINER(MaskEditorHBox), 4);
-
- /* The editor part */
- MaskEditorVBox = gtk_box_new(GTK_ORIENTATION_VERTICAL,2);
- gtk_box_pack_start(GTK_BOX(MaskEditorHBox),MaskEditorVBox,TRUE,TRUE,0);
- MaskEditorScrollWindow = gtk_scrolled_window_new(NULL,NULL);
- gtk_box_pack_start(GTK_BOX(MaskEditorVBox),MaskEditorScrollWindow,TRUE,TRUE,0);
- gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(MaskEditorScrollWindow),
- GTK_POLICY_AUTOMATIC,GTK_POLICY_AUTOMATIC);
- gtk_widget_set_size_request(GTK_WIDGET(MaskEditorScrollWindow), -1, 101);
-
- /* The list */
- MaskEditorList = gtk_tree_view_new();
- gtk_tree_view_set_model(GTK_TREE_VIEW(MaskEditorList), GTK_TREE_MODEL(ScanTagListModel));
-
- renderer = gtk_cell_renderer_text_new();
- column = gtk_tree_view_column_new_with_attributes(NULL,
- renderer, "text", MASK_EDITOR_TEXT, NULL);
- gtk_tree_view_append_column(GTK_TREE_VIEW(MaskEditorList), column);
- gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(MaskEditorList), FALSE);
- gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(MaskEditorList)),
- GTK_SELECTION_MULTIPLE);
- gtk_tree_view_set_reorderable(GTK_TREE_VIEW(MaskEditorList), TRUE);
- gtk_container_add(GTK_CONTAINER(MaskEditorScrollWindow), MaskEditorList);
- g_signal_connect_after(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(MaskEditorList))),
- "changed", G_CALLBACK(Mask_Editor_List_Row_Selected), NULL);
- g_signal_connect(G_OBJECT(MaskEditorList), "key-press-event",
- G_CALLBACK(Mask_Editor_List_Key_Press), NULL);
- /* The entry */
- hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,2);
- gtk_box_pack_start(GTK_BOX(MaskEditorVBox),hbox,FALSE,FALSE,0);
- MaskEditorEntry = gtk_entry_new();
- gtk_box_pack_start(GTK_BOX(hbox),MaskEditorEntry,TRUE,TRUE,2);
- g_signal_connect(G_OBJECT(MaskEditorEntry),"changed",
- G_CALLBACK(Mask_Editor_Entry_Changed),NULL);
- // Mask status icon
- // Signal connection to check if mask is correct into the mask entry
- g_signal_connect (MaskEditorEntry,"changed",
- G_CALLBACK (entry_check_scan_tag_mask), NULL);
-
- /* The buttons part */
- MaskEditorVBox = gtk_box_new(GTK_ORIENTATION_VERTICAL,0);
- gtk_box_pack_start(GTK_BOX(MaskEditorHBox),MaskEditorVBox,FALSE,FALSE,0);
-
- /* New mask button */
- MaskEditorNewButton = gtk_button_new();
- Icon = gtk_image_new_from_stock(GTK_STOCK_NEW, GTK_ICON_SIZE_SMALL_TOOLBAR);
- gtk_container_add(GTK_CONTAINER(MaskEditorNewButton),Icon);
- gtk_box_pack_start(GTK_BOX(MaskEditorVBox),MaskEditorNewButton,FALSE,FALSE,0);
- gtk_button_set_relief(GTK_BUTTON(MaskEditorNewButton),GTK_RELIEF_NONE);
- gtk_widget_set_tooltip_text(MaskEditorNewButton,_("Create New Mask"));
- g_signal_connect(G_OBJECT(MaskEditorNewButton),"clicked",
- G_CALLBACK(Mask_Editor_List_New),NULL);
-
- /* Move up mask button */
- MaskEditorUpButton = gtk_button_new();
- Icon = gtk_image_new_from_stock(GTK_STOCK_GO_UP, GTK_ICON_SIZE_SMALL_TOOLBAR);
- gtk_container_add(GTK_CONTAINER(MaskEditorUpButton),Icon);
- gtk_box_pack_start(GTK_BOX(MaskEditorVBox),MaskEditorUpButton,FALSE,FALSE,0);
- gtk_button_set_relief(GTK_BUTTON(MaskEditorUpButton),GTK_RELIEF_NONE);
- gtk_widget_set_tooltip_text(MaskEditorUpButton,_("Move Up this Mask"));
- g_signal_connect(G_OBJECT(MaskEditorUpButton),"clicked",
- G_CALLBACK(Mask_Editor_List_Move_Up),NULL);
-
- /* Move down mask button */
- MaskEditorDownButton = gtk_button_new();
- Icon = gtk_image_new_from_stock(GTK_STOCK_GO_DOWN, GTK_ICON_SIZE_SMALL_TOOLBAR);
- gtk_container_add(GTK_CONTAINER(MaskEditorDownButton),Icon);
- gtk_box_pack_start(GTK_BOX(MaskEditorVBox),MaskEditorDownButton,FALSE,FALSE,0);
- gtk_button_set_relief(GTK_BUTTON(MaskEditorDownButton),GTK_RELIEF_NONE);
- gtk_widget_set_tooltip_text(MaskEditorDownButton,_("Move Down this Mask"));
- g_signal_connect(G_OBJECT(MaskEditorDownButton),"clicked",
- G_CALLBACK(Mask_Editor_List_Move_Down),NULL);
-
- /* Copy mask button */
- MaskEditorCopyButton = gtk_button_new();
- Icon = gtk_image_new_from_stock(GTK_STOCK_COPY, GTK_ICON_SIZE_SMALL_TOOLBAR);
- gtk_container_add(GTK_CONTAINER(MaskEditorCopyButton),Icon);
- gtk_box_pack_start(GTK_BOX(MaskEditorVBox),MaskEditorCopyButton,FALSE,FALSE,0);
- gtk_button_set_relief(GTK_BUTTON(MaskEditorCopyButton),GTK_RELIEF_NONE);
- gtk_widget_set_tooltip_text(MaskEditorCopyButton,_("Duplicate Mask"));
- g_signal_connect(G_OBJECT(MaskEditorCopyButton),"clicked",
- G_CALLBACK(Mask_Editor_List_Duplicate),NULL);
-
- /* Add mask button */
- MaskEditorAddButton = gtk_button_new();
- Icon = gtk_image_new_from_stock(GTK_STOCK_ADD, GTK_ICON_SIZE_SMALL_TOOLBAR);
- gtk_container_add(GTK_CONTAINER(MaskEditorAddButton),Icon);
- gtk_box_pack_start(GTK_BOX(MaskEditorVBox),MaskEditorAddButton,FALSE,FALSE,0);
- gtk_button_set_relief(GTK_BUTTON(MaskEditorAddButton),GTK_RELIEF_NONE);
- gtk_widget_set_tooltip_text(MaskEditorAddButton,_("Add Default Masks"));
- g_signal_connect(G_OBJECT(MaskEditorAddButton),"clicked",
- G_CALLBACK(Mask_Editor_List_Add),NULL);
-
- /* Remove mask button */
- MaskEditorRemoveButton = gtk_button_new();
- Icon = gtk_image_new_from_stock(GTK_STOCK_REMOVE, GTK_ICON_SIZE_SMALL_TOOLBAR);
- gtk_container_add(GTK_CONTAINER(MaskEditorRemoveButton),Icon);
- gtk_box_pack_start(GTK_BOX(MaskEditorVBox),MaskEditorRemoveButton,FALSE,FALSE,0);
- gtk_button_set_relief(GTK_BUTTON(MaskEditorRemoveButton),GTK_RELIEF_NONE);
- gtk_widget_set_tooltip_text(MaskEditorRemoveButton,_("Remove Mask"));
- g_signal_connect(G_OBJECT(MaskEditorRemoveButton),"clicked",
- G_CALLBACK(Mask_Editor_List_Remove),NULL);
-
- /* Save mask button */
- MaskEditorSaveButton = gtk_button_new();
- Icon = gtk_image_new_from_stock(GTK_STOCK_SAVE, GTK_ICON_SIZE_SMALL_TOOLBAR);
- gtk_container_add(GTK_CONTAINER(MaskEditorSaveButton),Icon);
- gtk_box_pack_end(GTK_BOX(MaskEditorVBox),MaskEditorSaveButton,FALSE,FALSE,0);
- gtk_button_set_relief(GTK_BUTTON(MaskEditorSaveButton),GTK_RELIEF_NONE);
- gtk_widget_set_tooltip_text(MaskEditorSaveButton,_("Save Masks"));
- g_signal_connect(G_OBJECT(MaskEditorSaveButton),"clicked",
- G_CALLBACK(Mask_Editor_List_Save_Button),NULL);
-
- gtk_widget_show(ScanVBox);
- gtk_widget_show_all(HBox1);
- gtk_widget_show_all(HBox2);
- gtk_widget_show_all(HBox4);
- gtk_widget_show(ScannerWindow);
-
- /* Init position of the scanner window */
- Scan_Set_Scanner_Window_Init_Position();
-
- /* To initialize the mask status icon and visibility */
- g_signal_emit_by_name(G_OBJECT(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(ScanTagMaskCombo)))),"changed");
- g_signal_emit_by_name(G_OBJECT(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(RenameFileMaskCombo)))),"changed");
- g_signal_emit_by_name(G_OBJECT(MaskEditorEntry),"changed");
- g_signal_emit_by_name(G_OBJECT(LegendButton),"toggled"); /* To hide legend frame */
- g_signal_emit_by_name(G_OBJECT(MaskEditorButton),"toggled"); /* To hide mask editor frame */
- g_signal_emit_by_name(G_OBJECT(ProcessFieldsConvert),"toggled");/* To enable / disable entries */
- g_signal_emit_by_name(G_OBJECT(ProcessFieldsDetectRomanNumerals),"toggled");/* To enable / disable
entries */
-
- // Activate the current menu in the option menu
- gtk_combo_box_set_active(GTK_COMBO_BOX(ScannerOptionCombo), scanner_type);
-
- toggle_action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (UIManager,
- "/ToolBar/ShowScanner"));
- if (!gtk_toggle_action_get_active (toggle_action))
- {
- gtk_toggle_action_set_active (toggle_action, TRUE);
- }
-}
-
-/*
- * Select the scanner to run for the current ETFile
- */
-void Scan_Select_Mode_And_Run_Scanner (ET_File *ETFile)
-{
- g_return_if_fail (ScannerWindow != NULL || ETFile != NULL);
-
- if (gtk_combo_box_get_active(GTK_COMBO_BOX(ScannerOptionCombo)) == SCANNER_FILL_TAG)
- {
- /* Run Scanner Type: Scan Tag */
- Scan_Tag_With_Mask(ETFile);
- } else if (gtk_combo_box_get_active(GTK_COMBO_BOX(ScannerOptionCombo)) == SCANNER_RENAME_FILE)
- {
- /* Run Scanner Type: Rename File */
- Scan_Rename_File_With_Mask(ETFile);
- } else if (gtk_combo_box_get_active(GTK_COMBO_BOX(ScannerOptionCombo)) == SCANNER_PROCESS_FIELDS)
- {
- /* Run Scanner Type: Process Fields */
- Scan_Process_Fields(ETFile);
- }
-}
-
-/*
- * et_scan_show:
- * @action: the #GtkToggleAction that was activated
- * @user_data: user data set when the signal handler was connected
- *
- * Show the scanner window.
- */
void
-et_scan_show (GtkAction *action, gpointer user_data)
-{
- gboolean active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
-
- if (active)
- {
- if (!ScannerWindow)
- {
- Open_ScannerWindow (SCANNER_TYPE);
- }
- else
- {
- gtk_window_present (GTK_WINDOW (ScannerWindow));
- }
- }
- else
- {
- ScannerWindow_Quit ();
- }
-}
-
-
-/* Callback from Open_ScannerWindow */
-static void
-ScannerWindow_Quit (void)
-{
- GtkToggleAction *toggle_action;
-
- toggle_action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (UIManager,
- "/ToolBar/ShowScanner"));
-
- if (gtk_toggle_action_get_active (toggle_action))
- {
- gtk_toggle_action_set_active (toggle_action, FALSE);
- }
-
- if (ScannerWindow)
- {
- ScannerWindow_Apply_Changes();
-
- gtk_widget_destroy(ScannerWindow);
- ScannerWindow = NULL;
- ScannerOptionCombo= NULL;
-
- // To avoid crashs after tests
- ScanTagMaskCombo = NULL;
- RenameFileMaskCombo = NULL;
- MaskEditorEntry = NULL;
- LegendFrame = NULL;
- ProcessFieldsConvertIntoSpace = NULL;
- ProcessFieldsConvertSpace = NULL;
- FillTagPreviewLabel = NULL;
- RenameFilePreviewLabel = NULL;
- }
-}
-
-
-/*
- * For the configuration file...
- */
-void ScannerWindow_Apply_Changes (void)
-{
- if (ScannerWindow)
- {
- gint x, y;//, width, height;
- GdkWindow *window;
-
- window = gtk_widget_get_window(ScannerWindow);
-
- if ( window && gdk_window_is_visible(window) &&
gdk_window_get_state(window)!=GDK_WINDOW_STATE_MAXIMIZED )
- {
- // Position and Origin of the scanner window
- gdk_window_get_root_origin(window,&x,&y);
- SCANNER_WINDOW_X = x;
- SCANNER_WINDOW_Y = y;
- //gdk_window_get_size(window,&width,&height);
- //SCANNER_WINDOW_WIDTH = width;
- //SCANNER_WINDOW_HEIGHT = height;
- }
-
- // The scanner selected
- SCANNER_TYPE = gtk_combo_box_get_active(GTK_COMBO_BOX(ScannerOptionCombo));
-
- SCAN_MASK_EDITOR_BUTTON = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(MaskEditorButton));
- SCAN_LEGEND_BUTTON = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(LegendButton));
-
- /* Group: select entries to process */
- PROCESS_FILENAME_FIELD = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFileNameField));
- PROCESS_TITLE_FIELD = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessTitleField));
- PROCESS_ARTIST_FIELD = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessArtistField));
- PROCESS_ALBUM_ARTIST_FIELD= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessAlbumArtistField));
- PROCESS_ALBUM_FIELD = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessAlbumField));
- PROCESS_GENRE_FIELD = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessGenreField));
- PROCESS_COMMENT_FIELD = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessCommentField));
- PROCESS_COMPOSER_FIELD = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessComposerField));
- PROCESS_ORIG_ARTIST_FIELD = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessOrigArtistField));
- PROCESS_COPYRIGHT_FIELD = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessCopyrightField));
- PROCESS_URL_FIELD = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessURLField));
- PROCESS_ENCODED_BY_FIELD = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessEncodedByField));
-
- if (PROCESS_FIELDS_CONVERT_FROM) g_free(PROCESS_FIELDS_CONVERT_FROM);
- PROCESS_FIELDS_CONVERT_FROM = g_strdup(gtk_entry_get_text(GTK_ENTRY(ProcessFieldsConvertFrom)));
- if (PROCESS_FIELDS_CONVERT_TO) g_free(PROCESS_FIELDS_CONVERT_TO);
- PROCESS_FIELDS_CONVERT_TO = g_strdup(gtk_entry_get_text(GTK_ENTRY(ProcessFieldsConvertTo)));
-
- /* Group: convert one character */
- PF_CONVERT_INTO_SPACE =
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsConvertIntoSpace));
- PF_CONVERT_SPACE =
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsConvertSpace));
- PF_CONVERT = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsConvert));
-
- /* Group: capitalize */
- PF_CONVERT_ALL_UPPERCASE =
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsAllUppercase));
- PF_CONVERT_ALL_DOWNCASE =
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsAllDowncase));
- PF_CONVERT_FIRST_LETTER_UPPERCASE =
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsFirstLetterUppercase));
- PF_CONVERT_FIRST_LETTERS_UPPERCASE =
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsFirstLettersUppercase));
- PF_DETECT_ROMAN_NUMERALS =
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsDetectRomanNumerals));
-
- /* Group: remove/insert space */
- PF_REMOVE_SPACE = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsRemoveSpace));
- PF_INSERT_SPACE = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsInsertSpace));
- PF_ONLY_ONE_SPACE = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsOnlyOneSpace));
-
- // Save default masks...
- if (SCAN_TAG_DEFAULT_MASK) g_free(SCAN_TAG_DEFAULT_MASK);
- SCAN_TAG_DEFAULT_MASK =
g_strdup(gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(ScanTagMaskCombo)))));
- Add_String_To_Combo_List(ScanTagListModel, SCAN_TAG_DEFAULT_MASK);
- Save_Rename_File_Masks_List(ScanTagListModel, MASK_EDITOR_TEXT);
-
- if (RENAME_FILE_DEFAULT_MASK) g_free(RENAME_FILE_DEFAULT_MASK);
- RENAME_FILE_DEFAULT_MASK =
g_strdup(gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(RenameFileMaskCombo)))));
- Add_String_To_Combo_List(RenameFileListModel, RENAME_FILE_DEFAULT_MASK);
- Save_Rename_File_Masks_List(RenameFileListModel, MASK_EDITOR_TEXT);
-
- }
-}
-
-
-/* Callback from Option button */
-static void
-Scan_Option_Button (void)
-{
- et_application_window_show_preferences_dialog (NULL, ET_APPLICATION_WINDOW (MainWindow));
- gtk_notebook_set_current_page(GTK_NOTEBOOK(OptionsNoteBook), OptionsNoteBook_Scanner_Page_Num);
-}
-
-
-/*
- * entry_check_rename_file_mask:
- * @entry: the entry for which to check the mask
- * @user_data: user data set when the signal was connected
- *
- * Display an icon in the entry if the current text contains an invalid mask
- * for scanning tags.
- */
-static void
-entry_check_scan_tag_mask (GtkEntry *entry, gpointer user_data)
+Scan_Process_Fields_All_Uppercase (gchar *string)
{
- gchar *tmp = NULL;
- gchar *mask = NULL;
- gint loop = 0;
-
- g_return_if_fail (entry != NULL);
-
- mask = g_strdup (gtk_entry_get_text (entry));
- if (!mask || strlen(mask)<1)
- goto Bad_Mask;
+ gchar *temp;
+ gchar temp2[6]; // Must have at least 6 bytes of space
+ gunichar c;
- while (mask)
+ for (temp = string; *temp; temp = g_utf8_next_char(temp))
{
- if ( (tmp=strrchr(mask,'%'))==NULL )
- {
- if (loop==0)
- /* There is no code the first time => not accepted */
- goto Bad_Mask;
- else
- /* There is no more code => accepted */
- goto Good_Mask;
- }
- if ( strlen(tmp)>1
- && (tmp[1]=='a' || tmp[1]=='b' || tmp[1]=='c' || tmp[1]=='d' || tmp[1]=='p' ||
- tmp[1]=='r' || tmp[1]=='e' || tmp[1]=='g' || tmp[1]=='i' || tmp[1]=='l' ||
- tmp[1]=='o' || tmp[1]=='n' || tmp[1]=='t' || tmp[1]=='u' || tmp[1]=='y' ) )
- {
- /* Code is correct */
- *(mask+strlen(mask)-strlen(tmp)) = '\0';
- }else
- {
- goto Bad_Mask;
- }
-
- /* Check the following code and separator */
- if ( (tmp=strrchr(mask,'%'))==NULL )
- /* There is no more code => accepted */
- goto Good_Mask;
-
- if ( strlen(tmp)>2
- && (tmp[1]=='a' || tmp[1]=='b' || tmp[1]=='c' || tmp[1]=='d' || tmp[1]=='p' ||
- tmp[1]=='r' || tmp[1]=='e' || tmp[1]=='g' || tmp[1]=='i' || tmp[1]=='l' ||
- tmp[1]=='o' || tmp[1]=='n' || tmp[1]=='t' || tmp[1]=='u' || tmp[1]=='y' ) )
- {
- /* There is a separator and code is correct */
- *(mask+strlen(mask)-strlen(tmp)) = '\0';
- }else
- {
- goto Bad_Mask;
- }
- loop++;
+ c = g_utf8_get_char(temp);
+ if (g_unichar_islower(c))
+ strncpy(temp, temp2, g_unichar_to_utf8(g_unichar_toupper(c), temp2));
}
-
- Bad_Mask:
- g_free(mask);
- gtk_entry_set_icon_from_icon_name (entry, GTK_ENTRY_ICON_SECONDARY,
- "emblem-unreadable");
- gtk_entry_set_icon_tooltip_text (entry, GTK_ENTRY_ICON_SECONDARY,
- _("Invalid scanner mask"));
- return;
-
- Good_Mask:
- g_free(mask);
- gtk_entry_set_icon_from_icon_name (entry, GTK_ENTRY_ICON_SECONDARY,
- NULL);
}
-/*
- * entry_check_rename_file_mask:
- * @entry: the entry for which to check the mask
- * @user_data: user data set when the signal was connected
- *
- * Display an icon in the entry if the current text contains an invalid mask
- * for renaming files.
- */
void
-entry_check_rename_file_mask (GtkEntry *entry, gpointer user_data)
-{
- gchar *tmp = NULL;
- gchar *mask = NULL;
-
- g_return_if_fail (entry != NULL);
-
- mask = g_strdup (gtk_entry_get_text (entry));
- if (!mask || strlen(mask)<1)
- goto Bad_Mask;
-
- // Not a valid path....
- if ( strstr(mask,"//") != NULL
- || strstr(mask,"./") != NULL
- || strstr(mask,"data/") != NULL)
- goto Bad_Mask;
-
- while (mask)
- {
- if ( (tmp=strrchr(mask,'%'))==NULL )
- {
- /* There is no more code. */
- /* No code in mask is accepted. */
- goto Good_Mask;
- }
- if ( strlen(tmp)>1
- && (tmp[1]=='a' || tmp[1]=='b' || tmp[1]=='c' || tmp[1]=='d' || tmp[1]=='p' ||
- tmp[1]=='r' || tmp[1]=='e' || tmp[1]=='g' || tmp[1]=='i' || tmp[1]=='l' ||
- tmp[1]=='o' || tmp[1]=='n' || tmp[1]=='t' || tmp[1]=='u' || tmp[1]=='y' ) )
- {
- /* The code is valid. */
- /* No separator is accepted. */
- *(mask+strlen(mask)-strlen(tmp)) = '\0';
- }else
- {
- goto Bad_Mask;
- }
- }
-
- Bad_Mask:
- g_free(mask);
- gtk_entry_set_icon_from_icon_name (entry, GTK_ENTRY_ICON_SECONDARY,
- "emblem-unreadable");
- gtk_entry_set_icon_tooltip_text (entry, GTK_ENTRY_ICON_SECONDARY,
- _("Invalid scanner mask"));
- return;
-
- Good_Mask:
- g_free(mask);
- gtk_entry_set_icon_from_icon_name (entry, GTK_ENTRY_ICON_SECONDARY,
- NULL);
-}
-
-
-static void
-Scan_Toggle_Legend_Button (void)
-{
- g_return_if_fail (LegendButton != NULL || LegendFrame != NULL);
-
- if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(LegendButton)) )
- gtk_widget_show_all(LegendFrame);
- else
- gtk_widget_hide(LegendFrame);
-}
-
-
-static void
-Scan_Toggle_Mask_Editor_Button (void)
-{
- GtkTreeModel *treemodel;
- GtkTreeSelection *selection;
- GtkTreeIter iter;
-
- g_return_if_fail (MaskEditorButton != NULL || MaskEditorFrame != NULL ||
- MaskEditorList != NULL);
-
- if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(MaskEditorButton)) )
- {
- gtk_widget_show_all(MaskEditorFrame);
-
- // Select first row in list
- treemodel = gtk_tree_view_get_model(GTK_TREE_VIEW(MaskEditorList));
- if (gtk_tree_model_get_iter_first(treemodel, &iter))
- {
- selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(MaskEditorList));
- gtk_tree_selection_unselect_all(selection);
- gtk_tree_selection_select_iter(selection, &iter);
- }
-
- // Update status of the icon box cause prev instruction show it for all cases
- g_signal_emit_by_name(G_OBJECT(MaskEditorEntry),"changed");
- }else
- {
- gtk_widget_hide(MaskEditorFrame);
- }
-}
-
-
-
-static void
-Process_Fields_Convert_Check_Button_Toggled (GtkWidget *object)
-{
-
gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsConvertTo),gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(object)));
-
gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsConvertFrom),gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(object)));
-}
-
-static void
-Process_Fields_First_Letters_Check_Button_Toggled (GtkWidget *object)
-{
-
gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsDetectRomanNumerals),gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(object)));
-}
-
-
-/*
- * Small buttons of Process Fields scanner
- */
-static void
-Select_Fields_Invert_Selection (void)
-{
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessFileNameField),
- !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFileNameField)));
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessTitleField),
- !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessTitleField)));
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessArtistField),
- !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessArtistField)));
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessAlbumArtistField),
- !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessAlbumArtistField)));
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessAlbumField),
- !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessAlbumField)));
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessGenreField),
- !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessGenreField)));
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessCommentField),
- !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessCommentField)));
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessComposerField),
- !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessComposerField)));
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessOrigArtistField),
- !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessOrigArtistField)));
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessCopyrightField),
- !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessCopyrightField)));
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessURLField),
- !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessURLField)));
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessEncodedByField),
- !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessEncodedByField)));
-}
-
-static void
-Select_Fields_Select_Unselect_All (void)
-{
- static gboolean state = TRUE;
-
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessFileNameField), state);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessTitleField), state);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessArtistField), state);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessAlbumArtistField),state);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessAlbumField), state);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessGenreField), state);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessCommentField), state);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessComposerField), state);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessOrigArtistField), state);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessCopyrightField), state);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessURLField), state);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessEncodedByField), state);
- state = !state;
-}
-
-/*
- * Set sensitive state of the processing check boxes : if no one is selected => all disabled
- */
-static void
-Select_Fields_Set_Sensitive (void)
-{
- if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFileNameField))
- || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessTitleField))
- || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessArtistField))
- || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessAlbumArtistField))
- || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessAlbumField))
- || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessGenreField))
- || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessCommentField))
- || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessComposerField))
- || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessOrigArtistField))
- || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessCopyrightField))
- || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessURLField))
- || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessEncodedByField)))
- {
- gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsConvertIntoSpace), TRUE);
- gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsConvertSpace), TRUE);
- gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsConvert), TRUE);
- gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsConvertLabelTo), TRUE);
- // Activate the two entries only if the check box is activated, else keep them disabled
- if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsConvert)))
- {
- gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsConvertTo), TRUE);
- gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsConvertFrom), TRUE);
- }
- gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsAllUppercase), TRUE);
- gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsAllDowncase), TRUE);
- gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsFirstLetterUppercase), TRUE);
- gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsFirstLettersUppercase),TRUE);
- Process_Fields_First_Letters_Check_Button_Toggled (ProcessFieldsFirstLettersUppercase);
- gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsRemoveSpace), TRUE);
- gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsInsertSpace), TRUE);
- gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsOnlyOneSpace), TRUE);
- }else
- {
- gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsConvertIntoSpace), FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsConvertSpace), FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsConvert), FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsConvertTo), FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsConvertLabelTo), FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsConvertFrom), FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsAllUppercase), FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsAllDowncase), FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsFirstLetterUppercase), FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsFirstLettersUppercase),FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsDetectRomanNumerals), FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsRemoveSpace), FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsInsertSpace), FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsOnlyOneSpace), FALSE);
- }
-}
-
-/*
- * Callbacks from Mask Editor buttons
- */
-
-/*
- * Callback from the mask edit list
- * Previously known as Mask_Editor_List_Select_Row
- */
-static void
-Mask_Editor_List_Row_Selected (GtkTreeSelection* selection, gpointer data)
-{
- GList *selectedRows;
- gchar *text = NULL;
- GtkTreePath *lastSelected;
- GtkTreeIter lastFile;
- GtkTreeModel *treemodel;
- gboolean valid;
-
- treemodel = gtk_tree_view_get_model(GTK_TREE_VIEW(MaskEditorList));
-
- /* We must block the function, else the previous selected row will be modified */
- g_signal_handlers_block_by_func(G_OBJECT(MaskEditorEntry),
- G_CALLBACK(Mask_Editor_Entry_Changed),NULL);
-
- selectedRows = gtk_tree_selection_get_selected_rows(selection, NULL);
-
- /*
- * At some point, we might get called when no rows are selected?
- */
- if (!selectedRows)
- {
- g_signal_handlers_unblock_by_func(G_OBJECT(MaskEditorEntry),
- G_CALLBACK(Mask_Editor_Entry_Changed),NULL);
- return;
- }
-
- /* Get the text of the last selected row */
- lastSelected = (GtkTreePath *)g_list_last(selectedRows)->data;
-
- valid= gtk_tree_model_get_iter(treemodel, &lastFile, lastSelected);
- if (valid)
- {
- gtk_tree_model_get(treemodel, &lastFile, MASK_EDITOR_TEXT, &text, -1);
-
- if (text)
- {
- gtk_entry_set_text(GTK_ENTRY(MaskEditorEntry),text);
- g_free(text);
- }
- }
-
- g_signal_handlers_unblock_by_func(G_OBJECT(MaskEditorEntry),
- G_CALLBACK(Mask_Editor_Entry_Changed),NULL);
-
- g_list_free_full (selectedRows, (GDestroyNotify)gtk_tree_path_free);
-}
-
-
-/*
- * Add a new mask to the list
- */
-static void
-Mask_Editor_List_New (void)
-{
- gchar *text = _("New_mask");
- GtkTreeIter iter;
- GtkTreeSelection *selection;
- GtkTreeModel *treemodel;
-
- g_return_if_fail (MaskEditorList != NULL);
-
- selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(MaskEditorList));
- treemodel = gtk_tree_view_get_model(GTK_TREE_VIEW(MaskEditorList));
-
- gtk_list_store_insert(GTK_LIST_STORE(treemodel), &iter, 0);
- gtk_list_store_set(GTK_LIST_STORE(treemodel), &iter, MASK_EDITOR_TEXT, text, -1);
-
- gtk_tree_selection_unselect_all(selection);
- gtk_tree_selection_select_iter(selection, &iter);
-}
-
-/*
- * Duplicate a mask on the list
- */
-static void
-Mask_Editor_List_Duplicate (void)
-{
- gchar *text = NULL;
- GList *selectedRows;
- GList *l;
- GList *toInsert = NULL;
- GtkTreeSelection *selection;
- GtkTreeIter rowIter;
- GtkTreeModel *treeModel;
-
- g_return_if_fail (MaskEditorList != NULL);
-
- selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(MaskEditorList));
- selectedRows = gtk_tree_selection_get_selected_rows(selection, NULL);
- treeModel = gtk_tree_view_get_model(GTK_TREE_VIEW(MaskEditorList));
-
- if (!selectedRows)
- {
- Log_Print(LOG_ERROR,_("Copy: No row selected"));
- return;
- }
-
- /* Loop through selected rows, duplicating them into a GList
- * We cannot directly insert because the paths in selectedRows
- * get out of date after an insertion */
- for (l = selectedRows; l != NULL; l = g_list_next (l))
- {
- if (gtk_tree_model_get_iter (treeModel, &rowIter,
- (GtkTreePath*)l->data))
- {
- gtk_tree_model_get(treeModel, &rowIter, MASK_EDITOR_TEXT, &text, -1);
- toInsert = g_list_prepend (toInsert, text);
- }
- }
-
- for (l = toInsert; l != NULL; l = g_list_next (l))
- {
- gtk_list_store_insert_with_values (GTK_LIST_STORE(treeModel), &rowIter,
- 0, MASK_EDITOR_TEXT,
- (gchar *)l->data, -1);
- }
-
- // Set focus to the last inserted line
- if (toInsert)
- Mask_Editor_List_Set_Row_Visible(treeModel,&rowIter);
-
- /* Free data no longer needed */
- g_list_free_full (selectedRows, (GDestroyNotify)gtk_tree_path_free);
- g_list_free_full (toInsert, (GDestroyNotify)g_free);
-}
-
-static void
-Mask_Editor_List_Add (void)
+Scan_Process_Fields_All_Downcase (gchar *string)
{
- gint i = 0;
- GtkTreeModel *treemodel;
gchar *temp;
+ gchar temp2[6];
+ gunichar c;
- treemodel = gtk_tree_view_get_model(GTK_TREE_VIEW(MaskEditorList));
-
- if (gtk_combo_box_get_active(GTK_COMBO_BOX(ScannerOptionCombo)) == SCANNER_FILL_TAG)
- {
- while(Scan_Masks[i])
- {
- /*if (!g_utf8_validate(Scan_Masks[i], -1, NULL))
- temp = convert_to_utf8(Scan_Masks[i]);
- else
- temp = g_strdup(Scan_Masks[i]);*/
- temp = Try_To_Validate_Utf8_String(Scan_Masks[i]);
-
- gtk_list_store_insert_with_values (GTK_LIST_STORE (treemodel),
- NULL, G_MAXINT,
- MASK_EDITOR_TEXT, temp, -1);
- g_free(temp);
- i++;
- }
- } else if (gtk_combo_box_get_active(GTK_COMBO_BOX(ScannerOptionCombo)) == SCANNER_RENAME_FILE)
- {
- while(Rename_File_Masks[i])
- {
- /*if (!g_utf8_validate(Rename_File_Masks[i], -1, NULL))
- temp = convert_to_utf8(Rename_File_Masks[i]);
- else
- temp = g_strdup(Rename_File_Masks[i]);*/
- temp = Try_To_Validate_Utf8_String(Rename_File_Masks[i]);
-
- gtk_list_store_insert_with_values (GTK_LIST_STORE (treemodel),
- NULL, G_MAXINT,
- MASK_EDITOR_TEXT, temp, -1);
- g_free(temp);
- i++;
- }
- }
-}
-
-/*
- * Remove the selected rows from the mask editor list
- */
-static void
-Mask_Editor_List_Remove (void)
-{
- GtkTreeSelection *selection;
- GtkTreeIter iter;
- GtkTreeModel *treemodel;
-
- g_return_if_fail (MaskEditorList != NULL);
-
- selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(MaskEditorList));
- treemodel = gtk_tree_view_get_model(GTK_TREE_VIEW(MaskEditorList));
-
- if (gtk_tree_selection_count_selected_rows(selection) == 0) {
- Log_Print(LOG_ERROR,_("Remove: No row selected"));
- return;
- }
-
- if (!gtk_tree_model_get_iter_first(treemodel, &iter))
- return;
-
- while (TRUE)
- {
- if (gtk_tree_selection_iter_is_selected(selection, &iter))
- {
- if (!gtk_list_store_remove(GTK_LIST_STORE(treemodel), &iter))
- {
- break;
- }
- } else
- {
- if (!gtk_tree_model_iter_next(treemodel, &iter))
- {
- break;
- }
- }
- }
-}
-
-/*
- * Move all selected rows up one place in the mask list
- */
-static void
-Mask_Editor_List_Move_Up (void)
-{
- GtkTreeSelection *selection;
- GList *selectedRows;
- GList *l;
- GtkTreeIter currentFile;
- GtkTreeIter nextFile;
- GtkTreePath *currentPath;
- GtkTreeModel *treemodel;
-
- g_return_if_fail (MaskEditorList != NULL);
-
- selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(MaskEditorList));
- treemodel = gtk_tree_view_get_model(GTK_TREE_VIEW(MaskEditorList));
- selectedRows = gtk_tree_selection_get_selected_rows(selection, NULL);
-
- if (!selectedRows)
- {
- Log_Print(LOG_ERROR,_("Move Up: No row selected"));
- return;
- }
-
- for (l = selectedRows; l != NULL; l = g_list_next (l))
+ for (temp = string; *temp; temp = g_utf8_next_char(temp))
{
- currentPath = (GtkTreePath *)l->data;
- if (gtk_tree_model_get_iter(treemodel, ¤tFile, currentPath))
- {
- /* Find the entry above the node... */
- if (gtk_tree_path_prev(currentPath))
- {
- /* ...and if it exists, swap the two rows by iter */
- gtk_tree_model_get_iter(treemodel, &nextFile, currentPath);
- gtk_list_store_swap(GTK_LIST_STORE(treemodel), ¤tFile, &nextFile);
- }
- }
+ c = g_utf8_get_char(temp);
+ if (g_unichar_isupper(c))
+ strncpy(temp, temp2, g_unichar_to_utf8(g_unichar_tolower(c), temp2));
}
-
- g_list_free_full (selectedRows, (GDestroyNotify)gtk_tree_path_free);
}
-/*
- * Move all selected rows down one place in the mask list
- */
-static void
-Mask_Editor_List_Move_Down (void)
+void
+Scan_Process_Fields_Letter_Uppercase (gchar *string)
{
- GtkTreeSelection *selection;
- GList *selectedRows;
- GList *l;
- GtkTreeIter currentFile;
- GtkTreeIter nextFile;
- GtkTreePath *currentPath;
- GtkTreeModel *treemodel;
-
- g_return_if_fail (MaskEditorList != NULL);
-
- selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(MaskEditorList));
- treemodel = gtk_tree_view_get_model(GTK_TREE_VIEW(MaskEditorList));
- selectedRows = gtk_tree_selection_get_selected_rows(selection, NULL);
-
- if (!selectedRows)
- {
- Log_Print(LOG_ERROR,_("Move Down: No row selected"));
- return;
- }
+ gchar *temp;
+ gchar temp2[6];
+ gboolean set_to_upper_case = TRUE;
+ gunichar c;
+ gchar utf8_character[6];
+ gchar *word, *word1, *word2;
- for (l = selectedRows; l != NULL; l = g_list_next (l))
+ for (temp = string; *temp; temp = g_utf8_next_char(temp))
{
- currentPath = (GtkTreePath *)l->data;
-
- if (gtk_tree_model_get_iter(treemodel, ¤tFile, currentPath))
- {
- /* Find the entry below the node and swap the two nodes by iter */
- gtk_tree_path_next(currentPath);
- if (gtk_tree_model_get_iter(treemodel, &nextFile, currentPath))
- gtk_list_store_swap(GTK_LIST_STORE(treemodel), ¤tFile, &nextFile);
- }
+ c = g_utf8_get_char(temp);
+ if (set_to_upper_case && g_unichar_islower(c))
+ strncpy(temp, temp2, g_unichar_to_utf8(g_unichar_toupper(c), temp2));
+ else if (!set_to_upper_case && g_unichar_isupper(c))
+ strncpy(temp, temp2, g_unichar_to_utf8(g_unichar_tolower(c), temp2));
+ set_to_upper_case = FALSE; // After the first time, all will be down case
}
- g_list_free_full (selectedRows, (GDestroyNotify)gtk_tree_path_free);
-}
-
-/*
- * Set a row visible in the mask editor list (by scrolling the list)
- */
-static void
-Mask_Editor_List_Set_Row_Visible (GtkTreeModel *treeModel, GtkTreeIter *rowIter)
-{
- /*
- * TODO: Make this only scroll to the row if it is not visible
- * (like in easytag GTK1)
- * See function gtk_tree_view_get_visible_rect() ??
- */
- GtkTreePath *rowPath;
-
- g_return_if_fail (treeModel != NULL);
-
- rowPath = gtk_tree_model_get_path(treeModel, rowIter);
- gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(MaskEditorList), rowPath, NULL, FALSE, 0, 0);
- gtk_tree_path_free(rowPath);
-}
-
-/*
- * Save the currently displayed mask list in the mask editor
- */
-static void
-Mask_Editor_List_Save_Button (void)
-{
- Mask_Editor_Clean_Up_Masks_List();
+ temp = string;
- if (gtk_combo_box_get_active(GTK_COMBO_BOX(ScannerOptionCombo)) == SCANNER_FILL_TAG)
- {
- Save_Scan_Tag_Masks_List(ScanTagListModel, MASK_EDITOR_TEXT);
- } else if (gtk_combo_box_get_active(GTK_COMBO_BOX(ScannerOptionCombo)) == SCANNER_RENAME_FILE)
+ // Uppercase again the word 'I' in english
+ while ( temp )
{
- Save_Rename_File_Masks_List(RenameFileListModel, MASK_EDITOR_TEXT);
- }
-}
-
-/*
- * Clean up the currently displayed masks lists, ready for saving
- */
-static void
-Mask_Editor_Clean_Up_Masks_List (void)
-{
- gchar *text = NULL;
- gchar *text1 = NULL;
- GtkTreeIter currentIter;
- GtkTreeIter itercopy;
- GtkTreeModel *treemodel;
+ word = temp; // Needed if there is only one word
+ word1 = g_utf8_strchr(temp,-1,' ');
+ word2 = g_utf8_strchr(temp,-1,'_');
- treemodel = gtk_tree_view_get_model(GTK_TREE_VIEW(MaskEditorList));
+ // Take the first string found (near beginning of string)
+ if (word1 && word2)
+ word = MIN(word1,word2);
+ else if (word1)
+ word = word1;
+ else if (word2)
+ word = word2;
+ else
+ // Last word of the string
+ break;
- /* Remove blank and duplicate items */
- if (gtk_tree_model_get_iter_first(treemodel, ¤tIter))
- {
+ // Go to first character of the word (char. after ' ' or '_')
+ word = word+1;
- while(TRUE)
+ // Set uppercase word 'I'
+ if (g_ascii_strncasecmp("I ", word, strlen("I ")) == 0)
{
- gtk_tree_model_get(treemodel, ¤tIter, MASK_EDITOR_TEXT, &text, -1);
-
- /* Check for blank entry */
- if (text && g_utf8_strlen(text, -1) == 0)
- {
- g_free(text);
-
- if (!gtk_list_store_remove(GTK_LIST_STORE(treemodel), ¤tIter))
- break; /* No following entries */
- else
- continue; /* Go on to next entry, which the remove function already moved onto for us */
- }
-
- /* Check for duplicate entries */
- itercopy = currentIter;
- if (!gtk_tree_model_iter_next(treemodel, &itercopy))
- {
- g_free(text);
- break;
- }
-
- while(TRUE)
- {
- gtk_tree_model_get(treemodel, &itercopy, MASK_EDITOR_TEXT, &text1, -1);
- if (text1 && g_utf8_collate(text,text1) == 0)
- {
- g_free(text1);
-
- if (!gtk_list_store_remove(GTK_LIST_STORE(treemodel), &itercopy))
- break; /* No following entries */
- else
- continue; /* Go on to next entry, which the remove function already set iter to for
us */
-
- }
- g_free(text1);
- if (!gtk_tree_model_iter_next(treemodel, &itercopy))
- break;
- }
-
- g_free(text);
-
- if (!gtk_tree_model_iter_next(treemodel, ¤tIter))
- break;
+ c = g_utf8_get_char(word);
+ strncpy(word, utf8_character, g_unichar_to_utf8(g_unichar_toupper(c), utf8_character));
}
- }
-}
-
-/*
- * Update the Mask List with the new value of the entry box
- */
-static void
-Mask_Editor_Entry_Changed (void)
-{
- GtkTreeSelection *selection;
- GtkTreePath *firstSelected;
- GtkTreeModel *treemodel;
- GList *selectedRows;
- GtkTreeIter row;
- const gchar* text;
-
- g_return_if_fail (MaskEditorList != NULL);
-
- selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(MaskEditorList));
- treemodel = gtk_tree_view_get_model(GTK_TREE_VIEW(MaskEditorList));
- selectedRows = gtk_tree_selection_get_selected_rows(selection, NULL);
-
- if (!selectedRows)
- {
- return;
- }
-
- firstSelected = (GtkTreePath *)g_list_first(selectedRows)->data;
- text = gtk_entry_get_text(GTK_ENTRY(MaskEditorEntry));
-
- if (gtk_tree_model_get_iter (treemodel, &row, firstSelected))
- {
- gtk_list_store_set(GTK_LIST_STORE(treemodel), &row, MASK_EDITOR_TEXT, text, -1);
- }
-
- g_list_free_full (selectedRows, (GDestroyNotify)gtk_tree_path_free);
-}
-
-/*
- * Actions when the a key is pressed into the masks editor clist
- */
-static gboolean
-Mask_Editor_List_Key_Press (GtkWidget *widget, GdkEvent *event)
-{
- if (event && event->type == GDK_KEY_PRESS) {
- GdkEventKey *kevent = (GdkEventKey *)event;
-
- switch(kevent->keyval)
- {
- case GDK_KEY_Delete:
- Mask_Editor_List_Remove();
- break;
-/* case GDK_KEY_Up:
- Mask_Editor_Clist_Move_Up();
- break;
- case GDK_KEY_Down:
- Mask_Editor_Clist_Move_Down();
- break;
-*/ }
- }
- return TRUE;
-}
-
-/*
- * Function when you select an item of the option menu
- */
-static void
-Scanner_Option_Menu_Activate_Item (GtkWidget *combo, gpointer data)
-{
- GtkRadioAction *radio_action;
-
- radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (UIManager,
- "/MenuBar/ViewMenu/ScannerMenu/FillTag"));
- SCANNER_TYPE = gtk_combo_box_get_active (GTK_COMBO_BOX (combo));
- gtk_radio_action_set_current_value (radio_action, SCANNER_TYPE);
-
- switch (SCANNER_TYPE)
- {
- case SCANNER_FILL_TAG:
- gtk_widget_show(MaskEditorButton);
- gtk_widget_show(LegendButton);
- gtk_widget_show(ScanTagFrame);
- gtk_widget_hide(RenameFileFrame);
- gtk_widget_hide(ProcessFieldsFrame);
- gtk_tree_view_set_model(GTK_TREE_VIEW(MaskEditorList), GTK_TREE_MODEL(ScanTagListModel));
- Scan_Fill_Tag_Generate_Preview();
- g_signal_emit_by_name(G_OBJECT(LegendButton),"toggled"); /* To hide or show legend frame
*/
- g_signal_emit_by_name(G_OBJECT(MaskEditorButton),"toggled"); /* To hide or show mask editor
frame */
- break;
-
- case SCANNER_RENAME_FILE:
- gtk_widget_show(MaskEditorButton);
- gtk_widget_show(LegendButton);
- gtk_widget_hide(ScanTagFrame);
- gtk_widget_show(RenameFileFrame);
- gtk_widget_hide(ProcessFieldsFrame);
- gtk_tree_view_set_model(GTK_TREE_VIEW(MaskEditorList), GTK_TREE_MODEL(RenameFileListModel));
- Scan_Rename_File_Generate_Preview();
- g_signal_emit_by_name(G_OBJECT(LegendButton),"toggled"); /* To hide or show legend frame
*/
- g_signal_emit_by_name(G_OBJECT(MaskEditorButton),"toggled"); /* To hide or show mask editor
frame */
- break;
-
- case SCANNER_PROCESS_FIELDS:
- gtk_widget_hide(MaskEditorButton);
- gtk_widget_hide(LegendButton);
- gtk_widget_hide(ScanTagFrame);
- gtk_widget_hide(RenameFileFrame);
- gtk_widget_show_all(ProcessFieldsFrame);
- // Hide directly the frames to don't change state of the buttons!
- gtk_widget_hide(LegendFrame);
- gtk_widget_hide(MaskEditorFrame);
- gtk_tree_view_set_model(GTK_TREE_VIEW(MaskEditorList), NULL);
- break;
+ temp = word;
}
}
-/*
- * Init the position of the scanner window
- */
-static void
-Scan_Set_Scanner_Window_Init_Position (void)
-{
- if (ScannerWindow && SET_SCANNER_WINDOW_POSITION)
- {
- gtk_widget_realize(ScannerWindow);
- gtk_window_move(GTK_WINDOW(ScannerWindow),SCANNER_WINDOW_X,SCANNER_WINDOW_Y);
- }
-}
-/*
- * et_scan_on_response:
- * @dialog: the scanner window
- * @response_id: the #GtkResponseType corresponding to the dialog event
- * @user_data: user data set when the signal was connected
- *
- * Handle the response signal of the scanner dialog.
- */
-static void
-et_scan_on_response (GtkDialog *dialog, gint response_id, gpointer user_data)
-{
- switch (response_id)
- {
- case GTK_RESPONSE_APPLY:
- Action_Scan_Selected_Files ();
- break;
- case GTK_RESPONSE_DELETE_EVENT:
- case GTK_RESPONSE_CLOSE:
- ScannerWindow_Quit ();
- break;
- default:
- g_assert_not_reached ();
- break;
- }
-}
diff --git a/src/scan.h b/src/scan.h
index ef95bc4..4ad7b63 100644
--- a/src/scan.h
+++ b/src/scan.h
@@ -1,82 +1,21 @@
-/* scan.h - 2000/06/16 */
-/*
- * EasyTAG - Tag editor for MP3 and Ogg Vorbis files
- * Copyright (C) 2000-2003 Jerome Couderc <easytag gmail com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
+#ifndef ET_SCAN_H_
+#define ET_SCAN_H_
+#include <glib.h>
-#ifndef __SCAN_H__
-#define __SCAN_H__
-
-
-#include "et_core.h"
-
-#include <gtk/gtk.h>
-
-/****************
- * Declarations *
- ****************/
-GtkWidget *ScannerWindow;
-
-
-enum
-{
- SCANNER_FILL_TAG = 0,
- SCANNER_RENAME_FILE,
- SCANNER_PROCESS_FIELDS
-}; // Add a new item : Min and Max values used in Open_ScannerWindow
-
-enum {
- MASK_EDITOR_TEXT,
- MASK_EDITOR_COUNT
-};
-
-
-
-/**************
- * Prototypes *
- **************/
-
-void Scan_Select_Mode_And_Run_Scanner (ET_File *ETFile);
-gchar *Scan_Generate_New_Filename_From_Mask (ET_File *ETFile, gchar *mask, gboolean
no_dir_check_or_conversion);
-gchar *Scan_Generate_New_Directory_Name_From_Mask (ET_File *ETFile, gchar *mask, gboolean
no_dir_check_or_conversion);
-void Scan_Rename_File_Generate_Preview (void);
-void Scan_Fill_Tag_Generate_Preview (void);
-void Scan_Rename_Directory_Generate_Preview (void);
-
-void et_scan_show (GtkAction *action, gpointer user_data);
-
-void entry_check_rename_file_mask (GtkEntry *entry, gpointer user_data);
-
-void Scan_Process_Fields_All_Uppercase (gchar *string);
-void Scan_Process_Fields_All_Downcase (gchar *string);
-void Scan_Process_Fields_Letter_Uppercase (gchar *string);
-void Scan_Process_Fields_First_Letters_Uppercase (gchar *string);
-void Scan_Process_Fields_Remove_Space (gchar *string);
-void Scan_Process_Fields_Insert_Space (gchar **string);
-void Scan_Process_Fields_Keep_One_Space (gchar *string);
+G_BEGIN_DECLS
void Scan_Convert_Underscore_Into_Space (gchar *string);
-void Scan_Convert_P20_Into_Space (gchar *string);
-void Scan_Convert_Space_Into_Undescore (gchar *string);
-void Scan_Remove_Spaces (gchar *string);
-
-void Init_ScannerWindow (void);
-void Open_ScannerWindow (gint scanner_type);
-void ScannerWindow_Apply_Changes (void);
-
-#endif /* __SCAN_H__ */
+void Scan_Convert_P20_Into_Space (gchar *string);
+void Scan_Convert_Space_Into_Underscore (gchar *string);
+void Scan_Process_Fields_Remove_Space (gchar *string);
+void Scan_Process_Fields_Insert_Space (gchar **string);
+void Scan_Process_Fields_Keep_One_Space (gchar *string);
+void Scan_Remove_Spaces (gchar *string);
+void Scan_Process_Fields_All_Uppercase (gchar *string);
+void Scan_Process_Fields_All_Downcase (gchar *string);
+void Scan_Process_Fields_Letter_Uppercase (gchar *string);
+
+G_END_DECLS
+
+#endif /* !ET_SCAN_H_ */
diff --git a/src/scan_dialog.c b/src/scan_dialog.c
new file mode 100644
index 0000000..0313e44
--- /dev/null
+++ b/src/scan_dialog.c
@@ -0,0 +1,3873 @@
+/*
+ * EasyTAG - Tag editor for MP3 and Ogg Vorbis files
+ * Copyright (C) 2000-2003 Jerome Couderc <easytag gmail com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include "scan_dialog.h"
+
+#include <gtk/gtk.h>
+#include <string.h>
+#include <stdlib.h>
+#include <gdk/gdkkeysyms.h>
+#include <config.h>
+#include <glib/gi18n.h>
+
+#include "application_window.h"
+#include "gtk2_compat.h"
+#include "easytag.h"
+#include "preferences_dialog.h"
+#include "scan.h"
+#include "setting.h"
+#include "id3_tag.h"
+#include "bar.h"
+#include "browser.h"
+#include "log.h"
+#include "misc.h"
+#include "et_core.h"
+#include "crc32.h"
+#include "charset.h"
+
+/* TODO: Use G_DEFINE_TYPE_WITH_PRIVATE. */
+G_DEFINE_TYPE (EtScanDialog, et_scan_dialog, GTK_TYPE_DIALOG)
+
+#define et_scan_dialog_get_instance_private(dialog) (dialog->priv)
+
+#define step(a,b) (b-a)+1
+
+struct _EtScanDialogPrivate
+{
+ GtkListStore *rename_masks_model;
+ GtkListStore *scan_tag_masks_model;
+
+ GtkWidget *type_combo;
+
+ GtkWidget *fill_tag_preview_label;
+ GtkWidget *rename_file_preview_label;
+};
+
+/****************
+ * Declarations *
+ ****************/
+static GtkWidget *ScanTagMaskCombo = NULL;
+static GtkWidget *RenameFileMaskCombo = NULL;
+
+static GtkWidget *ScanTagFrame;
+static GtkWidget *RenameFileFrame;
+static GtkWidget *ProcessFieldsFrame;
+
+
+static GtkWidget *ProcessFileNameField;
+static GtkWidget *ProcessTitleField;
+static GtkWidget *ProcessArtistField;
+static GtkWidget *ProcessAlbumArtistField;
+static GtkWidget *ProcessAlbumField;
+static GtkWidget *ProcessGenreField;
+static GtkWidget *ProcessCommentField;
+static GtkWidget *ProcessComposerField;
+static GtkWidget *ProcessOrigArtistField;
+static GtkWidget *ProcessCopyrightField;
+static GtkWidget *ProcessURLField;
+static GtkWidget *ProcessEncodedByField;
+static GtkWidget *ProcessFieldsConvertIntoSpace = NULL;
+static GtkWidget *ProcessFieldsConvertSpace = NULL;
+static GtkWidget *ProcessFieldsConvert = NULL;
+static GtkWidget *ProcessFieldsConvertLabelTo;
+static GtkWidget *ProcessFieldsConvertTo = NULL;
+static GtkWidget *ProcessFieldsConvertFrom = NULL;
+static GtkWidget *ProcessFieldsAllUppercase = NULL;
+static GtkWidget *ProcessFieldsAllDowncase = NULL;
+static GtkWidget *ProcessFieldsFirstLetterUppercase = NULL;
+static GtkWidget *ProcessFieldsFirstLettersUppercase = NULL;
+static GtkWidget *ProcessFieldsDetectRomanNumerals = NULL;
+static GtkWidget *ProcessFieldsRemoveSpace = NULL;
+static GtkWidget *ProcessFieldsInsertSpace = NULL;
+static GtkWidget *ProcessFieldsOnlyOneSpace = NULL;
+
+static GtkWidget *LegendFrame = NULL;
+static GtkWidget *LegendButton = NULL;
+
+static GtkWidget *MaskEditorButton = NULL;
+static GtkWidget *MaskEditorFrame = NULL;
+static GtkWidget *MaskEditorVBox;
+static GtkWidget *MaskEditorHBox;
+static GtkWidget *MaskEditorScrollWindow;
+static GtkWidget *MaskEditorList;
+static GtkWidget *MaskEditorEntry;
+static GtkWidget *MaskEditorNewButton;
+static GtkWidget *MaskEditorCopyButton;
+static GtkWidget *MaskEditorAddButton;
+static GtkWidget *MaskEditorRemoveButton;
+static GtkWidget *MaskEditorUpButton;
+static GtkWidget *MaskEditorDownButton;
+static GtkWidget *MaskEditorSaveButton;
+
+static const guint BOX_SPACING = 6;
+
+/* Some predefined masks -- IMPORTANT: Null-terminate me! */
+static const gchar *Scan_Masks [] =
+{
+ "%a - %b"G_DIR_SEPARATOR_S"%n - %t",
+ "%a_-_%b"G_DIR_SEPARATOR_S"%n_-_%t",
+ "%a - %b (%y)"G_DIR_SEPARATOR_S"%n - %a - %t",
+ "%a_-_%b_(%y)"G_DIR_SEPARATOR_S"%n_-_%a_-_%t",
+ "%a - %b (%y) - %g"G_DIR_SEPARATOR_S"%n - %a - %t",
+ "%a_-_%b_(%y)_-_%g"G_DIR_SEPARATOR_S"%n_-_%a_-_%t",
+ "%a - %b"G_DIR_SEPARATOR_S"%n. %t",
+ "%a_-_%b"G_DIR_SEPARATOR_S"%n._%t",
+ "%a-%b"G_DIR_SEPARATOR_S"%n-%t",
+ "%b"G_DIR_SEPARATOR_S"%n. %a - %t",
+ "%b"G_DIR_SEPARATOR_S"%n._%a_-_%t",
+ "%b"G_DIR_SEPARATOR_S"%n - %a - %t",
+ "%b"G_DIR_SEPARATOR_S"%n_-_%a_-_%t",
+ "%b"G_DIR_SEPARATOR_S"%n-%a-%t",
+ "%a-%b"G_DIR_SEPARATOR_S"%n-%t",
+ "%a"G_DIR_SEPARATOR_S"%b"G_DIR_SEPARATOR_S"%n. %t",
+ "%g"G_DIR_SEPARATOR_S"%a"G_DIR_SEPARATOR_S"%b"G_DIR_SEPARATOR_S"%t",
+ "%a_-_%b-%n-%t-%y",
+ "%a - %b"G_DIR_SEPARATOR_S"%n. %t(%c)",
+ "%t",
+ "Track%n",
+ "Track%i %n",
+ NULL
+};
+
+static const gchar *Rename_File_Masks [] =
+{
+ "%n - %a - %t",
+ "%n_-_%a_-_%t",
+ "%n. %a - %t",
+ "%n._%a_-_%t",
+ "%a - %b"G_DIR_SEPARATOR_S"%n - %t",
+ "%a_-_%b"G_DIR_SEPARATOR_S"%n_-_%t",
+ "%a - %b (%y) - %g"G_DIR_SEPARATOR_S"%n - %t",
+ "%a_-_%b_(%y)_-_%g"G_DIR_SEPARATOR_S"%n_-_%t",
+ "%n - %t",
+ "%n_-_%t",
+ "%n. %t",
+ "%n._%t",
+ "%n - %a - %b - %t",
+ "%n_-_%a_-_%b_-_%t",
+ "%a - %b - %t",
+ "%a_-_%b_-_%t",
+ "%a - %b - %n - %t",
+ "%a_-_%b_-_%n_-_%t",
+ "%a - %t",
+ "%a_-_%t",
+ "Track %n",
+ NULL
+};
+
+/**gchar *Rename_Directory_Masks [] =
+{
+ "%a - %b",
+ "%a_-_%b",
+ "%a - %b (%y) - %g",
+ "%a_-_%b_(%y)_-_%g",
+ "VA - %b (%y)",
+ "VA_-_%b_(%y)",
+ NULL
+};**/
+
+
+static const gchar *Scanner_Option_Menu_Items [] =
+{
+ N_("Fill Tag"),
+ N_("Rename File and Directory"),
+ N_("Process Fields")
+};
+
+typedef enum
+{
+ UNKNOWN = 0, /* Default value when initialized */
+ LEADING_SEPARATOR, /* characters before the first code */
+ TRAILING_SEPARATOR, /* characters after the last code */
+ SEPARATOR, /* item is a separator between two codes */
+ DIRECTORY_SEPARATOR, /* item is a separator between two codes with character '/' (G_DIR_SEPARATOR) */
+ FIELD, /* item contains text (not empty) of entry */
+ EMPTY_FIELD /* item when entry contains no text */
+} Mask_Item_Type;
+
+
+
+/*
+ * Used into Rename File Scanner
+ */
+typedef struct _File_Mask_Item File_Mask_Item;
+struct _File_Mask_Item
+{
+ Mask_Item_Type type;
+ gchar *string;
+};
+
+/*
+ * Used into Scan Tag Scanner
+ */
+typedef struct _Scan_Mask_Item Scan_Mask_Item;
+struct _Scan_Mask_Item
+{
+ gchar code; // The code of the mask without % (ex: %a => a)
+ gchar *string; // The string found by the scanner for the code defined the line above
+};
+
+
+
+/**************
+ * Prototypes *
+ **************/
+static void Scan_Toggle_Legend_Button (void);
+static void Scan_Toggle_Mask_Editor_Button (void);
+static void Scan_Option_Button (void);
+static void entry_check_scan_tag_mask (GtkEntry *entry, gpointer user_data);
+
+static GList *Scan_Generate_New_Tag_From_Mask (ET_File *ETFile, gchar *mask);
+static void Scan_Rename_File_Prefix_Path (void);
+static void Scan_Free_File_Rename_List (GList *list);
+static void Scan_Free_File_Fill_Tag_List (GList *list);
+
+static gchar **Scan_Return_File_Tag_Field_From_Mask_Code (File_Tag *FileTag,
+ gchar code);
+static void Process_Fields_Convert_Check_Button_Toggled (GtkWidget *object);
+static void Process_Fields_First_Letters_Check_Button_Toggled (GtkWidget *object);
+static void Select_Fields_Invert_Selection (void);
+static void Select_Fields_Select_Unselect_All (void);
+static void Select_Fields_Set_Sensitive (void);
+
+static void Mask_Editor_List_Row_Selected (GtkTreeSelection* selection,
+ gpointer data);
+static void Mask_Editor_List_Set_Row_Visible (GtkTreeModel *treeModel,
+ GtkTreeIter *rowIter);
+static void Mask_Editor_List_New (void);
+static void Mask_Editor_List_Duplicate (void);
+static void Mask_Editor_List_Remove (void);
+static void Mask_Editor_List_Move_Up (void);
+static void Mask_Editor_List_Move_Down (void);
+static void Mask_Editor_Entry_Changed (void);
+static gboolean Mask_Editor_List_Key_Press (GtkWidget *widget,
+ GdkEvent *event);
+
+static void Mask_Editor_Clean_Up_Masks_List (void);
+
+static void Scan_Convert_Character (gchar **string);
+static GList *Scan_Generate_New_Tag_From_Mask (ET_File *ETFile, gchar *mask);
+
+static void et_scan_on_response (GtkDialog *dialog, gint response_id,
+ gpointer user_data);
+
+
+/*************
+ * Functions *
+ *************/
+
+/*
+ * Uses the filename and path to fill tag information
+ * Note: mask and source are read from the right to the left
+ */
+static void
+Scan_Tag_With_Mask (EtScanDialog *self, ET_File *ETFile)
+{
+ GList *fill_tag_list = NULL;
+ GList *l;
+ gchar **dest = NULL;
+ gchar *mask; // The 'mask' in the entry
+ gchar *filename_utf8;
+ File_Tag *FileTag;
+
+ g_return_if_fail (ScanTagMaskCombo != NULL);
+ g_return_if_fail (ETFile != NULL);
+
+ mask = g_strdup(gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(ScanTagMaskCombo)))));
+ if (!mask) return;
+
+ // Create a new File_Tag item
+ FileTag = ET_File_Tag_Item_New();
+ ET_Copy_File_Tag_Item(ETFile,FileTag);
+
+ // Process this mask with file
+ fill_tag_list = Scan_Generate_New_Tag_From_Mask(ETFile,mask);
+
+ for (l = fill_tag_list; l != NULL; l = g_list_next (l))
+ {
+ Scan_Mask_Item *mask_item = l->data;
+
+ // Get the target entry for this code
+ dest = Scan_Return_File_Tag_Field_From_Mask_Code(FileTag,mask_item->code);
+
+ // We display the text affected to the code
+ if ( dest && ( OVERWRITE_TAG_FIELD || *dest==NULL || strlen(*dest)==0 ) )
+ ET_Set_Field_File_Tag_Item(dest,mask_item->string);
+
+ }
+
+ Scan_Free_File_Fill_Tag_List(fill_tag_list);
+
+ // Set the default text to comment
+ if (SET_DEFAULT_COMMENT && (OVERWRITE_TAG_FIELD || FileTag->comment==NULL || strlen(FileTag->comment)==0
) )
+ ET_Set_Field_File_Tag_Item((void *)&FileTag->comment,DEFAULT_COMMENT);
+
+ // Set CRC-32 value as default comment (for files with ID3 tag only ;-)
+ if (SET_CRC32_COMMENT && (OVERWRITE_TAG_FIELD || FileTag->comment==NULL || strlen(FileTag->comment)==0 )
)
+ {
+ GError *error = NULL;
+ guint32 crc32_value;
+ gchar *buffer;
+ ET_File_Description *ETFileDescription;
+
+ ETFileDescription = ETFile->ETFileDescription;
+ switch (ETFileDescription->TagType)
+ {
+ case ID3_TAG:
+ if (crc32_file_with_ID3_tag (((File_Name *)((GList *)ETFile->FileNameNew)->data)->value,
+ &crc32_value, &error))
+ {
+ buffer = g_strdup_printf ("%.8" G_GUINT32_FORMAT,
+ crc32_value);
+ ET_Set_Field_File_Tag_Item((void *)&FileTag->comment,buffer);
+ g_free(buffer);
+ }
+ else
+ {
+ Log_Print (LOG_ERROR,
+ _("Cannot calculate CRC value of file (%s)"),
+ error->message);
+ g_error_free (error);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+
+ // Save changes of the 'File_Tag' item
+ ET_Manage_Changes_Of_File_Data(ETFile,NULL,FileTag);
+
+ g_free(mask);
+ Statusbar_Message(_("Tag successfully scanned"),TRUE);
+ filename_utf8 = g_path_get_basename( ((File_Name *)ETFile->FileNameNew->data)->value_utf8 );
+ Log_Print(LOG_OK,_("Tag successfully scanned: %s"),filename_utf8);
+ g_free(filename_utf8);
+}
+
+static GList *
+Scan_Generate_New_Tag_From_Mask (ET_File *ETFile, gchar *mask)
+{
+ GList *fill_tag_list = NULL;
+ gchar *filename_utf8;
+ gchar *tmp;
+ gchar *buf;
+ gchar *separator;
+ gchar *string;
+ gint len, i, loop=0;
+ gchar **mask_splitted;
+ gchar **file_splitted;
+ guint mask_splitted_number;
+ guint file_splitted_number;
+ guint mask_splitted_index;
+ guint file_splitted_index;
+ Scan_Mask_Item *mask_item;
+
+ g_return_val_if_fail (ETFile != NULL && mask != NULL, NULL);
+
+ filename_utf8 = g_strdup(((File_Name *)((GList *)ETFile->FileNameNew)->data)->value_utf8);
+ if (!filename_utf8) return NULL;
+
+ // Remove extension of file (if found)
+ tmp = strrchr(filename_utf8,'.');
+ for (i=0; i<=(gint)ET_FILE_DESCRIPTION_SIZE; i++)
+ {
+ if ( strcasecmp(tmp,ETFileDescription[i].Extension)==0 )
+ {
+ *tmp = 0; //strrchr(source,'.') = 0;
+ break;
+ }
+ }
+
+ if (i==ET_FILE_DESCRIPTION_SIZE)
+ {
+ gchar *tmp1 = g_path_get_basename(filename_utf8);
+ Log_Print(LOG_ERROR,_("Tag scanner: strange… the extension '%s' was not found in filename
'%s'"),tmp,tmp1);
+ g_free(tmp1);
+ }
+
+ // Replace characters into mask and filename before parsing
+ if (FTS_CONVERT_UNDERSCORE_AND_P20_INTO_SPACE)
+ {
+ Scan_Convert_Underscore_Into_Space(mask);
+ Scan_Convert_Underscore_Into_Space(filename_utf8);
+ Scan_Convert_P20_Into_Space(mask);
+ Scan_Convert_P20_Into_Space(filename_utf8);
+ }
+ if (FTS_CONVERT_SPACE_INTO_UNDERSCORE)
+ {
+ Scan_Convert_Space_Into_Underscore (mask);
+ Scan_Convert_Space_Into_Underscore (filename_utf8);
+ }
+
+
+ // Split the Scanner mask
+ mask_splitted = g_strsplit(mask,G_DIR_SEPARATOR_S,0);
+ // Get number of arguments into 'mask_splitted'
+ for (mask_splitted_number=0;mask_splitted[mask_splitted_number];mask_splitted_number++);
+
+ // Split the File Path
+ file_splitted = g_strsplit(filename_utf8,G_DIR_SEPARATOR_S,0);
+ // Get number of arguments into 'file_splitted'
+ for (file_splitted_number=0;file_splitted[file_splitted_number];file_splitted_number++);
+
+ // Set the starting position for each tab
+ if (mask_splitted_number <= file_splitted_number)
+ {
+ mask_splitted_index = 0;
+ file_splitted_index = file_splitted_number - mask_splitted_number;
+ }else
+ {
+ mask_splitted_index = mask_splitted_number - file_splitted_number;
+ file_splitted_index = 0;
+ }
+
+ loop = 0;
+ while ( mask_splitted[mask_splitted_index]!= NULL && file_splitted[file_splitted_index]!=NULL )
+ {
+ gchar *mask_seq = mask_splitted[mask_splitted_index];
+ gchar *file_seq = file_splitted[file_splitted_index];
+ gchar *file_seq_utf8 = filename_to_display(file_seq);
+
+ //g_print(">%d> seq '%s' '%s'\n",loop,mask_seq,file_seq);
+ while ( mask_seq && strlen(mask_seq)>0 )
+ {
+
+ /*
+ * Determine (first) code and destination
+ */
+ if ( (tmp=strchr(mask_seq,'%')) == NULL || strlen(tmp) < 2 )
+ {
+ break;
+ }
+
+ /*
+ * Allocate a new iten for the fill_tag_list
+ */
+ mask_item = g_malloc0(sizeof(Scan_Mask_Item));
+
+ // Get the code (used to determine the corresponding target entry)
+ mask_item->code = tmp[1];
+
+ /*
+ * Delete text before the code
+ */
+ if ( (len = strlen(mask_seq) - strlen(tmp)) > 0 )
+ {
+ // Get this text in 'mask_seq'
+ buf = g_strndup(mask_seq,len);
+ // We remove it in 'mask_seq'
+ mask_seq = mask_seq + len;
+ // Find the same text at the begining of 'file_seq' ?
+ if ( (strstr(file_seq,buf)) == file_seq )
+ {
+ file_seq = file_seq + len; // We remove it
+ }else
+ {
+ Log_Print(LOG_ERROR,_("Scan Error: can't find separator '%s' within
'%s'"),buf,file_seq_utf8);
+ }
+ g_free(buf);
+ }
+
+ // Remove the current code into 'mask_seq'
+ mask_seq = mask_seq + 2;
+
+ /*
+ * Determine separator between two code or trailing text (after code)
+ */
+ if ( mask_seq && strlen(mask_seq)>0 )
+ {
+ if ( (tmp=strchr(mask_seq,'%')) == NULL || strlen(tmp) < 2 )
+ {
+ // No more code found
+ len = strlen(mask_seq);
+ }else
+ {
+ len = strlen(mask_seq) - strlen(tmp);
+ }
+ separator = g_strndup(mask_seq,len);
+
+ // Remove the current separator in 'mask_seq'
+ mask_seq = mask_seq + len;
+
+ // Try to find the separator in 'file_seq'
+ if ( (tmp=strstr(file_seq,separator)) == NULL )
+ {
+ Log_Print(LOG_ERROR,_("Scan Error: can't find separator '%s' within
'%s'"),separator,file_seq_utf8);
+ separator[0] = 0; // Needed to avoid error when calculting 'len' below
+ }
+
+ // Get the string affected to the code (or the corresponding entry field)
+ len = strlen(file_seq) - (tmp!=NULL?strlen(tmp):0);
+ string = g_strndup(file_seq,len);
+
+ // Remove the current separator in 'file_seq'
+ file_seq = file_seq + strlen(string) + strlen(separator);
+ g_free(separator);
+
+ // We get the text affected to the code
+ mask_item->string = string;
+ }else
+ {
+ // We display the remaining text, affected to the code (no more data in 'mask_seq')
+ mask_item->string = g_strdup(file_seq);
+ }
+
+ // Add the filled mask_iten to the list
+ fill_tag_list = g_list_append(fill_tag_list,mask_item);
+ }
+
+ g_free(file_seq_utf8);
+
+ // Next sequences
+ mask_splitted_index++;
+ file_splitted_index++;
+ loop++;
+ }
+
+ g_free(filename_utf8);
+ g_strfreev(mask_splitted);
+ g_strfreev(file_splitted);
+
+ // The 'fill_tag_list' must be freed after use
+ return fill_tag_list;
+}
+
+static void
+Scan_Fill_Tag_Generate_Preview (EtScanDialog *self)
+{
+ EtScanDialogPrivate *priv;
+ gchar *mask = NULL;
+ gchar *preview_text = NULL;
+ GList *fill_tag_list = NULL;
+ GList *l;
+
+ priv = et_scan_dialog_get_instance_private (self);
+
+ if (!ETCore->ETFileDisplayedList
+ || !RenameFileMaskCombo || !priv->fill_tag_preview_label
+ || gtk_combo_box_get_active(GTK_COMBO_BOX(priv->type_combo)) != ET_SCAN_TYPE_FILL_TAG)
+ return;
+
+ mask = g_strdup(gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(ScanTagMaskCombo)))));
+ if (!mask)
+ return;
+
+ preview_text = g_strdup("");
+ fill_tag_list = Scan_Generate_New_Tag_From_Mask(ETCore->ETFileDisplayed,mask);
+ for (l = fill_tag_list; l != NULL; l = g_list_next (l))
+ {
+ Scan_Mask_Item *mask_item = l->data;
+ gchar *tmp_code = g_strdup_printf("%c",mask_item->code);
+ gchar *tmp_string = g_markup_printf_escaped("%s",mask_item->string); // To avoid problem with
strings containing characters like '&'
+ gchar *tmp_preview_text = preview_text;
+
+ preview_text = g_strconcat(tmp_preview_text,"<b>","%",tmp_code," = ",
+ "</b>","<i>",tmp_string,"</i>",NULL);
+ g_free(tmp_code);
+ g_free(tmp_string);
+ g_free(tmp_preview_text);
+
+ tmp_preview_text = preview_text;
+ preview_text = g_strconcat(tmp_preview_text," || ",NULL);
+ g_free(tmp_preview_text);
+ }
+
+ Scan_Free_File_Fill_Tag_List(fill_tag_list);
+
+ if (GTK_IS_LABEL(priv->fill_tag_preview_label))
+ {
+ if (preview_text)
+ {
+ //gtk_label_set_text(GTK_LABEL(priv->fill_tag_preview_label),preview_text);
+ gtk_label_set_markup(GTK_LABEL(priv->fill_tag_preview_label),preview_text);
+ } else
+ {
+ gtk_label_set_text(GTK_LABEL(priv->fill_tag_preview_label),"");
+ }
+
+ /* Force the window to be redrawn. */
+ gtk_widget_queue_resize (GTK_WIDGET (self));
+ }
+
+ g_free(mask);
+ g_free(preview_text);
+}
+
+static void
+Scan_Rename_File_Generate_Preview (EtScanDialog *self)
+{
+ EtScanDialogPrivate *priv;
+ gchar *preview_text = NULL;
+ gchar *mask = NULL;
+
+ priv = et_scan_dialog_get_instance_private (self);
+
+ if (!ETCore->ETFileDisplayed
+ || !RenameFileMaskCombo || !priv->rename_file_preview_label)
+ return;
+
+ if (gtk_combo_box_get_active(GTK_COMBO_BOX(priv->type_combo)) != ET_SCAN_TYPE_RENAME_FILE)
+ return;
+
+ mask = g_strdup(gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(RenameFileMaskCombo)))));
+ if (!mask)
+ return;
+
+ preview_text = Scan_Generate_New_Filename_From_Mask(ETCore->ETFileDisplayed,mask,FALSE);
+
+ if (GTK_IS_LABEL(priv->rename_file_preview_label))
+ {
+ if (preview_text)
+ {
+ //gtk_label_set_text(GTK_LABEL(priv->rename_file_preview_label),preview_text);
+ gchar *tmp_string = g_markup_printf_escaped("%s",preview_text); // To avoid problem with strings
containing characters like '&'
+ gchar *str = g_strdup_printf("<i>%s</i>",tmp_string);
+ gtk_label_set_markup(GTK_LABEL(priv->rename_file_preview_label),str);
+ g_free(tmp_string);
+ g_free(str);
+ } else
+ {
+ gtk_label_set_text(GTK_LABEL(priv->rename_file_preview_label),"");
+ }
+
+ /* Force the window to be redrawn. */
+ gtk_widget_queue_resize (GTK_WIDGET (self));
+ }
+
+ g_free(mask);
+ g_free(preview_text);
+}
+
+
+void
+et_scan_dialog_update_previews (EtScanDialog *self)
+{
+ g_return_if_fail (ET_SCAN_DIALOG (self));
+
+ Scan_Fill_Tag_Generate_Preview (self);
+ Scan_Rename_File_Generate_Preview (self);
+}
+
+static void
+Scan_Free_File_Fill_Tag_List (GList *list)
+{
+ GList *l;
+
+ list = g_list_first (list);
+
+ for (l = list; l != NULL; l = g_list_next (l))
+ {
+ if (l->data)
+ {
+ g_free (((Scan_Mask_Item *)l->data)->string);
+ g_free ((Scan_Mask_Item *)l->data);
+ }
+ }
+
+ g_list_free (list);
+}
+
+
+
+/**************************
+ * Scanner To Rename File *
+ **************************/
+/*
+ * Uses tag information (displayed into tag entries) to rename file
+ * Note: mask and source are read from the right to the left.
+ * Note1: a mask code may be used severals times...
+ */
+static void
+Scan_Rename_File_With_Mask (EtScanDialog *self, ET_File *ETFile)
+{
+ gchar *filename_generated_utf8 = NULL;
+ gchar *filename_generated = NULL;
+ gchar *filename_new_utf8 = NULL;
+ gchar *mask = NULL;
+ File_Name *FileName;
+
+ g_return_if_fail (RenameFileMaskCombo != NULL || ETFile != NULL);
+
+ mask = g_strdup(gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(RenameFileMaskCombo)))));
+ if (!mask) return;
+
+ // Note : if the first character is '/', we have a path with the filename,
+ // else we have only the filename. The both are in UTF-8.
+ filename_generated_utf8 = Scan_Generate_New_Filename_From_Mask(ETFile,mask,FALSE);
+ g_free(mask);
+
+ if (!filename_generated_utf8)
+ return;
+ if (g_utf8_strlen(filename_generated_utf8,-1)<1)
+ {
+ g_free(filename_generated_utf8);
+ return;
+ }
+
+ // Convert filename to file-system encoding
+ filename_generated = filename_from_display(filename_generated_utf8);
+ if (!filename_generated)
+ {
+ GtkWidget *msgdialog;
+ msgdialog = gtk_message_dialog_new (GTK_WINDOW (self),
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ _("Could not convert filename '%s' into system filename encoding"),
+ filename_generated_utf8);
+ gtk_window_set_title(GTK_WINDOW(msgdialog),_("Filename translation"));
+
+ gtk_dialog_run(GTK_DIALOG(msgdialog));
+ gtk_widget_destroy(msgdialog);
+ g_free(filename_generated_utf8);
+ return;
+ }
+
+ /* Build the filename with the full path or relative to old path */
+ filename_new_utf8 = ET_File_Name_Generate(ETFile,filename_generated_utf8);
+ g_free(filename_generated);
+ g_free(filename_generated_utf8);
+
+ /* Set the new filename */
+ // Create a new 'File_Name' item
+ FileName = ET_File_Name_Item_New();
+ // Save changes of the 'File_Name' item
+ ET_Set_Filename_File_Name_Item(FileName,filename_new_utf8,NULL);
+
+ ET_Manage_Changes_Of_File_Data(ETFile,FileName,NULL);
+ g_free(filename_new_utf8);
+
+ Statusbar_Message (_("New filename successfully scanned"),TRUE);
+
+ filename_new_utf8 = g_path_get_basename(((File_Name *)ETFile->FileNameNew->data)->value_utf8);
+ Log_Print (LOG_OK, _("New filename successfully scanned: %s"),
+ filename_new_utf8);
+ g_free(filename_new_utf8);
+
+ return;
+}
+
+/*
+ * Build the new filename using tag + mask
+ * Used also to rename the directory (from the browser)
+ * @param ETFile : the etfile to process
+ * @param mask : the pattern to parse
+ * @param no_dir_check_or_conversion : if FALSE, disable checking of a directory
+ * in the mask, and don't convert "illegal" characters. This is used in the
+ * function "Write_Playlist" for the content of the playlist.
+ * Returns filename in UTF-8
+ */
+gchar *Scan_Generate_New_Filename_From_Mask (ET_File *ETFile, gchar *mask, gboolean
no_dir_check_or_conversion)
+{
+ gchar *tmp;
+ gchar **source = NULL;
+ gchar *path_utf8_cur = NULL;
+ gchar *filename_new_utf8 = NULL;
+ gchar *filename_tmp = NULL;
+ GList *rename_file_list = NULL;
+ GList *l;
+ File_Mask_Item *mask_item;
+ File_Mask_Item *mask_item_prev;
+ File_Mask_Item *mask_item_next;
+ gint counter = 0;
+
+ g_return_val_if_fail (ETFile != NULL && mask != NULL, NULL);
+
+ /*
+ * Check for a directory in the mask
+ */
+ if (!no_dir_check_or_conversion)
+ {
+ if (g_path_is_absolute(mask))
+ {
+ // Absolute directory
+ }else if (strrchr(mask,G_DIR_SEPARATOR)!=NULL) // This is '/' on UNIX machines and '\' under Windows
+ {
+ // Relative path => set beginning of the path
+ path_utf8_cur = g_path_get_dirname( ((File_Name *)ETFile->FileNameCur->data)->value_utf8 );
+ }
+ }
+
+
+ /*
+ * Parse the codes to generate a list (1rst item = 1rst code)
+ */
+ while ( mask!=NULL && (tmp=strrchr(mask,'%'))!=NULL && strlen(tmp)>1 )
+ {
+ // Mask contains some characters after the code ('%b__')
+ if (strlen(tmp)>2)
+ {
+ mask_item = g_malloc0(sizeof(File_Mask_Item));
+ if (counter)
+ {
+ if (strchr(tmp+2,G_DIR_SEPARATOR))
+ mask_item->type = DIRECTORY_SEPARATOR;
+ else
+ mask_item->type = SEPARATOR;
+ } else
+ {
+ mask_item->type = TRAILING_SEPARATOR;
+ }
+ mask_item->string = g_strdup(tmp+2);
+ rename_file_list = g_list_prepend(rename_file_list,mask_item);
+ }
+
+ // Now, parses the code to get the corresponding string (from tag)
+ source = Scan_Return_File_Tag_Field_From_Mask_Code((File_Tag *)ETFile->FileTag->data,tmp[1]);
+ mask_item = g_malloc0(sizeof(File_Mask_Item));
+ if (source && *source && strlen(*source)>0)
+ {
+ mask_item->type = FIELD;
+ mask_item->string = g_strdup(*source);
+
+ // Replace invalid characters for this field
+ /* Do not replace characters in a playlist information field. */
+ if (!no_dir_check_or_conversion)
+ {
+ ET_File_Name_Convert_Character(mask_item->string);
+
+ if (RFS_CONVERT_UNDERSCORE_AND_P20_INTO_SPACE)
+ {
+ Scan_Convert_Underscore_Into_Space(mask_item->string);
+ Scan_Convert_P20_Into_Space(mask_item->string);
+ }
+ if (RFS_CONVERT_SPACE_INTO_UNDERSCORE)
+ {
+ Scan_Convert_Space_Into_Underscore (mask_item->string);
+ }
+ if (RFS_REMOVE_SPACES)
+ {
+ Scan_Remove_Spaces(mask_item->string);
+ }
+ }
+ }else
+ {
+ mask_item->type = EMPTY_FIELD;
+ mask_item->string = NULL;
+ }
+ rename_file_list = g_list_prepend(rename_file_list,mask_item);
+ *tmp = '\0'; // Cut parsed data of mask
+ counter++; // To indicate that we made at least one loop to identifiate 'separator' or
'trailing_separator'
+ }
+
+ // It may have some characters before the last remaining code ('__%a')
+ if (mask!=NULL && strlen(mask)>0)
+ {
+ mask_item = g_malloc0(sizeof(File_Mask_Item));
+ mask_item->type = LEADING_SEPARATOR;
+ mask_item->string = g_strdup(mask);
+ rename_file_list = g_list_prepend(rename_file_list,mask_item);
+ }
+
+ if (!rename_file_list) return NULL;
+
+ /*
+ * For Debugging : display the "rename_file_list" list
+ */
+ /***{
+ GList *list = g_list_first(rename_file_list);
+ gint i = 0;
+ g_print("## rename_file_list - start\n");
+ while (list)
+ {
+ File_Mask_Item *mask_item = (File_Mask_Item *)list->data;
+ Mask_Item_Type type = mask_item->type;
+ gchar *string = mask_item->string;
+
+ //g_print("item %d : \n",i++);
+ //g_print(" - type :
'%s'\n",type==UNKNOWN?"UNKNOWN":type==LEADING_SEPARATOR?"LEADING_SEPARATOR":type==TRAILING_SEPARATOR?"TRAILING_SEPARATOR":type==SEPARATOR?"SEPARATOR":type==DIRECTORY_SEPARATOR?"DIRECTORY_SEPARATOR":type==FIELD?"FIELD":type==EMPTY_FIELD?"EMPTY_FIELD":"???");
+ //g_print(" - string : '%s'\n",string);
+ g_print("%d -> %s (%s) |
",i++,type==UNKNOWN?"UNKNOWN":type==LEADING_SEPARATOR?"LEADING_SEPARATOR":type==TRAILING_SEPARATOR?"TRAILING_SEPARATOR":type==SEPARATOR?"SEPARATOR":type==DIRECTORY_SEPARATOR?"DIRECTORY_SEPARATOR":type==FIELD?"FIELD":type==EMPTY_FIELD?"EMPTY_FIELD":"???",string);
+
+ list = list->next;
+ }
+ g_print("\n## rename_file_list - end\n\n");
+ }***/
+
+ /*
+ * Build the new filename with items placed into the list
+ * (read the list from the end to the beginning)
+ */
+ filename_new_utf8 = g_strdup("");
+
+ for (l = g_list_last (rename_file_list); l != NULL;
+ l = g_list_previous (l))
+ {
+ File_Mask_Item *mask_item = l->data;
+
+ if ( mask_item->type==TRAILING_SEPARATOR ) // Trailing characters of mask
+ {
+ // Doesn't write it if previous field is empty
+ if (l->prev
+ && ((File_Mask_Item *)l->prev->data)->type != EMPTY_FIELD)
+ {
+ filename_tmp = filename_new_utf8;
+ filename_new_utf8 = g_strconcat(mask_item->string,filename_new_utf8,NULL);
+ g_free(filename_tmp);
+ }
+ }else
+ if ( mask_item->type==EMPTY_FIELD )
+ // We don't concatenate the field value (empty) and the previous
+ // separator (except leading separator) to the filename.
+ // If the empty field is the 'first', we don't concatenate it, and the
+ // next separator too.
+ {
+ if (l->prev)
+ {
+ // The empty field isn't the first.
+ // If previous string is a separator, we don't use it, except if the next
+ // string is a FIELD (not empty)
+ mask_item_prev = l->prev->data;
+ if ( mask_item_prev->type==SEPARATOR )
+ {
+ if (!(l->next
+ && (mask_item_next = rename_file_list->next->data)
+ && mask_item_next->type == FIELD))
+ {
+ l = l->prev;
+ }
+ }
+ }else
+ if (l->next && (mask_item_next = l->next->data)
+ && mask_item_next->type == SEPARATOR)
+ // We are at the 'beginning' of the mask (so empty field is the first)
+ // and next field is a separator. As the separator may have been already added, we remove it
+ {
+ if ( filename_new_utf8 && mask_item_next->string &&
(strncmp(filename_new_utf8,mask_item_next->string,strlen(mask_item_next->string))==0) ) // To avoid crash if
filename_new_utf8 is 'empty'
+ {
+ filename_tmp = filename_new_utf8;
+ filename_new_utf8 = g_strdup(filename_new_utf8+strlen(mask_item_next->string));
+ g_free(filename_tmp);
+ }
+ }
+
+ }else // SEPARATOR, FIELD, LEADING_SEPARATOR, DIRECTORY_SEPARATOR
+ {
+ filename_tmp = filename_new_utf8;
+ filename_new_utf8 = g_strconcat(mask_item->string,filename_new_utf8,NULL);
+ g_free(filename_tmp);
+ }
+ }
+
+ // Free the list
+ Scan_Free_File_Rename_List(rename_file_list);
+
+
+ // Add current path if relative path entered
+ if (path_utf8_cur)
+ {
+ filename_tmp = filename_new_utf8; // in UTF-8!
+ filename_new_utf8 = g_strconcat(path_utf8_cur,G_DIR_SEPARATOR_S,filename_new_utf8,NULL);
+ g_free(filename_tmp);
+ g_free(path_utf8_cur);
+ }
+
+ return filename_new_utf8; // in UTF-8!
+}
+
+static void
+Scan_Free_File_Rename_List (GList *list)
+{
+ GList *l;
+
+ for (l = list; l != NULL; l = g_list_next (l))
+ {
+ if (l->data)
+ {
+ g_free (((File_Mask_Item *)l->data)->string);
+ g_free ((File_Mask_Item *)l->data);
+ }
+ }
+
+ g_list_free (list);
+}
+
+/*
+ * Adds the current path of the file to the mask on the "Rename File Scanner" entry
+ */
+static void
+Scan_Rename_File_Prefix_Path (void)
+{
+ gint pos;
+ gchar *path_tmp;
+ const gchar *combo_text = NULL;
+ gchar *combo_tmp;
+ ET_File *ETFile = ETCore->ETFileDisplayed;
+ gchar *filename_utf8_cur = ((File_Name *)ETFile->FileNameCur->data)->value_utf8;
+ gchar *path_utf8_cur;
+
+
+ // The path to prefix
+ path_utf8_cur = g_path_get_dirname(filename_utf8_cur);
+
+ // The current text in the combobox
+ combo_text = gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(RenameFileMaskCombo))));
+ /*if (!g_utf8_validate(combo_text, -1, NULL))
+ {
+ combo_tmp = convert_to_utf8(combo_text);
+ }else
+ {
+ combo_tmp = g_strdup(combo_text);
+ }*/
+ combo_tmp = Try_To_Validate_Utf8_String(combo_text);
+
+ // If the path already exists we don't add it again
+ // Use g_utf8_collate_key instead of strncmp
+ if (combo_tmp && path_utf8_cur && strncmp(combo_tmp,path_utf8_cur,strlen(path_utf8_cur))!=0)
+ {
+ if (g_path_is_absolute(combo_tmp))
+ {
+ path_tmp = g_strdup(path_utf8_cur);
+ } else
+ {
+ path_tmp = g_strconcat(path_utf8_cur,G_DIR_SEPARATOR_S,NULL);
+ }
+ pos = 0;
+ gtk_editable_insert_text(GTK_EDITABLE(gtk_bin_get_child(GTK_BIN(RenameFileMaskCombo))),path_tmp, -1,
&pos);
+ g_free(path_tmp);
+ }
+
+ g_free(path_utf8_cur);
+}
+
+
+/*******************************
+ * Scanner To Rename Directory *
+ *******************************/
+void Scan_Rename_Directory_Generate_Preview (void)
+{
+ gchar *preview_text = NULL;
+ gchar *mask = NULL;
+
+ if (!ETCore->ETFileDisplayed
+ || !RenameDirectoryWindow || !RenameDirectoryMaskCombo || !RenameDirectoryPreviewLabel)
+ return;
+
+ mask = g_strdup(gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(RenameDirectoryMaskCombo)))));
+ if (!mask)
+ return;
+
+ preview_text = Scan_Generate_New_Filename_From_Mask(ETCore->ETFileDisplayed,mask,FALSE);
+
+ if (GTK_IS_LABEL(RenameDirectoryPreviewLabel))
+ {
+ if (preview_text)
+ {
+ //gtk_label_set_text(GTK_LABEL(priv->rename_file_preview_label),preview_text);
+ gchar *tmp_string = g_markup_printf_escaped("%s",preview_text); // To avoid problem with strings
containing characters like '&'
+ gchar *str = g_strdup_printf("<i>%s</i>",tmp_string);
+ gtk_label_set_markup(GTK_LABEL(RenameDirectoryPreviewLabel),str);
+ g_free(tmp_string);
+ g_free(str);
+ } else
+ {
+ gtk_label_set_text(GTK_LABEL(RenameDirectoryPreviewLabel),"");
+ }
+
+ // Force the window to be redrawed else the preview label may be not placed correctly
+ gtk_widget_queue_resize(RenameDirectoryWindow);
+ }
+
+ g_free(mask);
+ g_free(preview_text);
+}
+
+gchar *Scan_Generate_New_Directory_Name_From_Mask (ET_File *ETFile, gchar *mask, gboolean
no_dir_check_or_conversion)
+{
+ return Scan_Generate_New_Filename_From_Mask(ETFile,mask,no_dir_check_or_conversion);
+}
+
+
+static void
+Scan_Process_Fields_Functions (EtScanDialog *self, gchar **string)
+{
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsConvertIntoSpace)))
+ {
+ Scan_Convert_Underscore_Into_Space(*string);
+ Scan_Convert_P20_Into_Space(*string);
+ }
+
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsConvertSpace)))
+ Scan_Convert_Space_Into_Underscore (*string);
+
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsInsertSpace)))
+ Scan_Process_Fields_Insert_Space(string);
+
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsOnlyOneSpace)))
+ Scan_Process_Fields_Keep_One_Space(*string);
+
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsConvert)))
+ Scan_Convert_Character(string);
+
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsAllUppercase)))
+ Scan_Process_Fields_All_Uppercase(*string);
+
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsAllDowncase)))
+ Scan_Process_Fields_All_Downcase(*string);
+
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsFirstLetterUppercase)))
+ Scan_Process_Fields_Letter_Uppercase(*string);
+
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsFirstLettersUppercase)))
+ Scan_Process_Fields_First_Letters_Uppercase (self, *string);
+
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsRemoveSpace)))
+ Scan_Process_Fields_Remove_Space(*string);
+
+}
+
+
+/*****************************
+ * Scanner To Process Fields *
+ *****************************/
+/* See also functions : Convert_P20_And_Undescore_Into_Spaces, ... in easytag.c */
+static void
+Scan_Process_Fields (EtScanDialog *self, ET_File *ETFile)
+{
+ File_Name *FileName = NULL;
+ File_Tag *FileTag = NULL;
+ File_Name *st_filename;
+ File_Tag *st_filetag;
+ gchar *filename_utf8;
+ gchar *string;
+
+ g_return_if_fail (ETFile != NULL);
+
+ st_filename = (File_Name *)ETFile->FileNameNew->data;
+ st_filetag = (File_Tag *)ETFile->FileTag->data;
+
+ /* Process the filename */
+ if (st_filename != NULL)
+ {
+ if (st_filename->value_utf8 && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFileNameField)))
+ {
+ gchar *string_utf8;
+ gchar *pos;
+
+ filename_utf8 = st_filename->value_utf8;
+
+ if (!FileName)
+ FileName = ET_File_Name_Item_New();
+
+ string = g_path_get_basename(filename_utf8);
+ // Remove the extension to set it to lower case (to avoid problem with undo)
+ if ((pos=strrchr(string,'.'))!=NULL) *pos = 0;
+
+ Scan_Process_Fields_Functions (self, &string);
+
+ string_utf8 = ET_File_Name_Generate(ETFile,string);
+ ET_Set_Filename_File_Name_Item(FileName,string_utf8,NULL);
+ g_free(string_utf8);
+ g_free(string);
+ }
+ }
+
+ /* Process data of the tag */
+ if (st_filetag != NULL)
+ {
+ // Title field
+ if (st_filetag->title && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessTitleField)))
+ {
+ if (!FileTag)
+ {
+ FileTag = ET_File_Tag_Item_New();
+ ET_Copy_File_Tag_Item(ETFile,FileTag);
+ }
+
+ string = g_strdup(st_filetag->title);
+
+ Scan_Process_Fields_Functions (self, &string);
+
+ ET_Set_Field_File_Tag_Item(&FileTag->title,string);
+
+ g_free(string);
+ }
+
+ // Artist field
+ if (st_filetag->artist && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessArtistField)))
+ {
+ if (!FileTag)
+ {
+ FileTag = ET_File_Tag_Item_New();
+ ET_Copy_File_Tag_Item(ETFile,FileTag);
+ }
+
+ string = g_strdup(st_filetag->artist);
+
+ Scan_Process_Fields_Functions (self, &string);
+
+ ET_Set_Field_File_Tag_Item(&FileTag->artist,string);
+
+ g_free(string);
+ }
+
+ // Album Artist field
+ if (st_filetag->album_artist &&
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessAlbumArtistField)))
+ {
+ if (!FileTag)
+ {
+ FileTag = ET_File_Tag_Item_New();
+ ET_Copy_File_Tag_Item(ETFile,FileTag);
+ }
+
+ string = g_strdup(st_filetag->album_artist);
+
+ Scan_Process_Fields_Functions (self, &string);
+
+ ET_Set_Field_File_Tag_Item(&FileTag->album_artist,string);
+
+ g_free(string);
+ }
+ // Album field
+ if (st_filetag->album && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessAlbumField)))
+ {
+ if (!FileTag)
+ {
+ FileTag = ET_File_Tag_Item_New();
+ ET_Copy_File_Tag_Item(ETFile,FileTag);
+ }
+
+ string = g_strdup(st_filetag->album);
+
+ Scan_Process_Fields_Functions (self, &string);
+
+ ET_Set_Field_File_Tag_Item(&FileTag->album,string);
+
+ g_free(string);
+ }
+
+ // Genre field
+ if (st_filetag->genre && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessGenreField)))
+ {
+ if (!FileTag)
+ {
+ FileTag = ET_File_Tag_Item_New();
+ ET_Copy_File_Tag_Item(ETFile,FileTag);
+ }
+
+ string = g_strdup(st_filetag->genre);
+
+ Scan_Process_Fields_Functions (self, &string);
+
+ ET_Set_Field_File_Tag_Item(&FileTag->genre,string);
+
+ g_free(string);
+ }
+
+ // Comment field
+ if (st_filetag->comment && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessCommentField)))
+ {
+ if (!FileTag)
+ {
+ FileTag = ET_File_Tag_Item_New();
+ ET_Copy_File_Tag_Item(ETFile,FileTag);
+ }
+
+ string = g_strdup(st_filetag->comment);
+
+ Scan_Process_Fields_Functions (self, &string);
+
+ ET_Set_Field_File_Tag_Item(&FileTag->comment,string);
+
+ g_free(string);
+ }
+
+ // Composer field
+ if (st_filetag->composer && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessComposerField)))
+ {
+ if (!FileTag)
+ {
+ FileTag = ET_File_Tag_Item_New();
+ ET_Copy_File_Tag_Item(ETFile,FileTag);
+ }
+
+ string = g_strdup(st_filetag->composer);
+
+ Scan_Process_Fields_Functions (self, &string);
+
+ ET_Set_Field_File_Tag_Item(&FileTag->composer,string);
+
+ g_free(string);
+ }
+
+ // Original artist field
+ if (st_filetag->orig_artist &&
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessOrigArtistField)))
+ {
+ if (!FileTag)
+ {
+ FileTag = ET_File_Tag_Item_New();
+ ET_Copy_File_Tag_Item(ETFile,FileTag);
+ }
+
+ string = g_strdup(st_filetag->orig_artist);
+
+ Scan_Process_Fields_Functions (self, &string);
+
+ ET_Set_Field_File_Tag_Item(&FileTag->orig_artist,string);
+
+ g_free(string);
+ }
+
+ // Copyright field
+ if (st_filetag->copyright && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessCopyrightField)))
+ {
+ if (!FileTag)
+ {
+ FileTag = ET_File_Tag_Item_New();
+ ET_Copy_File_Tag_Item(ETFile,FileTag);
+ }
+
+ string = g_strdup(st_filetag->copyright);
+
+ Scan_Process_Fields_Functions (self, &string);
+
+ ET_Set_Field_File_Tag_Item(&FileTag->copyright,string);
+
+ g_free(string);
+ }
+
+ // URL field
+ if (st_filetag->url && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessURLField)))
+ {
+ if (!FileTag)
+ {
+ FileTag = ET_File_Tag_Item_New();
+ ET_Copy_File_Tag_Item(ETFile,FileTag);
+ }
+
+ string = g_strdup(st_filetag->url);
+
+ Scan_Process_Fields_Functions (self, &string);
+
+ ET_Set_Field_File_Tag_Item(&FileTag->url,string);
+
+ g_free(string);
+ }
+
+ // 'Encoded by' field
+ if (st_filetag->encoded_by && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessEncodedByField)))
+ {
+ if (!FileTag)
+ {
+ FileTag = ET_File_Tag_Item_New();
+ ET_Copy_File_Tag_Item(ETFile,FileTag);
+ }
+
+ string = g_strdup(st_filetag->encoded_by);
+
+ Scan_Process_Fields_Functions (self, &string);
+
+ ET_Set_Field_File_Tag_Item(&FileTag->encoded_by,string);
+
+ g_free(string);
+ }
+ }
+
+ if (FileName && FileTag)
+ {
+ // Synchronize undo key of the both structures (used for the
+ // undo functions, as they are generated as the same time)
+ FileName->key = FileTag->key;
+ }
+ ET_Manage_Changes_Of_File_Data(ETFile,FileName,FileTag);
+
+}
+
+/*
+ * Taken from :
+ * Roman Numeral Conversion API (http://sourceforge.net/project/showfiles.php?group_id=211070)
+ * Copyright (c) 2007 David M. Syzdek <roman-project syzdek net>
+ */
+/* Convert Roman numeral from integer to string */
+static char *
+int2roman_r (int num, char * str, size_t len)
+{
+ // local variables
+ unsigned pos;
+ unsigned u;
+ unsigned dividend;
+
+ g_return_val_if_fail (str != NULL, NULL);
+
+ // verify that number is withing boundaries
+ if ((num > 5000) || (num < 0))
+ {
+ return NULL;
+ };
+
+ // sets initial values
+ pos = 0;
+ memset(str, 0, len);
+ len--;
+
+ // checks for nullae
+ if (!(num))
+ {
+ str[0] = 'N';
+ return str;
+ };
+
+ // calculates sign
+ if (num < 0)
+ {
+ num *= -1;
+ if (1 > len)
+ {
+ return NULL;
+ };
+ str[pos] = '-';
+ pos++;
+ };
+
+ // calculates thousands
+ dividend = num/1000;
+ if (dividend > (len-1))
+ {
+ return NULL;
+ };
+ for (u = 0; u < dividend; u++)
+ str[pos+u] = 'M';
+ num %= 1000;
+ pos += u;
+
+ // calculates hundreds
+ dividend = num/100;
+ if (dividend > (len-1-pos))
+ {
+ return NULL;
+ };
+ if (dividend == 9)
+ {
+ str[pos+0] = 'C';
+ str[pos+1] = 'M';
+ pos += 2;
+ dividend = 0;
+ };
+ if (dividend >= 5)
+ {
+ str[pos] = 'D';
+ dividend -= 5;
+ pos++;
+ };
+ if (dividend == 4)
+ {
+ str[pos+0] = 'C';
+ str[pos+1] = 'D';
+ dividend -= 4;
+ pos += 2;
+ };
+ for(u = 0; u < dividend; u++)
+ str[pos+u] = 'C';
+ pos += u;
+ num %= 100;
+
+ // calculates tens
+ dividend = num/10;
+ if (dividend > (len-1-pos))
+ {
+ return NULL;
+ };
+ if (dividend == 9)
+ {
+ str[pos+0] = 'X';
+ str[pos+1] = 'C';
+ dividend = 0;
+ pos += 2;
+ };
+ if (dividend >= 5)
+ {
+ str[pos+0] = 'L';
+ dividend -= 5;
+ pos++;
+ };
+ if (dividend == 4)
+ {
+ str[pos+0] = 'X';
+ str[pos+1] = 'L';
+ pos += 2;
+ dividend -= 4;
+ };
+ for (u = 0; u < dividend; u++)
+ str[pos+u] = 'X';
+ pos += u;
+ num %= 10;
+
+ // calculates ones
+ dividend = num;
+ if (dividend > (len-1-pos))
+ {
+ return NULL;
+ };
+ if (dividend == 9)
+ {
+ str[pos+0] = 'I';
+ str[pos+1] = 'X';
+ dividend = 0;
+ pos += 2;
+ };
+ if (dividend >= 5)
+ {
+ str[pos+0] = 'V';
+ dividend -= 5;
+ pos++;
+ };
+ if (dividend == 4)
+ {
+ str[pos+0] = 'I';
+ str[pos+1] = 'V';
+ pos += 2;
+ dividend -= 4;
+ };
+ for(u = 0; u < dividend; u++)
+ str[pos+u] = 'I';
+
+ /* ends function */
+ return str;
+}
+
+static const char *
+int2roman (int num)
+{
+ #define ROMAN_BUFF_LEN 512
+
+ /* buffer for storing conversions */
+ char roman_string[ROMAN_BUFF_LEN];
+
+ /* wrap long2roman_r() with library buffer */
+ char *result = int2roman_r(num, roman_string, ROMAN_BUFF_LEN);
+
+ if (!result)
+ return NULL;
+ return g_strdup(roman_string);
+}
+
+/* Convert Roman numeral from string to integer */
+static int
+roman2int (const char *str)
+{
+ // declares local vars
+ int num;
+ unsigned i;
+ unsigned len;
+ unsigned last;
+ unsigned prevlast;
+
+ // checks args
+ if (!(str))
+ {
+ return(0);
+ };
+
+ // sets initial values
+ num = 0;
+ len = strlen(str);
+ last = 1000;
+ prevlast = 1000;
+
+ // loops through characters
+ for(i = 0; i < len; i++)
+ {
+ switch(str[i])
+ {
+ case 'n':
+ case 'N':
+ if (strlen(str) > 1)
+ {
+ return(-1);
+ };
+ return(0);
+ break;
+ case 'i':
+ case 'I':
+ num += 1;
+ // prevent patterns like IXI
+ if ((prevlast == 1) && (last != 1))
+ {
+ return(-1);
+ };
+ // prevent patterns like IIIII and VIIIII
+ if ((!(num%5)) || (!(num%10)))
+ {
+ return(-1);
+ };
+ // rotates value into history
+ prevlast = last;
+ last = 1;
+ break;
+ case 'v':
+ case 'V':
+ num += 5;
+ // tests for invalid syntax
+ if ( ((last <= 5) && (last != 1)) || (prevlast <= 5) )
+ {
+ return(-1);
+ }
+ // applies subtraction method & rotates value into history
+ if (last < 5)
+ num -= (last * 2);
+ prevlast = last;
+ last = 5;
+ break;
+ case 'x':
+ case 'X':
+ num += 10;
+ // tests for invalid syntax
+ if ( ((prevlast < 10) && (last <= 10)) || ((last < 10) && (last != 1)) )
+ {
+ return(-1);
+ };
+ // prevent patterns like XXXXX and VXXXXX
+ if ((!(num%50)) || (!(num%100)))
+ {
+ return(-1);
+ };
+ // applies subtraction method & rotates value into history
+ if (last == 1)
+ num -= (last * 2);
+ prevlast = last;
+ last = 10;
+ break;
+ case 'l':
+ case 'L':
+ num += 50;
+ // tests for invalid syntax
+ if ( ((last <= 50) && (last != 10)) || (prevlast <= 50) )
+ {
+ return(-1);
+ }
+ // applies subtraction method & rotates value into history
+ if (last < 50)
+ num -= (last * 2);
+ prevlast = last;
+ last = 50;
+ break;
+ case 'c':
+ case 'C':
+ num += 100;
+ // tests for invalid syntax
+ if ( ((prevlast < 100) && (last <= 100)) || ((last < 100) && (last != 10)) )
+ {
+ return(-1);
+ };
+ // prevent patterns like CCCCC and VCCCCC
+ if ((!(num%500)) || (!(num%1000)))
+ {
+ return(-1);
+ };
+ // applies subtraction method & rotates value into history
+ if (last == 10)
+ num -= (last * 2);
+ prevlast = last;
+ last = 100;
+ break;
+ case 'd':
+ case 'D':
+ num += 500;
+ // tests for invalid syntax
+ if ( ((last <= 500) && (last != 100)) || (prevlast <= 500) )
+ {
+ return(-1);
+ }
+ // applies subtraction method & rotates value into history
+ if (last < 500)
+ num -= (last * 2);
+ prevlast = last;
+ last = 500;
+ break;
+ case 'm':
+ case 'M':
+ num += 1000;
+ // tests for invalid syntax
+ if ( ((prevlast < 1000) && (last <= 1000)) || ((last < 1000) && (last != 100)) )
+ {
+ return(-1);
+ };
+ // prevent patterns like MMMMM and VMMMMM
+ if ((!(num%5000)) || (!(num%10000)))
+ {
+ return(-1);
+ };
+ // applies subtraction method & rotates value into history
+ if (last == 100)
+ num -= (last * 2);
+ prevlast = last;
+ last = 1000;
+ break;
+ default:
+ return(-1);
+ };
+ };
+
+ // ends function
+ return(num);
+}
+
+
+
+/*
+ * Quick roman numeral check (non-roman numerals may also return true)
+ * Patch from Slash Bunny (2007.08.12)
+ * (http://home.hiwaay.net/~lkseitz/math/roman/numerals.shtml)
+ * I = 1 (one)
+ * V = 5 (five)
+ * X = 10 (ten)
+ * L = 50 (fifty)
+ * C = 100 (one hundred)
+ * D = 500 (five hundred)
+ * M = 1000 (one thousand)
+ */
+static gint
+Scan_Word_Is_Roman_Numeral (EtScanDialog *self, const gchar *text)
+{
+ const gchar *tmp;
+ gint len;
+ gchar *buf = NULL;
+ gint rn_int;
+ gchar *rn_char;
+
+ if (!ProcessFieldsDetectRomanNumerals
+ || !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsDetectRomanNumerals)))
+ return 0;
+
+ tmp = text;
+ len = 0;
+
+ while (*tmp)
+ {
+ if (*tmp == (gunichar)'i'
+ || *tmp == (gunichar)'v'
+ || *tmp == (gunichar)'x'
+ || *tmp == (gunichar)'l'
+ || *tmp == (gunichar)'c'
+ || *tmp == (gunichar)'d'
+ || *tmp == (gunichar)'m')
+ {
+ // Found a roman numeral => continue
+ tmp++;
+ len++;
+ } else if (*tmp == ' '
+ || *tmp == '_'
+ || *tmp == '.'
+ || *tmp == ','
+ || *tmp == '-')
+ {
+ // A separator was found => end of word
+ // Check if it is a valid roman numeral
+ goto roman_numeral_found;
+
+ } else
+ {
+ return 0;
+ }
+ }
+
+ // Found in last word of the string
+
+roman_numeral_found:
+ // Check if it is a valid roman numeral
+ buf = g_strndup(text,len);
+ rn_int = roman2int(buf); // Convert the Roman numeral string to integer
+
+ if (rn_int >= 0 )
+ {
+ // Some strings as "IIIII" or "CCCCC" are returned as valid, which is not correct...
+ // Same problem with: IC MIC IM MIM IL CIL XM MXM VC MVC VM MVM VL MVL LC MLC LD MLD LM MLM MDM
+ // So we convert it again to a string, and compare to the initial one.
+ rn_char = (gchar *)int2roman(rn_int); // Convert the Roman numeral integer to string
+ if (rn_char
+ && strcasecmp(buf,rn_char)==0)
+ {
+ g_free(buf);
+ g_free(rn_char);
+ return len; // Roman numeral valid
+ }else
+ {
+ g_free(buf);
+ g_free(rn_char);
+ return 0;
+ }
+ }else
+ {
+ g_free(buf);
+ return 0;
+ }
+}
+
+
+
+/*
+ * Function to set the first letter of each word to uppercase, according the "Chicago Manual of Style"
(http://www.docstyles.com/cmscrib.htm#Note2)
+ * No needed to reallocate
+ */
+void
+Scan_Process_Fields_First_Letters_Uppercase (EtScanDialog *self, gchar *string)
+{
+/**** DANIEL TEST *****
+ gchar *iter;
+ gchar utf8_character[6];
+ gboolean set_to_upper_case = TRUE;
+ gunichar c;
+
+ for (iter = text; *iter; iter = g_utf8_next_char(iter))
+ {
+ c = g_utf8_get_char(iter);
+ if (set_to_upper_case && g_unichar_islower(c))
+ strncpy(iter, utf8_character, g_unichar_to_utf8(g_unichar_toupper(c), utf8_character));
+ else if (!set_to_upper_case && g_unichar_isupper(c))
+ strncpy(iter, utf8_character, g_unichar_to_utf8(g_unichar_tolower(c), utf8_character));
+
+ set_to_upper_case = (g_unichar_isalpha(c)
+ || c == (gunichar)'.'
+ || c == (gunichar)'\''
+ || c == (gunichar)'`') ? FALSE : TRUE;
+ }
+****/
+/**** Barış Çiçek version ****/
+ gchar *word, *word1, *word2, *temp;
+ gint i, len;
+ gchar utf8_character[6];
+ gunichar c;
+ gboolean set_to_upper_case, set_to_upper_case_tmp;
+ // There have to be space at the end of words to seperate them from prefix
+ // Chicago Manual of Style "Heading caps" Capitalization Rules (CMS 1993, 282)
(http://www.docstyles.com/cmscrib.htm#Note2)
+ const gchar * exempt[] =
+ {
+ "a ", "a_",
+ "against ", "against_",
+ "an ", "an_",
+ "and ", "and_",
+ "at ", "at_",
+ "between ", "between_",
+ "but ", "but_",
+ //"feat. ", "feat._", // Removed by Slash Bunny
+ "for ", "for_",
+ "in ", "in_",
+ "nor ", "nor_",
+ "of ", "of_",
+ //"off ", "off_", // Removed by Slash Bunny
+ "on ", "on_",
+ "or ", "or_",
+ //"over ", "over_", // Removed by Slash Bunny
+ "so ", "so_",
+ "the ", "the_",
+ "to ", "to_",
+ "with ", "with_",
+ "yet ", "yet_",
+ NULL
+ };
+
+ if (!PFS_DONT_UPPER_SOME_WORDS)
+ {
+ exempt[0] = NULL;
+ }
+ Scan_Process_Fields_All_Downcase(string);
+
+ if (!g_utf8_validate(string,-1,NULL))
+ {
+ Log_Print(LOG_ERROR,"Scan_Process_Fields_First_Letters_Uppercase: Not a valid utf8! quiting");
+ return;
+ }
+ /* Removes trailing whitespace. */
+ string = g_strchomp(string);
+
+ temp = string;
+
+ /* If the word is a roman numeral, capitalize all of it. */
+ if ((len = Scan_Word_Is_Roman_Numeral (self, temp)))
+ {
+ strncpy(string, g_utf8_strup(temp, len), len);
+ } else
+ {
+ // Set first character to uppercase
+ c = g_utf8_get_char(temp);
+ strncpy(string, utf8_character, g_unichar_to_utf8(g_unichar_toupper(c), utf8_character));
+ }
+
+ // Uppercase first character of each word, except for 'exempt[]' words lists
+ while ( temp )
+ {
+ word = temp; // Needed if there is only one word
+ word1 = g_utf8_strchr(temp,-1,' ');
+ word2 = g_utf8_strchr(temp,-1,'_');
+
+ // Take the first string found (near beginning of string)
+ if (word1 && word2)
+ word = MIN(word1,word2);
+ else if (word1)
+ word = word1;
+ else if (word2)
+ word = word2;
+ else
+ {
+ // Last word of the string: the first letter is always uppercase,
+ // even if it's in the exempt list. This is a Chicago Manual of Style rule.
+ // Last Word In String - Should Capitalize Regardless of Word (Chicago Manual of Style)
+ c = g_utf8_get_char(word);
+ strncpy(word, utf8_character, g_unichar_to_utf8(g_unichar_toupper(c), utf8_character));
+ break;
+ }
+
+ // Go to first character of the word (char. after ' ' or '_')
+ word = word+1;
+
+ // If the word is a roman numeral, capitalize all of it
+ if ((len = Scan_Word_Is_Roman_Numeral (self, word)))
+ {
+ strncpy(word, g_utf8_strup(word, len), len);
+ } else
+ {
+ // Set uppercase the first character of this word
+ c = g_utf8_get_char(word);
+ strncpy(word, utf8_character, g_unichar_to_utf8(g_unichar_toupper(c), utf8_character));
+
+ // Set lowercase the first character of this word if found in the exempt words list
+ for (i=0; exempt[i]!=NULL; i++)
+ {
+ if (g_ascii_strncasecmp(exempt[i], word, strlen(exempt[i])) == 0)
+ {
+ c = g_utf8_get_char(word);
+ strncpy(word, utf8_character, g_unichar_to_utf8(g_unichar_tolower(c), utf8_character));
+ break;
+ }
+ }
+ }
+
+ temp = word;
+ }
+
+ // Uppercase letter placed after some characters like '(', '[', '{'
+ set_to_upper_case = FALSE;
+ for (temp = string; *temp; temp = g_utf8_next_char(temp))
+ {
+ c = g_utf8_get_char(temp);
+ set_to_upper_case_tmp = ( c == (gunichar)'('
+ || c == (gunichar)'['
+ || c == (gunichar)'{'
+ || c == (gunichar)'"'
+ || c == (gunichar)':'
+ || c == (gunichar)'.'
+ || c == (gunichar)'`'
+ || c == (gunichar)'-'
+ ) ? TRUE : FALSE;
+
+ if (set_to_upper_case && g_unichar_islower(c))
+ strncpy(temp, utf8_character, g_unichar_to_utf8(g_unichar_toupper(c), utf8_character));
+
+ set_to_upper_case = set_to_upper_case_tmp;
+ }
+
+}
+
+/*
+ * Replace something with something else ;)
+ * Here use Regular Expression, to search and replace.
+ */
+static void
+Scan_Convert_Character (gchar **string)
+{
+ gchar *from;
+ gchar *to;
+ GRegex *regex;
+ GError *regex_error = NULL;
+ gchar *new_string;
+
+ from = gtk_editable_get_chars (GTK_EDITABLE (ProcessFieldsConvertFrom), 0,
+ -1);
+ to = gtk_editable_get_chars (GTK_EDITABLE (ProcessFieldsConvertTo), 0, -1);
+
+ regex = g_regex_new (from, 0, 0, ®ex_error);
+ if (regex_error != NULL)
+ {
+ goto handle_error;
+ }
+
+ new_string = g_regex_replace (regex, *string, -1, 0, to, 0, ®ex_error);
+ if (regex_error != NULL)
+ {
+ g_free (new_string);
+ g_regex_unref (regex);
+ goto handle_error;
+ }
+
+ /* Success. */
+ g_regex_unref (regex);
+ g_free (*string);
+ *string = new_string;
+
+out:
+ g_free (from);
+ g_free (to);
+ return;
+
+handle_error:
+ Log_Print (LOG_ERROR, _("Error while processing fields: %s"),
+ regex_error->message);
+
+ g_error_free (regex_error);
+
+ goto out;
+}
+
+/*
+ * Return the field of a 'File_Tag' structure corresponding to the mask code
+ */
+static gchar
+**Scan_Return_File_Tag_Field_From_Mask_Code (File_Tag *FileTag, gchar code)
+{
+ switch (code)
+ {
+ case 't': /* Title */
+ return &FileTag->title;
+ case 'a': /* Artist */
+ return &FileTag->artist;
+ case 'b': /* Album */
+ return &FileTag->album;
+ case 'd': /* Disc Number */
+ return &FileTag->disc_number;
+ case 'x': /* Total number of discs. */
+ return &FileTag->disc_total;
+ case 'y': /* Year */
+ return &FileTag->year;
+ case 'n': /* Track */
+ return &FileTag->track;
+ case 'l': /* Track Total */
+ return &FileTag->track_total;
+ case 'g': /* Genre */
+ return &FileTag->genre;
+ case 'c': /* Comment */
+ return &FileTag->comment;
+ case 'p': /* Composer */
+ return &FileTag->composer;
+ case 'o': /* Orig. Artist */
+ return &FileTag->orig_artist;
+ case 'r': /* Copyright */
+ return &FileTag->copyright;
+ case 'u': /* URL */
+ return &FileTag->url;
+ case 'e': /* Encoded by */
+ return &FileTag->encoded_by;
+ case 'z': /* Album Artist */
+ return &FileTag->album_artist;
+ case 'i': /* Ignored */
+ return NULL;
+ default:
+ Log_Print(LOG_ERROR,"Scanner: Invalid code '%%%c' found!",code);
+ return NULL;
+ }
+}
+
+
+
+/******************
+ * Scanner Window *
+ ******************/
+/*
+ * Function when you select an item of the option menu
+ */
+static void
+Scanner_Option_Menu_Activate_Item (EtScanDialog *self, GtkWidget *combo)
+{
+ EtScanDialogPrivate *priv;
+ GtkRadioAction *radio_action;
+
+ priv = et_scan_dialog_get_instance_private (self);
+
+ radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (UIManager,
+ "/MenuBar/ViewMenu/ScannerMenu/FillTag"));
+ SCANNER_TYPE = gtk_combo_box_get_active (GTK_COMBO_BOX (combo));
+ gtk_radio_action_set_current_value (radio_action, SCANNER_TYPE);
+
+ switch (SCANNER_TYPE)
+ {
+ case ET_SCAN_TYPE_FILL_TAG:
+ gtk_widget_show(MaskEditorButton);
+ gtk_widget_show(LegendButton);
+ gtk_widget_show(ScanTagFrame);
+ gtk_widget_hide(RenameFileFrame);
+ gtk_widget_hide(ProcessFieldsFrame);
+ gtk_tree_view_set_model(GTK_TREE_VIEW(MaskEditorList),
GTK_TREE_MODEL(priv->scan_tag_masks_model));
+ Scan_Fill_Tag_Generate_Preview (self);
+ g_signal_emit_by_name(G_OBJECT(LegendButton),"toggled"); /* To hide or show legend frame
*/
+ g_signal_emit_by_name(G_OBJECT(MaskEditorButton),"toggled"); /* To hide or show mask editor
frame */
+ break;
+
+ case ET_SCAN_TYPE_RENAME_FILE:
+ gtk_widget_show(MaskEditorButton);
+ gtk_widget_show(LegendButton);
+ gtk_widget_hide(ScanTagFrame);
+ gtk_widget_show(RenameFileFrame);
+ gtk_widget_hide(ProcessFieldsFrame);
+ gtk_tree_view_set_model(GTK_TREE_VIEW(MaskEditorList), GTK_TREE_MODEL(priv->rename_masks_model));
+ Scan_Rename_File_Generate_Preview (self);
+ g_signal_emit_by_name(G_OBJECT(LegendButton),"toggled"); /* To hide or show legend frame
*/
+ g_signal_emit_by_name(G_OBJECT(MaskEditorButton),"toggled"); /* To hide or show mask editor
frame */
+ break;
+
+ case ET_SCAN_TYPE_PROCESS_FIELDS:
+ gtk_widget_hide(MaskEditorButton);
+ gtk_widget_hide(LegendButton);
+ gtk_widget_hide(ScanTagFrame);
+ gtk_widget_hide(RenameFileFrame);
+ gtk_widget_show_all(ProcessFieldsFrame);
+ // Hide directly the frames to don't change state of the buttons!
+ gtk_widget_hide(LegendFrame);
+ gtk_widget_hide(MaskEditorFrame);
+
+ gtk_tree_view_set_model(GTK_TREE_VIEW(MaskEditorList), NULL);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+void
+et_scan_dialog_open (EtScanDialog *self, EtScanType scanner_type)
+{
+ EtScanDialogPrivate *priv;
+
+ g_return_if_fail (ET_SCAN_DIALOG (self));
+ g_return_if_fail (scanner_type >= ET_SCAN_TYPE_FILL_TAG
+ && scanner_type <= ET_SCAN_TYPE_PROCESS_FIELDS);
+
+ priv = et_scan_dialog_get_instance_private (self);
+
+ gtk_combo_box_set_active (GTK_COMBO_BOX (priv->type_combo), scanner_type);
+}
+
+static void
+Mask_Editor_List_Add (EtScanDialog *self)
+{
+ EtScanDialogPrivate *priv;
+ gint i = 0;
+ GtkTreeModel *treemodel;
+ gchar *temp;
+
+ priv = et_scan_dialog_get_instance_private (self);
+
+ treemodel = gtk_tree_view_get_model(GTK_TREE_VIEW(MaskEditorList));
+
+ if (gtk_combo_box_get_active(GTK_COMBO_BOX(priv->type_combo)) == ET_SCAN_TYPE_FILL_TAG)
+ {
+ while(Scan_Masks[i])
+ {
+ /*if (!g_utf8_validate(Scan_Masks[i], -1, NULL))
+ temp = convert_to_utf8(Scan_Masks[i]);
+ else
+ temp = g_strdup(Scan_Masks[i]);*/
+ temp = Try_To_Validate_Utf8_String(Scan_Masks[i]);
+
+ gtk_list_store_insert_with_values (GTK_LIST_STORE (treemodel),
+ NULL, G_MAXINT,
+ MASK_EDITOR_TEXT, temp, -1);
+ g_free(temp);
+ i++;
+ }
+ } else if (gtk_combo_box_get_active(GTK_COMBO_BOX(priv->type_combo)) == ET_SCAN_TYPE_RENAME_FILE)
+ {
+ while(Rename_File_Masks[i])
+ {
+ /*if (!g_utf8_validate(Rename_File_Masks[i], -1, NULL))
+ temp = convert_to_utf8(Rename_File_Masks[i]);
+ else
+ temp = g_strdup(Rename_File_Masks[i]);*/
+ temp = Try_To_Validate_Utf8_String(Rename_File_Masks[i]);
+
+ gtk_list_store_insert_with_values (GTK_LIST_STORE (treemodel),
+ NULL, G_MAXINT,
+ MASK_EDITOR_TEXT, temp, -1);
+ g_free(temp);
+ i++;
+ }
+ }
+}
+
+/*
+ * Save the currently displayed mask list in the mask editor
+ */
+static void
+Mask_Editor_List_Save_Button (EtScanDialog *self)
+{
+ EtScanDialogPrivate *priv;
+
+ priv = et_scan_dialog_get_instance_private (self);
+
+ Mask_Editor_Clean_Up_Masks_List();
+
+ if (gtk_combo_box_get_active(GTK_COMBO_BOX(priv->type_combo)) == ET_SCAN_TYPE_FILL_TAG)
+ {
+ Save_Scan_Tag_Masks_List(priv->scan_tag_masks_model, MASK_EDITOR_TEXT);
+ } else if (gtk_combo_box_get_active(GTK_COMBO_BOX(priv->type_combo)) == ET_SCAN_TYPE_RENAME_FILE)
+ {
+ Save_Rename_File_Masks_List(priv->rename_masks_model, MASK_EDITOR_TEXT);
+ }
+}
+
+static void
+on_hide (EtScanDialog *self)
+{
+ GtkToggleAction *toggle_action;
+
+ toggle_action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (UIManager,
+ "/ToolBar/ShowScanner"));
+
+ if (gtk_toggle_action_get_active (toggle_action))
+ {
+ gtk_toggle_action_set_active (toggle_action, FALSE);
+ }
+
+}
+
+static void
+create_scan_dialog (EtScanDialog *self)
+{
+ EtScanDialogPrivate *priv;
+ GtkWidget *scan_button;
+ GtkWidget *ScanVBox;
+ GtkWidget *HBox1, *HBox2, *HBox4, *VBox, *hbox, *vbox;
+ GtkWidget *Table;
+ GtkWidget *Label;
+ GtkWidget *Button;
+ GIcon *new_folder;
+ GtkWidget *Icon;
+ GtkWidget *group;
+ GtkWidget *process_fields_convert_none;
+ GtkWidget *process_fields_case_none;
+ GtkWidget *radio_space_none;
+ GtkTreeViewColumn * column;
+ GtkCellRenderer *renderer;
+
+ priv = et_scan_dialog_get_instance_private (self);
+
+ /* The window */
+ gtk_window_set_title (GTK_WINDOW (self), _("Tag and Filename Scan"));
+ gtk_window_set_transient_for (GTK_WINDOW (self), GTK_WINDOW (MainWindow));
+ gtk_window_set_destroy_with_parent (GTK_WINDOW (self), TRUE);
+ gtk_dialog_add_buttons (GTK_DIALOG (self), GTK_STOCK_CLOSE,
+ GTK_RESPONSE_CLOSE, NULL);
+
+ /* 'Scan selected files' button */
+ scan_button = gtk_button_new_from_stock (GTK_STOCK_APPLY);
+ /* TODO: Set related action to match AM_SCAN_FILES. */
+ gtk_button_set_label (GTK_BUTTON (scan_button), _("Scan Files"));
+ gtk_widget_set_can_default (scan_button, TRUE);
+ gtk_dialog_add_action_widget (GTK_DIALOG (self), scan_button,
+ GTK_RESPONSE_APPLY);
+ gtk_dialog_set_default_response (GTK_DIALOG (self), GTK_RESPONSE_APPLY);
+ gtk_widget_show (scan_button);
+ gtk_widget_set_tooltip_text (scan_button, _("Scan selected files"));
+
+ /* The response signal handles close, scan and the delete event. */
+ g_signal_connect (self, "response", G_CALLBACK (et_scan_on_response),
+ NULL);
+ g_signal_connect (self, "hide", G_CALLBACK (on_hide), NULL);
+ g_signal_connect (self, "delete-event",
+ G_CALLBACK (gtk_widget_hide_on_delete), NULL);
+
+ /* The main vbox */
+ ScanVBox = gtk_dialog_get_content_area (GTK_DIALOG (self));
+ gtk_container_set_border_width (GTK_CONTAINER (self), 6);
+ gtk_box_set_spacing (GTK_BOX (ScanVBox), 12);
+
+ /*
+ * The hbox for mode buttons + buttons + what to scan
+ */
+ HBox1 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,0);
+ gtk_box_pack_start(GTK_BOX(ScanVBox),HBox1,FALSE,FALSE,0);
+
+ /* Option Menu */
+ Label = gtk_label_new(_("Scanner:"));
+ gtk_box_pack_start(GTK_BOX(HBox1),Label,FALSE,FALSE,0);
+
+ priv->type_combo = gtk_combo_box_text_new();
+ gtk_box_pack_start(GTK_BOX (HBox1), priv->type_combo, TRUE, TRUE, 2);
+ gtk_widget_set_size_request(priv->type_combo, 160, -1);
+
+ /* Option for Tag */
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(priv->type_combo),
+ _(Scanner_Option_Menu_Items[ET_SCAN_TYPE_FILL_TAG]));
+
+ /* Option for FileName */
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(priv->type_combo),
+ _(Scanner_Option_Menu_Items[ET_SCAN_TYPE_RENAME_FILE]));
+
+ /* Option for ProcessFields */
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(priv->type_combo),
+ _(Scanner_Option_Menu_Items[ET_SCAN_TYPE_PROCESS_FIELDS]));
+
+ /* Selection of the item made at the end of the function. */
+ gtk_widget_set_tooltip_text (priv->type_combo,
+ _("Select the type of scanner to use"));
+ g_signal_connect_swapped (priv->type_combo, "changed",
+ G_CALLBACK (Scanner_Option_Menu_Activate_Item),
+ self);
+
+ /* Options button */
+ Button = gtk_button_new();
+ Icon = gtk_image_new_from_stock(GTK_STOCK_PREFERENCES, GTK_ICON_SIZE_BUTTON);
+ gtk_container_add(GTK_CONTAINER(Button),Icon);
+ gtk_box_pack_start(GTK_BOX(HBox1),Button,FALSE,FALSE,0);
+ gtk_button_set_relief(GTK_BUTTON(Button),GTK_RELIEF_NONE);
+ gtk_widget_set_tooltip_text(Button,_("Scanner Preferences"));
+ g_signal_connect(G_OBJECT(Button),"clicked",G_CALLBACK(Scan_Option_Button),NULL);
+
+ /* Mask Editor button */
+ MaskEditorButton = gtk_toggle_button_new();
+ Icon = gtk_image_new_from_stock("easytag-mask", GTK_ICON_SIZE_BUTTON);
+ gtk_container_add(GTK_CONTAINER(MaskEditorButton),Icon);
+ gtk_box_pack_start(GTK_BOX(HBox1),MaskEditorButton,FALSE,FALSE,0);
+ gtk_button_set_relief(GTK_BUTTON(MaskEditorButton),GTK_RELIEF_NONE);
+ gtk_widget_set_tooltip_text(MaskEditorButton,_("Show / Hide Masks Editor"));
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(MaskEditorButton),SCAN_MASK_EDITOR_BUTTON);
+ g_signal_connect(G_OBJECT(MaskEditorButton),"toggled",G_CALLBACK(Scan_Toggle_Mask_Editor_Button),NULL);
+
+ /* Legend button */
+ LegendButton = gtk_toggle_button_new();
+ Icon = gtk_image_new_from_stock(GTK_STOCK_HELP, GTK_ICON_SIZE_BUTTON);
+ gtk_container_add(GTK_CONTAINER(LegendButton),Icon);
+ gtk_box_pack_start(GTK_BOX(HBox1),LegendButton,FALSE,FALSE,0);
+ gtk_button_set_relief(GTK_BUTTON(LegendButton),GTK_RELIEF_NONE);
+ gtk_widget_set_tooltip_text(LegendButton,_("Show / Hide Legend"));
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(LegendButton),SCAN_LEGEND_BUTTON);
+ g_signal_connect(G_OBJECT(LegendButton),"toggled",G_CALLBACK(Scan_Toggle_Legend_Button),NULL);
+
+ /*
+ * Frame for Scan Tag
+ */
+ ScanTagFrame = gtk_frame_new (_(Scanner_Option_Menu_Items[0]));
+ gtk_box_pack_start(GTK_BOX(ScanVBox),ScanTagFrame,FALSE,FALSE,0);
+
+ vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, BOX_SPACING);
+ gtk_container_add(GTK_CONTAINER(ScanTagFrame),vbox);
+ gtk_container_set_border_width(GTK_CONTAINER(vbox), 4);
+ gtk_widget_show(vbox);
+
+ /* The combo box + Status icon */
+ HBox2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, BOX_SPACING);
+ gtk_box_pack_start(GTK_BOX(vbox),HBox2,TRUE,TRUE,0);
+
+ // Set up list model which is used both by the combobox and the editor
+ priv->scan_tag_masks_model = gtk_list_store_new(MASK_EDITOR_COUNT, G_TYPE_STRING);
+
+ // The combo box to select the mask to apply
+ ScanTagMaskCombo = gtk_combo_box_new_with_entry();
+ gtk_combo_box_set_model(GTK_COMBO_BOX(ScanTagMaskCombo), GTK_TREE_MODEL(priv->scan_tag_masks_model));
+ g_object_unref (priv->scan_tag_masks_model);
+ gtk_combo_box_set_entry_text_column(GTK_COMBO_BOX(ScanTagMaskCombo), MASK_EDITOR_TEXT);
+
+ gtk_box_pack_start(GTK_BOX(HBox2),ScanTagMaskCombo,TRUE,TRUE,2);
+ gtk_widget_set_tooltip_text(GTK_WIDGET(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(ScanTagMaskCombo)))),
+ _("Select or type in a mask using codes (see Legend) to parse "
+ "filename and path. Used to fill in tag fields"));
+ /* Signal to generate preview (preview of the new tag values). */
+ g_signal_connect_swapped (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (ScanTagMaskCombo))),
+ "changed",
+ G_CALLBACK (Scan_Fill_Tag_Generate_Preview),
+ self);
+
+ // Load masks into the combobox from a file
+ Load_Scan_Tag_Masks_List(priv->scan_tag_masks_model, MASK_EDITOR_TEXT, Scan_Masks);
+ if (SCAN_TAG_DEFAULT_MASK)
+ {
+ Add_String_To_Combo_List(priv->scan_tag_masks_model, SCAN_TAG_DEFAULT_MASK);
+ gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(ScanTagMaskCombo))), SCAN_TAG_DEFAULT_MASK);
+ }else
+ {
+ gtk_combo_box_set_active(GTK_COMBO_BOX(ScanTagMaskCombo), 0);
+ }
+
+ // Mask status icon
+ // Signal connection to check if mask is correct into the mask entry
+ g_signal_connect (gtk_bin_get_child (GTK_BIN (ScanTagMaskCombo)),
+ "changed", G_CALLBACK (entry_check_scan_tag_mask),
+ NULL);
+
+ /* Preview label. */
+ priv->fill_tag_preview_label = gtk_label_new (_("Fill tag preview"));
+ gtk_label_set_line_wrap(GTK_LABEL(priv->fill_tag_preview_label),TRUE);
+ gtk_widget_show(priv->fill_tag_preview_label);
+ gtk_box_pack_start(GTK_BOX(vbox),priv->fill_tag_preview_label,TRUE,TRUE,0);
+
+ /*
+ * Frame for Rename File
+ */
+ RenameFileFrame = gtk_frame_new (_(Scanner_Option_Menu_Items[1]));
+ gtk_box_pack_start(GTK_BOX(ScanVBox),RenameFileFrame,FALSE,FALSE,0);
+
+ vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL,4);
+ gtk_container_add(GTK_CONTAINER(RenameFileFrame),vbox);
+ gtk_container_set_border_width(GTK_CONTAINER(vbox), 4);
+ gtk_widget_show(vbox);
+
+ /* The button to prefix path + combo box + Status icon */
+ HBox4 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,2);
+ gtk_box_pack_start(GTK_BOX(vbox),HBox4,TRUE,TRUE,0);
+
+ // Button to prefix path
+ Button = gtk_button_new();
+ new_folder = g_themed_icon_new ("folder-new");
+ /* TODO: On Win32, GTK_ICON_SIZE_BUTTON enlarges the combobox. */
+ Icon = gtk_image_new_from_gicon (new_folder, GTK_ICON_SIZE_MENU);
+ g_object_unref (new_folder);
+ gtk_container_add (GTK_CONTAINER (Button), Icon);
+ gtk_box_pack_start (GTK_BOX (HBox4), Button, FALSE, FALSE, 0);
+ gtk_button_set_relief (GTK_BUTTON (Button), GTK_RELIEF_NONE);
+ g_signal_connect (Button, "clicked",
+ G_CALLBACK (Scan_Rename_File_Prefix_Path), NULL);
+ gtk_widget_set_tooltip_text (Button, _("Prefix mask with current path"));
+
+ // Set up list model which is used both by the combobox and the editor
+ priv->rename_masks_model = gtk_list_store_new(MASK_EDITOR_COUNT, G_TYPE_STRING);
+
+ // The combo box to select the mask to apply
+ RenameFileMaskCombo = gtk_combo_box_new_with_entry();
+ gtk_combo_box_set_model(GTK_COMBO_BOX(RenameFileMaskCombo), GTK_TREE_MODEL(priv->rename_masks_model));
+ g_object_unref (priv->rename_masks_model);
+ gtk_combo_box_set_entry_text_column(GTK_COMBO_BOX(RenameFileMaskCombo), MASK_EDITOR_TEXT);
+
+ gtk_box_pack_start(GTK_BOX(HBox4),RenameFileMaskCombo,TRUE,TRUE,2);
+ gtk_container_set_border_width(GTK_CONTAINER(HBox4), 2);
+ gtk_widget_set_tooltip_text(GTK_WIDGET(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(RenameFileMaskCombo)))),
+ _("Select or type in a mask using codes (see Legend) to parse tag fields. "
+ "Used to rename the file.\nUse / to make directories. If the first character "
+ "is /, it's a absolute path, otherwise is relative to the old path."));
+ // Signal to generate preview (preview of the new filename)
+ g_signal_connect_swapped (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (RenameFileMaskCombo))),
+ "changed",
+ G_CALLBACK (Scan_Rename_File_Generate_Preview),
+ self);
+
+ // Load masks into the combobox from a file
+ Load_Rename_File_Masks_List(priv->rename_masks_model, MASK_EDITOR_TEXT, Rename_File_Masks);
+ if (RENAME_FILE_DEFAULT_MASK)
+ {
+ Add_String_To_Combo_List(priv->rename_masks_model, RENAME_FILE_DEFAULT_MASK);
+ gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(RenameFileMaskCombo))),
RENAME_FILE_DEFAULT_MASK);
+ }else
+ {
+ gtk_combo_box_set_active(GTK_COMBO_BOX(RenameFileMaskCombo), 0);
+ }
+
+ // Mask status icon
+ // Signal connection to check if mask is correct into the mask entry
+ g_signal_connect (gtk_bin_get_child (GTK_BIN (RenameFileMaskCombo)),
+ "changed", G_CALLBACK (entry_check_rename_file_mask),
+ NULL);
+
+ /* Preview label */
+ priv->rename_file_preview_label = gtk_label_new (_("Rename file preview"));
+ gtk_label_set_line_wrap(GTK_LABEL(priv->rename_file_preview_label),TRUE);
+ gtk_widget_show(priv->rename_file_preview_label);
+ gtk_box_pack_start(GTK_BOX(vbox),priv->rename_file_preview_label,TRUE,TRUE,0);
+
+ /*
+ * Frame for Processing Fields
+ */
+ ProcessFieldsFrame = gtk_frame_new (_(Scanner_Option_Menu_Items[2]));
+ gtk_box_pack_start(GTK_BOX(ScanVBox),ProcessFieldsFrame,FALSE,FALSE,0);
+
+ VBox = gtk_box_new (GTK_ORIENTATION_VERTICAL, BOX_SPACING);
+ gtk_container_add(GTK_CONTAINER(ProcessFieldsFrame),VBox);
+ gtk_container_set_border_width(GTK_CONTAINER(VBox), 4);
+ gtk_widget_show(VBox);
+
+ /* Group: select entry fields to process */
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,0);
+ gtk_box_pack_start(GTK_BOX(VBox),hbox,FALSE,FALSE,2);
+ Label = gtk_label_new(_("Select fields:"));
+ gtk_box_pack_start (GTK_BOX (hbox), Label, FALSE, FALSE, 2);
+ gtk_widget_set_tooltip_text (Label,
+ _("The buttons on the right represent the "
+ "fields which can be processed. Select "
+ "those which interest you"));
+ // Advice for Translators: set the first letter of filename translated
+ ProcessFileNameField = gtk_toggle_button_new_with_label( _("F"));
+ gtk_widget_set_tooltip_text (ProcessFileNameField,
+ _("Process filename field"));
+ // Advice for Translators: set the first letter of title translated
+ ProcessTitleField = gtk_toggle_button_new_with_label( _("T"));
+ gtk_widget_set_tooltip_text(ProcessTitleField, _("Process title field"));
+ // Advice for Translators: set the first letter of artist translated
+ ProcessArtistField = gtk_toggle_button_new_with_label( _("Ar"));
+ gtk_widget_set_tooltip_text(ProcessArtistField, _("Process file artist field"));
+ // Advice for Translators: set the first letter of album artist translated
+ ProcessAlbumArtistField = gtk_toggle_button_new_with_label(_("AA"));
+ gtk_widget_set_tooltip_text(ProcessAlbumArtistField, _("Process album artist field"));
+ // Advice for Translators: set the first letter of album translated
+ ProcessAlbumField = gtk_toggle_button_new_with_label( _("Al"));
+ gtk_widget_set_tooltip_text(ProcessAlbumField, _("Process album field"));
+ // Advice for Translators: set the first letter of genre translated
+ ProcessGenreField = gtk_toggle_button_new_with_label( _("G"));
+ gtk_widget_set_tooltip_text(ProcessGenreField, _("Process genre field"));
+ // Advice for Translators: set the first letter of comment translated
+ ProcessCommentField = gtk_toggle_button_new_with_label( _("Cm"));
+ gtk_widget_set_tooltip_text(ProcessCommentField, _("Process comment field"));
+ // Advice for Translators: set the first letter of composer translated
+ ProcessComposerField = gtk_toggle_button_new_with_label( _("Cp"));
+ gtk_widget_set_tooltip_text(ProcessComposerField, _("Process composer field"));
+ // Advice for Translators: set the first letter of orig artist translated
+ ProcessOrigArtistField = gtk_toggle_button_new_with_label( _("O"));
+ gtk_widget_set_tooltip_text(ProcessOrigArtistField, _("Process original artist field"));
+ // Advice for Translators: set the first letter of copyright translated
+ ProcessCopyrightField = gtk_toggle_button_new_with_label( _("Cr"));
+ gtk_widget_set_tooltip_text(ProcessCopyrightField, _("Process copyright field"));
+ // Advice for Translators: set the first letter of URL translated
+ ProcessURLField = gtk_toggle_button_new_with_label( _("U"));
+ gtk_widget_set_tooltip_text(ProcessURLField, _("Process URL field"));
+ // Advice for Translators: set the first letter of encoder name translated
+ ProcessEncodedByField = gtk_toggle_button_new_with_label( _("E"));
+ gtk_widget_set_tooltip_text(ProcessEncodedByField, _("Process encoder name field"));
+ gtk_box_pack_start(GTK_BOX(hbox),ProcessFileNameField, TRUE,TRUE,2);
+ gtk_box_pack_start(GTK_BOX(hbox),ProcessTitleField, TRUE,TRUE,2);
+ gtk_box_pack_start(GTK_BOX(hbox),ProcessArtistField, TRUE,TRUE,2);
+ gtk_box_pack_start(GTK_BOX(hbox),ProcessAlbumArtistField,TRUE,TRUE,2);
+ gtk_box_pack_start(GTK_BOX(hbox),ProcessAlbumField, TRUE,TRUE,2);
+ gtk_box_pack_start(GTK_BOX(hbox),ProcessGenreField, TRUE,TRUE,2);
+ gtk_box_pack_start(GTK_BOX(hbox),ProcessCommentField, TRUE,TRUE,2);
+ gtk_box_pack_start(GTK_BOX(hbox),ProcessComposerField, TRUE,TRUE,2);
+ gtk_box_pack_start(GTK_BOX(hbox),ProcessOrigArtistField, TRUE,TRUE,2);
+ gtk_box_pack_start(GTK_BOX(hbox),ProcessCopyrightField, TRUE,TRUE,2);
+ gtk_box_pack_start(GTK_BOX(hbox),ProcessURLField, TRUE,TRUE,2);
+ gtk_box_pack_start(GTK_BOX(hbox),ProcessEncodedByField, TRUE,TRUE,2);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessFileNameField), PROCESS_FILENAME_FIELD);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessTitleField), PROCESS_TITLE_FIELD);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessArtistField), PROCESS_ARTIST_FIELD);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessAlbumArtistField),PROCESS_ALBUM_ARTIST_FIELD);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessAlbumField), PROCESS_ALBUM_FIELD);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessGenreField), PROCESS_GENRE_FIELD);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessCommentField), PROCESS_COMMENT_FIELD);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessComposerField), PROCESS_COMPOSER_FIELD);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessOrigArtistField), PROCESS_ORIG_ARTIST_FIELD);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessCopyrightField), PROCESS_COPYRIGHT_FIELD);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessURLField), PROCESS_URL_FIELD);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessEncodedByField), PROCESS_ENCODED_BY_FIELD);
+ g_signal_connect(G_OBJECT(ProcessFileNameField),
"toggled",G_CALLBACK(Select_Fields_Set_Sensitive),NULL);
+ g_signal_connect(G_OBJECT(ProcessTitleField),
"toggled",G_CALLBACK(Select_Fields_Set_Sensitive),NULL);
+ g_signal_connect(G_OBJECT(ProcessArtistField),
"toggled",G_CALLBACK(Select_Fields_Set_Sensitive),NULL);
+
g_signal_connect(G_OBJECT(ProcessAlbumArtistField),"toggled",G_CALLBACK(Select_Fields_Set_Sensitive),NULL);
+ g_signal_connect(G_OBJECT(ProcessAlbumField),
"toggled",G_CALLBACK(Select_Fields_Set_Sensitive),NULL);
+ g_signal_connect(G_OBJECT(ProcessGenreField),
"toggled",G_CALLBACK(Select_Fields_Set_Sensitive),NULL);
+ g_signal_connect(G_OBJECT(ProcessCommentField),
"toggled",G_CALLBACK(Select_Fields_Set_Sensitive),NULL);
+ g_signal_connect(G_OBJECT(ProcessComposerField),
"toggled",G_CALLBACK(Select_Fields_Set_Sensitive),NULL);
+ g_signal_connect(G_OBJECT(ProcessOrigArtistField),
"toggled",G_CALLBACK(Select_Fields_Set_Sensitive),NULL);
+ g_signal_connect(G_OBJECT(ProcessCopyrightField),
"toggled",G_CALLBACK(Select_Fields_Set_Sensitive),NULL);
+ g_signal_connect(G_OBJECT(ProcessURLField),
"toggled",G_CALLBACK(Select_Fields_Set_Sensitive),NULL);
+ g_signal_connect(G_OBJECT(ProcessEncodedByField),
"toggled",G_CALLBACK(Select_Fields_Set_Sensitive),NULL);
+ /* The small buttons */
+ Button = gtk_button_new();
+ g_signal_connect(G_OBJECT(Button),"clicked",G_CALLBACK(Select_Fields_Invert_Selection),NULL);
+ gtk_box_pack_end (GTK_BOX(hbox), Button, FALSE, FALSE, 0);
+ Icon = gtk_image_new_from_stock ("easytag-invert-selection",
+ GTK_ICON_SIZE_BUTTON);
+ gtk_container_add(GTK_CONTAINER(Button),Icon);
+ gtk_widget_set_tooltip_text (Button, _("Invert selection"));
+ Button = gtk_button_new();
+ g_signal_connect(G_OBJECT(Button),"clicked",G_CALLBACK(Select_Fields_Select_Unselect_All),NULL);
+ gtk_box_pack_end (GTK_BOX(hbox), Button, FALSE, FALSE, 0);
+ Icon = gtk_image_new_from_icon_name ("edit-select-all",
+ GTK_ICON_SIZE_BUTTON);
+ gtk_container_add(GTK_CONTAINER(Button),Icon);
+ gtk_widget_set_tooltip_text (Button, _("Select/Unselect all"));
+
+ /* Group: character conversion */
+ group = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+ gtk_box_pack_start (GTK_BOX (VBox), group, FALSE, FALSE, 0);
+ ProcessFieldsConvertIntoSpace = gtk_radio_button_new_with_label_from_widget (NULL, _("Convert '_' and
'%20' to spaces"));
+ ProcessFieldsConvertSpace = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON
(ProcessFieldsConvertIntoSpace),
+ _("Convert ' ' to '_'"));
+ gtk_box_pack_start (GTK_BOX (group), ProcessFieldsConvertIntoSpace, FALSE,
+ FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (group), ProcessFieldsConvertSpace, FALSE,
+ FALSE, 0);
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,2);
+ gtk_box_pack_start (GTK_BOX (group), hbox, FALSE, FALSE, 0);
+ ProcessFieldsConvert = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON
(ProcessFieldsConvertIntoSpace),
+ _("Convert:"));
+ ProcessFieldsConvertTo = gtk_entry_new();
+ ProcessFieldsConvertLabelTo = gtk_label_new(_("to: ")); // A "space" at the end to allow another
translation for "to :" (needed in French!)
+ ProcessFieldsConvertFrom = gtk_entry_new();
+ //gtk_entry_set_max_length(GTK_ENTRY(ProcessFieldsConvertTo), 1); // Now, it isn't limited to one
character
+ //gtk_entry_set_max_length(GTK_ENTRY(ProcessFieldsConvertFrom), 1);
+ gtk_widget_set_size_request(ProcessFieldsConvertTo,120,-1);
+ gtk_widget_set_size_request(ProcessFieldsConvertFrom,120,-1);
+ process_fields_convert_none = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON
(ProcessFieldsConvertIntoSpace),
+ _("Do not convert"));
+ gtk_box_pack_start(GTK_BOX(hbox),ProcessFieldsConvert, FALSE,FALSE,0);
+ gtk_box_pack_start(GTK_BOX(hbox),ProcessFieldsConvertFrom, FALSE,FALSE,0);
+ gtk_box_pack_start(GTK_BOX(hbox),ProcessFieldsConvertLabelTo,FALSE,FALSE,0);
+ gtk_box_pack_start(GTK_BOX(hbox),ProcessFieldsConvertTo, FALSE,FALSE,0);
+ gtk_box_pack_start (GTK_BOX (group), process_fields_convert_none, FALSE,
+ FALSE, 0);
+ if (PROCESS_FIELDS_CONVERT_FROM)
+ gtk_entry_set_text(GTK_ENTRY(ProcessFieldsConvertFrom),PROCESS_FIELDS_CONVERT_FROM);
+ if (PROCESS_FIELDS_CONVERT_TO)
+ gtk_entry_set_text(GTK_ENTRY(ProcessFieldsConvertTo),PROCESS_FIELDS_CONVERT_TO);
+ /* Toggled signals */
+ g_signal_connect(G_OBJECT(ProcessFieldsConvert),
"toggled",G_CALLBACK(Process_Fields_Convert_Check_Button_Toggled),NULL);
+ /* Set check buttons to init value */
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessFieldsConvertIntoSpace),PF_CONVERT_INTO_SPACE);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessFieldsConvertSpace),PF_CONVERT_SPACE);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessFieldsConvert),PF_CONVERT);
+ /* Tooltips */
+ gtk_widget_set_tooltip_text(ProcessFieldsConvertIntoSpace,
+ _("The underscore character or the string '%20' are replaced by one space. "
+ "Example, before: 'Text%20In%20An_Entry', after: 'Text In An Entry'."));
+ gtk_widget_set_tooltip_text(ProcessFieldsConvertSpace,
+ _("The space character is replaced by one underscore character. "
+ "Example, before: 'Text In An Entry', after: 'Text_In_An_Entry'."));
+ gtk_widget_set_tooltip_text(ProcessFieldsConvert,
+ _("Replace a string by another one. Note that the search is case sensitive."));
+
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,0);
+
+ /* Group: capitalize, ... */
+ group = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+ gtk_box_pack_start (GTK_BOX (VBox), group, FALSE, FALSE, 0);
+ ProcessFieldsAllUppercase = gtk_radio_button_new_with_label_from_widget (NULL, _("Capitalize all"));
+ ProcessFieldsAllDowncase = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON
(ProcessFieldsAllUppercase),
+ _("Lowercase all"));
+ ProcessFieldsFirstLetterUppercase = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON
(ProcessFieldsAllUppercase),
+ _("Capitalize first
letter"));
+ ProcessFieldsFirstLettersUppercase = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON
(ProcessFieldsAllUppercase),
+ _("Capitalize the
first letter of each word"));
+ ProcessFieldsDetectRomanNumerals = gtk_check_button_new_with_label(_("Detect Roman numerals"));
+ process_fields_case_none = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON
(ProcessFieldsAllUppercase),
+ _("Do not change
capitalization"));
+ gtk_box_pack_start (GTK_BOX (group), ProcessFieldsAllUppercase, FALSE,
+ FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (group),ProcessFieldsAllDowncase, FALSE, FALSE,
+ 0);
+ gtk_box_pack_start (GTK_BOX (group),ProcessFieldsFirstLetterUppercase,
+ FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (group), hbox, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox),ProcessFieldsFirstLettersUppercase,FALSE,FALSE,0);
+ gtk_box_pack_start(GTK_BOX(hbox),ProcessFieldsDetectRomanNumerals,FALSE,FALSE,0);
+ gtk_box_pack_start (GTK_BOX (group), process_fields_case_none, FALSE,
+ FALSE, 0);
+ /* Toggled signals */
+
g_signal_connect(G_OBJECT(ProcessFieldsFirstLettersUppercase),"toggled",G_CALLBACK(Process_Fields_First_Letters_Check_Button_Toggled),NULL);
+ /* Set check buttons to init value */
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessFieldsAllUppercase),PF_CONVERT_ALL_UPPERCASE);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessFieldsAllDowncase),PF_CONVERT_ALL_DOWNCASE);
+
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessFieldsFirstLetterUppercase),PF_CONVERT_FIRST_LETTER_UPPERCASE);
+
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessFieldsFirstLettersUppercase),PF_CONVERT_FIRST_LETTERS_UPPERCASE);
+
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessFieldsDetectRomanNumerals),PF_DETECT_ROMAN_NUMERALS);
+ /* Tooltips */
+ gtk_widget_set_tooltip_text(ProcessFieldsAllUppercase,
+ _("Convert all words in all fields to upper case. "
+ "Example, before: 'Text IN AN entry', after: 'TEXT IN AN ENTRY'."));
+ gtk_widget_set_tooltip_text(ProcessFieldsAllDowncase,
+ _("Convert all words in all fields to lower case. "
+ "Example, before: 'TEXT IN an entry', after: 'text in an entry'."));
+ gtk_widget_set_tooltip_text(ProcessFieldsFirstLetterUppercase,
+ _("Convert the initial of the first word in all fields to upper case. "
+ "Example, before: 'text IN An ENTRY', after: 'Text in an entry'."));
+ gtk_widget_set_tooltip_text(ProcessFieldsFirstLettersUppercase,
+ _("Convert the initial of each word in all fields to upper case. "
+ "Example, before: 'Text in an ENTRY', after: 'Text In An Entry'."));
+ gtk_widget_set_tooltip_text(ProcessFieldsDetectRomanNumerals,
+ _("Force to convert to upper case the Roman numerals. "
+ "Example, before: 'ix. text in an entry', after: 'IX. Text In An Entry'."));
+
+ /* Group: insert/remove spaces */
+ group = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+ gtk_box_pack_start (GTK_BOX (VBox), group, FALSE, FALSE, 0);
+ ProcessFieldsRemoveSpace = gtk_radio_button_new_with_label_from_widget (NULL, _("Remove spaces"));
+ ProcessFieldsInsertSpace = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON
(ProcessFieldsRemoveSpace),
+ _("Insert a space before
uppercase letters"));
+ ProcessFieldsOnlyOneSpace = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON
(ProcessFieldsRemoveSpace),
+ _("Remove duplicate spaces and
underscores"));
+ radio_space_none = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON
(ProcessFieldsRemoveSpace),
+ _("Do not change word separators"));
+ gtk_box_pack_start (GTK_BOX (group), ProcessFieldsRemoveSpace, FALSE,
+ FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (group), ProcessFieldsInsertSpace, FALSE,
+ FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (group), ProcessFieldsOnlyOneSpace, FALSE,
+ FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (group), radio_space_none, FALSE, FALSE, 0);
+ /* Set check buttons to init value */
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessFieldsRemoveSpace),PF_REMOVE_SPACE);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessFieldsInsertSpace),PF_INSERT_SPACE);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessFieldsOnlyOneSpace),PF_ONLY_ONE_SPACE);
+ /* Tooltips */
+ gtk_widget_set_tooltip_text(ProcessFieldsRemoveSpace,
+ _("All spaces between words are removed. "
+ "Example, before: 'Text In An Entry', after: 'TextInAnEntry'."));
+ gtk_widget_set_tooltip_text(ProcessFieldsInsertSpace,
+ _("A space is inserted before each upper case letter. "
+ "Example, before: 'TextInAnEntry', after: 'Text In An Entry'."));
+ gtk_widget_set_tooltip_text(ProcessFieldsOnlyOneSpace,
+ _("Duplicate spaces and underscores are removed. "
+ "Example, before: 'Text__In__An Entry', after: 'Text_In_An Entry'."));
+ Select_Fields_Set_Sensitive();
+
+ /*
+ * Frame to display codes legend
+ */
+ LegendFrame = gtk_frame_new (_("Legend"));
+ gtk_box_pack_start(GTK_BOX(ScanVBox),LegendFrame,FALSE,FALSE,0);
+ /* Legend labels */
+ Table = et_grid_new (3, 6);
+ gtk_container_add(GTK_CONTAINER(LegendFrame),Table);
+ gtk_container_set_border_width(GTK_CONTAINER(Table),4);
+ Label = gtk_label_new(_("%a: artist"));
+ et_grid_attach_margins (GTK_GRID (Table), Label, 0, 0, 1, 1, 6, 0);
+ gtk_misc_set_alignment(GTK_MISC(Label),0,0.5);
+ Label = gtk_label_new(_("%z: album artist"));
+ et_grid_attach_margins (GTK_GRID (Table), Label, 0, 1, 1, 1, 6, 0);
+ gtk_misc_set_alignment(GTK_MISC(Label),0,0.5);
+ Label = gtk_label_new(_("%b: album"));
+ et_grid_attach_margins (GTK_GRID (Table), Label, 0, 2, 1, 1, 6, 0);
+ gtk_misc_set_alignment(GTK_MISC(Label),0,0.5);
+ Label = gtk_label_new(_("%c: comment"));
+ et_grid_attach_margins (GTK_GRID (Table), Label, 0, 3, 1, 1, 6, 0);
+ gtk_misc_set_alignment(GTK_MISC(Label),0,0.5);
+ Label = gtk_label_new(_("%p: composer"));
+ et_grid_attach_margins (GTK_GRID (Table), Label, 0, 4, 1, 1, 6, 0);
+ gtk_misc_set_alignment(GTK_MISC(Label),0,0.5);
+ Label = gtk_label_new(_("%r: copyright"));
+ et_grid_attach_margins (GTK_GRID (Table), Label, 0, 5, 1, 1, 6, 0);
+ gtk_misc_set_alignment(GTK_MISC(Label),0,0.5);
+ Label = gtk_label_new(_("%d: disc number"));
+ et_grid_attach_margins (GTK_GRID (Table), Label, 1, 0, 1, 1, 6, 0);
+ gtk_misc_set_alignment(GTK_MISC(Label),0,0.5);
+ Label = gtk_label_new(_("%e: encoded by"));
+ et_grid_attach_margins (GTK_GRID (Table), Label, 1, 1, 1, 1, 6, 0);
+ gtk_misc_set_alignment(GTK_MISC(Label),0,0.5);
+ Label = gtk_label_new(_("%g: genre"));
+ et_grid_attach_margins (GTK_GRID (Table), Label, 1, 2, 1, 1, 6, 0);
+ gtk_misc_set_alignment(GTK_MISC(Label),0,0.5);
+ Label = gtk_label_new(_("%i: ignored"));
+ et_grid_attach_margins (GTK_GRID (Table), Label, 1, 3, 1, 1, 6, 0);
+ gtk_misc_set_alignment(GTK_MISC(Label),0,0.5);
+ Label = gtk_label_new(_("%l: number of tracks"));
+ et_grid_attach_margins (GTK_GRID (Table), Label, 1, 4, 1, 1, 6, 0);
+ gtk_misc_set_alignment(GTK_MISC(Label),0,0.5);
+ Label = gtk_label_new(_("%o: orig. artist"));
+ et_grid_attach_margins (GTK_GRID (Table), Label, 1, 5, 1, 1, 6, 0);
+ gtk_misc_set_alignment(GTK_MISC(Label),0,0.5);
+ Label = gtk_label_new(_("%n: track"));
+ et_grid_attach_margins (GTK_GRID (Table), Label, 2, 0, 1, 1, 6, 0);
+ gtk_misc_set_alignment(GTK_MISC(Label),0,0.5);
+ Label = gtk_label_new(_("%t: title"));
+ et_grid_attach_margins (GTK_GRID (Table), Label, 2, 1, 1, 1, 6, 0);
+ gtk_misc_set_alignment(GTK_MISC(Label),0,0.5);
+ Label = gtk_label_new(_("%u: URL"));
+ et_grid_attach_margins (GTK_GRID (Table), Label, 2, 2, 1, 1, 6, 0);
+ gtk_misc_set_alignment(GTK_MISC(Label),0,0.5);
+ Label = gtk_label_new (_("%x: number of discs"));
+ et_grid_attach_margins (GTK_GRID (Table), Label, 2, 3, 1, 1, 6, 0);
+ gtk_misc_set_alignment (GTK_MISC (Label), 0, 0.5);
+ Label = gtk_label_new(_("%y: year"));
+ et_grid_attach_margins (GTK_GRID (Table), Label, 2, 4, 1, 1, 6, 0);
+ gtk_misc_set_alignment(GTK_MISC(Label),0,0.5);
+
+ /*
+ * Masks Editor
+ */
+ MaskEditorFrame = gtk_frame_new (_("Mask Editor"));
+ gtk_box_pack_start(GTK_BOX(ScanVBox),MaskEditorFrame,FALSE,FALSE,0);
+ MaskEditorHBox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,4);
+ gtk_container_add(GTK_CONTAINER(MaskEditorFrame),MaskEditorHBox);
+ gtk_container_set_border_width(GTK_CONTAINER(MaskEditorHBox), 4);
+
+ /* The editor part */
+ MaskEditorVBox = gtk_box_new(GTK_ORIENTATION_VERTICAL,2);
+ gtk_box_pack_start(GTK_BOX(MaskEditorHBox),MaskEditorVBox,TRUE,TRUE,0);
+ MaskEditorScrollWindow = gtk_scrolled_window_new(NULL,NULL);
+ gtk_box_pack_start(GTK_BOX(MaskEditorVBox),MaskEditorScrollWindow,TRUE,TRUE,0);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(MaskEditorScrollWindow),
+ GTK_POLICY_AUTOMATIC,GTK_POLICY_AUTOMATIC);
+ gtk_widget_set_size_request(GTK_WIDGET(MaskEditorScrollWindow), -1, 101);
+
+ /* The list */
+ MaskEditorList = gtk_tree_view_new();
+ gtk_tree_view_set_model(GTK_TREE_VIEW(MaskEditorList), GTK_TREE_MODEL(priv->scan_tag_masks_model));
+
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes(NULL,
+ renderer, "text", MASK_EDITOR_TEXT, NULL);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(MaskEditorList), column);
+ gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(MaskEditorList), FALSE);
+ gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(MaskEditorList)),
+ GTK_SELECTION_MULTIPLE);
+ gtk_tree_view_set_reorderable(GTK_TREE_VIEW(MaskEditorList), TRUE);
+ gtk_container_add(GTK_CONTAINER(MaskEditorScrollWindow), MaskEditorList);
+ g_signal_connect_after(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(MaskEditorList))),
+ "changed", G_CALLBACK(Mask_Editor_List_Row_Selected), NULL);
+ g_signal_connect(G_OBJECT(MaskEditorList), "key-press-event",
+ G_CALLBACK(Mask_Editor_List_Key_Press), NULL);
+ /* The entry */
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,2);
+ gtk_box_pack_start(GTK_BOX(MaskEditorVBox),hbox,FALSE,FALSE,0);
+ MaskEditorEntry = gtk_entry_new();
+ gtk_box_pack_start(GTK_BOX(hbox),MaskEditorEntry,TRUE,TRUE,2);
+ g_signal_connect(G_OBJECT(MaskEditorEntry),"changed",
+ G_CALLBACK(Mask_Editor_Entry_Changed),NULL);
+ // Mask status icon
+ // Signal connection to check if mask is correct into the mask entry
+ g_signal_connect (MaskEditorEntry,"changed",
+ G_CALLBACK (entry_check_scan_tag_mask), NULL);
+
+ /* The buttons part */
+ MaskEditorVBox = gtk_box_new(GTK_ORIENTATION_VERTICAL,0);
+ gtk_box_pack_start(GTK_BOX(MaskEditorHBox),MaskEditorVBox,FALSE,FALSE,0);
+
+ /* New mask button */
+ MaskEditorNewButton = gtk_button_new();
+ Icon = gtk_image_new_from_stock(GTK_STOCK_NEW, GTK_ICON_SIZE_SMALL_TOOLBAR);
+ gtk_container_add(GTK_CONTAINER(MaskEditorNewButton),Icon);
+ gtk_box_pack_start(GTK_BOX(MaskEditorVBox),MaskEditorNewButton,FALSE,FALSE,0);
+ gtk_button_set_relief(GTK_BUTTON(MaskEditorNewButton),GTK_RELIEF_NONE);
+ gtk_widget_set_tooltip_text(MaskEditorNewButton,_("Create New Mask"));
+ g_signal_connect(G_OBJECT(MaskEditorNewButton),"clicked",
+ G_CALLBACK(Mask_Editor_List_New),NULL);
+
+ /* Move up mask button */
+ MaskEditorUpButton = gtk_button_new();
+ Icon = gtk_image_new_from_stock(GTK_STOCK_GO_UP, GTK_ICON_SIZE_SMALL_TOOLBAR);
+ gtk_container_add(GTK_CONTAINER(MaskEditorUpButton),Icon);
+ gtk_box_pack_start(GTK_BOX(MaskEditorVBox),MaskEditorUpButton,FALSE,FALSE,0);
+ gtk_button_set_relief(GTK_BUTTON(MaskEditorUpButton),GTK_RELIEF_NONE);
+ gtk_widget_set_tooltip_text(MaskEditorUpButton,_("Move Up this Mask"));
+ g_signal_connect(G_OBJECT(MaskEditorUpButton),"clicked",
+ G_CALLBACK(Mask_Editor_List_Move_Up),NULL);
+
+ /* Move down mask button */
+ MaskEditorDownButton = gtk_button_new();
+ Icon = gtk_image_new_from_stock(GTK_STOCK_GO_DOWN, GTK_ICON_SIZE_SMALL_TOOLBAR);
+ gtk_container_add(GTK_CONTAINER(MaskEditorDownButton),Icon);
+ gtk_box_pack_start(GTK_BOX(MaskEditorVBox),MaskEditorDownButton,FALSE,FALSE,0);
+ gtk_button_set_relief(GTK_BUTTON(MaskEditorDownButton),GTK_RELIEF_NONE);
+ gtk_widget_set_tooltip_text(MaskEditorDownButton,_("Move Down this Mask"));
+ g_signal_connect(G_OBJECT(MaskEditorDownButton),"clicked",
+ G_CALLBACK(Mask_Editor_List_Move_Down),NULL);
+
+ /* Copy mask button */
+ MaskEditorCopyButton = gtk_button_new();
+ Icon = gtk_image_new_from_stock(GTK_STOCK_COPY, GTK_ICON_SIZE_SMALL_TOOLBAR);
+ gtk_container_add(GTK_CONTAINER(MaskEditorCopyButton),Icon);
+ gtk_box_pack_start(GTK_BOX(MaskEditorVBox),MaskEditorCopyButton,FALSE,FALSE,0);
+ gtk_button_set_relief(GTK_BUTTON(MaskEditorCopyButton),GTK_RELIEF_NONE);
+ gtk_widget_set_tooltip_text(MaskEditorCopyButton,_("Duplicate Mask"));
+ g_signal_connect(G_OBJECT(MaskEditorCopyButton),"clicked",
+ G_CALLBACK(Mask_Editor_List_Duplicate),NULL);
+
+ /* Add mask button */
+ MaskEditorAddButton = gtk_button_new();
+ Icon = gtk_image_new_from_stock(GTK_STOCK_ADD, GTK_ICON_SIZE_SMALL_TOOLBAR);
+ gtk_container_add(GTK_CONTAINER(MaskEditorAddButton),Icon);
+ gtk_box_pack_start(GTK_BOX(MaskEditorVBox),MaskEditorAddButton,FALSE,FALSE,0);
+ gtk_button_set_relief(GTK_BUTTON(MaskEditorAddButton),GTK_RELIEF_NONE);
+ gtk_widget_set_tooltip_text(MaskEditorAddButton,_("Add Default Masks"));
+ g_signal_connect(G_OBJECT(MaskEditorAddButton),"clicked",
+ G_CALLBACK(Mask_Editor_List_Add),NULL);
+
+ /* Remove mask button */
+ MaskEditorRemoveButton = gtk_button_new();
+ Icon = gtk_image_new_from_stock(GTK_STOCK_REMOVE, GTK_ICON_SIZE_SMALL_TOOLBAR);
+ gtk_container_add(GTK_CONTAINER(MaskEditorRemoveButton),Icon);
+ gtk_box_pack_start(GTK_BOX(MaskEditorVBox),MaskEditorRemoveButton,FALSE,FALSE,0);
+ gtk_button_set_relief(GTK_BUTTON(MaskEditorRemoveButton),GTK_RELIEF_NONE);
+ gtk_widget_set_tooltip_text(MaskEditorRemoveButton,_("Remove Mask"));
+ g_signal_connect(G_OBJECT(MaskEditorRemoveButton),"clicked",
+ G_CALLBACK(Mask_Editor_List_Remove),NULL);
+
+ /* Save mask button */
+ MaskEditorSaveButton = gtk_button_new();
+ Icon = gtk_image_new_from_stock(GTK_STOCK_SAVE, GTK_ICON_SIZE_SMALL_TOOLBAR);
+ gtk_container_add(GTK_CONTAINER(MaskEditorSaveButton),Icon);
+ gtk_box_pack_end(GTK_BOX(MaskEditorVBox),MaskEditorSaveButton,FALSE,FALSE,0);
+ gtk_button_set_relief(GTK_BUTTON(MaskEditorSaveButton),GTK_RELIEF_NONE);
+ gtk_widget_set_tooltip_text(MaskEditorSaveButton,_("Save Masks"));
+ g_signal_connect(G_OBJECT(MaskEditorSaveButton),"clicked",
+ G_CALLBACK(Mask_Editor_List_Save_Button),NULL);
+
+ /* To initialize the mask status icon and visibility */
+ g_signal_emit_by_name(G_OBJECT(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(ScanTagMaskCombo)))),"changed");
+ g_signal_emit_by_name(G_OBJECT(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(RenameFileMaskCombo)))),"changed");
+ g_signal_emit_by_name(G_OBJECT(MaskEditorEntry),"changed");
+ g_signal_emit_by_name(G_OBJECT(LegendButton),"toggled"); /* To hide legend frame */
+ g_signal_emit_by_name(G_OBJECT(MaskEditorButton),"toggled"); /* To hide mask editor frame */
+ g_signal_emit_by_name(G_OBJECT(ProcessFieldsConvert),"toggled");/* To enable / disable entries */
+ g_signal_emit_by_name(G_OBJECT(ProcessFieldsDetectRomanNumerals),"toggled");/* To enable / disable
entries */
+
+ gtk_widget_show_all (GTK_WIDGET (self));
+
+ /* Activate the current menu in the option menu. */
+ gtk_combo_box_set_active (GTK_COMBO_BOX (priv->type_combo),
+ SCANNER_TYPE);
+}
+
+/*
+ * Select the scanner to run for the current ETFile
+ */
+void
+Scan_Select_Mode_And_Run_Scanner (EtScanDialog *self, ET_File *ETFile)
+{
+ EtScanDialogPrivate *priv;
+ EtScanType mode;
+
+ g_return_if_fail (ET_SCAN_DIALOG (self));
+ g_return_if_fail (ETFile != NULL);
+
+ priv = et_scan_dialog_get_instance_private (self);
+ mode = gtk_combo_box_get_active (GTK_COMBO_BOX (priv->type_combo));
+
+ switch (mode)
+ {
+ case ET_SCAN_TYPE_FILL_TAG:
+ Scan_Tag_With_Mask (self, ETFile);
+ break;
+ case ET_SCAN_TYPE_RENAME_FILE:
+ Scan_Rename_File_With_Mask (self, ETFile);
+ break;
+ case ET_SCAN_TYPE_PROCESS_FIELDS:
+ Scan_Process_Fields (self, ETFile);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+/*
+ * For the configuration file...
+ */
+void
+et_scan_dialog_apply_changes (EtScanDialog *self)
+{
+ EtScanDialogPrivate *priv;
+
+ g_return_if_fail (ET_SCAN_DIALOG (self));
+
+ priv = et_scan_dialog_get_instance_private (self);
+
+ /* The selected scanner type. */
+ SCANNER_TYPE = gtk_combo_box_get_active(GTK_COMBO_BOX(priv->type_combo));
+
+ SCAN_MASK_EDITOR_BUTTON = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(MaskEditorButton));
+ SCAN_LEGEND_BUTTON = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(LegendButton));
+
+ /* Group: select entries to process */
+ PROCESS_FILENAME_FIELD = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFileNameField));
+ PROCESS_TITLE_FIELD = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessTitleField));
+ PROCESS_ARTIST_FIELD = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessArtistField));
+ PROCESS_ALBUM_ARTIST_FIELD= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessAlbumArtistField));
+ PROCESS_ALBUM_FIELD = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessAlbumField));
+ PROCESS_GENRE_FIELD = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessGenreField));
+ PROCESS_COMMENT_FIELD = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessCommentField));
+ PROCESS_COMPOSER_FIELD = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessComposerField));
+ PROCESS_ORIG_ARTIST_FIELD = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessOrigArtistField));
+ PROCESS_COPYRIGHT_FIELD = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessCopyrightField));
+ PROCESS_URL_FIELD = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessURLField));
+ PROCESS_ENCODED_BY_FIELD = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessEncodedByField));
+
+ if (PROCESS_FIELDS_CONVERT_FROM) g_free(PROCESS_FIELDS_CONVERT_FROM);
+ PROCESS_FIELDS_CONVERT_FROM = g_strdup(gtk_entry_get_text(GTK_ENTRY(ProcessFieldsConvertFrom)));
+ if (PROCESS_FIELDS_CONVERT_TO) g_free(PROCESS_FIELDS_CONVERT_TO);
+ PROCESS_FIELDS_CONVERT_TO = g_strdup(gtk_entry_get_text(GTK_ENTRY(ProcessFieldsConvertTo)));
+
+ /* Group: convert one character */
+ PF_CONVERT_INTO_SPACE =
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsConvertIntoSpace));
+ PF_CONVERT_SPACE = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsConvertSpace));
+ PF_CONVERT = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsConvert));
+
+ /* Group: capitalize */
+ PF_CONVERT_ALL_UPPERCASE =
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsAllUppercase));
+ PF_CONVERT_ALL_DOWNCASE =
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsAllDowncase));
+ PF_CONVERT_FIRST_LETTER_UPPERCASE =
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsFirstLetterUppercase));
+ PF_CONVERT_FIRST_LETTERS_UPPERCASE =
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsFirstLettersUppercase));
+ PF_DETECT_ROMAN_NUMERALS =
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsDetectRomanNumerals));
+
+ /* Group: remove/insert space */
+ PF_REMOVE_SPACE = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsRemoveSpace));
+ PF_INSERT_SPACE = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsInsertSpace));
+ PF_ONLY_ONE_SPACE = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsOnlyOneSpace));
+
+ // Save default masks...
+ if (SCAN_TAG_DEFAULT_MASK) g_free(SCAN_TAG_DEFAULT_MASK);
+ SCAN_TAG_DEFAULT_MASK =
g_strdup(gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(ScanTagMaskCombo)))));
+ Add_String_To_Combo_List(priv->scan_tag_masks_model, SCAN_TAG_DEFAULT_MASK);
+ Save_Rename_File_Masks_List(priv->scan_tag_masks_model, MASK_EDITOR_TEXT);
+
+ if (RENAME_FILE_DEFAULT_MASK) g_free(RENAME_FILE_DEFAULT_MASK);
+ RENAME_FILE_DEFAULT_MASK =
g_strdup(gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(RenameFileMaskCombo)))));
+ Add_String_To_Combo_List(priv->rename_masks_model, RENAME_FILE_DEFAULT_MASK);
+ Save_Rename_File_Masks_List(priv->rename_masks_model, MASK_EDITOR_TEXT);
+}
+
+
+/* Callback from Option button */
+static void
+Scan_Option_Button (void)
+{
+ et_application_window_show_preferences_dialog (NULL, ET_APPLICATION_WINDOW (MainWindow));
+ gtk_notebook_set_current_page(GTK_NOTEBOOK(OptionsNoteBook), OptionsNoteBook_Scanner_Page_Num);
+}
+
+
+/*
+ * entry_check_rename_file_mask:
+ * @entry: the entry for which to check the mask
+ * @user_data: user data set when the signal was connected
+ *
+ * Display an icon in the entry if the current text contains an invalid mask
+ * for scanning tags.
+ */
+static void
+entry_check_scan_tag_mask (GtkEntry *entry, gpointer user_data)
+{
+ gchar *tmp = NULL;
+ gchar *mask = NULL;
+ gint loop = 0;
+
+ g_return_if_fail (entry != NULL);
+
+ mask = g_strdup (gtk_entry_get_text (entry));
+ if (!mask || strlen(mask)<1)
+ goto Bad_Mask;
+
+ while (mask)
+ {
+ if ( (tmp=strrchr(mask,'%'))==NULL )
+ {
+ if (loop==0)
+ /* There is no code the first time => not accepted */
+ goto Bad_Mask;
+ else
+ /* There is no more code => accepted */
+ goto Good_Mask;
+ }
+ if ( strlen(tmp)>1
+ && (tmp[1]=='a' || tmp[1]=='b' || tmp[1]=='c' || tmp[1]=='d' || tmp[1]=='p' ||
+ tmp[1]=='r' || tmp[1]=='e' || tmp[1]=='g' || tmp[1]=='i' || tmp[1]=='l' ||
+ tmp[1]=='o' || tmp[1]=='n' || tmp[1]=='t' || tmp[1]=='u' || tmp[1]=='y' ) )
+ {
+ /* Code is correct */
+ *(mask+strlen(mask)-strlen(tmp)) = '\0';
+ }else
+ {
+ goto Bad_Mask;
+ }
+
+ /* Check the following code and separator */
+ if ( (tmp=strrchr(mask,'%'))==NULL )
+ /* There is no more code => accepted */
+ goto Good_Mask;
+
+ if ( strlen(tmp)>2
+ && (tmp[1]=='a' || tmp[1]=='b' || tmp[1]=='c' || tmp[1]=='d' || tmp[1]=='p' ||
+ tmp[1]=='r' || tmp[1]=='e' || tmp[1]=='g' || tmp[1]=='i' || tmp[1]=='l' ||
+ tmp[1]=='o' || tmp[1]=='n' || tmp[1]=='t' || tmp[1]=='u' || tmp[1]=='y' ) )
+ {
+ /* There is a separator and code is correct */
+ *(mask+strlen(mask)-strlen(tmp)) = '\0';
+ }else
+ {
+ goto Bad_Mask;
+ }
+ loop++;
+ }
+
+ Bad_Mask:
+ g_free(mask);
+ gtk_entry_set_icon_from_icon_name (entry, GTK_ENTRY_ICON_SECONDARY,
+ "emblem-unreadable");
+ gtk_entry_set_icon_tooltip_text (entry, GTK_ENTRY_ICON_SECONDARY,
+ _("Invalid scanner mask"));
+ return;
+
+ Good_Mask:
+ g_free(mask);
+ gtk_entry_set_icon_from_icon_name (entry, GTK_ENTRY_ICON_SECONDARY,
+ NULL);
+}
+
+/*
+ * entry_check_rename_file_mask:
+ * @entry: the entry for which to check the mask
+ * @user_data: user data set when the signal was connected
+ *
+ * Display an icon in the entry if the current text contains an invalid mask
+ * for renaming files.
+ */
+void
+entry_check_rename_file_mask (GtkEntry *entry, gpointer user_data)
+{
+ gchar *tmp = NULL;
+ gchar *mask = NULL;
+
+ g_return_if_fail (entry != NULL);
+
+ mask = g_strdup (gtk_entry_get_text (entry));
+ if (!mask || strlen(mask)<1)
+ goto Bad_Mask;
+
+ // Not a valid path....
+ if ( strstr(mask,"//") != NULL
+ || strstr(mask,"./") != NULL
+ || strstr(mask,"data/") != NULL)
+ goto Bad_Mask;
+
+ while (mask)
+ {
+ if ( (tmp=strrchr(mask,'%'))==NULL )
+ {
+ /* There is no more code. */
+ /* No code in mask is accepted. */
+ goto Good_Mask;
+ }
+ if ( strlen(tmp)>1
+ && (tmp[1]=='a' || tmp[1]=='b' || tmp[1]=='c' || tmp[1]=='d' || tmp[1]=='p' ||
+ tmp[1]=='r' || tmp[1]=='e' || tmp[1]=='g' || tmp[1]=='i' || tmp[1]=='l' ||
+ tmp[1]=='o' || tmp[1]=='n' || tmp[1]=='t' || tmp[1]=='u' || tmp[1]=='y' ) )
+ {
+ /* The code is valid. */
+ /* No separator is accepted. */
+ *(mask+strlen(mask)-strlen(tmp)) = '\0';
+ }else
+ {
+ goto Bad_Mask;
+ }
+ }
+
+ Bad_Mask:
+ g_free(mask);
+ gtk_entry_set_icon_from_icon_name (entry, GTK_ENTRY_ICON_SECONDARY,
+ "emblem-unreadable");
+ gtk_entry_set_icon_tooltip_text (entry, GTK_ENTRY_ICON_SECONDARY,
+ _("Invalid scanner mask"));
+ return;
+
+ Good_Mask:
+ g_free(mask);
+ gtk_entry_set_icon_from_icon_name (entry, GTK_ENTRY_ICON_SECONDARY,
+ NULL);
+}
+
+
+static void
+Scan_Toggle_Legend_Button (void)
+{
+ g_return_if_fail (LegendButton != NULL || LegendFrame != NULL);
+
+ if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(LegendButton)) )
+ gtk_widget_show_all(LegendFrame);
+ else
+ gtk_widget_hide(LegendFrame);
+}
+
+
+static void
+Scan_Toggle_Mask_Editor_Button (void)
+{
+ GtkTreeModel *treemodel;
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
+
+ g_return_if_fail (MaskEditorButton != NULL || MaskEditorFrame != NULL ||
+ MaskEditorList != NULL);
+
+ if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(MaskEditorButton)) )
+ {
+ gtk_widget_show_all(MaskEditorFrame);
+
+ // Select first row in list
+ treemodel = gtk_tree_view_get_model(GTK_TREE_VIEW(MaskEditorList));
+ if (gtk_tree_model_get_iter_first(treemodel, &iter))
+ {
+ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(MaskEditorList));
+ gtk_tree_selection_unselect_all(selection);
+ gtk_tree_selection_select_iter(selection, &iter);
+ }
+
+ // Update status of the icon box cause prev instruction show it for all cases
+ g_signal_emit_by_name(G_OBJECT(MaskEditorEntry),"changed");
+ }else
+ {
+ gtk_widget_hide(MaskEditorFrame);
+ }
+}
+
+
+
+static void
+Process_Fields_Convert_Check_Button_Toggled (GtkWidget *object)
+{
+
gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsConvertTo),gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(object)));
+
gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsConvertFrom),gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(object)));
+}
+
+static void
+Process_Fields_First_Letters_Check_Button_Toggled (GtkWidget *object)
+{
+
gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsDetectRomanNumerals),gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(object)));
+}
+
+
+/*
+ * Small buttons of Process Fields scanner
+ */
+static void
+Select_Fields_Invert_Selection (void)
+{
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessFileNameField),
+ !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFileNameField)));
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessTitleField),
+ !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessTitleField)));
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessArtistField),
+ !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessArtistField)));
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessAlbumArtistField),
+ !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessAlbumArtistField)));
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessAlbumField),
+ !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessAlbumField)));
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessGenreField),
+ !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessGenreField)));
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessCommentField),
+ !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessCommentField)));
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessComposerField),
+ !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessComposerField)));
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessOrigArtistField),
+ !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessOrigArtistField)));
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessCopyrightField),
+ !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessCopyrightField)));
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessURLField),
+ !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessURLField)));
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessEncodedByField),
+ !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessEncodedByField)));
+}
+
+static void
+Select_Fields_Select_Unselect_All (void)
+{
+ static gboolean state = TRUE;
+
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessFileNameField), state);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessTitleField), state);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessArtistField), state);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessAlbumArtistField),state);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessAlbumField), state);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessGenreField), state);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessCommentField), state);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessComposerField), state);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessOrigArtistField), state);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessCopyrightField), state);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessURLField), state);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessEncodedByField), state);
+ state = !state;
+}
+
+/*
+ * Set sensitive state of the processing check boxes : if no one is selected => all disabled
+ */
+static void
+Select_Fields_Set_Sensitive (void)
+{
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFileNameField))
+ || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessTitleField))
+ || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessArtistField))
+ || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessAlbumArtistField))
+ || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessAlbumField))
+ || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessGenreField))
+ || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessCommentField))
+ || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessComposerField))
+ || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessOrigArtistField))
+ || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessCopyrightField))
+ || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessURLField))
+ || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessEncodedByField)))
+ {
+ gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsConvertIntoSpace), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsConvertSpace), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsConvert), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsConvertLabelTo), TRUE);
+ // Activate the two entries only if the check box is activated, else keep them disabled
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ProcessFieldsConvert)))
+ {
+ gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsConvertTo), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsConvertFrom), TRUE);
+ }
+ gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsAllUppercase), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsAllDowncase), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsFirstLetterUppercase), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsFirstLettersUppercase),TRUE);
+ Process_Fields_First_Letters_Check_Button_Toggled (ProcessFieldsFirstLettersUppercase);
+ gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsRemoveSpace), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsInsertSpace), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsOnlyOneSpace), TRUE);
+ }else
+ {
+ gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsConvertIntoSpace), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsConvertSpace), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsConvert), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsConvertTo), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsConvertLabelTo), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsConvertFrom), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsAllUppercase), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsAllDowncase), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsFirstLetterUppercase), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsFirstLettersUppercase),FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsDetectRomanNumerals), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsRemoveSpace), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsInsertSpace), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsOnlyOneSpace), FALSE);
+ }
+}
+
+/*
+ * Callbacks from Mask Editor buttons
+ */
+
+/*
+ * Callback from the mask edit list
+ * Previously known as Mask_Editor_List_Select_Row
+ */
+static void
+Mask_Editor_List_Row_Selected (GtkTreeSelection* selection, gpointer data)
+{
+ GList *selectedRows;
+ gchar *text = NULL;
+ GtkTreePath *lastSelected;
+ GtkTreeIter lastFile;
+ GtkTreeModel *treemodel;
+ gboolean valid;
+
+ treemodel = gtk_tree_view_get_model(GTK_TREE_VIEW(MaskEditorList));
+
+ /* We must block the function, else the previous selected row will be modified */
+ g_signal_handlers_block_by_func(G_OBJECT(MaskEditorEntry),
+ G_CALLBACK(Mask_Editor_Entry_Changed),NULL);
+
+ selectedRows = gtk_tree_selection_get_selected_rows(selection, NULL);
+
+ /*
+ * At some point, we might get called when no rows are selected?
+ */
+ if (!selectedRows)
+ {
+ g_signal_handlers_unblock_by_func(G_OBJECT(MaskEditorEntry),
+ G_CALLBACK(Mask_Editor_Entry_Changed),NULL);
+ return;
+ }
+
+ /* Get the text of the last selected row */
+ lastSelected = (GtkTreePath *)g_list_last(selectedRows)->data;
+
+ valid= gtk_tree_model_get_iter(treemodel, &lastFile, lastSelected);
+ if (valid)
+ {
+ gtk_tree_model_get(treemodel, &lastFile, MASK_EDITOR_TEXT, &text, -1);
+
+ if (text)
+ {
+ gtk_entry_set_text(GTK_ENTRY(MaskEditorEntry),text);
+ g_free(text);
+ }
+ }
+
+ g_signal_handlers_unblock_by_func(G_OBJECT(MaskEditorEntry),
+ G_CALLBACK(Mask_Editor_Entry_Changed),NULL);
+
+ g_list_free_full (selectedRows, (GDestroyNotify)gtk_tree_path_free);
+}
+
+
+/*
+ * Add a new mask to the list
+ */
+static void
+Mask_Editor_List_New (void)
+{
+ gchar *text = _("New_mask");
+ GtkTreeIter iter;
+ GtkTreeSelection *selection;
+ GtkTreeModel *treemodel;
+
+ g_return_if_fail (MaskEditorList != NULL);
+
+ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(MaskEditorList));
+ treemodel = gtk_tree_view_get_model(GTK_TREE_VIEW(MaskEditorList));
+
+ gtk_list_store_insert(GTK_LIST_STORE(treemodel), &iter, 0);
+ gtk_list_store_set(GTK_LIST_STORE(treemodel), &iter, MASK_EDITOR_TEXT, text, -1);
+
+ gtk_tree_selection_unselect_all(selection);
+ gtk_tree_selection_select_iter(selection, &iter);
+}
+
+/*
+ * Duplicate a mask on the list
+ */
+static void
+Mask_Editor_List_Duplicate (void)
+{
+ gchar *text = NULL;
+ GList *selectedRows;
+ GList *l;
+ GList *toInsert = NULL;
+ GtkTreeSelection *selection;
+ GtkTreeIter rowIter;
+ GtkTreeModel *treeModel;
+
+ g_return_if_fail (MaskEditorList != NULL);
+
+ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(MaskEditorList));
+ selectedRows = gtk_tree_selection_get_selected_rows(selection, NULL);
+ treeModel = gtk_tree_view_get_model(GTK_TREE_VIEW(MaskEditorList));
+
+ if (!selectedRows)
+ {
+ Log_Print(LOG_ERROR,_("Copy: No row selected"));
+ return;
+ }
+
+ /* Loop through selected rows, duplicating them into a GList
+ * We cannot directly insert because the paths in selectedRows
+ * get out of date after an insertion */
+ for (l = selectedRows; l != NULL; l = g_list_next (l))
+ {
+ if (gtk_tree_model_get_iter (treeModel, &rowIter,
+ (GtkTreePath*)l->data))
+ {
+ gtk_tree_model_get(treeModel, &rowIter, MASK_EDITOR_TEXT, &text, -1);
+ toInsert = g_list_prepend (toInsert, text);
+ }
+ }
+
+ for (l = toInsert; l != NULL; l = g_list_next (l))
+ {
+ gtk_list_store_insert_with_values (GTK_LIST_STORE(treeModel), &rowIter,
+ 0, MASK_EDITOR_TEXT,
+ (gchar *)l->data, -1);
+ }
+
+ // Set focus to the last inserted line
+ if (toInsert)
+ Mask_Editor_List_Set_Row_Visible(treeModel,&rowIter);
+
+ /* Free data no longer needed */
+ g_list_free_full (selectedRows, (GDestroyNotify)gtk_tree_path_free);
+ g_list_free_full (toInsert, (GDestroyNotify)g_free);
+}
+
+/*
+ * Remove the selected rows from the mask editor list
+ */
+static void
+Mask_Editor_List_Remove (void)
+{
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
+ GtkTreeModel *treemodel;
+
+ g_return_if_fail (MaskEditorList != NULL);
+
+ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(MaskEditorList));
+ treemodel = gtk_tree_view_get_model(GTK_TREE_VIEW(MaskEditorList));
+
+ if (gtk_tree_selection_count_selected_rows(selection) == 0) {
+ Log_Print(LOG_ERROR,_("Remove: No row selected"));
+ return;
+ }
+
+ if (!gtk_tree_model_get_iter_first(treemodel, &iter))
+ return;
+
+ while (TRUE)
+ {
+ if (gtk_tree_selection_iter_is_selected(selection, &iter))
+ {
+ if (!gtk_list_store_remove(GTK_LIST_STORE(treemodel), &iter))
+ {
+ break;
+ }
+ } else
+ {
+ if (!gtk_tree_model_iter_next(treemodel, &iter))
+ {
+ break;
+ }
+ }
+ }
+}
+
+/*
+ * Move all selected rows up one place in the mask list
+ */
+static void
+Mask_Editor_List_Move_Up (void)
+{
+ GtkTreeSelection *selection;
+ GList *selectedRows;
+ GList *l;
+ GtkTreeIter currentFile;
+ GtkTreeIter nextFile;
+ GtkTreePath *currentPath;
+ GtkTreeModel *treemodel;
+
+ g_return_if_fail (MaskEditorList != NULL);
+
+ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(MaskEditorList));
+ treemodel = gtk_tree_view_get_model(GTK_TREE_VIEW(MaskEditorList));
+ selectedRows = gtk_tree_selection_get_selected_rows(selection, NULL);
+
+ if (!selectedRows)
+ {
+ Log_Print(LOG_ERROR,_("Move Up: No row selected"));
+ return;
+ }
+
+ for (l = selectedRows; l != NULL; l = g_list_next (l))
+ {
+ currentPath = (GtkTreePath *)l->data;
+ if (gtk_tree_model_get_iter(treemodel, ¤tFile, currentPath))
+ {
+ /* Find the entry above the node... */
+ if (gtk_tree_path_prev(currentPath))
+ {
+ /* ...and if it exists, swap the two rows by iter */
+ gtk_tree_model_get_iter(treemodel, &nextFile, currentPath);
+ gtk_list_store_swap(GTK_LIST_STORE(treemodel), ¤tFile, &nextFile);
+ }
+ }
+ }
+
+ g_list_free_full (selectedRows, (GDestroyNotify)gtk_tree_path_free);
+}
+
+/*
+ * Move all selected rows down one place in the mask list
+ */
+static void
+Mask_Editor_List_Move_Down (void)
+{
+ GtkTreeSelection *selection;
+ GList *selectedRows;
+ GList *l;
+ GtkTreeIter currentFile;
+ GtkTreeIter nextFile;
+ GtkTreePath *currentPath;
+ GtkTreeModel *treemodel;
+
+ g_return_if_fail (MaskEditorList != NULL);
+
+ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(MaskEditorList));
+ treemodel = gtk_tree_view_get_model(GTK_TREE_VIEW(MaskEditorList));
+ selectedRows = gtk_tree_selection_get_selected_rows(selection, NULL);
+
+ if (!selectedRows)
+ {
+ Log_Print(LOG_ERROR,_("Move Down: No row selected"));
+ return;
+ }
+
+ for (l = selectedRows; l != NULL; l = g_list_next (l))
+ {
+ currentPath = (GtkTreePath *)l->data;
+
+ if (gtk_tree_model_get_iter(treemodel, ¤tFile, currentPath))
+ {
+ /* Find the entry below the node and swap the two nodes by iter */
+ gtk_tree_path_next(currentPath);
+ if (gtk_tree_model_get_iter(treemodel, &nextFile, currentPath))
+ gtk_list_store_swap(GTK_LIST_STORE(treemodel), ¤tFile, &nextFile);
+ }
+ }
+
+ g_list_free_full (selectedRows, (GDestroyNotify)gtk_tree_path_free);
+}
+
+/*
+ * Set a row visible in the mask editor list (by scrolling the list)
+ */
+static void
+Mask_Editor_List_Set_Row_Visible (GtkTreeModel *treeModel, GtkTreeIter *rowIter)
+{
+ /*
+ * TODO: Make this only scroll to the row if it is not visible
+ * (like in easytag GTK1)
+ * See function gtk_tree_view_get_visible_rect() ??
+ */
+ GtkTreePath *rowPath;
+
+ g_return_if_fail (treeModel != NULL);
+
+ rowPath = gtk_tree_model_get_path(treeModel, rowIter);
+ gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(MaskEditorList), rowPath, NULL, FALSE, 0, 0);
+ gtk_tree_path_free(rowPath);
+}
+
+/*
+ * Clean up the currently displayed masks lists, ready for saving
+ */
+static void
+Mask_Editor_Clean_Up_Masks_List (void)
+{
+ gchar *text = NULL;
+ gchar *text1 = NULL;
+ GtkTreeIter currentIter;
+ GtkTreeIter itercopy;
+ GtkTreeModel *treemodel;
+
+ treemodel = gtk_tree_view_get_model(GTK_TREE_VIEW(MaskEditorList));
+
+ /* Remove blank and duplicate items */
+ if (gtk_tree_model_get_iter_first(treemodel, ¤tIter))
+ {
+
+ while(TRUE)
+ {
+ gtk_tree_model_get(treemodel, ¤tIter, MASK_EDITOR_TEXT, &text, -1);
+
+ /* Check for blank entry */
+ if (text && g_utf8_strlen(text, -1) == 0)
+ {
+ g_free(text);
+
+ if (!gtk_list_store_remove(GTK_LIST_STORE(treemodel), ¤tIter))
+ break; /* No following entries */
+ else
+ continue; /* Go on to next entry, which the remove function already moved onto for us */
+ }
+
+ /* Check for duplicate entries */
+ itercopy = currentIter;
+ if (!gtk_tree_model_iter_next(treemodel, &itercopy))
+ {
+ g_free(text);
+ break;
+ }
+
+ while(TRUE)
+ {
+ gtk_tree_model_get(treemodel, &itercopy, MASK_EDITOR_TEXT, &text1, -1);
+ if (text1 && g_utf8_collate(text,text1) == 0)
+ {
+ g_free(text1);
+
+ if (!gtk_list_store_remove(GTK_LIST_STORE(treemodel), &itercopy))
+ break; /* No following entries */
+ else
+ continue; /* Go on to next entry, which the remove function already set iter to for
us */
+
+ }
+ g_free(text1);
+ if (!gtk_tree_model_iter_next(treemodel, &itercopy))
+ break;
+ }
+
+ g_free(text);
+
+ if (!gtk_tree_model_iter_next(treemodel, ¤tIter))
+ break;
+ }
+ }
+}
+
+/*
+ * Update the Mask List with the new value of the entry box
+ */
+static void
+Mask_Editor_Entry_Changed (void)
+{
+ GtkTreeSelection *selection;
+ GtkTreePath *firstSelected;
+ GtkTreeModel *treemodel;
+ GList *selectedRows;
+ GtkTreeIter row;
+ const gchar* text;
+
+ g_return_if_fail (MaskEditorList != NULL);
+
+ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(MaskEditorList));
+ treemodel = gtk_tree_view_get_model(GTK_TREE_VIEW(MaskEditorList));
+ selectedRows = gtk_tree_selection_get_selected_rows(selection, NULL);
+
+ if (!selectedRows)
+ {
+ return;
+ }
+
+ firstSelected = (GtkTreePath *)g_list_first(selectedRows)->data;
+ text = gtk_entry_get_text(GTK_ENTRY(MaskEditorEntry));
+
+ if (gtk_tree_model_get_iter (treemodel, &row, firstSelected))
+ {
+ gtk_list_store_set(GTK_LIST_STORE(treemodel), &row, MASK_EDITOR_TEXT, text, -1);
+ }
+
+ g_list_free_full (selectedRows, (GDestroyNotify)gtk_tree_path_free);
+}
+
+/*
+ * Actions when the a key is pressed into the masks editor clist
+ */
+static gboolean
+Mask_Editor_List_Key_Press (GtkWidget *widget, GdkEvent *event)
+{
+ if (event && event->type == GDK_KEY_PRESS) {
+ GdkEventKey *kevent = (GdkEventKey *)event;
+
+ switch(kevent->keyval)
+ {
+ case GDK_KEY_Delete:
+ Mask_Editor_List_Remove();
+ break;
+/* case GDK_KEY_Up:
+ Mask_Editor_Clist_Move_Up();
+ break;
+ case GDK_KEY_Down:
+ Mask_Editor_Clist_Move_Down();
+ break;
+*/ }
+ }
+ return TRUE;
+}
+
+void
+et_scan_dialog_scan_selected_files (EtScanDialog *self)
+{
+ gint progress_bar_index;
+ gint selectcount;
+ gchar progress_bar_text[30];
+ double fraction;
+ GList *selfilelist = NULL;
+ GList *l;
+ ET_File *etfile;
+ GtkTreeSelection *selection;
+
+ g_return_if_fail (ETCore->ETFileDisplayedList != NULL ||
+ BrowserList != NULL);
+
+ /* Save the current displayed data */
+ ET_Save_File_Data_From_UI(ETCore->ETFileDisplayed);
+
+ /* Initialize status bar */
+ selectcount =
gtk_tree_selection_count_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(BrowserList)));
+ gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(ProgressBar),0);
+ progress_bar_index = 0;
+ g_snprintf(progress_bar_text, 30, "%d/%d", progress_bar_index, selectcount);
+ gtk_progress_bar_set_text(GTK_PROGRESS_BAR(ProgressBar), progress_bar_text);
+
+ /* Set to unsensitive all command buttons (except Quit button) */
+ Disable_Command_Buttons();
+
+ progress_bar_index = 0;
+
+ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(BrowserList));
+ selfilelist = gtk_tree_selection_get_selected_rows(selection, NULL);
+
+ for (l = selfilelist; l != NULL; l = g_list_next (l))
+ {
+ etfile = Browser_List_Get_ETFile_From_Path (l->data);
+
+ /* Run the current scanner. */
+ Scan_Select_Mode_And_Run_Scanner (self, etfile);
+
+ fraction = (++progress_bar_index) / (double) selectcount;
+ gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(ProgressBar), fraction);
+ g_snprintf(progress_bar_text, 30, "%d/%d", progress_bar_index, selectcount);
+ gtk_progress_bar_set_text(GTK_PROGRESS_BAR(ProgressBar), progress_bar_text);
+
+ /* Needed to refresh status bar */
+ while (gtk_events_pending())
+ gtk_main_iteration();
+ }
+
+ g_list_free_full (selfilelist, (GDestroyNotify)gtk_tree_path_free);
+
+ // Refresh the whole list (faster than file by file) to show changes
+ Browser_List_Refresh_Whole_List();
+
+ /* Display the current file */
+ ET_Display_File_Data_To_UI(ETCore->ETFileDisplayed);
+
+ /* To update state of command buttons */
+ Update_Command_Buttons_Sensivity();
+
+ gtk_progress_bar_set_text(GTK_PROGRESS_BAR(ProgressBar), "");
+ gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(ProgressBar), 0);
+ Statusbar_Message(_("All tags have been scanned"),TRUE);
+}
+
+/*
+ * et_scan_on_response:
+ * @dialog: the scanner window
+ * @response_id: the #GtkResponseType corresponding to the dialog event
+ * @user_data: user data set when the signal was connected
+ *
+ * Handle the response signal of the scanner dialog.
+ */
+static void
+et_scan_on_response (GtkDialog *dialog, gint response_id, gpointer user_data)
+{
+ switch (response_id)
+ {
+ case GTK_RESPONSE_APPLY:
+ et_scan_dialog_scan_selected_files (ET_SCAN_DIALOG (dialog));
+ break;
+ case GTK_RESPONSE_CLOSE:
+ gtk_widget_hide (GTK_WIDGET (dialog));
+ break;
+ case GTK_RESPONSE_DELETE_EVENT:
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+
+static void
+et_scan_dialog_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (et_scan_dialog_parent_class)->finalize (object);
+}
+
+static void
+et_scan_dialog_init (EtScanDialog *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, ET_TYPE_SCAN_DIALOG,
+ EtScanDialogPrivate);
+
+ create_scan_dialog (self);
+}
+
+static void
+et_scan_dialog_class_init (EtScanDialogClass *klass)
+{
+ G_OBJECT_CLASS (klass)->finalize = et_scan_dialog_finalize;
+
+ g_type_class_add_private (klass, sizeof (EtScanDialogPrivate));
+}
+
+/*
+ * et_preferences_dialog_new:
+ *
+ * Create a new EtScanDialog instance.
+ *
+ * Returns: a new #EtScanDialog
+ */
+EtScanDialog *
+et_scan_dialog_new (void)
+{
+ return g_object_new (ET_TYPE_SCAN_DIALOG, NULL);
+}
diff --git a/src/scan_dialog.h b/src/scan_dialog.h
new file mode 100644
index 0000000..04b88c4
--- /dev/null
+++ b/src/scan_dialog.h
@@ -0,0 +1,94 @@
+/*
+ * EasyTAG - Tag editor for MP3 and Ogg Vorbis files
+ * Copyright (C) 2000-2003 Jerome Couderc <easytag gmail com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef ET_SCAN_DIALOG_H_
+#define ET_SCAN_DIALOG_H_
+
+#include "et_core.h"
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define ET_TYPE_SCAN_DIALOG (et_scan_dialog_get_type ())
+#define ET_SCAN_DIALOG(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), ET_TYPE_SCAN_DIALOG, EtScanDialog))
+
+typedef struct _EtScanDialog EtScanDialog;
+typedef struct _EtScanDialogClass EtScanDialogClass;
+typedef struct _EtScanDialogPrivate EtScanDialogPrivate;
+
+struct _EtScanDialog
+{
+ /*< private >*/
+ GtkDialog parent_instance;
+ EtScanDialogPrivate *priv;
+};
+
+struct _EtScanDialogClass
+{
+ /*< private >*/
+ GtkDialogClass parent_class;
+};
+
+/*
+ * The mode for the scanner window.
+ */
+typedef enum
+{
+ ET_SCAN_TYPE_FILL_TAG,
+ ET_SCAN_TYPE_RENAME_FILE,
+ ET_SCAN_TYPE_PROCESS_FIELDS
+} EtScanType;
+
+GType et_scan_dialog_get_type (void);
+EtScanDialog *et_scan_dialog_new (void);
+void et_scan_dialog_apply_changes (EtScanDialog *self);
+void et_scan_dialog_open (EtScanDialog *self, EtScanType scanner_type);
+void et_scan_dialog_scan_selected_files (EtScanDialog *self);
+void et_scan_dialog_update_previews (EtScanDialog *self);
+
+G_END_DECLS
+
+
+/****************
+ * Declarations *
+ ****************/
+
+enum {
+ MASK_EDITOR_TEXT,
+ MASK_EDITOR_COUNT
+};
+
+
+
+/**************
+ * Prototypes *
+ **************/
+
+void Scan_Select_Mode_And_Run_Scanner (EtScanDialog *self, ET_File *ETFile);
+gchar *Scan_Generate_New_Filename_From_Mask (ET_File *ETFile, gchar *mask, gboolean
no_dir_check_or_conversion);
+gchar *Scan_Generate_New_Directory_Name_From_Mask (ET_File *ETFile, gchar *mask, gboolean
no_dir_check_or_conversion);
+void Scan_Rename_Directory_Generate_Preview (void);
+
+void entry_check_rename_file_mask (GtkEntry *entry, gpointer user_data);
+
+void Scan_Process_Fields_First_Letters_Uppercase (EtScanDialog *self, gchar *string);
+
+#endif /* ET_SCAN_DIALOG_H_ */
diff --git a/src/search_dialog.c b/src/search_dialog.c
index cd4ac72..91c5259 100644
--- a/src/search_dialog.c
+++ b/src/search_dialog.c
@@ -30,7 +30,7 @@
#include "log.h"
#include "misc.h"
#include "picture.h"
-#include "scan.h"
+#include "scan_dialog.h"
#include "setting.h"
/* TODO: Use G_DEFINE_TYPE_WITH_PRIVATE. */
diff --git a/src/setting.c b/src/setting.c
index 2ccff23..534e9be 100644
--- a/src/setting.c
+++ b/src/setting.c
@@ -41,7 +41,7 @@
#include "bar.h"
#include "easytag.h"
#include "charset.h"
-#include "scan.h"
+#include "scan_dialog.h"
#include "log.h"
#include "misc.h"
#include "browser.h"
@@ -192,9 +192,6 @@ static const tConfigVariable Config_Variables[] =
{"default_comment", CV_TYPE_STRING, &DEFAULT_COMMENT },
{"crc32_comment", CV_TYPE_BOOL, &SET_CRC32_COMMENT },
{"open_scanner_window_on_startup", CV_TYPE_BOOL, &OPEN_SCANNER_WINDOW_ON_STARTUP },
- {"set_scanner_window_position", CV_TYPE_BOOL, &SET_SCANNER_WINDOW_POSITION },
- {"scanner_window_x", CV_TYPE_INT, &SCANNER_WINDOW_X },
- {"scanner_window_y", CV_TYPE_INT, &SCANNER_WINDOW_Y },
{"confirm_before_exit", CV_TYPE_BOOL, &CONFIRM_BEFORE_EXIT },
{"confirm_write_tag", CV_TYPE_BOOL, &CONFIRM_WRITE_TAG },
@@ -422,7 +419,7 @@ void Init_Config_Variables (void)
/*
* Scanner
*/
- SCANNER_TYPE = SCANNER_FILL_TAG;
+ SCANNER_TYPE = ET_SCAN_TYPE_FILL_TAG;
SCAN_MASK_EDITOR_BUTTON = 0;
SCAN_LEGEND_BUTTON = 0;
FTS_CONVERT_UNDERSCORE_AND_P20_INTO_SPACE = 1;
@@ -435,9 +432,6 @@ void Init_Config_Variables (void)
DEFAULT_COMMENT = g_strdup("Tagged with EasyTAG");
SET_CRC32_COMMENT = 0;
OPEN_SCANNER_WINDOW_ON_STARTUP = 0;
- SET_SCANNER_WINDOW_POSITION = 1; // Set it to '0' if problem with some Windows Manager
- SCANNER_WINDOW_X = -1;
- SCANNER_WINDOW_Y = -1;
/*
* Confirmation
@@ -805,12 +799,6 @@ Apply_Changes_Of_Preferences_Window (void)
// FIX ME : commented as it reloads files...
//Browser_Tree_Rebuild(NULL);
}
-
- if (ScannerWindow)
- {
- gtk_window_set_transient_for (GTK_WINDOW (ScannerWindow),
- GTK_WINDOW (MainWindow));
- }
}
/*
@@ -829,8 +817,9 @@ Apply_Changes_Of_UI (void)
* Function also called when destroying the window. */
et_preferences_dialog_apply_changes (ET_PREFERENCES_DIALOG (et_application_window_get_preferences_dialog
(ET_APPLICATION_WINDOW (MainWindow))));
- // Configuration of the scanner window (see scan.c) - Function also called when destroying the window
- ScannerWindow_Apply_Changes();
+ /* Configuration of the scanner window (see scan_dialog.c).
+ * Function also called when destroying the window. */
+ et_scan_dialog_apply_changes (ET_SCAN_DIALOG (et_application_window_get_scan_dialog
(ET_APPLICATION_WINDOW (MainWindow))));
/* Configuration of the cddb window (see cddb_dialog.c).
* Function also called when destroying the window. */
diff --git a/src/setting.h b/src/setting.h
index 6aa2b84..7d0e1f3 100644
--- a/src/setting.h
+++ b/src/setting.h
@@ -139,9 +139,6 @@ gint SET_DEFAULT_COMMENT;
gchar *DEFAULT_COMMENT;
gint SET_CRC32_COMMENT;
gint OPEN_SCANNER_WINDOW_ON_STARTUP;
-gint SET_SCANNER_WINDOW_POSITION;
-gint SCANNER_WINDOW_X;
-gint SCANNER_WINDOW_Y;
/* Confirmation */
gint CONFIRM_BEFORE_EXIT;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]