From 35982cd514f7f3f52d50c27ea496f845a3141cf7 Mon Sep 17 00:00:00 2001 From: andrewlalis Date: Fri, 30 Mar 2018 12:29:10 +0200 Subject: [PATCH] Added methods to get food groups of all recipes and individual recipe, revamped access to result table. --- gui/newrecipedialog.cpp | 1 + main.cpp | 33 ++++++++++++--- model/database/recipedatabase.cpp | 68 ++++++++++++++++++------------- model/database/recipedatabase.h | 1 + model/database/resulttable.cpp | 6 ++- model/database/resulttable.h | 5 ++- model/recipe/recipe.cpp | 12 +++++- model/recipe/recipe.h | 2 + model/recipe/recipetablemodel.cpp | 4 +- model/recipe/recipetablemodel.h | 2 +- utils/stringutils.cpp | 9 ++++ utils/stringutils.h | 1 + 12 files changed, 105 insertions(+), 39 deletions(-) diff --git a/gui/newrecipedialog.cpp b/gui/newrecipedialog.cpp index 5e35cee..f35b50d 100644 --- a/gui/newrecipedialog.cpp +++ b/gui/newrecipedialog.cpp @@ -195,6 +195,7 @@ void NewRecipeDialog::on_newUnitButton_clicked(){ QMessageBox::critical(this, "Error", "Unable to store new unit."); } else { this->populateUnitsBox(); + ui->unitComboBox->setCurrentText(QString::fromStdString(u.getName())); } } } diff --git a/main.cpp b/main.cpp index 688b57e..462f772 100644 --- a/main.cpp +++ b/main.cpp @@ -6,6 +6,8 @@ #include "model/database/recipedatabase.h" #include "utils/fileutils.h" +void test(RecipeDatabase *recipeDB); + int main(int argc, char *argv[]) { RecipeDatabase recipeDB(QString(FileUtils::appDataPath+"recipes.db").toStdString()); @@ -14,6 +16,18 @@ int main(int argc, char *argv[]) w.show(); //TESTING CODE + test(&recipeDB); + + //END TESTING CODE. + + w.loadFromRecipe(recipeDB.retrieveRandomRecipe()); + + a.exec(); + recipeDB.closeConnection(); + return 0; +} + +void test(RecipeDatabase *recipeDB){ vector ri; ri.push_back(RecipeIngredient("flour", "grains", 3.0f, UnitOfMeasure("cup", "cups", "c", UnitOfMeasure::VOLUME, 1.0), "")); ri.push_back(RecipeIngredient("baking powder", "additives", 1.0f, UnitOfMeasure("teaspoon", "teaspoons", "tsp", UnitOfMeasure::VOLUME, 1.0), "")); @@ -29,12 +43,21 @@ int main(int argc, char *argv[]) QTime(0, 25), 10.0f); - bool success = recipeDB.storeRecipe(rec); + bool success = recipeDB->storeRecipe(rec); printf("Storage successful: %d\n", success); - w.loadFromRecipe(recipeDB.retrieveRandomRecipe()); + vector foodGroups = recipeDB->retrieveAllFoodGroups(); + printf("Food Groups:\n"); + for (string s : foodGroups){ + printf("\t%s\n", s.c_str()); + } + + //Get food groups from recipe. + Recipe r = recipeDB->retrieveRecipe("Pannenkoeken"); + vector foodGroupsR = r.getFoodGroups(); + printf("Pannenkoeken Food Groups:\n"); + for (string s : foodGroupsR){ + printf("\t%s\n", s.c_str()); + } - a.exec(); - recipeDB.closeConnection(); - return 0; } diff --git a/model/database/recipedatabase.cpp b/model/database/recipedatabase.cpp index 412db80..24e5151 100644 --- a/model/database/recipedatabase.cpp +++ b/model/database/recipedatabase.cpp @@ -88,7 +88,7 @@ int RecipeDatabase::storeIngredient(Ingredient ingredient){ return -1; } } else { - return std::stoi(t.valueAt(0, 0)); + return std::stoi(t.at(0, 0)); } } @@ -162,12 +162,21 @@ Recipe RecipeDatabase::retrieveRandomRecipe(){ vector RecipeDatabase::retrieveAllRecipes(){ ResultTable t = this->selectFrom("recipe", "name", "ORDER BY name"); vector recipes; - for (unsigned int row = 0; row < t.rowCount(); row++){ - recipes.push_back(this->retrieveRecipe(t.valueAt(row, 0))); + for (TableRow row : t.rows()){ + recipes.push_back(this->retrieveRecipe(row.at(0))); } return recipes; } +vector RecipeDatabase::retrieveAllFoodGroups(){ + ResultTable t = this->executeSQL("SELECT DISTINCT foodGroup FROM ingredient ORDER BY foodGroup;"); + vector foodGroups; + for (TableRow row : t.rows()){ + foodGroups.push_back(row.at(0)); + } + return foodGroups; +} + vector RecipeDatabase::retrieveRecipeIngredients(int recipeId){ ResultTable t = this->executeSQL("SELECT ingredient.name, ingredient.foodGroup, "//0, 1 "recipeIngredient.quantity, recipeIngredient.unitName, recipeIngredient.comment,"//2, 3, 4 @@ -179,33 +188,33 @@ vector RecipeDatabase::retrieveRecipeIngredients(int recipeId) "ON recipeIngredient.unitName = unitOfMeasure.name " "WHERE recipeIngredient.recipeId = "+std::to_string(recipeId)+";"); vector 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, 5), t.valueAt(row, 6), t.valueAt(row, 7), std::stoi(t.valueAt(row, 8)), std::stod(t.valueAt(row, 9))), - t.valueAt(row, 4)); + for (TableRow row : t.rows()){ + RecipeIngredient r(row.at(0), + row.at(1), + std::stof(row.at(2)), + UnitOfMeasure(row.at(5), row.at(6), row.at(7), std::stoi(row.at(8)), std::stod(row.at(9))), + row.at(4)); ings.push_back(r); } return ings; } vector RecipeDatabase::retrieveAllIngredients(){ - ResultTable t = this->selectFrom("ingredient", "*", "ORDER BY name"); + ResultTable t = this->selectFrom("ingredient", "name, foodGroup", "ORDER BY name"); vector ings; - for (unsigned int row = 0; row < t.rowCount(); row++){ - Ingredient i(t.valueAt(row, 2), t.valueAt(row, 1)); + for (TableRow row : t.rows()){ + Ingredient i(row.at(0), row.at(1)); ings.push_back(i); } return ings; } vector RecipeDatabase::retrieveAllUnitsOfMeasure(){ - ResultTable t = this->selectFrom("unitOfMeasure", "*", "ORDER BY name"); + ResultTable t = this->selectFrom("unitOfMeasure", "name, plural, abbreviation, type, metricCoefficient", "ORDER BY name"); vector units; if (!t.isEmpty()){ - for (unsigned int row = 0; row < t.rowCount(); row++){ - UnitOfMeasure u(t.valueAt(row, 0), t.valueAt(row, 1), t.valueAt(row, 2), std::stoi(t.valueAt(row, 3)), std::stod(t.valueAt(row, 4))); + for (TableRow row : t.rows()){ + UnitOfMeasure u(row.at(0), row.at(1), row.at(2), std::stoi(row.at(3)), std::stod(row.at(4))); units.push_back(u); } } @@ -213,11 +222,11 @@ vector RecipeDatabase::retrieveAllUnitsOfMeasure(){ } vector RecipeDatabase::retrieveTags(int recipeId){ - ResultTable t = this->selectFrom("recipeTag", "tagName", "WHERE recipeId="+std::to_string(recipeId)); + ResultTable t = this->selectFrom("recipeTag", "tagName", "WHERE recipeId="+std::to_string(recipeId)+" ORDER BY tagName"); vector tags; if (!t.isEmpty()){ - for (unsigned int row = 0; row < t.rowCount(); row++){ - RecipeTag tag(t.valueAt(row, 0)); + for (TableRow row : t.rows()){ + RecipeTag tag(row.at(0)); tags.push_back(tag); } } @@ -228,8 +237,8 @@ vector RecipeDatabase::retrieveAllTags(){ ResultTable t = this->selectFrom("recipeTag", "tagName", "ORDER BY tagName"); vector tags; if (!t.isEmpty()){ - for (unsigned int row = 0; row < t.rowCount(); row++){ - RecipeTag tag(t.valueAt(row, 0)); + for (TableRow row : t.rows()){ + RecipeTag tag(row.at(0)); tags.push_back(tag); } } @@ -241,7 +250,7 @@ bool RecipeDatabase::deleteRecipe(string name){ if (t.rowCount() != 1){ return false; } - string recipeId = t.valueAt(0, 0); + string recipeId = t.at(0, 0); return this->deleteRecipe(std::stoi(recipeId)); } @@ -257,6 +266,8 @@ bool RecipeDatabase::deleteRecipe(int recipeId){ bool recipeDeleted = this->deleteFrom("recipe", "WHERE recipeId="+idString); bool instructionDeleted = FileUtils::deleteInstruction(recipeId); bool imageDeleted = FileUtils::deleteImage(recipeId); + Q_UNUSED(instructionDeleted); + Q_UNUSED(imageDeleted); if (tagsDeleted && recipeIngredientDeleted && recipeDeleted){ this->executeSQL("COMMIT;"); return true; @@ -334,14 +345,15 @@ void RecipeDatabase::ensureTablesExist(){ this->executeSQL("COMMIT;"); } -Recipe RecipeDatabase::readFromResultTable(ResultTable t, int row){ +Recipe RecipeDatabase::readFromResultTable(ResultTable t, int tRow){ Recipe r; - int id = std::stoi(t.valueAt(row, 0)); - r.setName(t.valueAt(row, 1)); - r.setCreatedDate(QDate::fromString(QString::fromStdString(t.valueAt(row, 2)))); - r.setPrepTime(QTime::fromString(QString::fromStdString(t.valueAt(row, 3)))); - r.setCookTime(QTime::fromString(QString::fromStdString(t.valueAt(row, 4)))); - r.setServings(std::stof(t.valueAt(row, 5))); + 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))); 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 c5466b7..e02c60a 100644 --- a/model/database/recipedatabase.h +++ b/model/database/recipedatabase.h @@ -34,6 +34,7 @@ class RecipeDatabase : public Database Recipe retrieveRecipe(string name); Recipe retrieveRandomRecipe(); vector retrieveAllRecipes(); + vector retrieveAllFoodGroups(); vector retrieveRecipeIngredients(int recipeId); vector retrieveAllIngredients(); vector retrieveAllUnitsOfMeasure(); diff --git a/model/database/resulttable.cpp b/model/database/resulttable.cpp index 9811d64..ac96d7b 100644 --- a/model/database/resulttable.cpp +++ b/model/database/resulttable.cpp @@ -47,7 +47,7 @@ bool ResultTable::isEmpty(){ return this->values.empty(); } -string ResultTable::valueAt(unsigned int row, unsigned int col){ +string ResultTable::at(unsigned int row, unsigned int col){ if (isIndexValid(row, col)){ return this->values[row][col]; } else { @@ -78,6 +78,10 @@ unsigned int ResultTable::rowCount(){ return this->values.size(); } +vector > ResultTable::rows(){ + return this->values; +} + string ResultTable::convertToString(sqlite3_value *val){ const unsigned char* raw_text = sqlite3_value_text(val); if (raw_text == 0){ diff --git a/model/database/resulttable.h b/model/database/resulttable.h index a138ea3..a4dcd84 100644 --- a/model/database/resulttable.h +++ b/model/database/resulttable.h @@ -12,6 +12,8 @@ using namespace std; * @brief The ResultTable class is an object that contains the results of an SQL query, in string form. */ +typedef vector TableRow; + class ResultTable { public: @@ -28,11 +30,12 @@ class ResultTable void printData(); bool isEmpty(); - string valueAt(unsigned int row, unsigned int col); + string at(unsigned int row, unsigned int col); int getReturnCode(); string getOriginalQuery(); unsigned int columnCount(); unsigned int rowCount(); + vector> rows(); private: vector> values; int queryCode; diff --git a/model/recipe/recipe.cpp b/model/recipe/recipe.cpp index 0859bd8..a899c1f 100644 --- a/model/recipe/recipe.cpp +++ b/model/recipe/recipe.cpp @@ -21,7 +21,17 @@ string Recipe::getName() const{ } vector Recipe::getIngredients() const{ - return this->ingredients; + return this->ingredients; +} + +vector Recipe::getFoodGroups() const{ + vector foodGroups; + for (RecipeIngredient ri : this->ingredients){ + if (find(foodGroups.begin(), foodGroups.end(), ri.getFoodGroup()) == foodGroups.end()){ + foodGroups.push_back(ri.getFoodGroup()); + } + } + return foodGroups; } Instruction Recipe::getInstruction() const{ diff --git a/model/recipe/recipe.h b/model/recipe/recipe.h index 048b09a..3bdb92d 100644 --- a/model/recipe/recipe.h +++ b/model/recipe/recipe.h @@ -6,6 +6,7 @@ #include #include #include +#include #include "model/recipe/ingredients/recipeingredient.h" #include "model/recipe/instruction.h" @@ -38,6 +39,7 @@ public: //Getters string getName() const; vector getIngredients() const; + vector getFoodGroups() const; Instruction getInstruction() const; QImage getImage() const; vector getTags() const; diff --git a/model/recipe/recipetablemodel.cpp b/model/recipe/recipetablemodel.cpp index 521fa51..aab90e4 100644 --- a/model/recipe/recipetablemodel.cpp +++ b/model/recipe/recipetablemodel.cpp @@ -72,8 +72,8 @@ void RecipeTableModel::setRecipes(vector recipes){ endInsertRows(); } -Recipe RecipeTableModel::getRecipeAt(int index){ - if (index < 0 || index >= this->recipes.size()){ +Recipe RecipeTableModel::getRecipeAt(unsigned int index){ + if (index >= this->recipes.size()){ return Recipe(); } return this->recipes[index]; diff --git a/model/recipe/recipetablemodel.h b/model/recipe/recipetablemodel.h index 7449619..74645d7 100644 --- a/model/recipe/recipetablemodel.h +++ b/model/recipe/recipetablemodel.h @@ -20,7 +20,7 @@ class RecipeTableModel : public QAbstractTableModel //Normal methods. void setRecipes(vector recipes); - Recipe getRecipeAt(int index); + Recipe getRecipeAt(unsigned int index); void clear(); private: vector recipes; diff --git a/utils/stringutils.cpp b/utils/stringutils.cpp index f6115e8..86cafc3 100644 --- a/utils/stringutils.cpp +++ b/utils/stringutils.cpp @@ -29,4 +29,13 @@ std::string toString(float val){ return s; } +void printVector(std::vector &vect){ + std::printf("Vector of %ld elements:\n", vect.size()); + int c = 0; + for (std::string s : vect){ + std::printf("\t[%d] = %s\n", c, s.c_str()); + c++; + } +} + } diff --git a/utils/stringutils.h b/utils/stringutils.h index c678e46..5646704 100644 --- a/utils/stringutils.h +++ b/utils/stringutils.h @@ -2,6 +2,7 @@ #define STRINGUTILS_H #include +#include #include namespace StringUtils{