diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index bc09378..c552432 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -19,19 +19,24 @@ MainWindow::~MainWindow(){ } void MainWindow::loadFromRecipe(Recipe recipe){ - setRecipeName(recipe.getName()); - setInstruction(recipe.getInstruction()); - setIngredients(recipe.getIngredients()); - if (recipe.getImage().isNull()){ - setImage(QImage(QString(":/images/images/no_image.png"))); + if (recipe.isEmpty()){ + setRecipeName("No recipes found."); + setAuthorName("Click 'New' to get started."); } else { - setImage(recipe.getImage()); + setRecipeName(recipe.getName()); + setInstruction(recipe.getInstruction()); + setIngredients(recipe.getIngredients()); + if (recipe.getImage().isNull()){ + setImage(QImage(QString(":/images/images/no_image.png"))); + } else { + setImage(recipe.getImage()); + } + setPrepTime(recipe.getPrepTime()); + setCookTime(recipe.getCookTime()); + setServings(recipe.getServings()); + setTags(recipe.getTags()); + this->currentRecipe = recipe; } - setPrepTime(recipe.getPrepTime()); - setCookTime(recipe.getCookTime()); - setServings(recipe.getServings()); - setTags(recipe.getTags()); - this->currentRecipe = recipe; } void MainWindow::setRecipeName(string name){ @@ -66,6 +71,10 @@ void MainWindow::setTags(vector tags){ this->tagsListModel.setTags(tags); } +void MainWindow::setAuthorName(string name){ + ui->authorLabel->setText(QString::fromStdString(name)); +} + void MainWindow::on_newButton_clicked(){ NewRecipeDialog d(this->recipeDB, this); d.show(); diff --git a/gui/mainwindow.h b/gui/mainwindow.h index 3ce5cf4..70ab7be 100644 --- a/gui/mainwindow.h +++ b/gui/mainwindow.h @@ -54,6 +54,7 @@ public: void setCookTime(QTime cookTime); void setServings(float servings); void setTags(vector tags); + void setAuthorName(string name); }; #endif // MAINWINDOW_H diff --git a/gui/mainwindow.ui b/gui/mainwindow.ui index 23922da..69bddb9 100644 --- a/gui/mainwindow.ui +++ b/gui/mainwindow.ui @@ -364,7 +364,7 @@ font: "Noto Sans CJK KR"; - false + true diff --git a/gui/newrecipedialog.cpp b/gui/newrecipedialog.cpp index ac3258c..fc8657f 100644 --- a/gui/newrecipedialog.cpp +++ b/gui/newrecipedialog.cpp @@ -23,6 +23,7 @@ NewRecipeDialog::NewRecipeDialog(RecipeDatabase *db, QWidget *parent) : NewRecip NewRecipeDialog::NewRecipeDialog(RecipeDatabase *db, Recipe recipe, QWidget *parent) : NewRecipeDialog(db, parent){ ui->recipeNameEdit->setText(QString::fromStdString(recipe.getName())); + ui->authorNameEdit->setText(QString::fromStdString(recipe.getAuthor())); ui->prepTimeEdit->setTime(recipe.getPrepTime()); ui->cookTimeEdit->setTime(recipe.getCookTime()); ui->servingsSpinBox->setValue((double)recipe.getServings()); @@ -38,6 +39,7 @@ NewRecipeDialog::~NewRecipeDialog(){ Recipe NewRecipeDialog::getRecipe(){ Recipe r(ui->recipeNameEdit->text().toStdString(), + ui->authorNameEdit->text().toStdString(), this->ingredientListModel.getIngredients(), ui->instructionsTextEdit->toHtml().toStdString(), ui->imageDisplayLabel->pixmap()->toImage(),//Image diff --git a/gui/newrecipedialog.ui b/gui/newrecipedialog.ui index a42a7a2..50bee64 100644 --- a/gui/newrecipedialog.ui +++ b/gui/newrecipedialog.ui @@ -96,15 +96,25 @@ + + 0 + + 14 3 false false + + background-color: rgb(255, 255, 255); + + + false + Qt::AlignCenter @@ -113,6 +123,30 @@ + + + + + 12 + 3 + false + false + + + + background-color: rgb(245, 245, 255); + + + false + + + Qt::AlignCenter + + + Author + + + @@ -141,7 +175,7 @@ 0 1999 12 - 23 + 22 @@ -252,6 +286,9 @@ + + 2 + 0 @@ -285,6 +322,9 @@ Create a new tag + + background-color: rgb(255, 255, 255); + :/images/images/plus_icon.png:/images/images/plus_icon.png @@ -296,6 +336,9 @@ Permanently delete this tag + + background-color: rgb(255, 255, 255); + :/images/images/minus_icon.png:/images/images/minus_icon.png @@ -308,6 +351,9 @@ + + 0 + 0 @@ -322,6 +368,27 @@ + + + 0 + 20 + + + + Add the above tag to the recipe + + + QPushButton#addTagButton { + background-color: rgb(235, 235, 255); + border: 0px; +} +QPushButton#addTagButton:hover{ + background-color: rgb(245, 245, 255); +} +QPushButton#addTagButton:pressed{ + background-color: rgb(255, 255, 255); +} + Add @@ -329,8 +396,29 @@ + + + 0 + 20 + + + + Remove this tag from the recipe + + + QPushButton#deleteTagButton { + background-color: rgb(225, 225, 255); + border: 0px; +} +QPushButton#deleteTagButton:hover{ + background-color: rgb(235, 235, 255); +} +QPushButton#deleteTagButton:pressed{ + background-color: rgb(245, 245, 255); +} + - Delete + Remove @@ -434,7 +522,7 @@ - Add Ingredient + Ingredients Qt::AlignCenter @@ -497,6 +585,9 @@ + + Delete this ingredient + @@ -581,6 +672,9 @@ + + Create a new unit of measure + :/images/images/plus_icon.png:/images/images/plus_icon.png @@ -589,6 +683,9 @@ + + Delete this unit of measure + @@ -626,6 +723,9 @@ + + 0 + 0 @@ -640,6 +740,27 @@ + + + 0 + 30 + + + + Add the above ingredient to the recipe + + + QPushButton#addIngredientButton { + background-color: rgb(235, 235, 255); + border: 0px; +} +QPushButton#addIngredientButton:hover{ + background-color: rgb(245, 245, 255); +} +QPushButton#addIngredientButton:pressed{ + background-color: rgb(255, 255, 255); +} + Add @@ -647,8 +768,29 @@ + + + 0 + 30 + + + + Remove this ingredient from the recipe + + + QPushButton#removeIngredientButton { + background-color: rgb(225, 225, 255); + border: 0px; +} +QPushButton#removeIngredientButton:hover{ + background-color: rgb(235, 235, 255); +} +QPushButton#removeIngredientButton:pressed{ + background-color: rgb(245, 245, 255); +} + - Delete + Remove diff --git a/main.cpp b/main.cpp index 42982af..cdd2938 100644 --- a/main.cpp +++ b/main.cpp @@ -8,19 +8,24 @@ void test(RecipeDatabase *recipeDB); +Recipe checkForFirstRun(RecipeDatabase *recipeDB){ + Recipe r = recipeDB->retrieveRandomRecipe(); + if (r.isEmpty()){//There are no recipes in the database. + //Add some basic units to the units, and some basic ingredients. + recipeDB->addBasicUnits(); + recipeDB->addBasicIngredients(); + } + return r; +} + int main(int argc, char *argv[]) { RecipeDatabase recipeDB(QString(FileUtils::appDataPath+"recipes.db").toStdString()); - QApplication a(argc, argv); + + QApplication a(argc, argv); MainWindow w(&recipeDB); - w.show(); - - //TESTING CODE - //test(&recipeDB); - - //END TESTING CODE. - - w.loadFromRecipe(recipeDB.retrieveRandomRecipe()); + w.loadFromRecipe(checkForFirstRun(&recipeDB)); + w.show(); a.exec(); recipeDB.closeConnection(); @@ -34,6 +39,7 @@ void test(RecipeDatabase *recipeDB){ ri.push_back(RecipeIngredient("baking powder", "additives", 1.0f, UnitOfMeasure("teaspoon", "teaspoons", "tsp", UnitOfMeasure::VOLUME, 1.0), "")); Recipe rec("Example", + "Andrew Lalis", ri, Instruction("Placeholder Text"), QImage(), diff --git a/model/database/recipedatabase.cpp b/model/database/recipedatabase.cpp index 42bf4ff..bae0eae 100644 --- a/model/database/recipedatabase.cpp +++ b/model/database/recipedatabase.cpp @@ -12,7 +12,7 @@ bool RecipeDatabase::storeRecipe(Recipe recipe){ return false; } //Store a recipe, if it doesn't already exist. This first tries to create the recipe entry, then all subsequent supporting table entries. - this->executeSQL("BEGIN;"); + this->beginTransaction(); ResultTable t = this->selectFrom("recipe", "*", "WHERE name="+surroundString(recipe.getName(), "'")); if (!t.isEmpty()){ fprintf(stderr, "Error storing recipe: Recipe with name %s already exists.\n", recipe.getName().c_str()); @@ -20,6 +20,7 @@ bool RecipeDatabase::storeRecipe(Recipe recipe){ bool success = this->insertInto("recipe", vector({ "name", + "authorName", "createdDate", "cookTime", "prepTime", @@ -27,6 +28,7 @@ bool RecipeDatabase::storeRecipe(Recipe recipe){ }), vector({ recipe.getName(), + recipe.getAuthor(), recipe.getCreatedDate().toString().toStdString(), recipe.getCookTime().toString().toStdString(), recipe.getPrepTime().toString().toStdString(), @@ -46,12 +48,12 @@ bool RecipeDatabase::storeRecipe(Recipe recipe){ this->storeInstruction(recipe.getInstruction(), recipeId) && this->storeImage(recipe.getImage(), recipeId) && this->storeTags(recipe.getTags(), recipeId)){ - this->executeSQL("COMMIT;"); + this->commitTransaction(); return true; } } } - this->executeSQL("ROLLBACK;"); + this->rollbackTransaction(); return false; } @@ -158,7 +160,7 @@ Recipe RecipeDatabase::retrieveRandomRecipe(){ } return this->readFromResultTable(t); } -//TODO: Change this to be more efficient! One query per recipe is not good! + vector RecipeDatabase::retrieveAllRecipes(){ ResultTable t = this->executeSQL("SELECT * FROM recipe ORDER BY name;"); return this->readRecipesFromTable(t); @@ -326,7 +328,7 @@ bool RecipeDatabase::deleteRecipe(int recipeId){ printf("Cannot delete. No recipe with ID %d exists.\n", recipeId); return false; } - this->executeSQL("BEGIN;"); + this->beginTransaction(); bool tagsDeleted = this->deleteFrom("recipeTag", "WHERE recipeId="+idString); bool recipeIngredientDeleted = this->deleteFrom("recipeIngredient", "WHERE recipeId="+idString); bool recipeDeleted = this->deleteFrom("recipe", "WHERE recipeId="+idString); @@ -335,10 +337,10 @@ bool RecipeDatabase::deleteRecipe(int recipeId){ Q_UNUSED(instructionDeleted); Q_UNUSED(imageDeleted); if (tagsDeleted && recipeIngredientDeleted && recipeDeleted){ - this->executeSQL("COMMIT;"); + this->commitTransaction(); return true; } else { - this->executeSQL("ROLLBACK;"); + this->rollbackTransaction(); return false; } } @@ -374,6 +376,7 @@ bool RecipeDatabase::updateRecipe(Recipe recipe, string originalName) { this->beginTransaction(); ResultTable t = this->executeSQL("UPDATE recipe " "SET name = '"+recipe.getName()+"', " + "authorName = '"+recipe.getAuthor()+"', " "createdDate = '"+recipe.getCreatedDate().toString().toStdString()+"', " "prepTime = '"+recipe.getPrepTime().toString().toStdString()+"', " "cookTime = '"+recipe.getCookTime().toString().toStdString()+"', " @@ -435,11 +438,55 @@ bool RecipeDatabase::updateRecipe(Recipe recipe, string originalName) { } } +bool RecipeDatabase::addBasicUnits(){ + this->beginTransaction(); + //Volume + this->storeUnitOfMeasure(UnitOfMeasure("Teaspoon", "Teaspoons", "tsp", UnitOfMeasure::VOLUME, 5.0)); + this->storeUnitOfMeasure(UnitOfMeasure("Tablespoon", "Tablespoons", "tbsp", UnitOfMeasure::VOLUME, 15.0)); + this->storeUnitOfMeasure(UnitOfMeasure("Fluid Ounce", "Fluid Ounces", "fl oz", UnitOfMeasure::VOLUME, 30.0)); + this->storeUnitOfMeasure(UnitOfMeasure("Cup", "Cups", "c", UnitOfMeasure::VOLUME, 250.0)); + this->storeUnitOfMeasure(UnitOfMeasure("Milliliter", "Milliliters", "mL", UnitOfMeasure::VOLUME, 1.0)); + this->storeUnitOfMeasure(UnitOfMeasure("Liter", "Liters", "L", UnitOfMeasure::VOLUME, 1000.0)); + this->storeUnitOfMeasure(UnitOfMeasure("Gallon", "Gallons", "gal", UnitOfMeasure::VOLUME, 3800.0)); + //Mass/Weight + this->storeUnitOfMeasure(UnitOfMeasure("Ounce", "Ounces", "oz", UnitOfMeasure::MASS, 28.0)); + this->storeUnitOfMeasure(UnitOfMeasure("Pound", "Pounds", "lb", UnitOfMeasure::MASS, 454.0)); + this->storeUnitOfMeasure(UnitOfMeasure("Gram", "Grams", "g", UnitOfMeasure::MASS, 1.0)); + this->storeUnitOfMeasure(UnitOfMeasure("Milligram", "Milligrams", "mg", UnitOfMeasure::MASS, 0.001)); + this->storeUnitOfMeasure(UnitOfMeasure("Kilogram", "Kilograms", "kg", UnitOfMeasure::MASS, 1000.0)); + //Length + this->storeUnitOfMeasure(UnitOfMeasure("Inch", "Inches", "in", UnitOfMeasure::LENGTH, 2.54)); + this->storeUnitOfMeasure(UnitOfMeasure("Centimeter", "Centimeters", "cm", UnitOfMeasure::LENGTH, 1.0)); + //MISC + this->storeUnitOfMeasure(UnitOfMeasure("Piece", "Pieces", "pc", UnitOfMeasure::MISC, 1.0)); + this->storeUnitOfMeasure(UnitOfMeasure("Item", "Items", "", UnitOfMeasure::MISC, 1.0)); + this->commitTransaction(); + return true; +} + +bool RecipeDatabase::addBasicIngredients(){ + this->beginTransaction(); + this->storeIngredient(Ingredient("Flour", "grains")); + this->storeIngredient(Ingredient("Eggs", "eggs")); + this->storeIngredient(Ingredient("Milk", "dairy")); + this->storeIngredient(Ingredient("Cheese", "dairy")); + this->storeIngredient(Ingredient("Salt", "spices")); + this->storeIngredient(Ingredient("Sugar", "sugars")); + this->storeIngredient(Ingredient("Vegetable Oil", "oils")); + this->storeIngredient(Ingredient("Olive Oil", "oils")); + this->storeIngredient(Ingredient("Water", "water")); + this->storeIngredient(Ingredient("Bell Pepper", "vegetables")); + this->storeIngredient(Ingredient("Onion", "vegetables")); + this->storeIngredient(Ingredient("Garlic", "spices")); + this->commitTransaction(); + return true; +} + void RecipeDatabase::ensureTablesExist(){ //Make sure that foreign keys are enabled. this->executeSQL("PRAGMA foreign_keys = ON;"); - this->executeSQL("BEGIN;"); + this->beginTransaction(); //Ingredients table. this->executeSQL("CREATE TABLE IF NOT EXISTS ingredient(" "ingredientId INTEGER PRIMARY KEY," @@ -456,6 +503,7 @@ void RecipeDatabase::ensureTablesExist(){ this->executeSQL("CREATE TABLE IF NOT EXISTS recipe(" "recipeId INTEGER PRIMARY KEY," "name varchar UNIQUE," + "authorName varchar," "createdDate date," "prepTime time," "cookTime time," @@ -475,18 +523,19 @@ void RecipeDatabase::ensureTablesExist(){ "FOREIGN KEY (ingredientId) REFERENCES ingredient(ingredientId)," "FOREIGN KEY (recipeId) REFERENCES recipe(recipeId)," "FOREIGN KEY (unitName) REFERENCES unitOfMeasure(name));"); - this->executeSQL("COMMIT;"); + this->commitTransaction(); } Recipe RecipeDatabase::readFromResultTable(ResultTable t, int tRow){ Recipe r; TableRow row = t.rows().at(tRow); - int id = std::stoi(row.at(0)); - r.setName(row.at(1)); - r.setCreatedDate(QDate::fromString(QString::fromStdString(row.at(2)))); - r.setPrepTime(QTime::fromString(QString::fromStdString(row.at(3)))); - r.setCookTime(QTime::fromString(QString::fromStdString(row.at(4)))); - r.setServings(std::stof(row.at(5))); + int id = std::stoi(row.at(0)); //id + r.setName(row.at(1)); //Name + r.setAuthor(row.at(2)); //author + r.setCreatedDate(QDate::fromString(QString::fromStdString(row.at(3)))); //createdDate + r.setPrepTime(QTime::fromString(QString::fromStdString(row.at(4)))); //prepTime + r.setCookTime(QTime::fromString(QString::fromStdString(row.at(5)))); //cookTime + r.setServings(std::stof(row.at(6))); //servings r.setInstruction(FileUtils::loadInstruction(id)); r.setImage(FileUtils::loadImage(id)); r.setIngredients(this->retrieveRecipeIngredients(id)); diff --git a/model/database/recipedatabase.h b/model/database/recipedatabase.h index 2b80d95..2452e42 100644 --- a/model/database/recipedatabase.h +++ b/model/database/recipedatabase.h @@ -49,6 +49,10 @@ class RecipeDatabase : public Database //Updating. bool updateRecipe(Recipe recipe, string originalName); + + //Adding basic information at start. + bool addBasicUnits(); + bool addBasicIngredients(); private: //Utility methods. diff --git a/model/recipe/recipe.cpp b/model/recipe/recipe.cpp index fb1e545..8d123e7 100644 --- a/model/recipe/recipe.cpp +++ b/model/recipe/recipe.cpp @@ -1,7 +1,8 @@ #include "model/recipe/recipe.h" -Recipe::Recipe(string name, vector ingredients, Instruction instruction, QImage image, vector tags, QDate createdDate, QTime prepTime, QTime cookTime, float servings){ +Recipe::Recipe(string name, string author, vector ingredients, Instruction instruction, QImage image, vector tags, QDate createdDate, QTime prepTime, QTime cookTime, float servings){ setName(name); + setAuthor(author); setIngredients(ingredients); setInstruction(instruction); setImage(image); @@ -12,12 +13,16 @@ Recipe::Recipe(string name, vector ingredients, Instruction in setServings(servings); } -Recipe::Recipe() : Recipe::Recipe("", vector(), Instruction(), QImage(), vector(), QDate::currentDate(), QTime(), QTime(), 1.0f){ +Recipe::Recipe() : Recipe::Recipe("", "", vector(), Instruction(), QImage(), vector(), QDate::currentDate(), QTime(), QTime(), 1.0f){ //Set default values when none are specified. } string Recipe::getName() const{ - return this->name; + return this->name; +} + +string Recipe::getAuthor() const{ + return this->authorName; } vector Recipe::getIngredients() const{ @@ -71,7 +76,11 @@ bool Recipe::isEmpty() const{ } void Recipe::setName(string newName){ - this->name = newName; + this->name = newName; +} + +void Recipe::setAuthor(string newName){ + this->authorName = newName; } void Recipe::setIngredients(vector ingredients){ @@ -111,8 +120,9 @@ void Recipe::setServings(float newServingsCount){ } void Recipe::print(){ - printf("Recipe: %s, Created on: %s, Prep time: %s, Cook time: %s, Serves: %f\n", + printf("Recipe: %s, Created on: %s, by %s, Prep time: %s, Cook time: %s, Serves: %f\n", this->name.c_str(), + this->authorName.c_str(), this->createdDate.toString().toStdString().c_str(), this->prepTime.toString().toStdString().c_str(), this->cookTime.toString().toStdString().c_str(), diff --git a/model/recipe/recipe.h b/model/recipe/recipe.h index 3bdb92d..4d8dca3 100644 --- a/model/recipe/recipe.h +++ b/model/recipe/recipe.h @@ -32,12 +32,13 @@ class Recipe { public: //Full constructor - Recipe(string name, vector ingredients, Instruction instruction, QImage image, vector tags, QDate createdDate, QTime prepTime, QTime cookTime, float servings); + Recipe(string name, string author, vector ingredients, Instruction instruction, QImage image, vector tags, QDate createdDate, QTime prepTime, QTime cookTime, float servings); //Constructor with default values. Recipe(); //Getters string getName() const; + string getAuthor() const; vector getIngredients() const; vector getFoodGroups() const; Instruction getInstruction() const; @@ -52,6 +53,7 @@ public: //Setters void setName(string newName); + void setAuthor(string newName); void setIngredients(vector ingredients); void setTags(vector tags); void addIngredient(RecipeIngredient newIngredient); @@ -66,6 +68,7 @@ public: private: //Main information. string name; //The name of the recipe. + string authorName; //The name of the author of this recipe. vector ingredients; //The list of ingredients in the recipe. Instruction instruction; //The instruction HTML document. QImage image; //An image displayed alongside the recipe.