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