summaryrefslogtreecommitdiffstats
path: root/src/rip/k3bpatternparser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/rip/k3bpatternparser.cpp')
-rw-r--r--src/rip/k3bpatternparser.cpp305
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;
+}