Almost at full release. #9

Merged
andrewlalis merged 4 commits from development into master 2018-03-30 21:30:20 +00:00
12 changed files with 294 additions and 103 deletions

View File

@ -1,5 +1,7 @@
# Recipe DB # Recipe DB
![screenshot](http://i.imgur.com/FbltFit.png)
Recipe DB is a simple, lightweight database powered by Qt and SQLite to allow you to save, retrieve, and search through many recipes without needing to be connected to the internet. Meant as a tool for those who enjoy making recipes their own, this tool lets you edit recipes, search by ingredients or food groups, and filter out recipes that meet certain criteria. Recipe DB was created initially out of a desire to organize my many recipes in one uniform way, as simply as possible, while still making sure that retrieving any given recipe is as effortless as possible. I wanted something where I could save recipes offline, change them if I need to, convert units on-the-fly, and add a few other small utilities that would save a few precious minutes in the kitchen. Recipe DB is a simple, lightweight database powered by Qt and SQLite to allow you to save, retrieve, and search through many recipes without needing to be connected to the internet. Meant as a tool for those who enjoy making recipes their own, this tool lets you edit recipes, search by ingredients or food groups, and filter out recipes that meet certain criteria. Recipe DB was created initially out of a desire to organize my many recipes in one uniform way, as simply as possible, while still making sure that retrieving any given recipe is as effortless as possible. I wanted something where I could save recipes offline, change them if I need to, convert units on-the-fly, and add a few other small utilities that would save a few precious minutes in the kitchen.
### How it works ### How it works

View File

@ -31,6 +31,7 @@ void MainWindow::loadFromRecipe(Recipe recipe){
setCookTime(recipe.getCookTime()); setCookTime(recipe.getCookTime());
setServings(recipe.getServings()); setServings(recipe.getServings());
setTags(recipe.getTags()); setTags(recipe.getTags());
this->currentRecipe = recipe;
} }
void MainWindow::setRecipeName(string name){ void MainWindow::setRecipeName(string name){
@ -91,3 +92,17 @@ void MainWindow::on_openButton_clicked(){
void MainWindow::on_exitButton_clicked(){ void MainWindow::on_exitButton_clicked(){
this->close(); this->close();
} }
void MainWindow::on_editButton_clicked(){
NewRecipeDialog d(this->recipeDB, this->currentRecipe, this);
d.show();
d.exec();
if (d.isAccepted()){
Recipe r = d.getRecipe();
if (!this->recipeDB->storeRecipe(r)){
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);
}
}
}

View File

@ -36,11 +36,14 @@ public:
void on_exitButton_clicked(); void on_exitButton_clicked();
void on_editButton_clicked();
private: private:
Ui::MainWindow *ui; Ui::MainWindow *ui;
RecipeDatabase *recipeDB; RecipeDatabase *recipeDB;
RecipeIngredientListModel ingredientModel; RecipeIngredientListModel ingredientModel;
TagListModel tagsListModel; TagListModel tagsListModel;
Recipe currentRecipe;
//Hidden manipulation methods. //Hidden manipulation methods.
void setRecipeName(string name); void setRecipeName(string name);

View File

@ -180,9 +180,9 @@ QPushButton#openButton:pressed{
</widget> </widget>
</item> </item>
<item alignment="Qt::AlignTop"> <item alignment="Qt::AlignTop">
<widget class="QPushButton" name="browseButton"> <widget class="QPushButton" name="editButton">
<property name="enabled"> <property name="enabled">
<bool>false</bool> <bool>true</bool>
</property> </property>
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
@ -201,19 +201,19 @@ QPushButton#openButton:pressed{
<bool>false</bool> <bool>false</bool>
</property> </property>
<property name="styleSheet"> <property name="styleSheet">
<string notr="true">QPushButton#browseButton { <string notr="true">QPushButton#editButton {
background-color: rgb(215, 215, 255); background-color: rgb(215, 215, 255);
border: 0px; border: 0px;
} }
QPushButton#browseButton:hover{ QPushButton#editButton:hover{
background-color: rgb(225, 225, 255); background-color: rgb(225, 225, 255);
} }
QPushButton#browseButton:pressed{ QPushButton#editButton:pressed{
background-color: rgb(255, 255, 255); background-color: rgb(255, 255, 255);
}</string> }</string>
</property> </property>
<property name="text"> <property name="text">
<string>Browse</string> <string>Edit</string>
</property> </property>
<property name="flat"> <property name="flat">
<bool>false</bool> <bool>false</bool>
@ -363,6 +363,9 @@ font: &quot;Noto Sans CJK KR&quot;;</string>
</item> </item>
<item alignment="Qt::AlignLeft|Qt::AlignBottom"> <item alignment="Qt::AlignLeft|Qt::AlignBottom">
<widget class="QLabel" name="authorLabel"> <widget class="QLabel" name="authorLabel">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum"> <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch> <horstretch>0</horstretch>

View File

@ -21,6 +21,17 @@ NewRecipeDialog::NewRecipeDialog(RecipeDatabase *db, QWidget *parent) : NewRecip
this->populateTagsBox(); this->populateTagsBox();
} }
NewRecipeDialog::NewRecipeDialog(RecipeDatabase *db, Recipe recipe, QWidget *parent) : NewRecipeDialog(db, parent){
ui->recipeNameEdit->setText(QString::fromStdString(recipe.getName()));
ui->prepTimeEdit->setTime(recipe.getPrepTime());
ui->cookTimeEdit->setTime(recipe.getCookTime());
ui->servingsSpinBox->setValue((double)recipe.getServings());
ui->instructionsTextEdit->setHtml(QString::fromStdString(recipe.getInstruction().getHTML()));
ui->imageDisplayLabel->setPixmap(QPixmap::fromImage(recipe.getImage()));
this->tagsListModel.setTags(recipe.getTags());
this->ingredientListModel.setIngredients(recipe.getIngredients());
}
NewRecipeDialog::~NewRecipeDialog(){ NewRecipeDialog::~NewRecipeDialog(){
delete ui; delete ui;
} }

View File

@ -26,6 +26,7 @@ class NewRecipeDialog : public QDialog
public: public:
explicit NewRecipeDialog(QWidget *parent = 0); explicit NewRecipeDialog(QWidget *parent = 0);
NewRecipeDialog(RecipeDatabase *db, QWidget *parent = 0); NewRecipeDialog(RecipeDatabase *db, QWidget *parent = 0);
NewRecipeDialog(RecipeDatabase *db, Recipe recipe, QWidget *parent = 0);
~NewRecipeDialog(); ~NewRecipeDialog();
Recipe getRecipe(); Recipe getRecipe();

View File

@ -11,17 +11,22 @@ OpenRecipeDialog::OpenRecipeDialog(QWidget *parent) :
ui->ingredientsListView->setModel(&this->ingredientsModel); ui->ingredientsListView->setModel(&this->ingredientsModel);
ui->tagsListView->setModel(&this->tagsModel); ui->tagsListView->setModel(&this->tagsModel);
connect(ui->ingredientsListView->selectionModel(), QObject::connect(ui->ingredientsListView->selectionModel(),
SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
this,
SLOT(onIngredientsListViewSelectionChanged(QItemSelection)));
QObject::connect(ui->tagsListView->selectionModel(),
SIGNAL(selectionChanged(QItemSelection,QItemSelection)), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
this, this,
SLOT(on_ingredientsListView_selectionChanged(QItemSelection))); SLOT(onTagsListViewSelectionChanged(QItemSelection)));
} }
OpenRecipeDialog::OpenRecipeDialog(RecipeDatabase *recipeDB, QWidget *parent) : OpenRecipeDialog(parent){ OpenRecipeDialog::OpenRecipeDialog(RecipeDatabase *recipeDB, QWidget *parent) : OpenRecipeDialog(parent){
this->recipeDB = recipeDB; this->recipeDB = recipeDB;
this->populateIngredientsList(); this->populateIngredientsList();
this->populateTagsList(); this->populateTagsList();
this->populateRecipesTable(); this->populateFoodGroupsList();
this->populateRecipesTable(this->recipeDB->retrieveAllRecipes());
} }
OpenRecipeDialog::~OpenRecipeDialog() OpenRecipeDialog::~OpenRecipeDialog()
@ -33,9 +38,8 @@ Recipe OpenRecipeDialog::getSelectedRecipe(){
return this->selectedRecipe; return this->selectedRecipe;
} }
void OpenRecipeDialog::populateRecipesTable(){ void OpenRecipeDialog::populateRecipesTable(vector<Recipe> recipes){
this->recipeTableModel.clear(); this->recipeTableModel.clear();
vector<Recipe> recipes = this->recipeDB->retrieveAllRecipes();
this->recipeTableModel.setRecipes(recipes); this->recipeTableModel.setRecipes(recipes);
ui->recipeTableView->resizeColumnsToContents(); ui->recipeTableView->resizeColumnsToContents();
ui->recipeTableView->show(); ui->recipeTableView->show();
@ -49,6 +53,13 @@ void OpenRecipeDialog::populateTagsList(){
this->tagsModel.setTags(this->recipeDB->retrieveAllTags()); this->tagsModel.setTags(this->recipeDB->retrieveAllTags());
} }
void OpenRecipeDialog::populateFoodGroupsList(){
for (string s : this->recipeDB->retrieveAllFoodGroups()){
ui->foodGroupsListWidget->addItem(QString::fromStdString(s));
}
//ui->foodGroupsListWidget->show();
}
void OpenRecipeDialog::on_deleteRecipeButton_clicked(){ void OpenRecipeDialog::on_deleteRecipeButton_clicked(){
QItemSelectionModel *selectModel = ui->recipeTableView->selectionModel(); QItemSelectionModel *selectModel = ui->recipeTableView->selectionModel();
if (!selectModel->hasSelection()){ if (!selectModel->hasSelection()){
@ -69,9 +80,10 @@ void OpenRecipeDialog::on_deleteRecipeButton_clicked(){
bool success = this->recipeDB->deleteRecipe(r.getName()); bool success = this->recipeDB->deleteRecipe(r.getName());
if (!success){ if (!success){
QMessageBox::critical(this, QString::fromStdString("Unable to Delete"), QString::fromStdString("Could not delete recipe "+r.getName())); QMessageBox::critical(this, QString::fromStdString("Unable to Delete"), QString::fromStdString("Could not delete recipe "+r.getName()));
} else {
this->populateRecipesTable(this->recipeDB->retrieveAllRecipes());
} }
} }
this->populateRecipesTable();
} }
} }
@ -80,13 +92,38 @@ void OpenRecipeDialog::on_recipeTableView_doubleClicked(const QModelIndex &index
this->close(); this->close();
} }
void OpenRecipeDialog::on_ingredientsListView_selectionChanged(const QItemSelection &selection){ void OpenRecipeDialog::onIngredientsListViewSelectionChanged(const QItemSelection &selection){
printf("Selection changed!\n"); Q_UNUSED(selection);
vector<Ingredient> ingredients; vector<Ingredient> ingredients;
for (QModelIndex index : selection.indexes()){ QModelIndexList indexes = ui->ingredientsListView->selectionModel()->selectedRows();
for (QModelIndex index : indexes){
Ingredient i = this->ingredientsModel.getIngredients().at(index.row()); Ingredient i = this->ingredientsModel.getIngredients().at(index.row());
ingredients.push_back(i); ingredients.push_back(i);
printf("Selected: %s\n", i.getName().c_str());
} }
this->populateRecipesTable(this->recipeDB->retrieveRecipesWithIngredients(ingredients));
}
void OpenRecipeDialog::onTagsListViewSelectionChanged(const QItemSelection &selection){
Q_UNUSED(selection);
vector<RecipeTag> tags;
QModelIndexList indexes = ui->tagsListView->selectionModel()->selectedRows();
for (QModelIndex index : indexes){
RecipeTag t = this->tagsModel.getTags().at(index.row());
tags.push_back(t);
}
this->populateRecipesTable(this->recipeDB->retrieveRecipesWithTags(tags));
}
void OpenRecipeDialog::on_nameEdit_textChanged(const QString &arg1){
Q_UNUSED(arg1);
this->populateRecipesTable(this->recipeDB->retrieveRecipesWithSubstring(ui->nameEdit->text().toStdString()));
}
void OpenRecipeDialog::on_foodGroupsListWidget_itemSelectionChanged(){
vector<string> groups;
for (QModelIndex index : ui->foodGroupsListWidget->selectionModel()->selectedRows()){
QListWidgetItem *item = ui->foodGroupsListWidget->item(index.row());
groups.push_back(item->text().toStdString());
}
this->populateRecipesTable(this->recipeDB->retrieveRecipesWithFoodGroups(groups));
} }

View File

@ -30,7 +30,13 @@ class OpenRecipeDialog : public QDialog
void on_recipeTableView_doubleClicked(const QModelIndex &index); void on_recipeTableView_doubleClicked(const QModelIndex &index);
void on_ingredientsListView_selectionChanged(const QItemSelection &selection); void onIngredientsListViewSelectionChanged(const QItemSelection &selection);
void onTagsListViewSelectionChanged(const QItemSelection &selection);
void on_nameEdit_textChanged(const QString &arg1);
void on_foodGroupsListWidget_itemSelectionChanged();
private: private:
Ui::OpenRecipeDialog *ui; Ui::OpenRecipeDialog *ui;
@ -41,9 +47,10 @@ class OpenRecipeDialog : public QDialog
IngredientListModel ingredientsModel; IngredientListModel ingredientsModel;
TagListModel tagsModel; TagListModel tagsModel;
void populateRecipesTable(); void populateRecipesTable(vector<Recipe> recipes);
void populateIngredientsList(); void populateIngredientsList();
void populateTagsList(); void populateTagsList();
void populateFoodGroupsList();
}; };
#endif // OPENRECIPEDIALOG_H #endif // OPENRECIPEDIALOG_H

View File

@ -6,7 +6,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1000</width> <width>1064</width>
<height>480</height> <height>480</height>
</rect> </rect>
</property> </property>
@ -25,73 +25,109 @@
<widget class="QWidget" name="searchPanel" native="true"> <widget class="QWidget" name="searchPanel" native="true">
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<item alignment="Qt::AlignLeft"> <item alignment="Qt::AlignLeft">
<widget class="QWidget" name="tagsSearchpanel" native="true"> <widget class="QTabWidget" name="tabWidget">
<layout class="QVBoxLayout" name="verticalLayout_3"> <property name="minimumSize">
<item> <size>
<widget class="QLabel" name="tagLabel"> <width>290</width>
<property name="text"> <height>0</height>
<string>Tag</string> </size>
</property> </property>
</widget> <property name="tabPosition">
</item> <enum>QTabWidget::South</enum>
<item> </property>
<widget class="QListView" name="tagsListView"> <property name="tabShape">
<property name="sizePolicy"> <enum>QTabWidget::Rounded</enum>
<sizepolicy hsizetype="Minimum" vsizetype="Expanding"> </property>
<horstretch>0</horstretch> <property name="currentIndex">
<verstretch>0</verstretch> <number>2</number>
</sizepolicy> </property>
</property> <widget class="QWidget" name="tagsTab">
<property name="frameShape"> <attribute name="title">
<enum>QFrame::NoFrame</enum> <string>Tags</string>
</property> </attribute>
<property name="selectionMode"> <layout class="QVBoxLayout" name="verticalLayout_5">
<enum>QAbstractItemView::ExtendedSelection</enum> <item>
</property> <widget class="QListView" name="tagsListView">
<property name="isWrapping" stdset="0"> <property name="sizePolicy">
<bool>false</bool> <sizepolicy hsizetype="Minimum" vsizetype="Expanding">
</property> <horstretch>0</horstretch>
<property name="wordWrap"> <verstretch>0</verstretch>
<bool>false</bool> </sizepolicy>
</property> </property>
</widget> <property name="frameShape">
</item> <enum>QFrame::NoFrame</enum>
</layout> </property>
</widget> <property name="selectionMode">
</item> <enum>QAbstractItemView::ExtendedSelection</enum>
<item alignment="Qt::AlignLeft"> </property>
<widget class="QWidget" name="ingredientSearchPanel" native="true"> <property name="verticalScrollMode">
<layout class="QVBoxLayout" name="verticalLayout_4"> <enum>QAbstractItemView::ScrollPerPixel</enum>
<item> </property>
<widget class="QLabel" name="ingredientLabel"> <property name="isWrapping" stdset="0">
<property name="text"> <bool>false</bool>
<string>Ingredient</string> </property>
</property> <property name="wordWrap">
</widget> <bool>true</bool>
</item> </property>
<item> </widget>
<widget class="QListView" name="ingredientsListView"> </item>
<property name="sizePolicy"> </layout>
<sizepolicy hsizetype="Minimum" vsizetype="Expanding"> </widget>
<horstretch>0</horstretch> <widget class="QWidget" name="ingredientsTab">
<verstretch>0</verstretch> <attribute name="title">
</sizepolicy> <string>Ingredients</string>
</property> </attribute>
<property name="frameShape"> <layout class="QVBoxLayout" name="verticalLayout_6">
<enum>QFrame::NoFrame</enum> <item>
</property> <widget class="QListView" name="ingredientsListView">
<property name="selectionMode"> <property name="sizePolicy">
<enum>QAbstractItemView::ExtendedSelection</enum> <sizepolicy hsizetype="Minimum" vsizetype="Expanding">
</property> <horstretch>0</horstretch>
<property name="isWrapping" stdset="0"> <verstretch>0</verstretch>
<bool>false</bool> </sizepolicy>
</property> </property>
<property name="wordWrap"> <property name="frameShape">
<bool>true</bool> <enum>QFrame::NoFrame</enum>
</property> </property>
</widget> <property name="selectionMode">
</item> <enum>QAbstractItemView::ExtendedSelection</enum>
</layout> </property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="isWrapping" stdset="0">
<bool>false</bool>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Food Groups</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QListWidget" name="foodGroupsListWidget">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget> </widget>
</item> </item>
<item> <item>

View File

@ -48,18 +48,18 @@ void test(RecipeDatabase *recipeDB){
bool success = recipeDB->storeRecipe(rec); bool success = recipeDB->storeRecipe(rec);
printf("Storage successful: %d\n", success); printf("Storage successful: %d\n", success);
vector<string> foodGroups = recipeDB->retrieveAllFoodGroups(); // vector<string> foodGroups = recipeDB->retrieveAllFoodGroups();
printf("Food Groups:\n"); // printf("Food Groups:\n");
for (string s : foodGroups){ // for (string s : foodGroups){
printf("\t%s\n", s.c_str()); // printf("\t%s\n", s.c_str());
} // }
//Get food groups from recipe. //Get food groups from recipe.
Recipe r = recipeDB->retrieveRecipe("Pannenkoeken"); // Recipe r = recipeDB->retrieveRecipe("Pannenkoeken");
vector<string> foodGroupsR = r.getFoodGroups(); // vector<string> foodGroupsR = r.getFoodGroups();
printf("Pannenkoeken Food Groups:\n"); // printf("Pannenkoeken Food Groups:\n");
for (string s : foodGroupsR){ // for (string s : foodGroupsR){
printf("\t%s\n", s.c_str()); // printf("\t%s\n", s.c_str());
} // }
} }

View File

@ -158,14 +158,68 @@ Recipe RecipeDatabase::retrieveRandomRecipe(){
} }
return this->readFromResultTable(t); return this->readFromResultTable(t);
} }
//TODO: Change this to be more efficient! One query per recipe is not good!
vector<Recipe> RecipeDatabase::retrieveAllRecipes(){ vector<Recipe> RecipeDatabase::retrieveAllRecipes(){
ResultTable t = this->selectFrom("recipe", "name", "ORDER BY name"); ResultTable t = this->executeSQL("SELECT * FROM recipe ORDER BY name;");
return this->readRecipesFromTable(t);
}
vector<Recipe> RecipeDatabase::retrieveRecipesWithIngredients(vector<Ingredient> ingredients){
vector<Recipe> recipes; vector<Recipe> recipes;
for (TableRow row : t.rows()){ if (ingredients.empty()){
recipes.push_back(this->retrieveRecipe(row.at(0))); return recipes;
} }
return recipes; string filterList = surroundString(ingredients.at(0).getName(), "'");
for (unsigned int i = 1; i < ingredients.size(); i++){
filterList += ", " + surroundString(ingredients[i].getName(), "'");
}
filterList = '(' + filterList + ')';
ResultTable t = this->executeSQL("SELECT * "
"FROM recipe "
"WHERE recipeId IN ("
" SELECT recipeIngredient.recipeId "
" FROM recipeIngredient "
" INNER JOIN ("
" SELECT ingredientId "
" FROM ingredient "
" WHERE name IN "+filterList+""
" ) filteredIngredients "
" ON recipeIngredient.ingredientId = filteredIngredients.ingredientId"
") ORDER BY name;");
return this->readRecipesFromTable(t);
}
vector<Recipe> RecipeDatabase::retrieveRecipesWithTags(vector<RecipeTag> tags){
vector<Recipe> recipes;
if (tags.empty()){
return recipes;
}
string filterList = surroundString(tags.at(0).getValue(), "'");
for (unsigned int i = 1; i < tags.size(); i++){
filterList += ", " + surroundString(tags[i].getValue(), "'");
}
filterList = '(' + filterList + ')';
ResultTable t = this->executeSQL("SELECT * FROM recipe WHERE recipeId IN (SELECT recipeId FROM recipeTag WHERE tagName IN "+filterList+" );");
return this->readRecipesFromTable(t);
}
vector<Recipe> RecipeDatabase::retrieveRecipesWithSubstring(string s){
ResultTable t = this->executeSQL("SELECT * FROM recipe WHERE name LIKE '%"+s+"%' COLLATE NOCASE;");
return this->readRecipesFromTable(t);
}
vector<Recipe> RecipeDatabase::retrieveRecipesWithFoodGroups(vector<string> groups){
vector<Recipe> recipes;
if (groups.empty()){
return recipes;
}
string filterList = surroundString(groups.at(0), "'");
for (unsigned int i = 1; i < groups.size(); i++){
filterList += ", " + surroundString(groups.at(i), "'");
}
filterList = '(' + filterList + ')';
ResultTable t = this->executeSQL("SELECT * FROM recipe WHERE recipeId IN (SELECT recipeId FROM recipeIngredient WHERE ingredientId IN (SELECT ingredientId FROM ingredient WHERE foodGroup IN "+filterList+" ) ) ORDER BY name;");
return this->readRecipesFromTable(t);
} }
vector<string> RecipeDatabase::retrieveAllFoodGroups(){ vector<string> RecipeDatabase::retrieveAllFoodGroups(){
@ -302,6 +356,10 @@ bool RecipeDatabase::deleteTag(RecipeTag tag){
return this->deleteFrom("recipeTag", "WHERE tagName='"+tag.getValue()+"'"); return this->deleteFrom("recipeTag", "WHERE tagName='"+tag.getValue()+"'");
} }
bool RecipeDatabase::updateRecipe(Recipe recipe){
}
void RecipeDatabase::ensureTablesExist(){ void RecipeDatabase::ensureTablesExist(){
//Make sure that foreign keys are enabled. //Make sure that foreign keys are enabled.
this->executeSQL("PRAGMA foreign_keys = ON;"); this->executeSQL("PRAGMA foreign_keys = ON;");
@ -360,3 +418,13 @@ Recipe RecipeDatabase::readFromResultTable(ResultTable t, int tRow){
r.setTags(this->retrieveTags(id)); r.setTags(this->retrieveTags(id));
return r; return r;
} }
//Retrieves recipes from a table with the following format:
// id, name, createdDate, prepTime, cookTime, servings
vector<Recipe> RecipeDatabase::readRecipesFromTable(ResultTable t){
vector<Recipe> recipes;
for (unsigned int row = 0; row < t.rowCount(); row++){
recipes.push_back(readFromResultTable(t, row));
}
return recipes;
}

View File

@ -34,6 +34,10 @@ class RecipeDatabase : public Database
Recipe retrieveRecipe(string name); Recipe retrieveRecipe(string name);
Recipe retrieveRandomRecipe(); Recipe retrieveRandomRecipe();
vector<Recipe> retrieveAllRecipes(); vector<Recipe> retrieveAllRecipes();
vector<Recipe> retrieveRecipesWithIngredients(vector<Ingredient> ingredients);
vector<Recipe> retrieveRecipesWithTags(vector<RecipeTag> tags);
vector<Recipe> retrieveRecipesWithSubstring(string s);
vector<Recipe> retrieveRecipesWithFoodGroups(vector<string> groups);
vector<string> retrieveAllFoodGroups(); vector<string> retrieveAllFoodGroups();
vector<RecipeIngredient> retrieveRecipeIngredients(int recipeId); vector<RecipeIngredient> retrieveRecipeIngredients(int recipeId);
vector<Ingredient> retrieveAllIngredients(); vector<Ingredient> retrieveAllIngredients();
@ -47,12 +51,16 @@ class RecipeDatabase : public Database
bool deleteIngredient(string name); bool deleteIngredient(string name);
bool deleteUnitOfMeasure(string name); bool deleteUnitOfMeasure(string name);
bool deleteTag(RecipeTag tag); bool deleteTag(RecipeTag tag);
//Updating.
bool updateRecipe(Recipe recipe);
private: private:
//Utility methods. //Utility methods.
void ensureTablesExist(); void ensureTablesExist();
//Read a recipe from a row of a result table. //Read a recipe from a row of a result table.
Recipe readFromResultTable(ResultTable t, int row=0); Recipe readFromResultTable(ResultTable t, int row=0);
vector<Recipe> readRecipesFromTable(ResultTable t);
}; };
#endif // RECIPEDATABASE_H #endif // RECIPEDATABASE_H