[kid3] /: Script to apply English title capitalization to tags

Urs Fleisch null at kde.org
Tue Apr 14 08:36:41 BST 2020


Git commit 5c8f85ca14658d7531ac4d05aae0a5352b1303e0 by Urs Fleisch.
Committed on 14/04/2020 at 06:42.
Pushed by ufleisch into branch 'master'.

Script to apply English title capitalization to tags

BUG: 419890

M  +5    -0    doc/en/index.docbook
M  +2    -1    src/core/config/configstore.cpp
M  +6    -0    src/core/config/useractionsconfig.cpp
M  +1    -0    src/qml/CMakeLists.txt
A  +125  -0    src/qml/script/TitleCase.qml     [License: LGPL]

https://invent.kde.org/kde/kid3/commit/5c8f85ca14658d7531ac4d05aae0a5352b1303e0

diff --git a/doc/en/index.docbook b/doc/en/index.docbook
index cf3b0727..87da30e7 100644
--- a/doc/en/index.docbook
+++ b/doc/en/index.docbook
@@ -4455,6 +4455,11 @@ Helps to find the encoding of ID3v1 tags by showing the tags of the
 current file in all available character encodings.
 </para></listitem>
 <listitem><para>
+<guilabel>English Title Case</guilabel>
+(<filename>TitleCase.qml</filename>):
+Formats text in the tags to English title case.
+</para></listitem>
+<listitem><para>
 <guilabel>Export CSV</guilabel>
 (<filename>ExportCsv.qml</filename>):
 Export recursively all tags of all files to a CSV file.
diff --git a/src/core/config/configstore.cpp b/src/core/config/configstore.cpp
index 6fc7a374..84e7730b 100644
--- a/src/core/config/configstore.cpp
+++ b/src/core/config/configstore.cpp
@@ -37,8 +37,9 @@ namespace {
  * 2: 3.2
  * 3: 3.3
  * 4: 3.7
+ * 5: 3.8.3
  */
-const int CONFIG_VERSION = 4;
+const int CONFIG_VERSION = 5;
 
 }
 
diff --git a/src/core/config/useractionsconfig.cpp b/src/core/config/useractionsconfig.cpp
index 775da5d0..646d793e 100644
--- a/src/core/config/useractionsconfig.cpp
+++ b/src/core/config/useractionsconfig.cpp
@@ -245,6 +245,12 @@ void UserActionsConfig::setDefaultUserActions(bool upgradeOnly)
             QLatin1String("@qml %{qmlpath}/script/ExportPlaylist.qml"),
             false, true));
   }
+  if (!upgradeOnly || ConfigStore::getConfigVersion() < 5) {
+    m_contextMenuCommands.push_back(
+      UserActionsConfig::MenuCommand(
+            QLatin1String("English Title Case"),
+            QLatin1String("@qml %{qmlpath}/script/TitleCase.qml")));
+  }
 #endif
 }
 
diff --git a/src/qml/CMakeLists.txt b/src/qml/CMakeLists.txt
index 68fe922d..04114754 100644
--- a/src/qml/CMakeLists.txt
+++ b/src/qml/CMakeLists.txt
@@ -28,6 +28,7 @@ if(NOT HAVE_QMLDIR_IN_QRC)
     script/EmbedAlbumArt.qml
     script/EmbedLyrics.qml
     script/ExportPlaylist.qml
+    script/TitleCase.qml
   )
   if(BUILD_QML_APP)
     # Only used to add the QML sources to the project.
diff --git a/src/qml/script/TitleCase.qml b/src/qml/script/TitleCase.qml
new file mode 100644
index 00000000..da047dc0
--- /dev/null
+++ b/src/qml/script/TitleCase.qml
@@ -0,0 +1,125 @@
+/**
+ * \file TitleCase.qml
+ * Use English title case in certain tag frames.
+ *
+ * \b Project: Kid3
+ * \author Urs Fleisch
+ * \date 12 Apr 2020
+ *
+ * Copyright (C) 2020  Urs Fleisch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; version 3.
+ *
+ * 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import Kid3 1.1
+
+Kid3Script {
+  onRun: {
+    var consideredTags = [Frame.Tag_1, Frame.Tag_2, Frame.Tag_3]
+    var consideredFrames = ["title", "album"]
+
+    var small = "(a|an|and|as|at|but|by|en|for|if|in|of|on|or|the|to|v[.]?|via|vs[.]?)";
+    var punct = "([!\"#$%&'()*+,./:;<=>?@[\\\\\\]^_`{|}~-]*)";
+    // This array only contains words which cannot be handled by the all lower
+    // and upper case handling at the end of the toTitleCase() function.
+    var unmodifiableWords = ["Pi-hsien"];
+
+    /*
+     * Title Caps
+     *
+     * Adapted for audio tag use case by Urs Fleisch - 12 Apr 2020
+     * Ported to JavaScript By John Resig - http://ejohn.org/ - 21 May 2008
+     * Original by John Gruber - http://daringfireball.net/ - 10 May 2008
+     * License: http://www.opensource.org/licenses/mit-license.php
+     */
+    function toTitleCase(title) {
+      var parts = [], split = /[:.;?!] |(?: |^)["\xab]/g, index = 0;
+
+      while (true) {
+        var m = split.exec(title);
+        var part = title.substring(index, m ? m.index : title.length);
+
+        parts.push(unmodifiableWords.indexOf(part) !== -1 ? part : part
+          .replace(/\b([A-Za-z][a-z.'`()\u2019]*)\b/g,
+                   function(all) {
+                     return /[A-Za-z]\.[A-Za-z]/.test(all) ? all : capitalize(all);
+                   })
+          .replace(new RegExp("\\b" + small + "\\b", "ig"),
+                   function(word) {
+                     return word.toLowerCase();
+                   })
+          .replace(new RegExp("^" + punct + small + "\\b", "ig"),
+                   function(all, punct, word) {
+                     return punct + capitalize(word);
+                   })
+          .replace(new RegExp("([-\\u2013\\u2014]\\s+)" + punct + small + "\\b", "ig"),
+                   function(all, dash, punct, word) {
+                     return dash + punct + capitalize(word);
+                   })
+          .replace(new RegExp("\\b" + small + punct + "$", "ig"), capitalize));
+
+        index = split.lastIndex;
+
+        if (m) {
+          parts.push(m[0]);
+        } else {
+          break;
+        }
+      }
+
+      return parts.join("")
+        .replace(/ V(s?)\. /ig, " v$1. ")
+        .replace(/(['`\u2019])S\b/ig, "$1s")
+        .replace(/\b(de|von|van|feat|n|http:\/\/)\b/ig, function(all) {
+          return all.toLowerCase();
+        })
+        .replace(/\b(AT&T|Q&A|OYF’N)\b/ig, function(all) {
+          return all.toUpperCase();
+        });
+      ;
+    };
+
+    function capitalize(word) {
+      return word.substr(0, 1).toUpperCase() + word.substr(1);
+    }
+
+    function doWork() {
+      for (var ti = 0; ti < consideredTags.length; ++ti) {
+        var tagNr = consideredTags[ti]
+        var tagMask = script.toTagVersion(1 << tagNr);
+        if (app.selectionInfo.tag(tagNr).tagFormat) {
+          for (var fi = 0; fi < consideredFrames.length; ++fi) {
+            var name = consideredFrames[fi];
+            var oldTxt = app.getFrame(tagMask, name)
+            var newTxt = toTitleCase(oldTxt)
+            if (newTxt !== oldTxt) {
+              app.setFrame(tagMask, name, newTxt)
+            }
+          }
+        }
+      }
+      if (!nextFile()) {
+        if (isStandalone()) {
+          // Save the changes if the script is started stand-alone, not from Kid3.
+          app.saveDirectory()
+        }
+        Qt.quit()
+      } else {
+        setTimeout(doWork, 1)
+      }
+    }
+
+    firstFile()
+    doWork()
+  }
+}



More information about the kde-doc-english mailing list