File indexing completed on 2023-05-30 11:30:52
0001 /** 0002 * Copyright (C) 2003 Frerich Raabe <raabe@kde.org> 0003 * 0004 * This program is free software; you can redistribute it and/or modify it under 0005 * the terms of the GNU General Public License as published by the Free Software 0006 * Foundation; either version 2 of the License, or (at your option) any later 0007 * version. 0008 * 0009 * This program is distributed in the hope that it will be useful, but WITHOUT ANY 0010 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 0011 * PARTICULAR PURPOSE. See the GNU General Public License for more details. 0012 * 0013 * You should have received a copy of the GNU General Public License along with 0014 * this program. If not, see <http://www.gnu.org/licenses/>. 0015 */ 0016 0017 #include "tagguesser.h" 0018 #include "juk_debug.h" 0019 0020 #include <kconfig.h> 0021 #include <kmacroexpander.h> 0022 #include <qhash.h> 0023 #include <kconfiggroup.h> 0024 #include <KSharedConfig> 0025 0026 FileNameScheme::FileNameScheme(const QString &s) 0027 : m_regExp(), 0028 m_titleField(-1), 0029 m_artistField(-1), 0030 m_albumField(-1), 0031 m_trackField(-1), 0032 m_commentField(-1) 0033 { 0034 int fieldNumber = 1; 0035 int i = s.indexOf('%'); 0036 while (i > -1) { 0037 switch (s[ i + 1 ].toLatin1()) { 0038 case 't': m_titleField = fieldNumber++; 0039 break; 0040 case 'a': m_artistField = fieldNumber++; 0041 break; 0042 case 'A': m_albumField = fieldNumber++; 0043 break; 0044 case 'T': m_trackField = fieldNumber++; 0045 break; 0046 case 'c': m_commentField = fieldNumber++; 0047 break; 0048 default: 0049 break; 0050 } 0051 i = s.indexOf('%', i + 1); 0052 } 0053 m_regExp.setPattern(composeRegExp(s)); 0054 } 0055 0056 bool FileNameScheme::matches(const QString &fileName) const 0057 { 0058 /* Strip extension ('.mp3') because '.' may be part of a title, and thus 0059 * does not work as a separator. 0060 */ 0061 QString stripped = fileName; 0062 stripped.truncate(stripped.lastIndexOf('.')); 0063 return m_regExp.exactMatch(stripped); 0064 } 0065 0066 QString FileNameScheme::title() const 0067 { 0068 if(m_titleField == -1) 0069 return QString(); 0070 return m_regExp.capturedTexts().at(m_titleField); 0071 } 0072 0073 QString FileNameScheme::artist() const 0074 { 0075 if(m_artistField == -1) 0076 return QString(); 0077 return m_regExp.capturedTexts().at(m_artistField); 0078 } 0079 0080 QString FileNameScheme::album() const 0081 { 0082 if(m_albumField == -1) 0083 return QString(); 0084 return m_regExp.capturedTexts().at(m_albumField); 0085 } 0086 0087 QString FileNameScheme::track() const 0088 { 0089 if(m_trackField == -1) 0090 return QString(); 0091 return m_regExp.capturedTexts().at(m_trackField); 0092 } 0093 0094 QString FileNameScheme::comment() const 0095 { 0096 if(m_commentField == -1) 0097 return QString(); 0098 return m_regExp.capturedTexts().at(m_commentField); 0099 } 0100 0101 QString FileNameScheme::composeRegExp(const QString &s) const 0102 { 0103 QHash<QChar, QString> substitutions; 0104 0105 KConfigGroup config(KSharedConfig::openConfig(), "TagGuesser"); 0106 0107 substitutions[ 't' ] = config.readEntry("Title regexp", "([\\w\\s'&_,\\.]+)"); 0108 substitutions[ 'a' ] = config.readEntry("Artist regexp", "([\\w\\s'&_,\\.]+)"); 0109 substitutions[ 'A' ] = config.readEntry("Album regexp", "([\\w\\s'&_,\\.]+)"); 0110 substitutions[ 'T' ] = config.readEntry("Track regexp", "(\\d+)"); 0111 substitutions[ 'c' ] = config.readEntry("Comment regexp", "([\\w\\s_]+)"); 0112 0113 QString regExp = QRegExp::escape(s.simplified()); 0114 regExp = ".*" + regExp; 0115 regExp.replace(' ', "\\s+"); 0116 regExp = KMacroExpander::expandMacros(regExp, substitutions); 0117 regExp += "[^/]*$"; 0118 return regExp; 0119 } 0120 0121 QStringList TagGuesser::schemeStrings() 0122 { 0123 QStringList schemes; 0124 0125 KConfigGroup config(KSharedConfig::openConfig(), "TagGuesser"); 0126 schemes = config.readEntry("Filename schemes", QStringList()); 0127 0128 if ( schemes.isEmpty() ) { 0129 schemes += "%a - (%T) - %t [%c]"; 0130 schemes += "%a - (%T) - %t (%c)"; 0131 schemes += "%a - (%T) - %t"; 0132 schemes += "%a - [%T] - %t [%c]"; 0133 schemes += "%a - [%T] - %t (%c)"; 0134 schemes += "%a - [%T] - %t"; 0135 schemes += "%a - %T - %t [%c]"; 0136 schemes += "%a - %T - %t (%c)"; 0137 schemes += "%a - %T - %t"; 0138 schemes += "(%T) %a - %t [%c]"; 0139 schemes += "(%T) %a - %t (%c)"; 0140 schemes += "(%T) %a - %t"; 0141 schemes += "[%T] %a - %t [%c]"; 0142 schemes += "[%T] %a - %t (%c)"; 0143 schemes += "[%T] %a - %t"; 0144 schemes += "%T %a - %t [%c]"; 0145 schemes += "%T %a - %t (%c)"; 0146 schemes += "%T %a - %t"; 0147 schemes += "(%a) %t [%c]"; 0148 schemes += "(%a) %t (%c)"; 0149 schemes += "(%a) %t"; 0150 schemes += "%a - %t [%c]"; 0151 schemes += "%a - %t (%c)"; 0152 schemes += "%a - %t"; 0153 schemes += "%a/%A/[%T] %t [%c]"; 0154 schemes += "%a/%A/[%T] %t (%c)"; 0155 schemes += "%a/%A/[%T] %t"; 0156 } 0157 return schemes; 0158 } 0159 0160 void TagGuesser::setSchemeStrings(const QStringList &schemes) 0161 { 0162 KSharedConfig::Ptr cfg = KSharedConfig::openConfig(); 0163 KConfigGroup group(cfg, "TagGuesser"); 0164 group.writeEntry("Filename schemes", schemes); 0165 cfg->sync(); 0166 } 0167 0168 TagGuesser::TagGuesser() 0169 { 0170 loadSchemes(); 0171 } 0172 0173 TagGuesser::TagGuesser(const QString &absFileName) 0174 { 0175 loadSchemes(); 0176 guess(absFileName); 0177 } 0178 0179 void TagGuesser::loadSchemes() 0180 { 0181 const QStringList schemes = schemeStrings(); 0182 QStringList::ConstIterator it = schemes.begin(); 0183 QStringList::ConstIterator end = schemes.end(); 0184 for ( ; it != end; ++it ) 0185 m_schemes += FileNameScheme( *it ); 0186 } 0187 0188 void TagGuesser::guess(const QString &absFileName) 0189 { 0190 m_title.clear(); 0191 m_artist.clear(); 0192 m_album.clear(); 0193 m_track.clear(); 0194 m_comment.clear(); 0195 0196 FileNameScheme::List::ConstIterator it = m_schemes.constBegin(); 0197 FileNameScheme::List::ConstIterator end = m_schemes.constEnd(); 0198 for (; it != end; ++it) { 0199 const FileNameScheme schema(*it); 0200 if(schema.matches(absFileName)) { 0201 m_title = capitalizeWords(schema.title().replace('_', " ")).trimmed(); 0202 m_artist = capitalizeWords(schema.artist().replace('_', " ")).trimmed(); 0203 m_album = capitalizeWords(schema.album().replace('_', " ")).trimmed(); 0204 m_track = schema.track().trimmed(); 0205 m_comment = schema.comment().replace('_', " ").trimmed(); 0206 break; 0207 } 0208 } 0209 } 0210 0211 QString TagGuesser::capitalizeWords(const QString &s) 0212 { 0213 if(s.isEmpty()) 0214 return s; 0215 0216 QString result = s; 0217 result[ 0 ] = result[ 0 ].toUpper(); 0218 0219 const QRegExp wordRegExp("\\s\\w"); 0220 int i = result.indexOf( wordRegExp ); 0221 while ( i > -1 ) { 0222 result[ i + 1 ] = result[ i + 1 ].toUpper(); 0223 i = result.indexOf( wordRegExp, ++i ); 0224 } 0225 0226 return result; 0227 } 0228 0229 // vim: set et sw=4 tw=0 sta: