diff options
Diffstat (limited to 'src/rip/k3bpatternparser.cpp')
-rw-r--r-- | src/rip/k3bpatternparser.cpp | 305 |
1 files changed, 305 insertions, 0 deletions
diff --git a/src/rip/k3bpatternparser.cpp b/src/rip/k3bpatternparser.cpp new file mode 100644 index 0000000..8ba04e6 --- /dev/null +++ b/src/rip/k3bpatternparser.cpp @@ -0,0 +1,305 @@ +/* + * + * $Id: k3bpatternparser.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg <[email protected]> + * Copyright (C) 2004-2005 Jakob Petsovits <[email protected]> + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * See the file "COPYING" for the exact licensing terms. + */ + + +#include "k3bpatternparser.h" + +#include <qregexp.h> +#include <qdatetime.h> +#include <qvaluestack.h> + +#include <kglobal.h> +#include <klocale.h> + + +QString K3bPatternParser::parsePattern( const K3bCddbResultEntry& entry, + unsigned int trackNumber, + const QString& pattern, + bool replace, + const QString& replaceString ) +{ + if( entry.titles.count() < trackNumber ) + return ""; + + QString dir, s; + char c = ' '; // contains the character representation of a special string + unsigned int len; // length of the current special string + + + for( unsigned int i = 0; i < pattern.length(); ++i ) { + + if( pattern[i] == '%' ) { + + if( i + 1 < pattern.length() ) { + len = 2; + + if( pattern[i+1] != '{' ) { // strings like %a + c = pattern[i+1]; + } + else if( i + 3 >= pattern.length() ) { // too short to contain a %{*} string + c = ' '; + } + else { // long enough to contain %{*} + + if( pattern[i+3] == '}' ) { // strings like %{a} + c = pattern[i+2]; + len = 4; + } + else { // strings like %{artist}, or anything like %{* + + while( i + len - 1 < pattern.length() ) { + ++len; + + if( pattern[i + len - 1] == '%' ) { // don't touch other special strings + c = ' '; + --len; + break; + } + else if( pattern[i + len - 1] == '}' ) { + s = pattern.mid( i + 2, len - 3 ); + + if( s == "title" ) { + c = TITLE; + } + else if( s == "artist" ) { + c = ARTIST; + } + else if( s == "number" ) { + c = NUMBER; + } + else if( s == "comment" ) { + c = COMMENT; + } + else if( s == "year" ) { + c = YEAR; + } + else if( s == "genre" ) { + c = GENRE; + } + else if( s == "albumtitle" ) { + c = ALBUMTITLE; + } + else if( s == "albumartist" ) { + c = ALBUMARTIST; + } + else if( s == "albumcomment" ) { + c = ALBUMCOMMENT; + } + else if( s == "date" ) { + c = DATE; + } + else { // no valid pattern in here, don't replace anything + c = ' '; + } + break; // finished parsing %{* string + } + } // end of while(...) + + } // end of %{* strings + + } // end of if( long enough to contain %{*} ) + + switch( c ) { + case ARTIST: + s = entry.artists[trackNumber-1]; + s.replace( '/', '_' ); + s.replace( '*', '_' ); + s.replace( '}', '*' ); // for conditional inclusion + dir.append( s.isEmpty() + ? i18n("unknown") + QString(" %1").arg(trackNumber) + : s ); + break; + case TITLE: + s = entry.titles[trackNumber-1]; + s.replace( '/', '_' ); + s.replace( '*', '_' ); + s.replace( '}', '*' ); + dir.append( s.isEmpty() + ? i18n("Track %1").arg(trackNumber) + : s ); + break; + case NUMBER: + dir.append( QString::number(trackNumber).rightJustify( 2, '0' ) ); + break; + case YEAR: + dir.append( QString::number( entry.year ) ); + break; + case COMMENT: + s = entry.extInfos[trackNumber-1]; + s.replace( '/', '_' ); + s.replace( '*', '_' ); + s.replace( '}', '*' ); + dir.append( s ); + break; + case GENRE: + s = ( entry.genre.isEmpty() ? entry.category : entry.genre ); + s.replace( '/', '_' ); + s.replace( '*', '_' ); + s.replace( '}', '*' ); + dir.append( s ); + break; + case ALBUMARTIST: + dir.append( entry.cdArtist.isEmpty() + ? i18n("unknown") : entry.cdArtist ); + break; + case ALBUMTITLE: + s = entry.cdTitle; + s.replace( '/', '_' ); + s.replace( '*', '_' ); + s.replace( '}', '*' ); + dir.append( s.isEmpty() + ? i18n("unknown") : s ); + break; + case ALBUMCOMMENT: + s = entry.cdExtInfo; + s.replace( '/', '_' ); + s.replace( '*', '_' ); + s.replace( '}', '*' ); + dir.append( s ); // I think it makes more sense to allow empty comments + break; + case DATE: + dir.append( KGlobal::locale()->formatDate( QDate::currentDate() ) ); + break; + default: + dir.append( pattern.mid(i, len) ); + break; + } + i += len - 1; + } + else { // end of pattern + dir.append( "%" ); + } + } + else { + dir.append( pattern[i] ); + } + } + + + + // /* delete line comment to comment out + // the following part: Conditional Inclusion + + QValueStack<int> offsetStack; + QString inclusion; + bool isIncluded; + + static QRegExp conditionrx( "^[@|!][atyegrmx](?:='.*')?\\{" ); + conditionrx.setMinimal( TRUE ); + + for( unsigned int i = 0; i < dir.length(); ++i ) { + + offsetStack.push( + conditionrx.search(dir, i, QRegExp::CaretAtOffset) ); + + if( offsetStack.top() == -1 ) { + offsetStack.pop(); + } + else { + i += conditionrx.matchedLength() - 1; + continue; + } + + if( dir[i] == '}' && !offsetStack.isEmpty() ) { + + int offset = offsetStack.pop(); + int length = i - offset + 1; + + switch( (QChar) dir[offset+1] ) { + case ARTIST: + s = entry.artists[trackNumber-1]; + break; + case TITLE: + s = entry.titles[trackNumber-1]; + break; + case NUMBER: + s = QString::number( trackNumber ); + break; + case YEAR: + s = QString::number( entry.year ); + break; + case COMMENT: + s = entry.extInfos[trackNumber-1]; + break; + case GENRE: + s = ( entry.genre.isEmpty() ? entry.category : entry.genre ); + break; + case ALBUMARTIST: + s = entry.cdArtist; + break; + case ALBUMTITLE: + s = entry.cdTitle; + break; + case ALBUMCOMMENT: + s = entry.cdExtInfo; + break; + case DATE: + s = KGlobal::locale()->formatDate( QDate::currentDate() ); + break; + default: // we must never get here, + break; // all choices should be covered + } + + if( dir[offset+2] == '{' ) { // no string matching, e.g. ?y{text} + switch( (QChar) dir[offset+1] ) { + case YEAR: + isIncluded = (s != "0"); + break; + default: + isIncluded = !s.isEmpty(); + break; + } + inclusion = dir.mid( offset + 3, length - 4 ); + } + else { // with string matching, e.g. ?y='2004'{text} + + // Be aware that there might be ' in the condition text + int endOfCondition = dir.find( '{', offset+4 )-1; + QString condition = dir.mid( offset+4, + endOfCondition - (offset+4) ); + + isIncluded = (s == condition); + inclusion = dir.mid( endOfCondition+2, + i - (endOfCondition+2) ); + } + + if( dir[offset] == '!' ) + isIncluded = !isIncluded; + // Leave it when it's '@'. + + dir.replace( offset, length, ( isIncluded ? inclusion : QString("") ) ); + + if( isIncluded == TRUE ) + i -= length - inclusion.length(); + else + i = offset - 1; // start next loop at offset + + continue; + + } // end of replace (at closing bracket '}') + + } // end of conditional inclusion for(...) + + // end of Conditional Inclusion */ + + + dir.replace( '*', '}' ); // bring the brackets back, if there were any + + if( replace ) + dir.replace( QRegExp( "\\s" ), replaceString ); + + return dir; +} |