File indexing completed on 2024-05-19 04:56:13
0001 /** 0002 * \file trackdata.cpp 0003 * Track data, frames with association to tagged file. 0004 * 0005 * \b Project: Kid3 0006 * \author Urs Fleisch 0007 * \date 23 Feb 2007 0008 * 0009 * Copyright (C) 2007-2024 Urs Fleisch 0010 * 0011 * This file is part of Kid3. 0012 * 0013 * Kid3 is free software; you can redistribute it and/or modify 0014 * it under the terms of the GNU General Public License as published by 0015 * the Free Software Foundation; either version 2 of the License, or 0016 * (at your option) any later version. 0017 * 0018 * Kid3 is distributed in the hope that it will be useful, 0019 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0020 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0021 * GNU General Public License for more details. 0022 * 0023 * You should have received a copy of the GNU General Public License 0024 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0025 */ 0026 0027 #include "trackdata.h" 0028 #include <QString> 0029 #include <QUrl> 0030 #include <QDir> 0031 #include <QDateTime> 0032 #include <QCoreApplication> 0033 #include "fileproxymodel.h" 0034 0035 /** 0036 * Constructor. 0037 * 0038 * @param trackData track data 0039 * @param str string with format codes 0040 */ 0041 TrackDataFormatReplacer::TrackDataFormatReplacer( 0042 const TrackData& trackData, const QString& str) 0043 : FrameFormatReplacer(trackData, str), m_trackData(trackData) {} 0044 0045 /** 0046 * Replace a format code (one character %c or multiple characters %{chars}). 0047 * Supported format fields: 0048 * Those supported by FrameFormatReplacer::getReplacement() 0049 * %f filename 0050 * %p path to file 0051 * %u URL of file 0052 * %d duration in minutes:seconds 0053 * %D duration in seconds 0054 * %n number of tracks 0055 * 0056 * @param code format code 0057 * 0058 * @return replacement string, 0059 * QString::null if code not found. 0060 */ 0061 QString TrackDataFormatReplacer::getReplacement(const QString& code) const 0062 { 0063 QString result = FrameFormatReplacer::getReplacement(code); 0064 if (result.isNull()) { 0065 QString name; 0066 0067 if (code.length() == 1) { 0068 static const struct { 0069 const char* longCode; 0070 char shortCode; 0071 } shortToLong[] = { 0072 { "file", 'f' }, 0073 { "filepath", 'p' }, 0074 { "url", 'u' }, 0075 { "duration", 'd' }, 0076 { "seconds", 'D' }, 0077 { "tracks", 'n' }, 0078 { "extension", 'e' }, 0079 { "tag1", 'O' }, 0080 { "tag2", 'o' }, 0081 { "bitrate", 'b' }, 0082 { "vbr", 'v' }, 0083 { "samplerate", 'r' }, 0084 { "mode", 'm' }, 0085 { "channels", 'C' }, 0086 { "codec", 'k' }, 0087 { "marked", 'w' } 0088 }; 0089 const char c = code[0].toLatin1(); 0090 for (const auto& [longCode, shortCode] : shortToLong) { 0091 if (shortCode == c) { 0092 name = QString::fromLatin1(longCode); 0093 break; 0094 } 0095 } 0096 } else if (code.length() > 1) { 0097 name = code; 0098 } 0099 0100 if (!name.isNull()) { 0101 TaggedFile::DetailInfo info; 0102 m_trackData.getDetailInfo(info); 0103 if (name == QLatin1String("file")) { 0104 QString filename(m_trackData.getAbsFilename()); 0105 int sepPos = filename.lastIndexOf(QLatin1Char('/')); 0106 if (sepPos < 0) { 0107 sepPos = filename.lastIndexOf(QDir::separator()); 0108 } 0109 if (sepPos >= 0) { 0110 filename.remove(0, sepPos + 1); 0111 } 0112 result = filename; 0113 } else if (name == QLatin1String("filepath")) { 0114 result = m_trackData.getAbsFilename(); 0115 } else if (name == QLatin1String("modificationdate")) { 0116 return QFileInfo(m_trackData.getAbsFilename()) 0117 .lastModified().toString(Qt::ISODate); 0118 } else if (name == QLatin1String("creationdate")) { 0119 #if QT_VERSION >= 0x050a00 0120 return QFileInfo(m_trackData.getAbsFilename()) 0121 .birthTime().toString(Qt::ISODate); 0122 #else 0123 return QFileInfo(m_trackData.getAbsFilename()) 0124 .created().toString(Qt::ISODate); 0125 #endif 0126 } else if (name == QLatin1String("url")) { 0127 QUrl url; 0128 url.setPath(m_trackData.getAbsFilename()); 0129 url.setScheme(QLatin1String("file")); 0130 result = url.toString(); 0131 } else if (name == QLatin1String("dirname")) { 0132 const QString dirPath = m_trackData.getDirname(); 0133 int sepPos = dirPath.lastIndexOf(QLatin1Char('/')); 0134 if (sepPos < 0) { 0135 sepPos = dirPath.lastIndexOf(QDir::separator()); 0136 } 0137 result = sepPos >= 0 ? dirPath.mid(sepPos + 1) : dirPath; 0138 } else if (name == QLatin1String("duration")) { 0139 result = TaggedFile::formatTime(m_trackData.getFileDuration()); 0140 } else if (name == QLatin1String("seconds")) { 0141 result = QString::number(m_trackData.getFileDuration()); 0142 } else if (name == QLatin1String("tracks")) { 0143 result = QString::number(m_trackData.getTotalNumberOfTracksInDir()); 0144 } else if (name == QLatin1String("extension")) { 0145 result = m_trackData.getFileExtension(); 0146 } else if (name.startsWith(QLatin1String("tag")) && name.length() == 4) { 0147 if (Frame::TagNumber tagNr = Frame::tagNumberFromString(name.mid(3)); 0148 tagNr < Frame::Tag_NumValues) { 0149 result = m_trackData.getTagFormat(tagNr); 0150 } 0151 } else if (name == QLatin1String("bitrate")) { 0152 result.setNum(info.bitrate); 0153 } else if (name == QLatin1String("vbr")) { 0154 result = info.vbr ? QLatin1String("VBR") : QLatin1String(""); 0155 } else if (name == QLatin1String("samplerate")) { 0156 result.setNum(info.sampleRate); 0157 } else if (name == QLatin1String("mode")) { 0158 switch (info.channelMode) { 0159 case TaggedFile::DetailInfo::CM_Stereo: 0160 result = QLatin1String("Stereo"); 0161 break; 0162 case TaggedFile::DetailInfo::CM_JointStereo: 0163 result = QLatin1String("Joint Stereo"); 0164 break; 0165 case TaggedFile::DetailInfo::CM_None: 0166 default: 0167 result = QLatin1String(""); 0168 } 0169 } else if (name == QLatin1String("channels")) { 0170 result.setNum(info.channels); 0171 } else if (name == QLatin1String("codec")) { 0172 result = info.format; 0173 } else if (name == QLatin1String("marked")) { 0174 TaggedFile* taggedFile = m_trackData.getTaggedFile(); 0175 result = taggedFile && taggedFile->isMarked() 0176 ? QLatin1String("1") : QLatin1String(""); 0177 } 0178 } 0179 } 0180 0181 return result; 0182 } 0183 0184 /** 0185 * Get help text for supported format codes. 0186 * 0187 * @param onlyRows if true only the tr elements are returned, 0188 * not the surrounding table 0189 * 0190 * @return help text. 0191 */ 0192 QString TrackDataFormatReplacer::getToolTip(bool onlyRows) 0193 { 0194 QString str; 0195 if (!onlyRows) str += QLatin1String("<table>\n"); 0196 str += FrameFormatReplacer::getToolTip(true); 0197 0198 str += QLatin1String("<tr><td>%f</td><td>%{file}</td><td>"); 0199 str += QCoreApplication::translate("@default", "Filename"); 0200 str += QLatin1String("</td></tr>\n"); 0201 0202 str += QLatin1String("<tr><td>%p</td><td>%{filepath}</td><td>"); 0203 const char* const absolutePathToFileStr = 0204 QT_TRANSLATE_NOOP("@default", "Absolute path to file"); 0205 str += QCoreApplication::translate("@default", absolutePathToFileStr); 0206 str += QLatin1String("</td></tr>\n"); 0207 0208 str += QLatin1String("<tr><td></td><td>%{modificationdate}</td><td>"); 0209 const char* const modificationDateStr = 0210 QT_TRANSLATE_NOOP("@default", "Modification date"); 0211 str += QCoreApplication::translate("@default", modificationDateStr); 0212 str += QLatin1String("</td></tr>\n"); 0213 0214 str += QLatin1String("<tr><td></td><td>%{creationdate}</td><td>"); 0215 const char* const creationDateStr = 0216 QT_TRANSLATE_NOOP("@default", "Creation date"); 0217 str += QCoreApplication::translate("@default", creationDateStr); 0218 str += QLatin1String("</td></tr>\n"); 0219 0220 str += QLatin1String("<tr><td>%u</td><td>%{url}</td><td>"); 0221 str += QCoreApplication::translate("@default", "URL"); 0222 str += QLatin1String("</td></tr>\n"); 0223 0224 str += QLatin1String("<tr><td></td><td>%{dirname}</td><td>"); 0225 const char* const directoryNameStr = 0226 QT_TRANSLATE_NOOP("@default", "Directory name"); 0227 str += QCoreApplication::translate("@default", directoryNameStr); 0228 str += QLatin1String("</td></tr>\n"); 0229 0230 str += QLatin1String("<tr><td>%d</td><td>%{duration}</td><td>"); 0231 const char* const lengthStr = QT_TRANSLATE_NOOP("@default", "Length"); 0232 str += QCoreApplication::translate("@default", lengthStr); 0233 str += QLatin1String(" "M:S"</td></tr>\n"); 0234 0235 str += QLatin1String("<tr><td>%D</td><td>%{seconds}</td><td>"); 0236 str += QCoreApplication::translate("@default", lengthStr); 0237 str += QLatin1String(" "S"</td></tr>\n"); 0238 0239 str += QLatin1String("<tr><td>%n</td><td>%{tracks}</td><td>"); 0240 const char* const numberOfTracksStr = 0241 QT_TRANSLATE_NOOP("@default", "Number of tracks"); 0242 str += QCoreApplication::translate("@default", numberOfTracksStr); 0243 str += QLatin1String("</td></tr>\n"); 0244 0245 str += QLatin1String("<tr><td>%e</td><td>%{extension}</td><td>"); 0246 const char* const extensionStr = QT_TRANSLATE_NOOP("@default", "Extension"); 0247 str += QCoreApplication::translate("@default", extensionStr); 0248 str += QLatin1String("</td></tr>\n"); 0249 0250 str += QLatin1String("<tr><td>%O</td><td>%{tag1}</td><td>"); 0251 str += QCoreApplication::translate("@default", "Tag 1"); 0252 str += QLatin1String("</td></tr>\n"); 0253 0254 str += QLatin1String("<tr><td>%o</td><td>%{tag2}</td><td>"); 0255 str += QCoreApplication::translate("@default", "Tag 2"); 0256 str += QLatin1String("</td></tr>\n"); 0257 0258 str += QLatin1String("<tr><td>%b</td><td>%{bitrate}</td><td>"); 0259 const char* const bitrateStr = QT_TRANSLATE_NOOP("@default", "Bitrate"); 0260 str += QCoreApplication::translate("@default", bitrateStr); 0261 str += QLatin1String("</td></tr>\n"); 0262 0263 str += QLatin1String("<tr><td>%v</td><td>%{vbr}</td><td>"); 0264 const char* const vbrStr = QT_TRANSLATE_NOOP("@default", "VBR"); 0265 str += QCoreApplication::translate("@default", vbrStr); 0266 str += QLatin1String("</td></tr>\n"); 0267 0268 str += QLatin1String("<tr><td>%r</td><td>%{samplerate}</td><td>"); 0269 const char* const samplerateStr = QT_TRANSLATE_NOOP("@default", "Samplerate"); 0270 str += QCoreApplication::translate("@default", samplerateStr); 0271 str += QLatin1String("</td></tr>\n"); 0272 0273 str += QLatin1String("<tr><td>%m</td><td>%{mode}</td><td>Stereo, Joint Stereo</td></tr>\n"); 0274 0275 str += QLatin1String("<tr><td>%C</td><td>%{channels}</td><td>"); 0276 const char* const channelsStr = QT_TRANSLATE_NOOP("@default", "Channels"); 0277 str += QCoreApplication::translate("@default", channelsStr); 0278 str += QLatin1String("</td></tr>\n"); 0279 0280 str += QLatin1String("<tr><td>%k</td><td>%{codec}</td><td>"); 0281 const char* const codecStr = QT_TRANSLATE_NOOP("@default", "Codec"); 0282 str += QCoreApplication::translate("@default", codecStr); 0283 str += QLatin1String("</td></tr>\n"); 0284 0285 str += QLatin1String("<tr><td>%w</td><td>%{marked}</td><td>"); 0286 const char* const markedStr = QT_TRANSLATE_NOOP("@default", "Marked"); 0287 str += QCoreApplication::translate("@default", markedStr); 0288 str += QLatin1String("</td></tr>\n"); 0289 0290 str += QLatin1String("<tr><td>%ha...</td><td>%h{artist}...</td><td>"); 0291 const char* const escapeForHtmlStr = 0292 QT_TRANSLATE_NOOP("@default", "Escape for HTML"); 0293 str += QCoreApplication::translate("@default", escapeForHtmlStr); 0294 str += QLatin1String("</td></tr>\n"); 0295 0296 if (!onlyRows) str += QLatin1String("</table>\n"); 0297 return str; 0298 } 0299 0300 0301 /** 0302 * Constructor. 0303 */ 0304 TrackData::TrackData() = default; 0305 0306 /** 0307 * Constructor. 0308 * All fields except the import duration are set from the tagged file, 0309 * which should be read using readTags() before. 0310 * 0311 * @param taggedFile tagged file providing track data 0312 * @param tagVersion source of frames 0313 */ 0314 TrackData::TrackData(TaggedFile& taggedFile, Frame::TagVersion tagVersion) 0315 : m_taggedFileIndex(taggedFile.getIndex()) 0316 { 0317 for (Frame::TagNumber tagNr : Frame::tagNumbersFromMask(tagVersion)) { 0318 if (empty()) { 0319 taggedFile.getAllFrames(tagNr, *this); 0320 } else { 0321 FrameCollection frames; 0322 taggedFile.getAllFrames(tagNr, frames); 0323 merge(frames); 0324 } 0325 } 0326 } 0327 0328 /** 0329 * Get tagged file associated with this track data. 0330 * @return tagged file, 0 if none assigned. 0331 */ 0332 TaggedFile* TrackData::getTaggedFile() const { 0333 return FileProxyModel::getTaggedFileOfIndex(m_taggedFileIndex); 0334 } 0335 0336 /** 0337 * Get duration of file. 0338 * @return duration of file. 0339 */ 0340 int TrackData::getFileDuration() const 0341 { 0342 TaggedFile* taggedFile = getTaggedFile(); 0343 return taggedFile ? taggedFile->getDuration() : 0; 0344 } 0345 0346 /** 0347 * Get absolute filename. 0348 * 0349 * @return absolute file path. 0350 */ 0351 QString TrackData::getAbsFilename() const 0352 { 0353 TaggedFile* taggedFile = getTaggedFile(); 0354 return taggedFile ? taggedFile->getAbsFilename() : QString(); 0355 } 0356 0357 /** 0358 * Get filename. 0359 * 0360 * @return filename. 0361 */ 0362 QString TrackData::getFilename() const 0363 { 0364 TaggedFile* taggedFile = getTaggedFile(); 0365 return taggedFile ? taggedFile->getFilename() : QString(); 0366 } 0367 0368 /** 0369 * Get directory name. 0370 * 0371 * @return directory name. 0372 */ 0373 QString TrackData::getDirname() const 0374 { 0375 TaggedFile* taggedFile = getTaggedFile(); 0376 return taggedFile ? taggedFile->getDirname() : QString(); 0377 } 0378 0379 /** 0380 * Get the format of tag. 0381 * 0382 * @param tagNr tag number 0383 * @return string describing format of tag 1, 0384 * e.g. "ID3v1.1", "ID3v2.3", "Vorbis", "APE", 0385 * QString::null if unknown. 0386 */ 0387 QString TrackData::getTagFormat(Frame::TagNumber tagNr) const 0388 { 0389 TaggedFile* taggedFile = getTaggedFile(); 0390 return taggedFile ? taggedFile->getTagFormat(tagNr) : QString(); 0391 } 0392 0393 /** 0394 * Get detail info. 0395 * @param info the detail information is returned here 0396 */ 0397 void TrackData::getDetailInfo(TaggedFile::DetailInfo& info) const 0398 { 0399 if (TaggedFile* taggedFile = getTaggedFile()) { 0400 taggedFile->getDetailInfo(info); 0401 } 0402 } 0403 0404 /** 0405 * Format a string from track data. 0406 * Supported format fields: 0407 * Those supported by TrackDataFormatReplacer::getReplacement() 0408 * 0409 * @param format format specification 0410 * 0411 * @return formatted string. 0412 */ 0413 QString TrackData::formatString(const QString& format) const 0414 { 0415 TrackDataFormatReplacer fmt(*this, format); 0416 fmt.replaceEscapedChars(); 0417 fmt.replacePercentCodes(FormatReplacer::FSF_SupportHtmlEscape); 0418 return fmt.getString(); 0419 } 0420 0421 /** 0422 * Create filename from tags according to format string. 0423 * 0424 * @param str format string containing codes supported by 0425 * TrackDataFormatReplacer::getReplacement() 0426 * @param isDirname true to generate a directory name 0427 * 0428 * @return format string with format codes replaced by tags. 0429 */ 0430 QString TrackData::formatFilenameFromTags(QString str, bool isDirname) const 0431 { 0432 if (!isDirname) { 0433 transformToFilename(str); 0434 } 0435 0436 TrackDataFormatReplacer fmt(*this, str); 0437 fmt.replacePercentCodes(isDirname ? 0438 FormatReplacer::FSF_ReplaceSeparators : 0); 0439 return fmt.getString(); 0440 } 0441 0442 /** 0443 * Transform string to file name. 0444 * The directory part is removed and a file extension added. 0445 * @param str string to transform 0446 */ 0447 void TrackData::transformToFilename(QString& str) const 0448 { 0449 // first remove directory part from str 0450 if (const int sepPos = str.lastIndexOf(QLatin1Char('/')); sepPos >= 0) { 0451 str.remove(0, sepPos + 1); 0452 } 0453 // add extension to str 0454 str += getFileExtension(true); 0455 } 0456 0457 /** 0458 * Get help text for format codes supported by formatString(). 0459 * 0460 * @param onlyRows if true only the tr elements are returned, 0461 * not the surrounding table 0462 * 0463 * @return help text. 0464 */ 0465 QString TrackData::getFormatToolTip(bool onlyRows) 0466 { 0467 return TrackDataFormatReplacer::getToolTip(onlyRows); 0468 } 0469 0470 /** 0471 * Get file extension including the dot. 0472 * 0473 * @param preferFromFilename true to prefer extension from current filename 0474 * over default extension for file type 0475 * 0476 * @return file extension, e.g. ".mp3". 0477 */ 0478 QString TrackData::getFileExtension(bool preferFromFilename) const 0479 { 0480 QString fileExtension; 0481 QString absFilename; 0482 if (TaggedFile* taggedFile = getTaggedFile()) { 0483 fileExtension = taggedFile->getFileExtension(); 0484 absFilename = taggedFile->getAbsFilename(); 0485 } 0486 if (preferFromFilename || fileExtension.isEmpty()) { 0487 if (int dotPos = absFilename.lastIndexOf(QLatin1Char('.')); dotPos != -1) { 0488 return absFilename.mid(dotPos); 0489 } 0490 } 0491 return fileExtension; 0492 } 0493 0494 /** 0495 * Get the total number of tracks in the directory. 0496 * 0497 * @return total number of tracks, -1 if unavailable. 0498 */ 0499 int TrackData::getTotalNumberOfTracksInDir() const 0500 { 0501 TaggedFile* taggedFile = getTaggedFile(); 0502 return taggedFile ? taggedFile->getTotalNumberOfTracksInDir() : -1; 0503 } 0504 0505 0506 /** 0507 * Get the difference between the imported duration and the track's duration. 0508 * @return absolute value of time difference in seconds, -1 if not available. 0509 */ 0510 int ImportTrackData::getTimeDifference() const 0511 { 0512 int fileDuration = getFileDuration(); 0513 int importDuration = getImportDuration(); 0514 return fileDuration != 0 && importDuration != 0 0515 ? fileDuration > importDuration 0516 ? fileDuration - importDuration 0517 : importDuration - fileDuration 0518 : -1; 0519 } 0520 0521 namespace { 0522 0523 /** 0524 * Get lower case words found in string. 0525 * @return lower case words. 0526 */ 0527 QSet<QString> getLowerCaseWords(const QString& str) 0528 { 0529 if (!str.isEmpty()) { 0530 QString normalized = str.normalized(QString::NormalizationForm_D).toLower(); 0531 QString simplified; 0532 for (auto it = normalized.constBegin(); it != normalized.constEnd(); ++it) { 0533 if (it->isLetter()) { 0534 simplified += *it; 0535 } else if (it->isPunct() || it->isSpace() || it->isSymbol()) { 0536 simplified += QLatin1Char(' '); 0537 } 0538 } 0539 #if QT_VERSION >= 0x050e00 0540 const QStringList words = 0541 simplified.split(QLatin1Char(' '), Qt::SkipEmptyParts); 0542 return QSet(words.constBegin(), words.constEnd()); 0543 #else 0544 return simplified.split(QLatin1Char(' '), QString::SkipEmptyParts).toSet(); 0545 #endif 0546 } 0547 return QSet<QString>(); 0548 } 0549 0550 } 0551 0552 /** 0553 * Get words of file name. 0554 * @return lower case words found in file name. 0555 */ 0556 QSet<QString> ImportTrackData::getFilenameWords() const 0557 { 0558 QString fileName = getFilename(); 0559 if (int endIndex = fileName.lastIndexOf(QLatin1Char('.')); endIndex > 0) { 0560 fileName.truncate(endIndex); 0561 } 0562 return getLowerCaseWords(fileName); 0563 } 0564 0565 /** 0566 * Get words of title. 0567 * @return lower case words found in title. 0568 */ 0569 QSet<QString> ImportTrackData::getTitleWords() const 0570 { 0571 return getLowerCaseWords(getTitle()); 0572 } 0573 0574 0575 /** 0576 * Clear vector and associated data. 0577 */ 0578 void ImportTrackDataVector::clearData() 0579 { 0580 clear(); 0581 m_coverArtUrl.clear(); 0582 } 0583 0584 /** 0585 * Get album artist. 0586 * @return album artist. 0587 */ 0588 QString ImportTrackDataVector::getArtist() const 0589 { 0590 return getFrame(Frame::FT_Artist); 0591 } 0592 0593 /** 0594 * Get album title. 0595 * @return album title. 0596 */ 0597 QString ImportTrackDataVector::getAlbum() const 0598 { 0599 return getFrame(Frame::FT_Album); 0600 } 0601 0602 /** 0603 * Check if tag is supported in the first track. 0604 * @param tagNr tag number 0605 * @return true if tag is supported. 0606 */ 0607 bool ImportTrackDataVector::isTagSupported(Frame::TagNumber tagNr) const 0608 { 0609 if (!isEmpty()) { 0610 if (TaggedFile* taggedFile = at(0).getTaggedFile()) { 0611 return taggedFile->isTagSupported(tagNr); 0612 } 0613 } 0614 return true; 0615 } 0616 0617 /** 0618 * Get frame from first track. 0619 * @param type frame type 0620 * @return value of frame. 0621 */ 0622 QString ImportTrackDataVector::getFrame(Frame::Type type) const 0623 { 0624 QString result; 0625 if (!isEmpty()) { 0626 const ImportTrackData& trackData = at(0); 0627 result = trackData.getValue(type); 0628 if (!result.isEmpty()) 0629 return result; 0630 TaggedFile* taggedFile = trackData.getTaggedFile(); 0631 FrameCollection frames; 0632 for (Frame::TagNumber tagNr : Frame::allTagNumbers()) { 0633 taggedFile->getAllFrames(tagNr, frames); 0634 result = frames.getValue(type); 0635 if (!result.isEmpty()) 0636 return result; 0637 } 0638 } 0639 return result; 0640 } 0641 0642 /** 0643 * Read the tags from the files. 0644 * This can be used to fill the track data with another tag version. 0645 * 0646 * @param tagVersion tag version to read 0647 */ 0648 void ImportTrackDataVector::readTags(Frame::TagVersion tagVersion) 0649 { 0650 for (auto it = begin(); it != end(); ++it) { 0651 if (TaggedFile* taggedFile = it->getTaggedFile()) { 0652 it->clear(); 0653 for (Frame::TagNumber tagNr : Frame::tagNumbersFromMask(tagVersion)) { 0654 if (it->empty()) { 0655 taggedFile->getAllFrames(tagNr, *it); 0656 } else { 0657 FrameCollection frames; 0658 taggedFile->getAllFrames(tagNr, frames); 0659 it->merge(frames); 0660 } 0661 } 0662 } 0663 it->setImportDuration(0); 0664 it->setEnabled(true); 0665 } 0666 setCoverArtUrl(QUrl()); 0667 } 0668 0669 #ifndef QT_NO_DEBUG 0670 /** 0671 * Dump contents of tracks to debug console. 0672 */ 0673 void ImportTrackDataVector::dump() const 0674 { 0675 qDebug("ImportTrackDataVector (%s - %s, %s):", 0676 qPrintable(getArtist()), qPrintable(getAlbum()), 0677 qPrintable(getCoverArtUrl().toString())); 0678 for (auto it = constBegin(); it != constEnd(); ++it) { 0679 const ImportTrackData& trackData = *it; 0680 int fileDuration = trackData.getFileDuration(); 0681 int importDuration = trackData.getImportDuration(); 0682 qDebug("%d:%02d, %d:%02d, %s, %d, %s, %s, %s, %d, %s", 0683 fileDuration / 60, fileDuration % 60, 0684 importDuration / 60, importDuration % 60, 0685 qPrintable(trackData.getFilename()), 0686 trackData.getTrack(), 0687 qPrintable(trackData.getTitle()), 0688 qPrintable(trackData.getArtist()), 0689 qPrintable(trackData.getAlbum()), 0690 trackData.getYear(), 0691 qPrintable(trackData.getGenre())); 0692 } 0693 } 0694 #endif