diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index d2de990..bc09378 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -95,11 +95,12 @@ void MainWindow::on_exitButton_clicked(){ void MainWindow::on_editButton_clicked(){ NewRecipeDialog d(this->recipeDB, this->currentRecipe, this); + string originalName = this->currentRecipe.getName(); d.show(); d.exec(); if (d.isAccepted()){ Recipe r = d.getRecipe(); - if (!this->recipeDB->storeRecipe(r)){ + if (!this->recipeDB->updateRecipe(r, originalName)){ QMessageBox::critical(this, QString("Unable to Save Recipe"), QString("The program was not able to successfully save the recipe. Make sure to give the recipe a name, instructions, and some ingredients!")); } else { this->loadFromRecipe(r); diff --git a/gui/newrecipedialog.ui b/gui/newrecipedialog.ui index 937ee33..a42a7a2 100644 --- a/gui/newrecipedialog.ui +++ b/gui/newrecipedialog.ui @@ -100,7 +100,6 @@ - 16 3 false false @@ -142,7 +141,7 @@ 0 1999 12 - 24 + 23 @@ -352,6 +351,9 @@ QAbstractItemView::MultiSelection + + QAbstractItemView::ScrollPerPixel + @@ -667,6 +669,9 @@ QAbstractItemView::MultiSelection + + QAbstractItemView::ScrollPerPixel + 100 @@ -746,16 +751,6 @@ background-color: rgb(250, 250, 255); - - - - Instructions - - - Qt::AlignCenter - - - @@ -769,7 +764,7 @@ - I + Italic true @@ -789,7 +784,7 @@ - B + Bold true @@ -827,7 +822,7 @@ Qt::LeftToRight - true + false background-color: rgb(255, 255, 255); diff --git a/gui/openrecipedialog.cpp b/gui/openrecipedialog.cpp index 184ea18..c0458b8 100644 --- a/gui/openrecipedialog.cpp +++ b/gui/openrecipedialog.cpp @@ -127,3 +127,11 @@ void OpenRecipeDialog::on_foodGroupsListWidget_itemSelectionChanged(){ } this->populateRecipesTable(this->recipeDB->retrieveRecipesWithFoodGroups(groups)); } + +void OpenRecipeDialog::on_clearSearchButton_clicked(){ + ui->nameEdit->clear(); + ui->foodGroupsListWidget->selectionModel()->clearSelection(); + ui->tagsListView->selectionModel()->clearSelection(); + ui->ingredientsListView->selectionModel()->clearSelection(); + this->populateRecipesTable(this->recipeDB->retrieveAllRecipes()); +} diff --git a/gui/openrecipedialog.h b/gui/openrecipedialog.h index 8e63496..f0989da 100644 --- a/gui/openrecipedialog.h +++ b/gui/openrecipedialog.h @@ -38,6 +38,8 @@ class OpenRecipeDialog : public QDialog void on_foodGroupsListWidget_itemSelectionChanged(); + void on_clearSearchButton_clicked(); + private: Ui::OpenRecipeDialog *ui; RecipeDatabase *recipeDB; diff --git a/gui/openrecipedialog.ui b/gui/openrecipedialog.ui index 93cb94b..460e738 100644 --- a/gui/openrecipedialog.ui +++ b/gui/openrecipedialog.ui @@ -147,13 +147,9 @@ - + - - - - - :/images/images/search_icon.png:/images/images/search_icon.png + Clear search criteria diff --git a/model/database/database.cpp b/model/database/database.cpp index db53c3f..6e914b0 100644 --- a/model/database/database.cpp +++ b/model/database/database.cpp @@ -14,12 +14,11 @@ ResultTable Database::executeSQL(string statement){ sqlite3_stmt* stmt; this->sql = statement; this->returnCode = sqlite3_prepare_v2(this->db, statement.c_str(), -1, &stmt, NULL); - ResultTable t(statement); if (this->returnCode != SQLITE_OK){ fprintf(stderr, "Unable to successfully prepare SQL statement. Error code: %d\n\tError Message: %s\n", this->returnCode, sqlite3_errmsg(this->db)); - return t; + return ResultTable(this->returnCode); } - + ResultTable t(statement); t.extractData(stmt); this->returnCode = sqlite3_finalize(stmt); @@ -78,6 +77,18 @@ void Database::closeConnection(){ this->dbIsOpen = false; } +void Database::beginTransaction(){ + this->executeSQL("BEGIN;"); +} + +void Database::commitTransaction(){ + this->executeSQL("COMMIT;"); +} + +void Database::rollbackTransaction(){ + this->executeSQL("ROLLBACK;"); +} + string Database::combineVector(std::vector strings, string mid){ if (strings.empty()){ return ""; diff --git a/model/database/database.h b/model/database/database.h index d0bd435..0ccc9fd 100644 --- a/model/database/database.h +++ b/model/database/database.h @@ -35,6 +35,10 @@ public: void closeConnection(); + void beginTransaction(); + void commitTransaction(); + void rollbackTransaction(); + protected: string surroundString(string s, string surround); diff --git a/model/database/recipedatabase.cpp b/model/database/recipedatabase.cpp index 1a9f83a..0ebd528 100644 --- a/model/database/recipedatabase.cpp +++ b/model/database/recipedatabase.cpp @@ -253,6 +253,18 @@ vector RecipeDatabase::retrieveRecipeIngredients(int recipeId) return ings; } +int RecipeDatabase::retrieveIngredientId(string ingredientName){ + return std::stoi(this->selectFrom("ingredient", "ingredientId", "WHERE name = '"+ingredientName+"'").at(0, 0)); +} + +bool RecipeDatabase::deleteRecipeTags(int recipeId){ + return this->deleteFrom("recipeTag", "WHERE recipeId = "+std::to_string(recipeId)); +} + +bool RecipeDatabase::deleteRecipeIngredients(int recipeId){ + return this->deleteFrom("recipeIngredient", "WHERE recipeId = "+std::to_string(recipeId)); +} + vector RecipeDatabase::retrieveAllIngredients(){ ResultTable t = this->selectFrom("ingredient", "name, foodGroup", "ORDER BY name"); vector ings; @@ -356,8 +368,71 @@ bool RecipeDatabase::deleteTag(RecipeTag tag){ return this->deleteFrom("recipeTag", "WHERE tagName='"+tag.getValue()+"'"); } -bool RecipeDatabase::updateRecipe(Recipe recipe){ - +bool RecipeDatabase::updateRecipe(Recipe recipe, string originalName) { + string idS = this->selectFrom("recipe", "recipeId", "WHERE name="+surroundString(originalName, "'")).at(0, 0); + int id = std::stoi(idS); + this->beginTransaction(); + ResultTable t = this->executeSQL("UPDATE recipe " + "SET name = '"+recipe.getName()+"', " + "createdDate = '"+recipe.getCreatedDate().toString().toStdString()+"', " + "prepTime = '"+recipe.getPrepTime().toString().toStdString()+"', " + "cookTime = '"+recipe.getCookTime().toString().toStdString()+"', " + "servingCount = "+std::to_string(recipe.getServings())+" " + "WHERE recipeId = "+idS+";"); + bool recipeSuccess = t.getReturnCode() == SQLITE_DONE; + if (!recipeSuccess){ + this->rollbackTransaction(); + return false; + } + bool tagsSuccess = this->deleteRecipeTags(id); + for (RecipeTag tag : recipe.getTags()){ + tagsSuccess = tagsSuccess && this->insertInto( + "recipeTag", + vector({ + "recipeId", + "tagName" + }), + vector({ + idS, + tag.getValue() + })); + } + if (!tagsSuccess){ + this->rollbackTransaction(); + return false; + } + bool ingredientsSuccess = this->deleteRecipeIngredients(id); + for (RecipeIngredient ri : recipe.getIngredients()){ + ingredientsSuccess = ingredientsSuccess && this->insertInto( + "recipeIngredient", + vector({ + "recipeId", + "ingredientId", + "unitName", + "quantity", + "comment" + }), + vector({ + idS, + std::to_string(this->retrieveIngredientId(ri.getName())), + ri.getUnit().getName(), + std::to_string(ri.getQuantity()), + ri.getComment() + })); + } + if (!ingredientsSuccess){ + this->rollbackTransaction(); + return false; + } + bool instructionSuccess = FileUtils::saveInstruction(id, recipe.getInstruction()); + bool imageSuccess = FileUtils::saveImage(id, recipe.getImage()); + if (!(instructionSuccess && imageSuccess)){ + this->rollbackTransaction(); + return false; + } else { + this->commitTransaction(); + return true; + } } void RecipeDatabase::ensureTablesExist(){ diff --git a/model/database/recipedatabase.h b/model/database/recipedatabase.h index c68b0c9..2b80d95 100644 --- a/model/database/recipedatabase.h +++ b/model/database/recipedatabase.h @@ -26,9 +26,6 @@ class RecipeDatabase : public Database bool storeRecipeIngredient(RecipeIngredient ri, int recipeId); int storeIngredient(Ingredient ingredient); bool storeUnitOfMeasure(UnitOfMeasure u); - bool storeInstruction(Instruction instruction, int recipeId); - bool storeImage(QImage image, int recipeId); - bool storeTags(vector tags, int recipeId); //Retrieval. Recipe retrieveRecipe(string name); @@ -39,10 +36,8 @@ class RecipeDatabase : public Database vector retrieveRecipesWithSubstring(string s); vector retrieveRecipesWithFoodGroups(vector groups); vector retrieveAllFoodGroups(); - vector retrieveRecipeIngredients(int recipeId); vector retrieveAllIngredients(); vector retrieveAllUnitsOfMeasure(); - vector retrieveTags(int recipeId); vector retrieveAllTags(); //Deletion. @@ -53,7 +48,7 @@ class RecipeDatabase : public Database bool deleteTag(RecipeTag tag); //Updating. - bool updateRecipe(Recipe recipe); + bool updateRecipe(Recipe recipe, string originalName); private: //Utility methods. @@ -61,6 +56,20 @@ class RecipeDatabase : public Database //Read a recipe from a row of a result table. Recipe readFromResultTable(ResultTable t, int row=0); vector readRecipesFromTable(ResultTable t); + + //Storage + bool storeInstruction(Instruction instruction, int recipeId); + bool storeImage(QImage image, int recipeId); + bool storeTags(vector tags, int recipeId); + + //Retrieval + vector retrieveTags(int recipeId); + vector retrieveRecipeIngredients(int recipeId); + int retrieveIngredientId(string ingredientName); + + //Deletion + bool deleteRecipeTags(int recipeId); + bool deleteRecipeIngredients(int recipeId); }; #endif // RECIPEDATABASE_H diff --git a/model/database/resulttable.cpp b/model/database/resulttable.cpp index ac96d7b..a8a3ac0 100644 --- a/model/database/resulttable.cpp +++ b/model/database/resulttable.cpp @@ -8,6 +8,10 @@ ResultTable::ResultTable(string query){ this->originalQuery = query; } +ResultTable::ResultTable(int resultCode){ + this->queryCode = resultCode; +} + void ResultTable::extractData(sqlite3_stmt *stmt){ this->values.clear(); int res = sqlite3_step(stmt); @@ -30,6 +34,7 @@ void ResultTable::processRow(sqlite3_stmt *stmt){ } void ResultTable::printData(){ + printf("--> Result Code: [%d] <--\n", this->getReturnCode()); if (this->isEmpty()){ printf("Result table is empty.\n"); return; diff --git a/model/database/resulttable.h b/model/database/resulttable.h index a4dcd84..361f75c 100644 --- a/model/database/resulttable.h +++ b/model/database/resulttable.h @@ -21,6 +21,8 @@ class ResultTable ResultTable(); //Constructs a table with the original query saved. ResultTable(string query); + //Constructs an empty table with a result code. + ResultTable(int resultCode); //Gets all the data from the result set and stores it internally as strings. void extractData(sqlite3_stmt* stmt);