29 #include <kstringhandler.h>
35 class InfoBasePrivate {
42 createLine(
const QString& name,
const QString& value)
44 Q_ASSERT(name.length() < 254);
46 int maxLength = 256 - name.length() - 2;
48 QString tmpValue = escape(value);
52 while (tmpValue.length() > maxLength)
54 lines += QString::fromLatin1(
"%1=%2\n").arg(name,tmpValue.left(maxLength));
55 tmpValue = tmpValue.mid(maxLength);
58 lines += QString::fromLatin1(
"%1=%2\n").arg(name,tmpValue);
67 escape(
const QString &value )
70 s.replace( QLatin1String(
"\\" ), QLatin1String(
"\\\\" ) );
71 s.replace( QLatin1String(
"\n" ), QLatin1String(
"\\n" ) );
72 s.replace( QLatin1String(
"\t" ), QLatin1String(
"\\t" ) );
81 unescape(
const QString &value )
85 s.replace( QLatin1String(
"\\n" ), QLatin1String(
"\n" ) );
86 s.replace( QLatin1String(
"\\t" ), QLatin1String(
"\t" ) );
87 s.replace( QLatin1String(
"\\\\" ), QLatin1String(
"\\" ) );
93 get(
const QString& type)
95 return data[type.toUpper()];
102 return get(QLatin1String(
"title" ));
104 return get(QLatin1String(
"comment" ));
106 return get(QLatin1String(
"artist" ));
108 return get(QLatin1String(
"genre" ));
110 return get(QLatin1String(
"year" ));
112 return get(QLatin1String(
"length" ));
114 return get(QLatin1String(
"category" ));
120 set(
const QString& type,
const QVariant &d)
123 if(type.contains(QRegExp( QLatin1String(
"^T.*_.*$" )) )){
124 kDebug(60010) <<
"Error: custom cdinfo::set data can not start with T and contain a _";
127 if(type.toUpper() == QLatin1String(
"DTITLE" )){
128 kDebug(60010) <<
"Error: type: DTITLE is reserved and can not be set.";
132 data[type.toUpper()] = d;
135 set(
Type type,
const QVariant &d)
140 set(QLatin1String(
"title" ), d);
143 set(QLatin1String(
"comment" ), d);
146 set(QLatin1String(
"artist" ), d);
149 set(QLatin1String(
"genre" ), d);
152 set(QLatin1String(
"year" ), d);
155 set(QLatin1String(
"length" ), d);
158 set(QLatin1String(
"category" ), d);
167 append(
const QString& type,
const QString& text)
169 set(type,
get(type).toString().append(text));
172 append(
Type type,
const QString& text)
174 set(type,
get(type).toString().append(text));
177 QMap<QString, QVariant> data;
180 class TrackInfoPrivate :
public InfoBasePrivate {
185 d =
new TrackInfoPrivate();
189 : d(new TrackInfoPrivate)
191 d->data = clone.d->data;
201 d->data = clone.d->data;
228 int track =
get(QLatin1String(
"tracknumber" )).toInt(&ok);
230 kDebug(60010) <<
"Warning toString() on a track that doesn't have track number assigned.";
231 QMap<QString, QVariant>::const_iterator i = d->data.constBegin();
232 while (i != d->data.constEnd()) {
233 if(i.key() != QLatin1String(
"COMMENT" ) && i.key() != QLatin1String(
"TITLE" ) && i.key() != QLatin1String(
"ARTIST" ) && i.key() != QLatin1String(
"TRACKNUMBER" )) {
234 out += d->createLine(QString::fromLatin1(
"T%1_%2").arg(i.key()).arg(track),i.value().toString());
243 return d->data == other.d->data;
248 return d->data != other.d->data;
251 class CDInfoPrivate :
public InfoBasePrivate {
257 : d(new CDInfoPrivate())
259 set(QLatin1String(
"revision" ), 0);
263 : d(new CDInfoPrivate())
265 d->data = clone.d->data;
266 d->trackInfoList = clone.d->trackInfoList;
276 d->trackInfoList = clone.d->trackInfoList;
277 d->data = clone.d->data;
284 return load(
string.split(QLatin1Char(
'\n' ),QString::SkipEmptyParts));
295 QStringList::ConstIterator it = lineList.begin();
297 QRegExp rev(QLatin1String(
"# Revision: (\\d+)" ));
298 QRegExp eol(QLatin1String(
"[\r\n]" ));
300 while ( it != lineList.end() )
303 line.replace(eol,QLatin1String(
"" ));
306 if (rev.indexIn(line) != -1)
308 set(QLatin1String(
"revision" ), rev.cap(1).toUInt());
312 QStringList tokenList = KStringHandler::perlSplit(QLatin1Char(
'=' ), line, 2);
314 if (2 != tokenList.count())
319 QString key = tokenList[0].trimmed();
320 QString value = d->unescape ( tokenList[1] );
322 if ( QLatin1String(
"DTITLE" ) == key )
326 else if ( key.startsWith(QLatin1String(
"TTITLE" )) )
328 uint trackNumber = key.mid(6).toUInt();
334 else if ( QLatin1String(
"EXTD" ) == key )
338 else if ( QLatin1String(
"DGENRE" ) == key )
340 d->append(
Genre, value);
342 else if ( QLatin1String(
"DYEAR" ) == key )
346 else if ( key.startsWith(QLatin1String(
"EXTT" )) )
348 uint trackNumber = key.mid( 4 ).toUInt();
355 else if ( key.startsWith(QLatin1String(
"T" )) )
358 uint trackNumber = key.mid( key.indexOf(QLatin1Char(
'_' ))+1 ).toUInt();
361 QRegExp data(QString::fromLatin1(
"^T.*_%1$").arg(trackNumber));
362 if ( key.contains( data ) )
364 QString k = key.mid(1, key.indexOf(QLatin1Char(
'_' ))-1);
366 ti.
set( k, ti.
get(k).toString().append(value) );
372 d->append( key, value );
376 int slashPos = dtitle.indexOf(QLatin1String(
" / " ));
386 set(
Artist, dtitle.left(slashPos).trimmed());
387 set(
Title, dtitle.mid(slashPos + 3).trimmed());
390 bool isSampler =
true;
391 for (TrackInfoList::Iterator it = d->trackInfoList.begin(); it != d->trackInfoList.end(); ++it)
393 if (!(*it).get(
Title).toString().contains(QLatin1String(
" / " )))
398 for (TrackInfoList::Iterator it = d->trackInfoList.begin(); it != d->trackInfoList.end(); ++it)
402 int delimiter = (*it).get(
Title).toString().indexOf(QLatin1String(
" / " ));
403 (*it).set(
Artist, (*it).get(
Title).toString().left(delimiter));
404 (*it).set(
Title, (*it).get(
Title).toString().mid(delimiter + 3));
413 set(
Genre, QLatin1String(
"Unknown" ));
415 kDebug(60010) <<
"Loaded CDInfo for " <<
get(QLatin1String(
"discid" )).
toString();
425 if (
get(QLatin1String(
"revision" )) != 0)
426 s += QLatin1String(
"# Revision: " ) +
get(QLatin1String(
"revision" )).
toString() + QLatin1Char(
'\n' );
431 s += QLatin1String(
"#\n" );
432 s += QString::fromLatin1(
"# Submitted via: %1 %2\n").arg(
CDDB::clientName(),
436 s += d->createLine(QLatin1String(
"DISCID" ),
get(QLatin1String(
"discid" )).
toString() );
438 s += d->createLine(QLatin1String(
"DTITLE" ), artist + QLatin1String(
" / " ) +
get(
Title).
toString() );
439 int year =
get(
Year).toInt();
440 s += QLatin1String(
"DYEAR=" ) + (0 == year ? QString::null : QString::number(year)) + QLatin1Char(
'\n' );
441 if (
get(
Genre) == QLatin1String(
"Unknown" ))
442 s += d->createLine(QLatin1String(
"DGENRE" ), QString());
444 s += d->createLine(QLatin1String(
"DGENRE" ),
get(
Genre).
toString());
446 bool isSampler =
false;
447 for (
int i = 0; i < d->trackInfoList.count(); ++i){
448 QString trackArtist = d->trackInfoList[i].get(
Artist).toString();
449 if (!trackArtist.isEmpty() && trackArtist != artist)
456 for (
int i = 0; i < d->trackInfoList.count(); ++i){
457 QString trackTitle = d->trackInfoList[i].get(
Title).toString();
458 QString trackArtist = d->trackInfoList[i].get(
Artist).toString();
461 if (trackArtist.isEmpty())
462 s += d->createLine(QString::fromLatin1(
"TTITLE%1").arg(i), QString::fromLatin1(
"%1 / %2").arg(artist).arg(trackTitle));
464 s += d->createLine(QString::fromLatin1(
"TTITLE%1").arg(i), QString::fromLatin1(
"%1 / %2").arg(trackArtist).arg(trackTitle));
468 s += d->createLine(QString::fromLatin1(
"TTITLE%1").arg(i), trackTitle);
474 for (
int i = 0; i < d->trackInfoList.count(); ++i)
475 s += d->createLine(QString::fromLatin1(
"EXTT%1").arg(i), d->trackInfoList[i].get(
Comment).toString());
479 s += d->createLine(QLatin1String(
"PLAYORDER" ), QString());
483 s += d->createLine(QLatin1String(
"PLAYORDER" ),
get(QLatin1String(
"playorder" )).
toString() );
486 for (
int i = 0; i < d->trackInfoList.count(); ++i)
487 s += d->trackInfoList[i].toString();
489 QStringList cddbKeywords;
491 << QLatin1String(
"DISCID" )
492 << QLatin1String(
"ARTIST" )
493 << QLatin1String(
"TITLE" )
494 << QLatin1String(
"COMMENT" )
495 << QLatin1String(
"YEAR" )
496 << QLatin1String(
"GENRE" )
497 << QLatin1String(
"PLAYORDER" )
498 << QLatin1String(
"CATEGORY" )
499 << QLatin1String(
"REVISION" );
502 QMap<QString, QVariant>::const_iterator i = d->data.constBegin();
503 while (i != d->data.constEnd()){
504 if (!cddbKeywords.contains(i.key()) && i.key() != QLatin1String(
"SOURCE" ))
506 s+= d->createLine(i.key(), i.value().toString());
534 while ( d->trackInfoList.count() <= trackNumber ){
535 int count = d->trackInfoList.count();
537 d->trackInfoList[count].set(QLatin1String(
"tracknumber" ), count);
545 d->trackInfoList.clear();
551 QString discid =
get(QLatin1String(
"DISCID" )).
toString();
552 if (discid.isEmpty())
555 if (discid == QLatin1String(
"0" ))
565 return d->trackInfoList[trackNumber];
571 if (trackNumber < d->trackInfoList.count())
572 return d->trackInfoList[trackNumber];
575 kWarning() <<
"Couldn't find track " << trackNumber;
581 CDInfo::numberOfTracks()
const
583 return d->trackInfoList.count();
586 bool CDInfo::operator==(
const CDInfo& other )
const
588 return( d->data == other.d->data &&
589 d->trackInfoList == other.d->trackInfoList );
592 bool CDInfo::operator!=(
const CDInfo& other )
const
594 return( d->data != other.d->data ||
595 d->trackInfoList != other.d->trackInfoList );
static QString clientName()
The title of the track or CD.
The freedb category of the entry.
The length of a track or a full CD.
bool operator!=(const TrackInfo &) const
QVariant get(const QString &type) const
Get data for type that has been assigned to this disc.
QVariant get(const QString &type) const
Get data for type that has been assigned to this track.
TrackInfo & operator=(const TrackInfo &clone)
QList< TrackInfo > TrackInfoList
The genre of the track or CD.
A comment for the track or CD.
static QString clientVersion()
Type
The most common types.
TrackInfo & track(int trackNumber)
Returns track with nr trackNumber and adds it to the track list if it doesn't exist (first track is 0...
void set(const QString &type, const QVariant &data)
Set any data from this disc.
CDInfo & operator=(const CDInfo &clone)
The artist of the track or CD.
void clear()
Clear all information, setting this to invalid internal.
The year the cd or track was produced By default, the year of the track is the same as for the whole ...
QString toString(bool submit=false) const
bool operator==(const TrackInfo &) const
Information about a sepecific track in a cd.
void checkTrack(int trackNumber)
Checks to make sure that trackNumber exists.
bool load(const QString &string)
Load CDInfo from a string that is CDDB compatible.
void set(const QString &type, const QVariant &data)
Set any data from this track.