From 596d67387fbd9e40747c961f61b7dbf58866024b Mon Sep 17 00:00:00 2001 From: Martchus Date: Wed, 25 Nov 2020 18:05:23 +0100 Subject: [PATCH] Improve renaming utility * Improve UI * Add simple example script (the current example script grew quite big and is likely not good to get started) * Add script to format example scripts --- gui/renamefilesdialog.cpp | 20 ++++++---- gui/renamefilesdialog.h | 3 +- gui/renamefilesdialog.ui | 4 +- resources/scripts.qrc | 3 +- resources/scripts/renamefiles/.jsbeautifyrc | 27 +++++++++++++ .../{example1.js => advanced-example.js} | 40 ++++++++----------- resources/scripts/renamefiles/format.sh | 6 +++ .../scripts/renamefiles/simple-example.js | 38 ++++++++++++++++++ 8 files changed, 107 insertions(+), 34 deletions(-) create mode 100644 resources/scripts/renamefiles/.jsbeautifyrc rename resources/scripts/renamefiles/{example1.js => advanced-example.js} (89%) create mode 100755 resources/scripts/renamefiles/format.sh create mode 100644 resources/scripts/renamefiles/simple-example.js diff --git a/gui/renamefilesdialog.cpp b/gui/renamefilesdialog.cpp index a93661f..ec9b9e3 100644 --- a/gui/renamefilesdialog.cpp +++ b/gui/renamefilesdialog.cpp @@ -54,10 +54,11 @@ RenameFilesDialog::RenameFilesDialog(QWidget *parent) m_ui->notificationLabel->setHidden(true); // setup pasteScriptButton menu - QMenu *pasteScriptButtonMenu = new QMenu(m_ui->pasteScriptPushButton); - pasteScriptButtonMenu->addAction(tr("from file"), this, &RenameFilesDialog::showSelectScriptFileDlg); - pasteScriptButtonMenu->addAction(tr("from clipboard"), this, &RenameFilesDialog::pasteScriptFromClipboard); - pasteScriptButtonMenu->addAction(tr("default script"), this, &RenameFilesDialog::pasteDefaultExampleScript); + auto *const pasteScriptButtonMenu = new QMenu(m_ui->pasteScriptPushButton); + pasteScriptButtonMenu->addAction(tr("File"), this, &RenameFilesDialog::showSelectScriptFileDlg); + pasteScriptButtonMenu->addAction(tr("Paste from clipboard"), this, &RenameFilesDialog::pasteScriptFromClipboard); + pasteScriptButtonMenu->addAction(tr("Simple example"), this, &RenameFilesDialog::pasteSimpleExampleScript); + pasteScriptButtonMenu->addAction(tr("Advanced example"), this, &RenameFilesDialog::pasteAdvancedExampleScript); m_ui->pasteScriptPushButton->setMenu(pasteScriptButtonMenu); // setup icons @@ -76,7 +77,7 @@ RenameFilesDialog::RenameFilesDialog(QWidget *parent) m_ui->javaScriptPlainTextEdit->setPlainText(settings.editorScript); m_scriptModified = true; } else { - pasteDefaultExampleScript(); + pasteSimpleExampleScript(); } // connect signals and slots @@ -354,9 +355,14 @@ void RenameFilesDialog::pasteScriptFromClipboard() m_ui->javaScriptPlainTextEdit->setPlainText(script); } -void RenameFilesDialog::pasteDefaultExampleScript() +void RenameFilesDialog::pasteSimpleExampleScript() { - pasteScriptFromFile(QStringLiteral(":/scripts/renamefiles/example1")); + pasteScriptFromFile(QStringLiteral(":/scripts/renamefiles/simple-example")); +} + +void RenameFilesDialog::pasteAdvancedExampleScript() +{ + pasteScriptFromFile(QStringLiteral(":/scripts/renamefiles/advanced-example")); } void RenameFilesDialog::showTreeViewContextMenu(const QPoint &position) diff --git a/gui/renamefilesdialog.h b/gui/renamefilesdialog.h index f6a9eb3..5c832e1 100644 --- a/gui/renamefilesdialog.h +++ b/gui/renamefilesdialog.h @@ -45,7 +45,8 @@ private Q_SLOTS: void previewItemSelected(const QItemSelection &selected, const QItemSelection &deselected); void pasteScriptFromFile(const QString &fileName); void pasteScriptFromClipboard(); - void pasteDefaultExampleScript(); + void pasteSimpleExampleScript(); + void pasteAdvancedExampleScript(); void showTreeViewContextMenu(const QPoint &position); void showSelectScriptFileDlg(); void abortClose(); diff --git a/gui/renamefilesdialog.ui b/gui/renamefilesdialog.ui index bcd6126..54d525c 100644 --- a/gui/renamefilesdialog.ui +++ b/gui/renamefilesdialog.ui @@ -98,7 +98,7 @@ - Paste + Open/Examples @@ -578,7 +578,7 @@ - select a script file + Select a script file diff --git a/resources/scripts.qrc b/resources/scripts.qrc index fe867d2..254c913 100644 --- a/resources/scripts.qrc +++ b/resources/scripts.qrc @@ -1,5 +1,6 @@ - scripts/renamefiles/example1.js + scripts/renamefiles/simple-example.js + scripts/renamefiles/advanced-example.js diff --git a/resources/scripts/renamefiles/.jsbeautifyrc b/resources/scripts/renamefiles/.jsbeautifyrc new file mode 100644 index 0000000..f9552fd --- /dev/null +++ b/resources/scripts/renamefiles/.jsbeautifyrc @@ -0,0 +1,27 @@ +{ + "indent_size": 4, + "indent_char": " ", + "indent_with_tabs": false, + "editorconfig": false, + "eol": "\n", + "end_with_newline": false, + "indent_level": 0, + "preserve_newlines": true, + "max_preserve_newlines": 10, + "space_in_paren": false, + "space_in_empty_paren": false, + "jslint_happy": true, + "space_after_anon_function": false, + "space_after_named_function": false, + "brace_style": "collapse", + "unindent_chained_methods": false, + "break_chained_methods": false, + "keep_array_indentation": false, + "unescape_strings": false, + "wrap_line_length": 0, + "e4x": false, + "comma_first": false, + "operator_position": "before-newline", + "indent_empty_lines": false, + "templating": ["auto"] +} \ No newline at end of file diff --git a/resources/scripts/renamefiles/example1.js b/resources/scripts/renamefiles/advanced-example.js similarity index 89% rename from resources/scripts/renamefiles/example1.js rename to resources/scripts/renamefiles/advanced-example.js index b51c820..6163365 100644 --- a/resources/scripts/renamefiles/example1.js +++ b/resources/scripts/renamefiles/advanced-example.js @@ -18,7 +18,7 @@ var keepTitleFromFileName = false // specifies whether track information should be appended (like [H.265-320p AAC-LC-2ch-eng AAC-LC-2ch-ger]) var includeTrackInfo = false // specifies the "distribution directory" -//var distDir = false; // don't move files around +//var distDir = false // don't move files around var distDir = "/path/to/my/music-collection" // move files to an appropriate subdirectory under this path // directory used to store collections which contain songs from multiple artists var collectionsDir = "collections" @@ -59,16 +59,16 @@ function appropriateDigitCount(pos, total) { // returns a copy of the specified \a name with characters that might be avoided in file names striped out function validFileName(name) { return name !== undefined ? name.replace(/[\/\\]/gi, " - ").replace( - /[<>?!*|:\"\n\f\r]/gi, "") : "" + /[<>?!*|:\"\n\f\r]/gi, "") : "" } // returns a copy of the specified \a name with characters that might be avoided in directory names striped out. function validDirectoryName(name) { return name !== undefined ? name.replace(/[\/\\]/gi, " - ").replace( - /[<>?!*|:\".\n\f\r]/gi, "") : "" + /[<>?!*|:\".\n\f\r]/gi, "") : "" } // strips tags from the beginning or end of the string if configured function tagsStripped(name) { - return stripTags ? name.replace(/^(\[[^\]]*\]\s*)+/g, "").replace(/(\s*\[[^\]]*\])+$/g, "") : name; + return stripTags ? name.replace(/^(\[[^\]]*\]\s*)+/g, "").replace(/(\s*\[[^\]]*\])+$/g, "") : name } // @@ -90,26 +90,26 @@ var tracks = fileInfo.tracks var infoFromFileName = tageditor.parseFileName(fileInfo.currentBaseName) // skip hidden and "desktop.ini" files -if (fileInfo.currentName.indexOf(".") === 0 - || fileInfo.currentName === "desktop.ini") { +if (fileInfo.currentName.indexOf(".") === 0 || + fileInfo.currentName === "desktop.ini") { tageditor.skip() return } // treat *.lrc files like their corresponding audio files -var keepSuffix; +var keepSuffix if (fileInfo.currentSuffix === "lrc") { - keepSuffix = fileInfo.currentSuffix; // keep the lrc suffix later - for(let extension of ["mp3", "flac", "m4a"]) { - fileInfo = tageditor.parseFileInfo(fileInfo.currentPathWithoutExtension + "." + extension); - tag = fileInfo.tag; + keepSuffix = fileInfo.currentSuffix // keep the lrc suffix later + for (let extension of ["mp3", "flac", "m4a"]) { + fileInfo = tageditor.parseFileInfo(fileInfo.currentPathWithoutExtension + "." + extension) + tag = fileInfo.tag if (!fileInfo.ioErrorOccured) { - break; + break } } if (fileInfo.ioErrorOccured) { - tageditor.skip("skipping, corresponding audio file not present"); - return; + tageditor.skip("skipping, corresponding audio file not present") + return } } @@ -133,10 +133,7 @@ if (fileInfo.currentSuffix === "tmp") { var fields = [] // get the artist (preferably album artist), remove invalid characters and add it to fields array -var artist = validFileName(tag.albumartist) -if (artist.length === 0) { - artist = validFileName(tag.artist) -} +var artist = validFileName(tag.albumartist || tag.artist) if (includeArtist && !isPartOfCollection(tag) && notEmpty(artist)) { fields.push(artist) } @@ -214,10 +211,7 @@ if (!distDir) { return } var path = [distDir] -var artist = validDirectoryName(tag.albumartist) -if (artist.length === 0) { - artist = validDirectoryName(tag.artist) -} +var artist = validDirectoryName(tag.albumartist || tag.artist) if (isPartOfCollection(tag)) { path.push(collectionsDir) } else if (isMiscFile(tag)) { @@ -241,4 +235,4 @@ if (tag.diskTotal >= 2) { path.push("Disk " + appropriateDigitCount(tag.diskPos, tag.diskTotal)) } // apply new relative directory -tageditor.move(path.join("/")) +tageditor.move(path.join("/")) \ No newline at end of file diff --git a/resources/scripts/renamefiles/format.sh b/resources/scripts/renamefiles/format.sh new file mode 100755 index 0000000..8d01765 --- /dev/null +++ b/resources/scripts/renamefiles/format.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +set -e +for js_file in *.js; do + js-beautify --jslint-happy -r "$js_file" +done diff --git a/resources/scripts/renamefiles/simple-example.js b/resources/scripts/renamefiles/simple-example.js new file mode 100644 index 0000000..e628c72 --- /dev/null +++ b/resources/scripts/renamefiles/simple-example.js @@ -0,0 +1,38 @@ +// This is a simple example script demonstrating how the renaming tool can be used. +// script configuration + +// skip directories in this example script +if (!tageditor.isFile) { + tageditor.skip() + return +} + +// parse file using the built-in parseFileInfo function +const fileInfo = tageditor.parseFileInfo(tageditor.currentPath) +const tag = fileInfo.tag +const tracks = fileInfo.tracks + +// deduce title and track number from the file name using the built-in parseFileName function (as fallback if tags missing) +const infoFromFileName = tageditor.parseFileName(fileInfo.currentBaseName) + +// skip files which don't contain audio or video tracks +if (!fileInfo.hasAudioTracks && !fileInfo.hasVideoTracks) { + tageditor.skip() + return +} + +// make new filename +const fieldsToInclude = [tag.albumartist || tag.artist, tag.album, tag.trackPos || infoFromFileName.trackPos, tag.title || infoFromFileName.title] +let newName = "" +for (let field of fieldsToInclude) { + if (typeof field === "number") { + for (field = field + "", count = (tag.trackTotal + "").length; field.length < count; field = "0" + field); + } + if (field && field.length !== 0) { + newName = newName.concat(newName.length === 0 ? "" : " - ", field) + } +} +newName = newName.concat(".", fileInfo.suitableSuffix || fileInfo.currentSuffix) + +// apply new name +tageditor.rename(newName) \ No newline at end of file