diff options
Diffstat (limited to 'src/importers/rezkonvimporter.cpp')
-rw-r--r-- | src/importers/rezkonvimporter.cpp | 291 |
1 files changed, 291 insertions, 0 deletions
diff --git a/src/importers/rezkonvimporter.cpp b/src/importers/rezkonvimporter.cpp new file mode 100644 index 0000000..58e59c0 --- /dev/null +++ b/src/importers/rezkonvimporter.cpp @@ -0,0 +1,291 @@ +/*************************************************************************** +* Copyright (C) 2003 by * +* Jason Kivlighn ([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. * +***************************************************************************/ + +#include "rezkonvimporter.h" + +#include <tdeapplication.h> +#include <tdelocale.h> +#include <kdebug.h> + +#include <tqfile.h> +#include <tqregexp.h> +#include <tqtextstream.h> + +#include "datablocks/mixednumber.h" + +RezkonvImporter::RezkonvImporter() : BaseImporter() +{} + +RezkonvImporter::~RezkonvImporter() +{} + +void RezkonvImporter::parseFile( const TQString &filename ) +{ + TQFile input( filename ); + + if ( input.open( IO_ReadOnly ) ) { + TQTextStream stream( &input ); + stream.skipWhiteSpace(); + + TQString line; + + while ( !stream.atEnd() ) { + line = stream.readLine(); + + if ( line.contains( TQRegExp( "^=====.*REZKONV.*" ) ) ) { + TQStringList raw_recipe; + while ( !( line = stream.readLine() ).contains( TQRegExp( "^=====\\s*$" ) ) && !stream.atEnd() ) + raw_recipe << line; + + readRecipe( raw_recipe ); + } + } + + if ( fileRecipeCount() == 0 ) + setErrorMsg( i18n( "No recipes found in this file." ) ); + } + else + setErrorMsg( i18n( "Unable to open file." ) ); +} + +void RezkonvImporter::readRecipe( const TQStringList &raw_recipe ) +{ + kapp->processEvents(); //don't want the user to think its frozen... especially for files with thousands of recipes + + Recipe recipe; + + TQStringList::const_iterator text_it = raw_recipe.begin(); + m_end_it = raw_recipe.end(); + + //title (Titel) + text_it++; + recipe.title = ( *text_it ).mid( ( *text_it ).find( ":" ) + 1, ( *text_it ).length() ).stripWhiteSpace(); + kdDebug() << "Found title: " << recipe.title << endl; + + //categories (Kategorien): + text_it++; + TQStringList categories = TQStringList::split( ',', ( *text_it ).mid( ( *text_it ).find( ":" ) + 1, ( *text_it ).length() ) ); + for ( TQStringList::const_iterator it = categories.begin(); it != categories.end(); ++it ) { + Element new_cat; + new_cat.name = TQString( *it ).stripWhiteSpace(); + kdDebug() << "Found category: " << new_cat.name << endl; + recipe.categoryList.append( new_cat ); + } + + //yield (Menge) + text_it++; + //get the number between the ":" and the next space after it + TQString yield_str = ( *text_it ).stripWhiteSpace(); + yield_str.remove( TQRegExp( "^Menge:\\s*" ) ); + int sep_index = yield_str.find( ' ' ); + if ( sep_index != -1 ) + recipe.yield.type = yield_str.mid( sep_index+1 ); + readRange( yield_str.mid( 0, sep_index ), recipe.yield.amount, recipe.yield.amount_offset ); + kdDebug() << "Found yield: " << recipe.yield.amount << endl; + + bool is_sub = false; + bool last_line_empty = false; + text_it++; + while ( text_it != raw_recipe.end() ) { + if ( ( *text_it ).isEmpty() ) { + last_line_empty = true; + text_it++; + continue; + } + + if ( ( *text_it ).contains( TQRegExp( "^=====.*=$" ) ) ) //is a header + { + if ( ( *text_it ).contains( "quelle", false ) ) + { + loadReferences( text_it, recipe ); + break; //reference lines are the last before the instructions + } + else + loadIngredientHeader( *text_it, recipe ); + } + + //if it has no more than two spaces followed by a non-digit + //then we'll assume it is a direction line + else if ( last_line_empty && ( *text_it ).contains( TQRegExp( "^\\s{0,2}[^\\d\\s=]" ) ) ) + break; + else + loadIngredient( *text_it, recipe, is_sub ); + + last_line_empty = false; + text_it++; + } + + loadInstructions( text_it, recipe ); + + add + ( recipe ); + + current_header = TQString::null; +} + +void RezkonvImporter::loadIngredient( const TQString &string, Recipe &recipe, bool &is_sub ) +{ + Ingredient new_ingredient; + new_ingredient.amount = 0; //amount not required, so give default of 0 + + TQRegExp cont_test( "^-{1,2}" ); + if ( string.stripWhiteSpace().contains( cont_test ) ) { + TQString name = string.stripWhiteSpace(); + name.remove( cont_test ); + kdDebug() << "Appending to last ingredient: " << name << endl; + if ( !recipe.ingList.isEmpty() ) //so it doesn't crash when the first ingredient appears to be a continuation of another + ( *recipe.ingList.at( recipe.ingList.count() - 1 ) ).name += " " + name; + + return ; + } + + //amount + if ( !string.mid( 0, 7 ).stripWhiteSpace().isEmpty() ) + readRange( string.mid( 0, 7 ), new_ingredient.amount, new_ingredient.amount_offset ); + + //unit + TQString unit_str = string.mid( 8, 9 ).stripWhiteSpace(); + new_ingredient.units = Unit( unit_str, new_ingredient.amount ); + + //name and preparation method + new_ingredient.name = string.mid( 18, string.length() - 18 ).stripWhiteSpace(); + + //separate out the preparation method + TQString name_and_prep = new_ingredient.name; + int separator_index = name_and_prep.find( "," ); + if ( separator_index != -1 ) { + new_ingredient.name = name_and_prep.mid( 0, separator_index ).stripWhiteSpace(); + new_ingredient.prepMethodList = ElementList::split(",",name_and_prep.mid( separator_index + 1, name_and_prep.length() ).stripWhiteSpace() ); + } + + //header (if present) + new_ingredient.group = current_header; + + bool last_is_sub = is_sub; + if ( new_ingredient.prepMethodList.last().name == "or" ) { + new_ingredient.prepMethodList.pop_back(); + is_sub = true; + } + else + is_sub = false; + + if ( last_is_sub ) + ( *recipe.ingList.at( recipe.ingList.count() - 1 ) ).substitutes.append(new_ingredient); + else + recipe.ingList.append( new_ingredient ); +} + +void RezkonvImporter::loadIngredientHeader( const TQString &string, Recipe &/*recipe*/ ) +{ + TQString header = string; + header.remove( TQRegExp( "^=*" ) ).remove( TQRegExp( "=*$" ) ); + header = header.stripWhiteSpace(); + + kdDebug() << "found ingredient header: " << header << endl; + + current_header = header; +} + +void RezkonvImporter::loadInstructions( TQStringList::const_iterator &text_it, Recipe &recipe ) +{ + TQString instr; + TQRegExp rx_title( "^:{0,1}\\s*O-Titel\\s*:" ); + TQString line; + while ( text_it != m_end_it ) { + line = *text_it; + + //titles longer than the line width are rewritten here + if ( line.contains( rx_title ) ) { + line.remove( rx_title ); + recipe.title = line.stripWhiteSpace(); + + TQRegExp rx_line_cont( ":\\s*>{0,1}\\s*:" ); + while ( ( line = *text_it ).contains( rx_line_cont ) ) { + line.remove( rx_line_cont ); + recipe.title += line; + + text_it++; + } + kdDebug() << "Found long title: " << recipe.title << endl; + } + else { + if ( line.isEmpty() ) + instr += "\n\n"; + + instr += line; + } + + text_it++; + } + + recipe.instructions = instr; +} + +void RezkonvImporter::loadReferences( TQStringList::const_iterator &text_it, Recipe &recipe ) +{ + kdDebug() << "Found source header" << endl; + + while ( text_it != m_end_it ) { + text_it++; + TQRegExp rx_line_begin( "^\\s*-{0,2}\\s*" ); + + TQRegExp rx_creation_date = TQRegExp( "^\\s*-{0,2}\\s*Erfasst \\*RK\\*", false ); + if ( ( *text_it ).contains( rx_creation_date ) ) // date followed by typist + { + TQString date = *text_it; + date.remove( rx_creation_date ).remove( TQRegExp( " von\\s*$" ) ); + + // Date is given as DD.MM.YY + TQString s = date.section( ".", 0, 0 ); + int day = s.toInt(); + + s = date.section( ".", 1, 1 ); + int month = s.toInt(); + + s = date.section( ".", 2, 2 ); + int year = s.toInt(); + year += 1900; + if ( year < 1970 ) + year += 100; //we'll assume nothing has been created before 1970 (y2k issues :p) + + recipe.ctime = TQDate(year,month,day); + + #if 0 + //typist + text_it++; + TQString typist = = *text_it; + typist.remove( rx_line_begin ); + #endif + + } + else //everything else is an author + { + if ( ( *text_it ).contains( rx_line_begin ) ) { + TQString author = *text_it; + author.remove( rx_line_begin ); + + recipe.authorList.append( Element( author ) ); + } + else + break; + } + } +} + +void RezkonvImporter::readRange( const TQString &range_str, double &amount, double &amount_offset ) +{ + TQString from = range_str.section( '-', 0, 0 ); + TQString to = range_str.section( '-', 1, 1 ); + + amount = MixedNumber::fromString( from ).toDouble(); + + if ( !to.stripWhiteSpace().isEmpty() ) + amount_offset = MixedNumber::fromString( to ).toDouble() - amount; +} |