diff options
Diffstat (limited to 'src/exporters/kreexporter.cpp')
-rw-r--r-- | src/exporters/kreexporter.cpp | 264 |
1 files changed, 264 insertions, 0 deletions
diff --git a/src/exporters/kreexporter.cpp b/src/exporters/kreexporter.cpp new file mode 100644 index 0000000..e0d27c0 --- /dev/null +++ b/src/exporters/kreexporter.cpp @@ -0,0 +1,264 @@ +/*************************************************************************** +* Copyright (C) 2003 by * +* Cyril Bosselut ([email protected]) * +* * +* Copyright (C) 2003-2005 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 "kreexporter.h" + +#include <tqfile.h> +#include <tqstylesheet.h> +#include <tqbuffer.h> +#include <tqimage.h> + +#include <kdebug.h> +#include <tdelocale.h> +#include <kmdcodec.h> +#include <tdeglobal.h> +#include <kstandarddirs.h> + +#include "backends/recipedb.h" + +KreExporter::KreExporter( CategoryTree *_categories, const TQString& filename, const TQString &format ) : + BaseExporter( filename, format ), categories( _categories ) +{ + if ( format == "*.kre" ) { + setCompressed(true); + } +} + + +KreExporter::~KreExporter() +{ + delete categories; +} + +int KreExporter::supportedItems() const +{ + return RecipeDB::All; +} + +int KreExporter::headerFlags() const +{ + return RecipeDB::Categories; +} + +TQString KreExporter::createHeader( const RecipeList& recipes ) +{ + TQString xml; + + xml += "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"; + xml += "<krecipes version=\"" + krecipes_version() + "\" lang=\"" + ( TDEGlobal::locale() )->language() + "\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"krecipes.xsd\">\n"; + + createCategoryStructure( xml, recipes ); + + return xml; +} + +TQString KreExporter::createFooter() +{ + return "</krecipes>\n"; +} + +TQString KreExporter::generateIngredient( const IngredientData &ing ) +{ + TQString xml; + + xml += "<name>" + TQStyleSheet::escape( ( ing ).name ) + "</name>\n"; + xml += "<amount>"; + if ( ing.amount_offset < 1e-10 ) { + xml += TQString::number( ing.amount ); + } + else { + xml += "<min>"+TQString::number( ing.amount )+"</min>"; + xml += "<max>"+TQString::number( ing.amount + ing.amount_offset )+"</max>"; + } + xml += "</amount>\n"; + TQString unit_str = ( ing.amount+ing.amount_offset > 1 ) ? ing.units.plural : ing.units.name; + xml += "<unit>" + TQStyleSheet::escape( unit_str ) + "</unit>\n"; + if ( ing.prepMethodList.count() > 0 ) + xml += "<prep>" + TQStyleSheet::escape( ing.prepMethodList.join(",") ) + "</prep>\n"; + + return xml; +} + +//TODO: use TQDOM (see recipemlexporter.cpp)? +TQString KreExporter::createContent( const RecipeList& recipes ) +{ + TQString xml; + + RecipeList::const_iterator recipe_it; + for ( recipe_it = recipes.begin(); recipe_it != recipes.end(); ++recipe_it ) { + + xml += "<krecipes-recipe>\n"; + xml += "<krecipes-description>\n"; + xml += "<title>" + TQStyleSheet::escape( ( *recipe_it ).title ) + "</title>\n"; + + for ( ElementList::const_iterator author_it = ( *recipe_it ).authorList.begin(); author_it != ( *recipe_it ).authorList.end(); ++author_it ) + xml += "<author>" + TQStyleSheet::escape( ( *author_it ).name ) + "</author>\n"; + + xml += "<pictures>\n"; + if ( !( *recipe_it ).photo.isNull() ) { + xml += "<pic format=\"JPEG\" id=\"1\"><![CDATA["; //fixed id until we implement multiple photos ability + TQByteArray data; + TQBuffer buffer( data ); + buffer.open( IO_WriteOnly ); + TQImageIO iio( &buffer, "JPEG" ); + iio.setImage( ( *recipe_it ).photo.convertToImage() ); + iio.write(); + + xml += KCodecs::base64Encode( data, true ); + + xml += "]]></pic>\n"; + } + xml += "</pictures>\n"; + xml += "<category>\n"; + + for ( ElementList::const_iterator cat_it = ( *recipe_it ).categoryList.begin(); cat_it != ( *recipe_it ).categoryList.end(); ++cat_it ) + xml += "<cat>" + TQStyleSheet::escape( ( *cat_it ).name ) + "</cat>\n"; + + xml += "</category>\n"; + xml += "<yield>"; + xml += "<amount>"; + if ( ( *recipe_it ).yield.amount_offset < 1e-10 ) { + xml += TQString::number( ( *recipe_it ).yield.amount ); + } + else { + xml += "<min>"+TQString::number( ( *recipe_it ).yield.amount )+"</min>"; + xml += "<max>"+TQString::number( ( *recipe_it ).yield.amount + ( *recipe_it ).yield.amount_offset )+"</max>"; + } + xml += "</amount>"; + xml += "<type>"+( *recipe_it ).yield.type+"</type>"; + xml += "</yield>\n"; + xml += "<preparation-time>"; + xml += ( *recipe_it ).prepTime.toString( "hh:mm" ); + xml += "</preparation-time>\n"; + xml += "</krecipes-description>\n"; + xml += "<krecipes-ingredients>\n"; + + IngredientList list_copy = ( *recipe_it ).ingList; + for ( IngredientList group_list = list_copy.firstGroup(); group_list.count() != 0; group_list = list_copy.nextGroup() ) { + TQString group = group_list[ 0 ].group; //just use the first's name... they're all the same + if ( !group.isEmpty() ) + xml += "<ingredient-group name=\"" + TQStyleSheet::escape(group) + "\">\n"; + + for ( IngredientList::const_iterator ing_it = group_list.begin(); ing_it != group_list.end(); ++ing_it ) { + xml += "<ingredient>\n"; + + xml += generateIngredient(*ing_it); + + if ( (*ing_it).substitutes.count() > 0 ) { + xml += "<substitutes>\n"; + for ( TQValueList<IngredientData>::const_iterator sub_it = (*ing_it).substitutes.begin(); sub_it != (*ing_it).substitutes.end(); ++sub_it ) { + xml += "<ingredient>\n"; + xml += generateIngredient(*sub_it); + xml += "</ingredient>\n"; + } + xml += "</substitutes>\n"; + } + + xml += "</ingredient>\n"; + } + + if ( !group.isEmpty() ) + xml += "</ingredient-group>\n"; + } + + /// @todo add ingredient properties + + xml += "</krecipes-ingredients>\n"; + xml += "<krecipes-instructions>\n"; + xml += TQStyleSheet::escape( ( *recipe_it ).instructions ); + xml += "</krecipes-instructions>\n"; + + //ratings + xml += "<krecipes-ratings>"; + for ( RatingList::const_iterator rating_it = (*recipe_it).ratingList.begin(); rating_it != (*recipe_it).ratingList.end(); ++rating_it ) { + xml += "<rating>"; + xml += "<comment>"+TQStyleSheet::escape( ( *rating_it ).comment )+"</comment>"; + xml += "<rater>"+TQStyleSheet::escape( ( *rating_it ).rater )+"</rater>"; + + xml += "<criterion>"; + for ( RatingCriteriaList::const_iterator rc_it = (*rating_it).ratingCriteriaList.begin(); rc_it != (*rating_it).ratingCriteriaList.end(); ++rc_it ) { + xml += "<criteria>"; + xml += "<name>"+(*rc_it).name+"</name>"; + xml += "<stars>"+TQString::number((*rc_it).stars)+"</stars>"; + xml += "</criteria>"; + } + xml += "</criterion>"; + xml += "</rating>"; + } + xml += "</krecipes-ratings>"; + + xml += "</krecipes-recipe>\n"; + } + + return xml; +} + +void KreExporter::createCategoryStructure( TQString &xml, const RecipeList &recipes ) +{ + TQValueList<int> categoriesUsed; + for ( RecipeList::const_iterator recipe_it = recipes.begin(); recipe_it != recipes.end(); ++recipe_it ) { + for ( ElementList::const_iterator cat_it = ( *recipe_it ).categoryList.begin(); cat_it != ( *recipe_it ).categoryList.end(); ++cat_it ) { + if ( categoriesUsed.find( ( *cat_it ).id ) == categoriesUsed.end() ) + categoriesUsed << ( *cat_it ).id; + } + } + + if ( !categoriesUsed.empty() ) { + //only keep the relevant category structure + removeIfUnused( categoriesUsed, categories ); + + xml += "<krecipes-category-structure>\n"; + writeCategoryStructure( xml, categories ); + xml += "</krecipes-category-structure>\n"; + } +} + +bool KreExporter::removeIfUnused( const TQValueList<int> &cat_ids, CategoryTree *parent, bool parent_should_show ) +{ + for ( CategoryTree * it = parent->firstChild(); it; it = it->nextSibling() ) { + if ( cat_ids.find( it->category.id ) != cat_ids.end() ) { + parent_should_show = true; + removeIfUnused( cat_ids, it, true ); //still recurse, but doesn't affect 'parent' + } + else { + bool result = removeIfUnused( cat_ids, it ); + if ( parent_should_show == false ) + parent_should_show = result; + } + } + + if ( !parent_should_show && parent->category.id != -1 ) { + //FIXME: CategoryTree is broken when deleting items + //delete parent; + + parent->category.id = -2; //temporary workaround + } + + return parent_should_show; +} + +void KreExporter::writeCategoryStructure( TQString &xml, const CategoryTree *categoryTree ) +{ + if ( categoryTree->category.id != -2 ) { + if ( categoryTree->category.id != -1 ) + xml += "<category name=\"" + TQStyleSheet::escape( categoryTree->category.name ).replace("\"",""") + "\">\n"; + + for ( CategoryTree * child_it = categoryTree->firstChild(); child_it; child_it = child_it->nextSibling() ) { + writeCategoryStructure( xml, child_it ); + } + + if ( categoryTree->category.id != -1 ) + xml += "</category>\n"; + } +} + |