Shift to master. Not done but database abstraction is nearly done. #3
			
				
			
		
		
		
	
							
								
								
									
										5
									
								
								main.cpp
								
								
								
								
							
							
						
						
									
										5
									
								
								main.cpp
								
								
								
								
							| 
						 | 
				
			
			@ -30,11 +30,10 @@ int main(int argc, char *argv[])
 | 
			
		|||
	bool success = recipeDB.storeRecipe(rec);
 | 
			
		||||
	printf("Storage successful: %d\n", success);
 | 
			
		||||
 | 
			
		||||
	recipeDB.executeSQL("SELECT * FROM recipeIngredient;").printData();
 | 
			
		||||
 | 
			
		||||
	Recipe reloadRec = recipeDB.retrieveRecipe("Example");
 | 
			
		||||
	reloadRec.print();
 | 
			
		||||
 | 
			
		||||
	w.loadFromRecipe(rec);
 | 
			
		||||
	w.loadFromRecipe(reloadRec);
 | 
			
		||||
 | 
			
		||||
	return a.exec();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,7 +8,6 @@ bool RecipeDatabase::storeRecipe(Recipe recipe){
 | 
			
		|||
	///TODO: Implement this in a smart way using transaction.
 | 
			
		||||
	this->executeSQL("BEGIN;");
 | 
			
		||||
	ResultTable t = this->selectFrom("recipe", "*", "name="+surroundString(recipe.getName(), "'"));
 | 
			
		||||
	//ResultTable t = this->executeSQL("SELECT * FROM recipe WHERE name='"+recipe.getName()+"';");
 | 
			
		||||
	if (!t.isEmpty()){
 | 
			
		||||
		fprintf(stderr, "Error storing recipe: Recipe with name %s already exists.\n", recipe.getName().c_str());
 | 
			
		||||
	} else {
 | 
			
		||||
| 
						 | 
				
			
			@ -28,7 +27,7 @@ bool RecipeDatabase::storeRecipe(Recipe recipe){
 | 
			
		|||
											std::to_string(recipe.getServings())
 | 
			
		||||
										}));
 | 
			
		||||
		if (success){
 | 
			
		||||
			//If successful, proceed to insert instructions, image, and ingredients.
 | 
			
		||||
			//If successful, proceed to insert instructions, image, and ingredients, and tags.
 | 
			
		||||
			int recipeId = this->getLastInsertedRowId();
 | 
			
		||||
			bool ingredientSuccess = true;
 | 
			
		||||
			for (unsigned int i = 0; i < recipe.getIngredients().size(); i++){
 | 
			
		||||
| 
						 | 
				
			
			@ -37,7 +36,10 @@ bool RecipeDatabase::storeRecipe(Recipe recipe){
 | 
			
		|||
					break;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if (ingredientSuccess && this->storeInstruction(recipe.getInstruction(), recipeId) && this->storeImage(recipe.getImage(), recipeId)){
 | 
			
		||||
			if (ingredientSuccess &&
 | 
			
		||||
					this->storeInstruction(recipe.getInstruction(), recipeId) &&
 | 
			
		||||
					this->storeImage(recipe.getImage(), recipeId) &&
 | 
			
		||||
					this->storeTags(recipe.getTags(), recipeId)){
 | 
			
		||||
				this->executeSQL("COMMIT;");
 | 
			
		||||
				return true;
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -50,7 +52,6 @@ bool RecipeDatabase::storeRecipe(Recipe recipe){
 | 
			
		|||
bool RecipeDatabase::storeRecipeIngredient(RecipeIngredient ri, int recipeId){
 | 
			
		||||
	//First check if the base ingredient has been added to the database. This is done within storeIngredient().
 | 
			
		||||
	ResultTable t = this->selectFrom("ingredient", "ingredientId", "name="+surroundString(ri.getName(), "'"));
 | 
			
		||||
	//ResultTable t = this->executeSQL("SELECT ingredientId FROM ingredient WHERE name='"+ri.getName()+"';");
 | 
			
		||||
	int ingId = 0;
 | 
			
		||||
	if (t.isEmpty()){
 | 
			
		||||
		if (!this->insertInto("ingredient", vector<string>({"foodGroup", "name"}), vector<string>({ri.getFoodGroup(), ri.getName()}))){
 | 
			
		||||
| 
						 | 
				
			
			@ -79,7 +80,6 @@ bool RecipeDatabase::storeRecipeIngredient(RecipeIngredient ri, int recipeId){
 | 
			
		|||
 | 
			
		||||
void RecipeDatabase::storeIngredient(Ingredient ingredient){
 | 
			
		||||
	ResultTable t = this->selectFrom("ingredient", "*", "name="+surroundString(ingredient.getName(), "'"));
 | 
			
		||||
	//ResultTable t = this->executeSQL("SELECT * FROM ingredient WHERE name='"+ingredient.getName()+"';");
 | 
			
		||||
	if (t.isEmpty()){
 | 
			
		||||
		this->insertInto("ingredient", vector<string>({"foodGroup", "name"}), vector<string>({ingredient.getFoodGroup(), ingredient.getName()}));
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -93,6 +93,24 @@ bool RecipeDatabase::storeImage(QImage image, int recipeId){
 | 
			
		|||
	return FileUtils::saveImage(recipeId, image);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RecipeDatabase::storeTags(vector<RecipeTag> tags, int recipeId){
 | 
			
		||||
	for (vector<RecipeTag>::iterator it = tags.begin(); it != tags.end(); ++it){
 | 
			
		||||
		bool s = this->insertInto("recipeTag",
 | 
			
		||||
								  vector<string>({
 | 
			
		||||
													 "recipeId",
 | 
			
		||||
													 "tagName"
 | 
			
		||||
												 }),
 | 
			
		||||
								  vector<string>({
 | 
			
		||||
													 std::to_string(recipeId),
 | 
			
		||||
													 (*it).getValue()
 | 
			
		||||
												 }));
 | 
			
		||||
		if (!s){
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Recipe RecipeDatabase::retrieveRecipe(string name){
 | 
			
		||||
	ResultTable t = this->selectFrom("recipe", "*", "name="+surroundString(name, "'"));
 | 
			
		||||
	if (t.isEmpty()){
 | 
			
		||||
| 
						 | 
				
			
			@ -100,12 +118,39 @@ Recipe RecipeDatabase::retrieveRecipe(string name){
 | 
			
		|||
		return Recipe();
 | 
			
		||||
	}
 | 
			
		||||
	t.printData();
 | 
			
		||||
	return Recipe();
 | 
			
		||||
	Recipe r;
 | 
			
		||||
	int id = std::stoi(t.valueAt(0, 0));
 | 
			
		||||
	r.setName(t.valueAt(0, 1));
 | 
			
		||||
	r.setCreatedDate(QDate::fromString(QString::fromStdString(t.valueAt(0, 2))));
 | 
			
		||||
	r.setPrepTime(QTime::fromString(QString::fromStdString(t.valueAt(0, 3))));
 | 
			
		||||
	r.setCookTime(QTime::fromString(QString::fromStdString(t.valueAt(0, 4))));
 | 
			
		||||
	r.setServings(std::stof(t.valueAt(0, 5)));
 | 
			
		||||
	r.setInstruction(FileUtils::loadInstruction(id));
 | 
			
		||||
	r.setImage(FileUtils::loadImage(id));
 | 
			
		||||
	r.setIngredients(this->retrieveRecipeIngredients(id));
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
vector<RecipeIngredient> RecipeDatabase::retrieveRecipeIngredients(int recipeId){
 | 
			
		||||
	ResultTable t = this->executeSQL("SELECT ingredient.name, ingredient.foodGroup, recipeIngredient.quantity, recipeIngredient.unitName, recipeIngredient.comment "
 | 
			
		||||
									 "FROM ingredient "
 | 
			
		||||
									 "INNER JOIN recipeIngredient "
 | 
			
		||||
									 "ON ingredient.ingredientId = recipeIngredient.ingredientId "
 | 
			
		||||
									 "AND recipeIngredient.recipeId = "+std::to_string(recipeId)+";");
 | 
			
		||||
	t.printData();
 | 
			
		||||
	vector<RecipeIngredient> ings;
 | 
			
		||||
	for (unsigned int row = 0; row < t.rowCount(); row++){
 | 
			
		||||
		RecipeIngredient r(t.valueAt(row, 0), t.valueAt(row, 1), std::stof(t.valueAt(row, 2)), UnitOfMeasure(t.valueAt(row, 3)));
 | 
			
		||||
		ings.push_back(r);
 | 
			
		||||
	}
 | 
			
		||||
	return ings;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RecipeDatabase::ensureTablesExist(){
 | 
			
		||||
	//Make sure that foreign keys are enabled.
 | 
			
		||||
	this->executeSQL("PRAGMA foreign_keys = ON;");
 | 
			
		||||
 | 
			
		||||
	this->executeSQL("BEGIN;");
 | 
			
		||||
	//Ingredients table.
 | 
			
		||||
	this->executeSQL("CREATE TABLE IF NOT EXISTS ingredient("
 | 
			
		||||
					 "ingredientId INTEGER PRIMARY KEY,"
 | 
			
		||||
| 
						 | 
				
			
			@ -114,14 +159,14 @@ void RecipeDatabase::ensureTablesExist(){
 | 
			
		|||
	//Recipe table. Each recipe can have at most one instruction, and one image.
 | 
			
		||||
	this->executeSQL("CREATE TABLE IF NOT EXISTS recipe("
 | 
			
		||||
					 "recipeId INTEGER PRIMARY KEY,"
 | 
			
		||||
					 "createdDate date,"
 | 
			
		||||
					 "name varchar UNIQUE,"
 | 
			
		||||
					 "cookTime time,"
 | 
			
		||||
					 "createdDate date,"
 | 
			
		||||
					 "prepTime time,"
 | 
			
		||||
					 "cookTime time,"
 | 
			
		||||
					 "servingCount real);");
 | 
			
		||||
	//Recipe tags table.
 | 
			
		||||
	this->executeSQL("CREATE TABLE IF NOT EXISTS recipeTag("
 | 
			
		||||
					 "recipeId INTEGER PRIMARY KEY,"
 | 
			
		||||
					 "recipeId int,"
 | 
			
		||||
					 "tagName varchar,"
 | 
			
		||||
					 "FOREIGN KEY (recipeId) REFERENCES recipe(recipeId));");
 | 
			
		||||
	//RecipeIngredient table.
 | 
			
		||||
| 
						 | 
				
			
			@ -133,4 +178,5 @@ void RecipeDatabase::ensureTablesExist(){
 | 
			
		|||
					 "comment varchar,"
 | 
			
		||||
					 "FOREIGN KEY (ingredientId) REFERENCES ingredient(ingredientId),"
 | 
			
		||||
					 "FOREIGN KEY (recipeId) REFERENCES recipe(recipeId));");
 | 
			
		||||
	this->executeSQL("COMMIT;");
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,8 +26,10 @@ class RecipeDatabase : public Database
 | 
			
		|||
		void storeIngredient(Ingredient ingredient);
 | 
			
		||||
		bool storeInstruction(Instruction instruction, int recipeId);
 | 
			
		||||
		bool storeImage(QImage image, int recipeId);
 | 
			
		||||
		bool storeTags(vector<RecipeTag> tags, int recipeId);
 | 
			
		||||
 | 
			
		||||
		Recipe retrieveRecipe(string name);
 | 
			
		||||
		vector<RecipeIngredient> retrieveRecipeIngredients(int recipeId);
 | 
			
		||||
	private:
 | 
			
		||||
 | 
			
		||||
		//Utility methods.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,7 +9,11 @@ RecipeIngredient::RecipeIngredient(Ingredient i, float quantity, UnitOfMeasure u
 | 
			
		|||
    setName(i.getName());
 | 
			
		||||
    setFoodGroup(i.getFoodGroup());
 | 
			
		||||
    setQuantity(quantity);
 | 
			
		||||
    setUnit(unit);
 | 
			
		||||
	setUnit(unit);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RecipeIngredient::RecipeIngredient(){
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float RecipeIngredient::getQuantity() const{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,6 +19,7 @@ public:
 | 
			
		|||
    RecipeIngredient(string name, string foodGroup, float quantity, UnitOfMeasure unit);
 | 
			
		||||
    //Constructor using data from a child ingredient.
 | 
			
		||||
    RecipeIngredient(Ingredient i, float quantity, UnitOfMeasure unit);
 | 
			
		||||
	RecipeIngredient();
 | 
			
		||||
 | 
			
		||||
    //Getters
 | 
			
		||||
    float getQuantity() const;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,14 @@
 | 
			
		|||
UnitOfMeasure::UnitOfMeasure(string name, string plural, string abbreviation){
 | 
			
		||||
    this->name = name;
 | 
			
		||||
    this->plural = plural;
 | 
			
		||||
    this->abbreviation = abbreviation;
 | 
			
		||||
	this->abbreviation = abbreviation;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
UnitOfMeasure::UnitOfMeasure(string name){
 | 
			
		||||
	this->name = name;
 | 
			
		||||
	this->plural = name + "s";
 | 
			
		||||
	this->abbreviation = "NULL";
 | 
			
		||||
	///TODO: Make actual guessing of this stuff.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
UnitOfMeasure::UnitOfMeasure() : UnitOfMeasure::UnitOfMeasure("", "", ""){
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,6 +14,8 @@ class UnitOfMeasure
 | 
			
		|||
public:
 | 
			
		||||
    //Full constructor.
 | 
			
		||||
    UnitOfMeasure(string name, string plural, string abbreviation);
 | 
			
		||||
	//Attempt to guess unit from just a string.
 | 
			
		||||
	UnitOfMeasure(string name);
 | 
			
		||||
    //Constructor with default values.
 | 
			
		||||
    UnitOfMeasure();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,7 +29,11 @@ Instruction Recipe::getInstruction() const{
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
QImage Recipe::getImage() const{
 | 
			
		||||
    return this->image;
 | 
			
		||||
	return this->image;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
vector<RecipeTag> Recipe::getTags() const{
 | 
			
		||||
	return this->tags;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QDate Recipe::getCreatedDate() const{
 | 
			
		||||
| 
						 | 
				
			
			@ -89,5 +93,29 @@ void Recipe::setCookTime(QTime newTime){
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void Recipe::setServings(float newServingsCount){
 | 
			
		||||
    this->servings = newServingsCount;
 | 
			
		||||
	this->servings = newServingsCount;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Recipe::print(){
 | 
			
		||||
	printf("Recipe: %s, Created on: %s, Prep time: %s, Cook time: %s, Serves: %f\n",
 | 
			
		||||
		   this->name.c_str(),
 | 
			
		||||
		   this->createdDate.toString().toStdString().c_str(),
 | 
			
		||||
		   this->prepTime.toString().toStdString().c_str(),
 | 
			
		||||
		   this->cookTime.toString().toStdString().c_str(),
 | 
			
		||||
		   this->servings);
 | 
			
		||||
	printf("\tInstruction: %s\n", this->instruction.getHTML().c_str());
 | 
			
		||||
	printf("\tIngredients:\n");
 | 
			
		||||
	for (vector<RecipeIngredient>::iterator it = this->ingredients.begin(); it != this->ingredients.end(); ++it){
 | 
			
		||||
		RecipeIngredient ri = *it;
 | 
			
		||||
		printf("\t\t%s, Food Group: %s, Quantity: %f, Unit: %s\n",
 | 
			
		||||
			   ri.getName().c_str(),
 | 
			
		||||
			   ri.getFoodGroup().c_str(),
 | 
			
		||||
			   ri.getQuantity(),
 | 
			
		||||
			   ri.getUnit().getName().c_str());
 | 
			
		||||
	}
 | 
			
		||||
	printf("\tTags:\n");
 | 
			
		||||
	for (vector<RecipeTag>::iterator it = this->tags.begin(); it != this->tags.end(); ++it){
 | 
			
		||||
		RecipeTag t = *it;
 | 
			
		||||
		printf("\t\t%s\n", t.getValue().c_str());
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -58,6 +58,8 @@ public:
 | 
			
		|||
    void setPrepTime(QTime newTime);
 | 
			
		||||
    void setCookTime(QTime newTime);
 | 
			
		||||
    void setServings(float newServingsCount);
 | 
			
		||||
 | 
			
		||||
	void print();
 | 
			
		||||
private:
 | 
			
		||||
    //Main information.
 | 
			
		||||
    string name;                                //The name of the recipe.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue