\n");
str += QLatin1String("%s | %{title} | ");
str += QCoreApplication::translate("@default", "Title");
str += QLatin1String(" |
\n");
str += QLatin1String("%l | %{album} | ");
str += QCoreApplication::translate("@default", "Album");
str += QLatin1String(" |
\n");
str += QLatin1String("%a | %{artist} | ");
str += QCoreApplication::translate("@default", "Artist");
str += QLatin1String(" |
\n");
str += QLatin1String("%c | %{comment} | ");
str += QCoreApplication::translate("@default", "Comment");
str += QLatin1String(" |
\n");
str += QLatin1String("%y | %{year} | ");
const char* const yearStr = QT_TRANSLATE_NOOP("@default", "Year");
str += QCoreApplication::translate("@default", yearStr);
str += QLatin1String(" |
\n");
str += QLatin1String("%t | %{track} | ");
str += QCoreApplication::translate("@default", "Track");
str += QLatin1String(" |
\n");
str += QLatin1String("%g | %{genre} | ");
str += QCoreApplication::translate("@default", "Genre");
str += QLatin1String(" |
\n");
str += QLatin1String("%d | %{duration} | ");
const char* const lengthStr = QT_TRANSLATE_NOOP("@default", "Length");
str += QCoreApplication::translate("@default", lengthStr);
str += QLatin1String(" |
\n");
if (!onlyRows) str += QLatin1String("
\n");
return str;
}
/**
* Set import format.
*
* @param fmt format regexp
* @param enableTrackIncr enable automatic track increment if no %t is found
*/
void ImportParser::setFormat(const QString& fmt, bool enableTrackIncr)
{
static const struct {
const char* from;
const char* to;
} codeToName[] = {
{ "%s", "%{title}" },
{ "%l", "%{album}" },
{ "%a", "%{artist}" },
{ "%c", "%{comment}" },
{ "%y", "%{date}" },
{ "%t", "%{track number}" },
{ "%g", "%{genre}" },
{ "%d", "%{__duration}" },
{ "%f", "%{file}" },
{ "%{year}", "%{date}" },
{ "%{track}", "%{track number}" },
{ "%{tracknumber}", "%{track number}" },
{ "%{duration}", "%{__duration}" },
};
int percentIdx = 0, nr = 1, lastIdx = fmt.length() - 1;
m_pattern = fmt;
for (const auto& c2n : codeToName) {
m_pattern.replace(QString::fromLatin1(c2n.from), QString::fromLatin1(c2n.to));
}
m_codePos.clear();
while (((percentIdx = m_pattern.indexOf(QLatin1String("%{"), percentIdx)) >= 0) &&
(percentIdx < lastIdx)) {
int closingBracePos = m_pattern.indexOf(QLatin1String("}("), percentIdx + 2);
if (closingBracePos > percentIdx + 2) {
QString code =
m_pattern.mid(percentIdx + 2, closingBracePos - percentIdx - 2);
m_codePos[code] = nr;
percentIdx = closingBracePos + 2;
++nr;
} else {
percentIdx += 2;
}
}
if (enableTrackIncr && !m_codePos.contains(QLatin1String("track number"))) {
m_trackIncrEnabled = true;
m_trackIncrNr = 1;
} else {
m_trackIncrEnabled = false;
m_trackIncrNr = 0;
}
m_pattern.remove(QRegularExpression(QLatin1String("%\\{[^}]+\\}")));
m_re.setPattern(m_pattern);
}
/**
* Get next tags in text buffer.
*
* @param text text buffer containing data from file or clipboard
* @param frames frames for output
* @param pos current position in buffer, will be updated to point
* behind current match (to be used for next call)
* @return true if tags found (pos is index behind match).
*/
bool ImportParser::getNextTags(const QString& text, TrackData& frames, int& pos)
{
QRegularExpressionMatch match;
int idx, oldpos = pos;
if (m_pattern.isEmpty()) {
m_trackDuration.clear();
return false;
}
if (!m_codePos.contains(QLatin1String("__duration"))) {
m_trackDuration.clear();
} else if (pos == 0) {
m_trackDuration.clear();
int dsp = 0; // "duration search pos"
int lastDsp = dsp;
while ((idx = (match = m_re.match(text, dsp)).capturedStart()) != -1) {
QString durationStr = match.captured(m_codePos.value(QLatin1String("__duration")));
int duration;
QRegularExpression durationRe(QLatin1String("(\\d+):(\\d+)"));
auto durationMatch = durationRe.match(durationStr);
if (durationMatch.hasMatch()) {
duration = durationMatch.captured(1).toInt() * 60 +
durationMatch.captured(2).toInt();
} else {
duration = durationStr.toInt();
}
m_trackDuration.append(duration);
dsp = idx + durationMatch.capturedLength();
if (dsp > lastDsp) { /* avoid endless loop */
lastDsp = dsp;
} else {
break;
}
}
}
if ((idx = (match = m_re.match(text, pos)).capturedStart()) != -1) {
for (auto it = m_codePos.constBegin(); it != m_codePos.constEnd(); ++it) {
const QString& name = it.key();
QString str = match.captured(*it);
if (name == QLatin1String("__return")) {
m_returnValues.append(str);
} else if (!str.isEmpty() && !name.startsWith(QLatin1String("__"))) {
if (name == QLatin1String("file")) {
if (TaggedFile* taggedFile = frames.getTaggedFile()) {
frames.transformToFilename(str);
taggedFile->setFilenameFormattedIfEnabled(str);
}
} else {
frames.setValue(Frame::ExtendedType(name), str);
}
}
}
if (m_trackIncrEnabled) {
frames.setTrack(m_trackIncrNr++);
}
pos = idx + match.capturedLength();
if (pos > oldpos) { /* avoid endless loop */
return true;
}
}
return false;
}