diff options
Diffstat (limited to 'src/importers/baseimporter.cpp')
-rw-r--r-- | src/importers/baseimporter.cpp | 399 |
1 files changed, 399 insertions, 0 deletions
diff --git a/src/importers/baseimporter.cpp b/src/importers/baseimporter.cpp new file mode 100644 index 0000000..b0ecd61 --- /dev/null +++ b/src/importers/baseimporter.cpp @@ -0,0 +1,399 @@ +/*************************************************************************** +* 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 "baseimporter.h" + +#include <tdeapplication.h> +#include <tdeconfig.h> +#include <kdebug.h> +#include <tdelocale.h> +#include <kprogress.h> +#include <tdemessagebox.h> + +#include <tqvaluevector.h> + +#include "datablocks/recipe.h" +#include "backends/recipedb.h" +#include "datablocks/categorytree.h" +#include "datablocks/unit.h" + +BaseImporter::BaseImporter() : + m_recipe_list( new RecipeList ), + m_cat_structure( 0 ), + file_recipe_count( 0 ) +{ + TDEConfig * config = kapp->config(); + config->setGroup( "Import" ); + + direct = config->readBoolEntry( "DirectImport", false ); +} + +BaseImporter::~BaseImporter() +{ + delete m_recipe_list; + delete m_cat_structure; +} + +void BaseImporter::add( const RecipeList &recipe_list ) +{ + file_recipe_count += recipe_list.count(); + + for ( RecipeList::const_iterator it = recipe_list.begin(); it != recipe_list.end(); ++it ) { + Recipe copy = *it; + copy.recipeID = -1; //make sure an importer didn't give this a value + for ( RatingList::iterator rating_it = copy.ratingList.begin(); rating_it != copy.ratingList.end(); ++rating_it ) { + (*rating_it).id = -1; + } + m_recipe_list->append( copy ); + } + + if ( direct ) { + if ( !m_progress_dialog->wasCancelled() ) + importRecipes( *m_recipe_list, m_database, m_progress_dialog ); + } +} + +void BaseImporter::add( const Recipe &recipe ) +{ + file_recipe_count++; + Recipe copy = recipe; + copy.recipeID = -1; //make sure an importer didn't give this a value + + if ( direct ) { + if ( !m_progress_dialog->wasCancelled() ) { + RecipeList list; + list.append( recipe ); + importRecipes( list, m_database, m_progress_dialog ); + } + } + else + m_recipe_list->append( copy ); +} + +void BaseImporter::parseFiles( const TQStringList &filenames ) +{ + if ( direct ) + m_filenames = filenames; + else { + for ( TQStringList::const_iterator file_it = filenames.begin(); file_it != filenames.end(); ++file_it ) { + file_recipe_count = 0; + parseFile( *file_it ); + processMessages( *file_it ); + } + } +} + +void BaseImporter::import( RecipeDB *db, bool automatic ) +{ + if ( direct ) { + m_database = db; + + m_progress_dialog = new KProgressDialog( kapp->mainWidget(), 0, + i18n( "Importing selected recipes" ), TQString::null, true ); + KProgress *progress = m_progress_dialog->progressBar(); + progress->setPercentageVisible(false); + progress->setTotalSteps( 0 ); + + for ( TQStringList::const_iterator file_it = m_filenames.begin(); file_it != m_filenames.end(); ++file_it ) { + file_recipe_count = 0; + parseFile( *file_it ); + processMessages( *file_it ); + + if ( m_progress_dialog->wasCancelled() ) + break; + } + + importUnitRatios( db ); + delete m_progress_dialog; + } + else { + if ( m_recipe_list->count() == 0 ) + return; + + m_recipe_list->empty(); + //db->blockSignals(true); + + m_progress_dialog = new KProgressDialog( kapp->mainWidget(), 0, + i18n( "Importing selected recipes" ), TQString::null, true ); + KProgress *progress = m_progress_dialog->progressBar(); + progress->setTotalSteps( m_recipe_list->count() ); + progress->setFormat( i18n( "%v/%m Recipes" ) ); + + if ( m_cat_structure ) { + importCategoryStructure( db, m_cat_structure ); + delete m_cat_structure; + m_cat_structure = 0; + } + importRecipes( *m_recipe_list, db, m_progress_dialog ); + importUnitRatios( db ); + + //db->blockSignals(false); + delete m_progress_dialog; m_progress_dialog = 0; + } +} + +void BaseImporter::importIngredient( IngredientData &ing, RecipeDB *db, KProgressDialog *progress_dialog ) +{ + //cache some data we'll need + int max_units_length = db->maxUnitNameLength(); + int max_group_length = db->maxIngGroupNameLength(); + + if ( direct ) { + progress_dialog->progressBar()->advance( 1 ); + kapp->processEvents(); + } + + //create ingredient groups + TQString real_group_name = ing.group.left( max_group_length ); + int new_group_id = db->findExistingIngredientGroupByName(real_group_name); + if ( new_group_id == -1 ) { + db->createNewIngGroup( real_group_name ); + new_group_id = db->lastInsertID(); + } + ing.groupID = new_group_id; + + int new_ing_id = db->findExistingIngredientByName(ing.name); + if ( new_ing_id == -1 && !ing.name.isEmpty() ) + { + db->createNewIngredient( ing.name ); + new_ing_id = db->lastInsertID(); + } + + if ( direct ) { + progress_dialog->progressBar()->advance( 1 ); + kapp->processEvents(); + } + + Unit real_unit( ing.units.name.left( max_units_length ), ing.units.plural.left( max_units_length ) ); + if ( real_unit.name.isEmpty() ) + real_unit.name = real_unit.plural; + else if ( real_unit.plural.isEmpty() ) + real_unit.plural = real_unit.name; + + int new_unit_id = db->findExistingUnitByName(real_unit.name); + if ( new_unit_id == -1 ) { + db->createNewUnit( Unit(real_unit.name, real_unit.plural) ); + new_unit_id = db->lastInsertID(); + } + + if ( direct ) { + progress_dialog->progressBar()->advance( 1 ); + kapp->processEvents(); + } + + if ( ing.prepMethodList.count() > 0 ) { + for ( ElementList::iterator prep_it = ing.prepMethodList.begin(); prep_it != ing.prepMethodList.end(); ++prep_it ) { + int new_prep_id = db->findExistingPrepByName((*prep_it).name); + if ( new_prep_id == -1 ) { + db->createNewPrepMethod((*prep_it).name); + new_prep_id = db->lastInsertID(); + } + (*prep_it).id = new_prep_id; + } + } + + ing.units.id = new_unit_id; + ing.ingredientID = new_ing_id; + + if ( !db->ingredientContainsUnit( new_ing_id, new_unit_id ) ) + db->addUnitToIngredient( new_ing_id, new_unit_id ); +} + +void BaseImporter::importRecipes( RecipeList &selected_recipes, RecipeDB *db, KProgressDialog *progress_dialog ) +{ + // Load Current Settings + TDEConfig *config = kapp->config(); + config->setGroup( "Import" ); + bool overwrite = config->readBoolEntry( "OverwriteExisting", false ); + + RecipeList::iterator recipe_it; RecipeList::iterator recipe_list_end( selected_recipes.end() ); + RecipeList::iterator recipe_it_old = selected_recipes.end(); + for ( recipe_it = selected_recipes.begin(); recipe_it != recipe_list_end; ++recipe_it ) { + if ( !direct ) { + if ( progress_dialog->wasCancelled() ) { + KMessageBox::information( kapp->mainWidget(), i18n( "All recipes up unto this point have been successfully imported." ) ); + //db->blockSignals(false); + return ; + } + } + + if ( recipe_it_old != selected_recipes.end() ) + selected_recipes.remove( recipe_it_old ); + + progress_dialog->setLabel( TQString( i18n( "Importing recipe: %1" ) ).arg( ( *recipe_it ).title ) ); + progress_dialog->progressBar()->advance( 1 ); + kapp->processEvents(); + + //add all recipe items (authors, ingredients, etc. to the database if they aren't already + IngredientList::iterator ing_list_end( ( *recipe_it ).ingList.end() ); + for ( IngredientList::iterator ing_it = ( *recipe_it ).ingList.begin(); ing_it != ing_list_end; ++ing_it ) { + importIngredient( *ing_it, db, progress_dialog ); + + for ( TQValueList<IngredientData>::iterator sub_it = (*ing_it).substitutes.begin(); sub_it != (*ing_it).substitutes.end(); ++sub_it ) { + importIngredient( *sub_it, db, progress_dialog ); + } + } + + ElementList::iterator author_list_end( ( *recipe_it ).authorList.end() ); + for ( ElementList::iterator author_it = ( *recipe_it ).authorList.begin(); author_it != author_list_end; ++author_it ) { + if ( direct ) { + progress_dialog->progressBar()->advance( 1 ); + kapp->processEvents(); + } + + int new_author_id = db->findExistingAuthorByName(( *author_it ).name); + if ( new_author_id == -1 && !( *author_it ).name.isEmpty() ) { + db->createNewAuthor( ( *author_it ).name ); + new_author_id = db->lastInsertID(); + } + + ( *author_it ).id = new_author_id; + } + + ElementList::iterator cat_list_end( ( *recipe_it ).categoryList.end() ); + for ( ElementList::iterator cat_it = ( *recipe_it ).categoryList.begin(); cat_it != cat_list_end; ++cat_it ) { + if ( direct ) { + progress_dialog->progressBar()->advance( 1 ); + kapp->processEvents(); + } + + int new_cat_id = db->findExistingCategoryByName(( *cat_it ).name); + if ( new_cat_id == -1 && !( *cat_it ).name.isEmpty() ) { + db->createNewCategory( ( *cat_it ).name ); + new_cat_id = db->lastInsertID(); + } + + ( *cat_it ).id = new_cat_id; + } + + if ( !(*recipe_it).yield.type.isEmpty() ) { + int new_id = db->findExistingYieldTypeByName((*recipe_it).yield.type); + if ( new_id == -1 ) { + db->createNewYieldType( (*recipe_it).yield.type ); + new_id = db->lastInsertID(); + } + (*recipe_it).yield.type_id = new_id; + } + + RatingList::iterator rating_list_end( ( *recipe_it ).ratingList.end() ); + for ( RatingList::iterator rating_it = ( *recipe_it ).ratingList.begin(); rating_it != rating_list_end; ++rating_it ) { + if ( direct ) { + progress_dialog->progressBar()->advance( 1 ); + kapp->processEvents(); + } + + for ( RatingCriteriaList::iterator rc_it = (*rating_it).ratingCriteriaList.begin(); rc_it != (*rating_it).ratingCriteriaList.end(); ++rc_it ) { + int new_criteria_id = db->findExistingRatingByName(( *rc_it ).name); + if ( new_criteria_id == -1 && !( *rc_it ).name.isEmpty() ) { + db->createNewRating( ( *rc_it ).name ); + new_criteria_id = db->lastInsertID(); + } + + ( *rc_it ).id = new_criteria_id; + } + } + + if ( overwrite ) //overwrite existing + ( *recipe_it ).recipeID = db->findExistingRecipeByName( ( *recipe_it ).title ); + else //rename + ( *recipe_it ).title = db->getUniqueRecipeTitle( ( *recipe_it ).title ); + + if ( direct ) { + progress_dialog->progressBar()->advance( 1 ); + kapp->processEvents(); + } + + //save into the database + db->saveRecipe( &( *recipe_it ) ); + + recipe_it_old = recipe_it; //store to delete once we've got the next recipe + } +} + +void BaseImporter::setCategoryStructure( CategoryTree *cat_structure ) +{ + if ( direct ) { + importCategoryStructure( m_database, cat_structure ); + } + else { + delete m_cat_structure; + m_cat_structure = cat_structure; + } +} + +void BaseImporter::importCategoryStructure( RecipeDB *db, const CategoryTree *categoryTree ) +{ + for ( CategoryTree * child_it = categoryTree->firstChild(); child_it; child_it = child_it->nextSibling() ) { + int new_cat_id = db->findExistingCategoryByName( child_it->category.name ); + if ( new_cat_id == -1 ) { + db->createNewCategory( child_it->category.name, categoryTree->category.id ); + new_cat_id = db->lastInsertID(); + } + + child_it->category.id = new_cat_id; + + importCategoryStructure( db, child_it ); + } +} + +void BaseImporter::setUnitRatioInfo( UnitRatioList &ratioList, UnitList &unitList ) +{ + m_ratioList = ratioList; + m_unitList = unitList; +} + +void BaseImporter::importUnitRatios( RecipeDB *db ) +{ + for ( UnitRatioList::const_iterator it = m_ratioList.begin(); it != m_ratioList.end(); ++it ) { + TQString unitName1, unitName2; + for ( UnitList::const_iterator unit_it = m_unitList.begin(); unit_it != m_unitList.end(); ++unit_it ) { + if ( ( *it ).uID1 == ( *unit_it ).id ) { + unitName1 = ( *unit_it ).name; + if ( !unitName2.isNull() ) + break; + } + else if ( ( *it ).uID2 == ( *unit_it ).id ) { + unitName2 = ( *unit_it ).name; + if ( !unitName1.isNull() ) + break; + } + } + + int unitId1 = db->findExistingUnitByName( unitName1 ); + int unitId2 = db->findExistingUnitByName( unitName2 ); + + //the unit needed for the ratio may not have been added, because the + //recipes chosen did not include the unit + if ( unitId1 != -1 && unitId2 != -1 ) { + UnitRatio ratio; + ratio.uID1 = unitId1; + ratio.uID2 = unitId2; + ratio.ratio = ( *it ).ratio; + db->saveUnitRatio( &ratio ); + } + } +} + +void BaseImporter::processMessages( const TQString &file ) +{ + if ( m_error_msgs.count() > 0 ) { + //<!doc> ensures it is detected as RichText + m_master_error += TQString( i18n( "<!doc>Import of recipes from the file <b>\"%1\"</b> <b>failed</b> due to the following error(s):" ) ).arg( file ); + m_master_error += "<ul><li>" + m_error_msgs.join( "</li><li>" ) + "</li></ul>"; + + m_error_msgs.clear(); + } + else if ( m_warning_msgs.count() > 0 ) { + m_master_warning += TQString( i18n( "The file <b>%1</b> generated the following warning(s):" ) ).arg( file ); + m_master_warning += "<ul><li>" + m_warning_msgs.join( "</li><li>" ) + "</li></ul>"; + + m_warning_msgs.clear(); + } +} |