Stable first release #10

Merged
andrewlalis merged 3 commits from development into master 2018-03-31 18:36:02 +00:00
22 changed files with 654 additions and 115 deletions

View File

@ -19,6 +19,10 @@ MainWindow::~MainWindow(){
} }
void MainWindow::loadFromRecipe(Recipe recipe){ void MainWindow::loadFromRecipe(Recipe recipe){
if (recipe.isEmpty()){
setRecipeName("No recipes found.");
setAuthorName("Click 'New' to get started.");
} else {
setRecipeName(recipe.getName()); setRecipeName(recipe.getName());
setInstruction(recipe.getInstruction()); setInstruction(recipe.getInstruction());
setIngredients(recipe.getIngredients()); setIngredients(recipe.getIngredients());
@ -32,6 +36,7 @@ void MainWindow::loadFromRecipe(Recipe recipe){
setServings(recipe.getServings()); setServings(recipe.getServings());
setTags(recipe.getTags()); setTags(recipe.getTags());
this->currentRecipe = recipe; this->currentRecipe = recipe;
}
} }
void MainWindow::setRecipeName(string name){ void MainWindow::setRecipeName(string name){
@ -66,6 +71,10 @@ void MainWindow::setTags(vector<RecipeTag> tags){
this->tagsListModel.setTags(tags); this->tagsListModel.setTags(tags);
} }
void MainWindow::setAuthorName(string name){
ui->authorLabel->setText(QString::fromStdString(name));
}
void MainWindow::on_newButton_clicked(){ void MainWindow::on_newButton_clicked(){
NewRecipeDialog d(this->recipeDB, this); NewRecipeDialog d(this->recipeDB, this);
d.show(); d.show();
@ -95,11 +104,12 @@ void MainWindow::on_exitButton_clicked(){
void MainWindow::on_editButton_clicked(){ void MainWindow::on_editButton_clicked(){
NewRecipeDialog d(this->recipeDB, this->currentRecipe, this); NewRecipeDialog d(this->recipeDB, this->currentRecipe, this);
string originalName = this->currentRecipe.getName();
d.show(); d.show();
d.exec(); d.exec();
if (d.isAccepted()){ if (d.isAccepted()){
Recipe r = d.getRecipe(); 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!")); 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 { } else {
this->loadFromRecipe(r); this->loadFromRecipe(r);

View File

@ -54,6 +54,7 @@ public:
void setCookTime(QTime cookTime); void setCookTime(QTime cookTime);
void setServings(float servings); void setServings(float servings);
void setTags(vector<RecipeTag> tags); void setTags(vector<RecipeTag> tags);
void setAuthorName(string name);
}; };
#endif // MAINWINDOW_H #endif // MAINWINDOW_H

View File

@ -364,7 +364,7 @@ font: &quot;Noto Sans CJK KR&quot;;</string>
<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"> <property name="enabled">
<bool>false</bool> <bool>true</bool>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum"> <sizepolicy hsizetype="Minimum" vsizetype="Minimum">

View File

@ -23,6 +23,7 @@ NewRecipeDialog::NewRecipeDialog(RecipeDatabase *db, QWidget *parent) : NewRecip
NewRecipeDialog::NewRecipeDialog(RecipeDatabase *db, Recipe recipe, QWidget *parent) : NewRecipeDialog(db, parent){ NewRecipeDialog::NewRecipeDialog(RecipeDatabase *db, Recipe recipe, QWidget *parent) : NewRecipeDialog(db, parent){
ui->recipeNameEdit->setText(QString::fromStdString(recipe.getName())); ui->recipeNameEdit->setText(QString::fromStdString(recipe.getName()));
ui->authorNameEdit->setText(QString::fromStdString(recipe.getAuthor()));
ui->prepTimeEdit->setTime(recipe.getPrepTime()); ui->prepTimeEdit->setTime(recipe.getPrepTime());
ui->cookTimeEdit->setTime(recipe.getCookTime()); ui->cookTimeEdit->setTime(recipe.getCookTime());
ui->servingsSpinBox->setValue((double)recipe.getServings()); ui->servingsSpinBox->setValue((double)recipe.getServings());
@ -38,9 +39,10 @@ NewRecipeDialog::~NewRecipeDialog(){
Recipe NewRecipeDialog::getRecipe(){ Recipe NewRecipeDialog::getRecipe(){
Recipe r(ui->recipeNameEdit->text().toStdString(), Recipe r(ui->recipeNameEdit->text().toStdString(),
ui->authorNameEdit->text().toStdString(),
this->ingredientListModel.getIngredients(), this->ingredientListModel.getIngredients(),
ui->instructionsTextEdit->toHtml().toStdString(), ui->instructionsTextEdit->toHtml().toStdString(),
this->img,//Image ui->imageDisplayLabel->pixmap()->toImage(),//Image
this->tagsListModel.getTags(),//Tags this->tagsListModel.getTags(),//Tags
QDate::currentDate(), QDate::currentDate(),
ui->prepTimeEdit->time(), ui->prepTimeEdit->time(),
@ -126,7 +128,6 @@ void NewRecipeDialog::on_deleteTagButton_clicked(){
void NewRecipeDialog::on_selectImageButton_clicked(){ void NewRecipeDialog::on_selectImageButton_clicked(){
QString filename = QFileDialog::getOpenFileName(this, "Open Image", QString(), "Image Files (*.png *.jpg *.bmp)"); QString filename = QFileDialog::getOpenFileName(this, "Open Image", QString(), "Image Files (*.png *.jpg *.bmp)");
if (!filename.isEmpty()){ if (!filename.isEmpty()){
this->img = QImage(filename);
ui->imageDisplayLabel->setPixmap(QPixmap(filename)); ui->imageDisplayLabel->setPixmap(QPixmap(filename));
} }
} }

View File

@ -70,7 +70,6 @@ class NewRecipeDialog : public QDialog
vector<RecipeTag> tags; vector<RecipeTag> tags;
RecipeIngredientListModel ingredientListModel; RecipeIngredientListModel ingredientListModel;
TagListModel tagsListModel; TagListModel tagsListModel;
QImage img;
bool accepted = false; bool accepted = false;
//Helper functions to fill fields. //Helper functions to fill fields.

View File

@ -96,16 +96,25 @@
<item> <item>
<widget class="QWidget" name="recipeNamePanel" native="true"> <widget class="QWidget" name="recipeNamePanel" native="true">
<layout class="QVBoxLayout" name="verticalLayout_9"> <layout class="QVBoxLayout" name="verticalLayout_9">
<property name="spacing">
<number>0</number>
</property>
<item> <item>
<widget class="QLineEdit" name="recipeNameEdit"> <widget class="QLineEdit" name="recipeNameEdit">
<property name="font"> <property name="font">
<font> <font>
<pointsize>16</pointsize> <pointsize>14</pointsize>
<weight>3</weight> <weight>3</weight>
<italic>false</italic> <italic>false</italic>
<bold>false</bold> <bold>false</bold>
</font> </font>
</property> </property>
<property name="styleSheet">
<string notr="true">background-color: rgb(255, 255, 255);</string>
</property>
<property name="frame">
<bool>false</bool>
</property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignCenter</set> <set>Qt::AlignCenter</set>
</property> </property>
@ -114,6 +123,30 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QLineEdit" name="authorNameEdit">
<property name="font">
<font>
<pointsize>12</pointsize>
<weight>3</weight>
<italic>false</italic>
<bold>false</bold>
</font>
</property>
<property name="styleSheet">
<string notr="true">background-color: rgb(245, 245, 255);</string>
</property>
<property name="frame">
<bool>false</bool>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="placeholderText">
<string>Author</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
@ -142,7 +175,7 @@
<second>0</second> <second>0</second>
<year>1999</year> <year>1999</year>
<month>12</month> <month>12</month>
<day>24</day> <day>22</day>
</datetime> </datetime>
</property> </property>
<property name="currentSection"> <property name="currentSection">
@ -253,6 +286,9 @@
<item alignment="Qt::AlignTop"> <item alignment="Qt::AlignTop">
<widget class="QWidget" name="newTagBoxPanel" native="true"> <widget class="QWidget" name="newTagBoxPanel" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_7"> <layout class="QHBoxLayout" name="horizontalLayout_7">
<property name="spacing">
<number>2</number>
</property>
<property name="leftMargin"> <property name="leftMargin">
<number>0</number> <number>0</number>
</property> </property>
@ -286,6 +322,9 @@
<property name="toolTip"> <property name="toolTip">
<string>Create a new tag</string> <string>Create a new tag</string>
</property> </property>
<property name="styleSheet">
<string notr="true">background-color: rgb(255, 255, 255);</string>
</property>
<property name="icon"> <property name="icon">
<iconset resource="../images.qrc"> <iconset resource="../images.qrc">
<normaloff>:/images/images/plus_icon.png</normaloff>:/images/images/plus_icon.png</iconset> <normaloff>:/images/images/plus_icon.png</normaloff>:/images/images/plus_icon.png</iconset>
@ -297,6 +336,9 @@
<property name="toolTip"> <property name="toolTip">
<string>Permanently delete this tag</string> <string>Permanently delete this tag</string>
</property> </property>
<property name="styleSheet">
<string notr="true">background-color: rgb(255, 255, 255);</string>
</property>
<property name="icon"> <property name="icon">
<iconset resource="../images.qrc"> <iconset resource="../images.qrc">
<normaloff>:/images/images/minus_icon.png</normaloff>:/images/images/minus_icon.png</iconset> <normaloff>:/images/images/minus_icon.png</normaloff>:/images/images/minus_icon.png</iconset>
@ -309,6 +351,9 @@
<item> <item>
<widget class="QWidget" name="tagsListControlPanel" native="true"> <widget class="QWidget" name="tagsListControlPanel" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_8"> <layout class="QHBoxLayout" name="horizontalLayout_8">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin"> <property name="leftMargin">
<number>0</number> <number>0</number>
</property> </property>
@ -323,6 +368,27 @@
</property> </property>
<item> <item>
<widget class="QPushButton" name="addTagButton"> <widget class="QPushButton" name="addTagButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="toolTip">
<string>Add the above tag to the recipe</string>
</property>
<property name="styleSheet">
<string notr="true">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);
}</string>
</property>
<property name="text"> <property name="text">
<string>Add</string> <string>Add</string>
</property> </property>
@ -330,8 +396,29 @@
</item> </item>
<item> <item>
<widget class="QPushButton" name="deleteTagButton"> <widget class="QPushButton" name="deleteTagButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="toolTip">
<string>Remove this tag from the recipe</string>
</property>
<property name="styleSheet">
<string notr="true">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);
}</string>
</property>
<property name="text"> <property name="text">
<string>Delete</string> <string>Remove</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -352,6 +439,9 @@
<property name="selectionMode"> <property name="selectionMode">
<enum>QAbstractItemView::MultiSelection</enum> <enum>QAbstractItemView::MultiSelection</enum>
</property> </property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
</widget> </widget>
</item> </item>
</layout> </layout>
@ -432,7 +522,7 @@
<item> <item>
<widget class="QLabel" name="addIngredientLabel"> <widget class="QLabel" name="addIngredientLabel">
<property name="text"> <property name="text">
<string>Add Ingredient</string> <string>Ingredients</string>
</property> </property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignCenter</set> <set>Qt::AlignCenter</set>
@ -495,6 +585,9 @@
</item> </item>
<item> <item>
<widget class="QPushButton" name="deleteIngredientButton"> <widget class="QPushButton" name="deleteIngredientButton">
<property name="toolTip">
<string>Delete this ingredient</string>
</property>
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
@ -579,6 +672,9 @@
</item> </item>
<item alignment="Qt::AlignRight"> <item alignment="Qt::AlignRight">
<widget class="QPushButton" name="newUnitButton"> <widget class="QPushButton" name="newUnitButton">
<property name="toolTip">
<string>Create a new unit of measure</string>
</property>
<property name="icon"> <property name="icon">
<iconset resource="../images.qrc"> <iconset resource="../images.qrc">
<normaloff>:/images/images/plus_icon.png</normaloff>:/images/images/plus_icon.png</iconset> <normaloff>:/images/images/plus_icon.png</normaloff>:/images/images/plus_icon.png</iconset>
@ -587,6 +683,9 @@
</item> </item>
<item> <item>
<widget class="QPushButton" name="deleteUnitButton"> <widget class="QPushButton" name="deleteUnitButton">
<property name="toolTip">
<string>Delete this unit of measure</string>
</property>
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
@ -624,6 +723,9 @@
<item> <item>
<widget class="QWidget" name="ingredientsListControlPanel" native="true"> <widget class="QWidget" name="ingredientsListControlPanel" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_9"> <layout class="QHBoxLayout" name="horizontalLayout_9">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin"> <property name="leftMargin">
<number>0</number> <number>0</number>
</property> </property>
@ -638,6 +740,27 @@
</property> </property>
<item> <item>
<widget class="QPushButton" name="addIngredientButton"> <widget class="QPushButton" name="addIngredientButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<property name="toolTip">
<string>Add the above ingredient to the recipe</string>
</property>
<property name="styleSheet">
<string notr="true">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);
}</string>
</property>
<property name="text"> <property name="text">
<string>Add</string> <string>Add</string>
</property> </property>
@ -645,8 +768,29 @@
</item> </item>
<item> <item>
<widget class="QPushButton" name="removeIngredientButton"> <widget class="QPushButton" name="removeIngredientButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<property name="toolTip">
<string>Remove this ingredient from the recipe</string>
</property>
<property name="styleSheet">
<string notr="true">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);
}</string>
</property>
<property name="text"> <property name="text">
<string>Delete</string> <string>Remove</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -667,6 +811,9 @@
<property name="selectionMode"> <property name="selectionMode">
<enum>QAbstractItemView::MultiSelection</enum> <enum>QAbstractItemView::MultiSelection</enum>
</property> </property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="batchSize"> <property name="batchSize">
<number>100</number> <number>100</number>
</property> </property>
@ -746,16 +893,6 @@
<string notr="true">background-color: rgb(250, 250, 255);</string> <string notr="true">background-color: rgb(250, 250, 255);</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_8"> <layout class="QVBoxLayout" name="verticalLayout_8">
<item>
<widget class="QLabel" name="instructionsLabel">
<property name="text">
<string>Instructions</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item alignment="Qt::AlignLeft|Qt::AlignTop"> <item alignment="Qt::AlignLeft|Qt::AlignTop">
<widget class="QWidget" name="textControlPanel" native="true"> <widget class="QWidget" name="textControlPanel" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_5"> <layout class="QHBoxLayout" name="horizontalLayout_5">
@ -769,7 +906,7 @@
</font> </font>
</property> </property>
<property name="text"> <property name="text">
<string>I</string> <string>Italic</string>
</property> </property>
<property name="checkable"> <property name="checkable">
<bool>true</bool> <bool>true</bool>
@ -789,7 +926,7 @@
</font> </font>
</property> </property>
<property name="text"> <property name="text">
<string>B</string> <string>Bold</string>
</property> </property>
<property name="checkable"> <property name="checkable">
<bool>true</bool> <bool>true</bool>
@ -827,7 +964,7 @@
<enum>Qt::LeftToRight</enum> <enum>Qt::LeftToRight</enum>
</property> </property>
<property name="autoFillBackground"> <property name="autoFillBackground">
<bool>true</bool> <bool>false</bool>
</property> </property>
<property name="styleSheet"> <property name="styleSheet">
<string notr="true">background-color: rgb(255, 255, 255);</string> <string notr="true">background-color: rgb(255, 255, 255);</string>

View File

@ -72,7 +72,7 @@ void OpenRecipeDialog::on_deleteRecipeButton_clicked(){
} }
string recipePlural = (rows.size() == 1) ? "recipe" : "recipes"; string recipePlural = (rows.size() == 1) ? "recipe" : "recipes";
QString title = QString::fromStdString("Delete " + recipePlural); QString title = QString::fromStdString("Delete " + recipePlural);
QString content = QString::fromStdString("Are you sure you wish to delete the selected "+recipePlural+"?"); QString content = QString::fromStdString("Are you sure you wish to delete the selected "+recipePlural+"?\nAll deleted recipes are permanently deleted.");
QMessageBox::StandardButton reply = QMessageBox::question(this, title, content); QMessageBox::StandardButton reply = QMessageBox::question(this, title, content);
if (reply == QMessageBox::Yes){ if (reply == QMessageBox::Yes){
for (int row : rows){ for (int row : rows){
@ -127,3 +127,15 @@ void OpenRecipeDialog::on_foodGroupsListWidget_itemSelectionChanged(){
} }
this->populateRecipesTable(this->recipeDB->retrieveRecipesWithFoodGroups(groups)); 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());
}
void OpenRecipeDialog::on_exitButton_clicked(){
this->close();
}

View File

@ -38,6 +38,10 @@ class OpenRecipeDialog : public QDialog
void on_foodGroupsListWidget_itemSelectionChanged(); void on_foodGroupsListWidget_itemSelectionChanged();
void on_clearSearchButton_clicked();
void on_exitButton_clicked();
private: private:
Ui::OpenRecipeDialog *ui; Ui::OpenRecipeDialog *ui;
RecipeDatabase *recipeDB; RecipeDatabase *recipeDB;

View File

@ -17,13 +17,37 @@
<iconset resource="../images.qrc"> <iconset resource="../images.qrc">
<normaloff>:/images/images/icon.png</normaloff>:/images/images/icon.png</iconset> <normaloff>:/images/images/icon.png</normaloff>:/images/images/icon.png</iconset>
</property> </property>
<property name="styleSheet">
<string notr="true">font: 25 &quot;Noto Sans CJK KR Light&quot;;</string>
</property>
<property name="modal"> <property name="modal">
<bool>true</bool> <bool>true</bool>
</property> </property>
<layout class="QHBoxLayout" name="horizontalLayout_6"> <layout class="QHBoxLayout" name="horizontalLayout_6">
<item alignment="Qt::AlignLeft|Qt::AlignTop"> <property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item alignment="Qt::AlignLeft">
<widget class="QWidget" name="searchPanel" native="true"> <widget class="QWidget" name="searchPanel" native="true">
<property name="styleSheet">
<string notr="true">background-color: rgb(245, 245, 255);</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<item alignment="Qt::AlignLeft"> <item alignment="Qt::AlignLeft">
<widget class="QTabWidget" name="tabWidget"> <widget class="QTabWidget" name="tabWidget">
<property name="minimumSize"> <property name="minimumSize">
@ -39,13 +63,35 @@
<enum>QTabWidget::Rounded</enum> <enum>QTabWidget::Rounded</enum>
</property> </property>
<property name="currentIndex"> <property name="currentIndex">
<number>2</number> <number>1</number>
</property> </property>
<widget class="QWidget" name="tagsTab"> <widget class="QWidget" name="Tags">
<attribute name="icon">
<iconset resource="../images.qrc">
<normaloff>:/images/images/tag.png</normaloff>:/images/images/tag.png</iconset>
</attribute>
<attribute name="title"> <attribute name="title">
<string/>
</attribute>
<attribute name="toolTip">
<string>Tags</string> <string>Tags</string>
</attribute> </attribute>
<layout class="QVBoxLayout" name="verticalLayout_5"> <layout class="QVBoxLayout" name="verticalLayout_5">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item> <item>
<widget class="QListView" name="tagsListView"> <widget class="QListView" name="tagsListView">
<property name="sizePolicy"> <property name="sizePolicy">
@ -74,10 +120,32 @@
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="ingredientsTab"> <widget class="QWidget" name="ingredientsTab">
<attribute name="icon">
<iconset resource="../images.qrc">
<normaloff>:/images/images/ingredients.png</normaloff>:/images/images/ingredients.png</iconset>
</attribute>
<attribute name="title"> <attribute name="title">
<string/>
</attribute>
<attribute name="toolTip">
<string>Ingredients</string> <string>Ingredients</string>
</attribute> </attribute>
<layout class="QVBoxLayout" name="verticalLayout_6"> <layout class="QVBoxLayout" name="verticalLayout_6">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item> <item>
<widget class="QListView" name="ingredientsListView"> <widget class="QListView" name="ingredientsListView">
<property name="sizePolicy"> <property name="sizePolicy">
@ -105,11 +173,33 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="tab"> <widget class="QWidget" name="foodGroups">
<attribute name="icon">
<iconset resource="../images.qrc">
<normaloff>:/images/images/foodPyramid.png</normaloff>:/images/images/foodPyramid.png</iconset>
</attribute>
<attribute name="title"> <attribute name="title">
<string/>
</attribute>
<attribute name="toolTip">
<string>Food Groups</string> <string>Food Groups</string>
</attribute> </attribute>
<layout class="QVBoxLayout" name="verticalLayout_3"> <layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item> <item>
<widget class="QListWidget" name="foodGroupsListWidget"> <widget class="QListWidget" name="foodGroupsListWidget">
<property name="frameShape"> <property name="frameShape">
@ -132,6 +222,9 @@
</item> </item>
<item> <item>
<widget class="QWidget" name="nameSearchPanel" native="true"> <widget class="QWidget" name="nameSearchPanel" native="true">
<property name="styleSheet">
<string notr="true">background-color: rgb(240, 240, 255);</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2"> <layout class="QHBoxLayout" name="horizontalLayout_2">
<item> <item>
<widget class="QLabel" name="nameLabel"> <widget class="QLabel" name="nameLabel">
@ -141,33 +234,83 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QLineEdit" name="nameEdit"/> <widget class="QLineEdit" name="nameEdit">
<property name="font">
<font>
<pointsize>12</pointsize>
<weight>3</weight>
<italic>false</italic>
<bold>false</bold>
</font>
</property>
<property name="styleSheet">
<string notr="true">background-color: rgb(255, 255, 255);</string>
</property>
<property name="frame">
<bool>false</bool>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="placeholderText">
<string>Recipe Name</string>
</property>
</widget>
</item> </item>
</layout> </layout>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="searchButton"> <widget class="QPushButton" name="clearSearchButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>40</height>
</size>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="styleSheet">
<string notr="true">QPushButton#clearSearchButton {
background-color: rgb(235, 235, 255);
border: 0px;
}
QPushButton#clearSearchButton:hover{
background-color: rgb(245, 245, 255);
}
QPushButton#clearSearchButton:pressed{
background-color: rgb(255, 255, 255);
}</string>
</property>
<property name="text"> <property name="text">
<string/> <string>Clear search criteria</string>
</property> </property>
<property name="icon"> <property name="flat">
<iconset resource="../images.qrc"> <bool>false</bool>
<normaloff>:/images/images/search_icon.png</normaloff>:/images/images/search_icon.png</iconset>
</property> </property>
</widget> </widget>
</item> </item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="contentPanel" native="true">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item alignment="Qt::AlignLeft">
<widget class="QWidget" name="interactionPanel" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item> <item>
<widget class="QPushButton" name="deleteRecipeButton"> <widget class="QPushButton" name="deleteRecipeButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>40</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">QPushButton#deleteRecipeButton {
background-color: rgb(225, 225, 255);
border: 0px;
}
QPushButton#deleteRecipeButton:hover{
background-color: rgb(235, 235, 255);
}
QPushButton#deleteRecipeButton:pressed{
background-color: rgb(245, 245, 255);
}</string>
</property>
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
@ -177,20 +320,86 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QPushButton" name="exitButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>40</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">QPushButton#exitButton {
background-color: rgb(215, 215, 255);
border: 0px;
}
QPushButton#exitButton:hover{
background-color: rgb(225, 225, 255);
}
QPushButton#exitButton:pressed{
background-color: rgb(235, 235, 255);
}</string>
</property>
<property name="text">
<string>Close</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
<item>
<widget class="QWidget" name="contentPanel" native="true">
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item> <item>
<widget class="QTableView" name="recipeTableView"> <widget class="QTableView" name="recipeTableView">
<property name="font">
<font>
<pointsize>14</pointsize>
<weight>3</weight>
<italic>false</italic>
<bold>false</bold>
</font>
</property>
<property name="styleSheet">
<string notr="true">background-color: rgb(250, 250, 255);</string>
</property>
<property name="frameShape"> <property name="frameShape">
<enum>QFrame::NoFrame</enum> <enum>QFrame::NoFrame</enum>
</property> </property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionBehavior"> <property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum> <enum>QAbstractItemView::SelectRows</enum>
</property> </property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="gridStyle">
<enum>Qt::NoPen</enum>
</property>
<property name="sortingEnabled"> <property name="sortingEnabled">
<bool>true</bool> <bool>true</bool>
</property> </property>
<attribute name="horizontalHeaderShowSortIndicator" stdset="0">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderVisible"> <attribute name="verticalHeaderVisible">
<bool>false</bool> <bool>false</bool>
</attribute> </attribute>

View File

@ -6,5 +6,8 @@
<file>images/minus_icon.png</file> <file>images/minus_icon.png</file>
<file>images/search_icon.png</file> <file>images/search_icon.png</file>
<file>images/trash.png</file> <file>images/trash.png</file>
<file>images/tag.png</file>
<file>images/foodPyramid.png</file>
<file>images/ingredients.png</file>
</qresource> </qresource>
</RCC> </RCC>

BIN
images/foodPyramid.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

BIN
images/ingredients.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
images/tag.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -8,23 +8,27 @@
void test(RecipeDatabase *recipeDB); 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[]) int main(int argc, char *argv[])
{ {
RecipeDatabase recipeDB(QString(FileUtils::appDataPath+"recipes.db").toStdString()); RecipeDatabase recipeDB(QString(FileUtils::appDataPath+"recipes.db").toStdString());
QApplication a(argc, argv); QApplication a(argc, argv);
MainWindow w(&recipeDB); MainWindow w(&recipeDB);
w.loadFromRecipe(checkForFirstRun(&recipeDB));
w.show(); w.show();
//TESTING CODE
test(&recipeDB);
//END TESTING CODE.
w.loadFromRecipe(recipeDB.retrieveRandomRecipe());
a.exec(); a.exec();
recipeDB.closeConnection(); recipeDB.closeConnection();
printf("Total queries: %lu\n", recipeDB.getQueryCount());
return 0; return 0;
} }
@ -35,6 +39,7 @@ void test(RecipeDatabase *recipeDB){
ri.push_back(RecipeIngredient("baking powder", "additives", 1.0f, UnitOfMeasure("teaspoon", "teaspoons", "tsp", UnitOfMeasure::VOLUME, 1.0), "")); ri.push_back(RecipeIngredient("baking powder", "additives", 1.0f, UnitOfMeasure("teaspoon", "teaspoons", "tsp", UnitOfMeasure::VOLUME, 1.0), ""));
Recipe rec("Example", Recipe rec("Example",
"Andrew Lalis",
ri, ri,
Instruction("Placeholder Text"), Instruction("Placeholder Text"),
QImage(), QImage(),
@ -48,18 +53,4 @@ 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();
// 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<string> foodGroupsR = r.getFoodGroups();
// printf("Pannenkoeken Food Groups:\n");
// for (string s : foodGroupsR){
// printf("\t%s\n", s.c_str());
// }
} }

View File

@ -14,12 +14,11 @@ ResultTable Database::executeSQL(string statement){
sqlite3_stmt* stmt; sqlite3_stmt* stmt;
this->sql = statement; this->sql = statement;
this->returnCode = sqlite3_prepare_v2(this->db, statement.c_str(), -1, &stmt, NULL); this->returnCode = sqlite3_prepare_v2(this->db, statement.c_str(), -1, &stmt, NULL);
ResultTable t(statement);
if (this->returnCode != SQLITE_OK){ 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)); 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); t.extractData(stmt);
this->returnCode = sqlite3_finalize(stmt); this->returnCode = sqlite3_finalize(stmt);
@ -78,6 +77,18 @@ void Database::closeConnection(){
this->dbIsOpen = false; 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<string> strings, string mid){ string Database::combineVector(std::vector<string> strings, string mid){
if (strings.empty()){ if (strings.empty()){
return ""; return "";

View File

@ -35,6 +35,10 @@ public:
void closeConnection(); void closeConnection();
void beginTransaction();
void commitTransaction();
void rollbackTransaction();
protected: protected:
string surroundString(string s, string surround); string surroundString(string s, string surround);

View File

@ -12,7 +12,7 @@ bool RecipeDatabase::storeRecipe(Recipe recipe){
return false; 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. //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(), "'")); ResultTable t = this->selectFrom("recipe", "*", "WHERE name="+surroundString(recipe.getName(), "'"));
if (!t.isEmpty()){ if (!t.isEmpty()){
fprintf(stderr, "Error storing recipe: Recipe with name %s already exists.\n", recipe.getName().c_str()); 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", bool success = this->insertInto("recipe",
vector<string>({ vector<string>({
"name", "name",
"authorName",
"createdDate", "createdDate",
"cookTime", "cookTime",
"prepTime", "prepTime",
@ -27,6 +28,7 @@ bool RecipeDatabase::storeRecipe(Recipe recipe){
}), }),
vector<string>({ vector<string>({
recipe.getName(), recipe.getName(),
recipe.getAuthor(),
recipe.getCreatedDate().toString().toStdString(), recipe.getCreatedDate().toString().toStdString(),
recipe.getCookTime().toString().toStdString(), recipe.getCookTime().toString().toStdString(),
recipe.getPrepTime().toString().toStdString(), recipe.getPrepTime().toString().toStdString(),
@ -46,12 +48,12 @@ bool RecipeDatabase::storeRecipe(Recipe recipe){
this->storeInstruction(recipe.getInstruction(), recipeId) && this->storeInstruction(recipe.getInstruction(), recipeId) &&
this->storeImage(recipe.getImage(), recipeId) && this->storeImage(recipe.getImage(), recipeId) &&
this->storeTags(recipe.getTags(), recipeId)){ this->storeTags(recipe.getTags(), recipeId)){
this->executeSQL("COMMIT;"); this->commitTransaction();
return true; return true;
} }
} }
} }
this->executeSQL("ROLLBACK;"); this->rollbackTransaction();
return false; return false;
} }
@ -158,7 +160,7 @@ 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->executeSQL("SELECT * FROM recipe ORDER BY name;"); ResultTable t = this->executeSQL("SELECT * FROM recipe ORDER BY name;");
return this->readRecipesFromTable(t); return this->readRecipesFromTable(t);
@ -204,7 +206,7 @@ vector<Recipe> RecipeDatabase::retrieveRecipesWithTags(vector<RecipeTag> tags){
} }
vector<Recipe> RecipeDatabase::retrieveRecipesWithSubstring(string s){ vector<Recipe> RecipeDatabase::retrieveRecipesWithSubstring(string s){
ResultTable t = this->executeSQL("SELECT * FROM recipe WHERE name LIKE '%"+s+"%' COLLATE NOCASE;"); ResultTable t = this->executeSQL("SELECT * FROM recipe WHERE name LIKE '%"+s+"%' COLLATE NOCASE ORDER BY name;");
return this->readRecipesFromTable(t); return this->readRecipesFromTable(t);
} }
@ -253,6 +255,18 @@ vector<RecipeIngredient> RecipeDatabase::retrieveRecipeIngredients(int recipeId)
return ings; 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<Ingredient> RecipeDatabase::retrieveAllIngredients(){ vector<Ingredient> RecipeDatabase::retrieveAllIngredients(){
ResultTable t = this->selectFrom("ingredient", "name, foodGroup", "ORDER BY name"); ResultTable t = this->selectFrom("ingredient", "name, foodGroup", "ORDER BY name");
vector<Ingredient> ings; vector<Ingredient> ings;
@ -314,7 +328,7 @@ bool RecipeDatabase::deleteRecipe(int recipeId){
printf("Cannot delete. No recipe with ID %d exists.\n", recipeId); printf("Cannot delete. No recipe with ID %d exists.\n", recipeId);
return false; return false;
} }
this->executeSQL("BEGIN;"); this->beginTransaction();
bool tagsDeleted = this->deleteFrom("recipeTag", "WHERE recipeId="+idString); bool tagsDeleted = this->deleteFrom("recipeTag", "WHERE recipeId="+idString);
bool recipeIngredientDeleted = this->deleteFrom("recipeIngredient", "WHERE recipeId="+idString); bool recipeIngredientDeleted = this->deleteFrom("recipeIngredient", "WHERE recipeId="+idString);
bool recipeDeleted = this->deleteFrom("recipe", "WHERE recipeId="+idString); bool recipeDeleted = this->deleteFrom("recipe", "WHERE recipeId="+idString);
@ -323,10 +337,10 @@ bool RecipeDatabase::deleteRecipe(int recipeId){
Q_UNUSED(instructionDeleted); Q_UNUSED(instructionDeleted);
Q_UNUSED(imageDeleted); Q_UNUSED(imageDeleted);
if (tagsDeleted && recipeIngredientDeleted && recipeDeleted){ if (tagsDeleted && recipeIngredientDeleted && recipeDeleted){
this->executeSQL("COMMIT;"); this->commitTransaction();
return true; return true;
} else { } else {
this->executeSQL("ROLLBACK;"); this->rollbackTransaction();
return false; return false;
} }
} }
@ -356,15 +370,123 @@ 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){ 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()+"', "
"authorName = '"+recipe.getAuthor()+"', "
"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<string>({
"recipeId",
"tagName"
}),
vector<string>({
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<string>({
"recipeId",
"ingredientId",
"unitName",
"quantity",
"comment"
}),
vector<string>({
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;
}
}
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(){ 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;");
this->executeSQL("BEGIN;"); this->beginTransaction();
//Ingredients table. //Ingredients table.
this->executeSQL("CREATE TABLE IF NOT EXISTS ingredient(" this->executeSQL("CREATE TABLE IF NOT EXISTS ingredient("
"ingredientId INTEGER PRIMARY KEY," "ingredientId INTEGER PRIMARY KEY,"
@ -381,6 +503,7 @@ void RecipeDatabase::ensureTablesExist(){
this->executeSQL("CREATE TABLE IF NOT EXISTS recipe(" this->executeSQL("CREATE TABLE IF NOT EXISTS recipe("
"recipeId INTEGER PRIMARY KEY," "recipeId INTEGER PRIMARY KEY,"
"name varchar UNIQUE," "name varchar UNIQUE,"
"authorName varchar,"
"createdDate date," "createdDate date,"
"prepTime time," "prepTime time,"
"cookTime time," "cookTime time,"
@ -400,18 +523,19 @@ void RecipeDatabase::ensureTablesExist(){
"FOREIGN KEY (ingredientId) REFERENCES ingredient(ingredientId)," "FOREIGN KEY (ingredientId) REFERENCES ingredient(ingredientId),"
"FOREIGN KEY (recipeId) REFERENCES recipe(recipeId)," "FOREIGN KEY (recipeId) REFERENCES recipe(recipeId),"
"FOREIGN KEY (unitName) REFERENCES unitOfMeasure(name));"); "FOREIGN KEY (unitName) REFERENCES unitOfMeasure(name));");
this->executeSQL("COMMIT;"); this->commitTransaction();
} }
Recipe RecipeDatabase::readFromResultTable(ResultTable t, int tRow){ Recipe RecipeDatabase::readFromResultTable(ResultTable t, int tRow){
Recipe r; Recipe r;
TableRow row = t.rows().at(tRow); TableRow row = t.rows().at(tRow);
int id = std::stoi(row.at(0)); int id = std::stoi(row.at(0)); //id
r.setName(row.at(1)); r.setName(row.at(1)); //Name
r.setCreatedDate(QDate::fromString(QString::fromStdString(row.at(2)))); r.setAuthor(row.at(2)); //author
r.setPrepTime(QTime::fromString(QString::fromStdString(row.at(3)))); r.setCreatedDate(QDate::fromString(QString::fromStdString(row.at(3)))); //createdDate
r.setCookTime(QTime::fromString(QString::fromStdString(row.at(4)))); r.setPrepTime(QTime::fromString(QString::fromStdString(row.at(4)))); //prepTime
r.setServings(std::stof(row.at(5))); r.setCookTime(QTime::fromString(QString::fromStdString(row.at(5)))); //cookTime
r.setServings(std::stof(row.at(6))); //servings
r.setInstruction(FileUtils::loadInstruction(id)); r.setInstruction(FileUtils::loadInstruction(id));
r.setImage(FileUtils::loadImage(id)); r.setImage(FileUtils::loadImage(id));
r.setIngredients(this->retrieveRecipeIngredients(id)); r.setIngredients(this->retrieveRecipeIngredients(id));

View File

@ -26,9 +26,6 @@ class RecipeDatabase : public Database
bool storeRecipeIngredient(RecipeIngredient ri, int recipeId); bool storeRecipeIngredient(RecipeIngredient ri, int recipeId);
int storeIngredient(Ingredient ingredient); int storeIngredient(Ingredient ingredient);
bool storeUnitOfMeasure(UnitOfMeasure u); bool storeUnitOfMeasure(UnitOfMeasure u);
bool storeInstruction(Instruction instruction, int recipeId);
bool storeImage(QImage image, int recipeId);
bool storeTags(vector<RecipeTag> tags, int recipeId);
//Retrieval. //Retrieval.
Recipe retrieveRecipe(string name); Recipe retrieveRecipe(string name);
@ -39,10 +36,8 @@ class RecipeDatabase : public Database
vector<Recipe> retrieveRecipesWithSubstring(string s); vector<Recipe> retrieveRecipesWithSubstring(string s);
vector<Recipe> retrieveRecipesWithFoodGroups(vector<string> groups); vector<Recipe> retrieveRecipesWithFoodGroups(vector<string> groups);
vector<string> retrieveAllFoodGroups(); vector<string> retrieveAllFoodGroups();
vector<RecipeIngredient> retrieveRecipeIngredients(int recipeId);
vector<Ingredient> retrieveAllIngredients(); vector<Ingredient> retrieveAllIngredients();
vector<UnitOfMeasure> retrieveAllUnitsOfMeasure(); vector<UnitOfMeasure> retrieveAllUnitsOfMeasure();
vector<RecipeTag> retrieveTags(int recipeId);
vector<RecipeTag> retrieveAllTags(); vector<RecipeTag> retrieveAllTags();
//Deletion. //Deletion.
@ -53,7 +48,11 @@ class RecipeDatabase : public Database
bool deleteTag(RecipeTag tag); bool deleteTag(RecipeTag tag);
//Updating. //Updating.
bool updateRecipe(Recipe recipe); bool updateRecipe(Recipe recipe, string originalName);
//Adding basic information at start.
bool addBasicUnits();
bool addBasicIngredients();
private: private:
//Utility methods. //Utility methods.
@ -61,6 +60,20 @@ class RecipeDatabase : public Database
//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); vector<Recipe> readRecipesFromTable(ResultTable t);
//Storage
bool storeInstruction(Instruction instruction, int recipeId);
bool storeImage(QImage image, int recipeId);
bool storeTags(vector<RecipeTag> tags, int recipeId);
//Retrieval
vector<RecipeTag> retrieveTags(int recipeId);
vector<RecipeIngredient> retrieveRecipeIngredients(int recipeId);
int retrieveIngredientId(string ingredientName);
//Deletion
bool deleteRecipeTags(int recipeId);
bool deleteRecipeIngredients(int recipeId);
}; };
#endif // RECIPEDATABASE_H #endif // RECIPEDATABASE_H

View File

@ -8,6 +8,10 @@ ResultTable::ResultTable(string query){
this->originalQuery = query; this->originalQuery = query;
} }
ResultTable::ResultTable(int resultCode){
this->queryCode = resultCode;
}
void ResultTable::extractData(sqlite3_stmt *stmt){ void ResultTable::extractData(sqlite3_stmt *stmt){
this->values.clear(); this->values.clear();
int res = sqlite3_step(stmt); int res = sqlite3_step(stmt);
@ -30,6 +34,7 @@ void ResultTable::processRow(sqlite3_stmt *stmt){
} }
void ResultTable::printData(){ void ResultTable::printData(){
printf("--> Result Code: [%d] <--\n", this->getReturnCode());
if (this->isEmpty()){ if (this->isEmpty()){
printf("Result table is empty.\n"); printf("Result table is empty.\n");
return; return;

View File

@ -21,6 +21,8 @@ class ResultTable
ResultTable(); ResultTable();
//Constructs a table with the original query saved. //Constructs a table with the original query saved.
ResultTable(string query); 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. //Gets all the data from the result set and stores it internally as strings.
void extractData(sqlite3_stmt* stmt); void extractData(sqlite3_stmt* stmt);

View File

@ -1,7 +1,8 @@
#include "model/recipe/recipe.h" #include "model/recipe/recipe.h"
Recipe::Recipe(string name, vector<RecipeIngredient> ingredients, Instruction instruction, QImage image, vector<RecipeTag> tags, QDate createdDate, QTime prepTime, QTime cookTime, float servings){ Recipe::Recipe(string name, string author, vector<RecipeIngredient> ingredients, Instruction instruction, QImage image, vector<RecipeTag> tags, QDate createdDate, QTime prepTime, QTime cookTime, float servings){
setName(name); setName(name);
setAuthor(author);
setIngredients(ingredients); setIngredients(ingredients);
setInstruction(instruction); setInstruction(instruction);
setImage(image); setImage(image);
@ -12,7 +13,7 @@ Recipe::Recipe(string name, vector<RecipeIngredient> ingredients, Instruction in
setServings(servings); setServings(servings);
} }
Recipe::Recipe() : Recipe::Recipe("", vector<RecipeIngredient>(), Instruction(), QImage(), vector<RecipeTag>(), QDate::currentDate(), QTime(1, 0), QTime(0, 30), 10.0f){ Recipe::Recipe() : Recipe::Recipe("", "", vector<RecipeIngredient>(), Instruction(), QImage(), vector<RecipeTag>(), QDate::currentDate(), QTime(), QTime(), 1.0f){
//Set default values when none are specified. //Set default values when none are specified.
} }
@ -20,6 +21,10 @@ string Recipe::getName() const{
return this->name; return this->name;
} }
string Recipe::getAuthor() const{
return this->authorName;
}
vector<RecipeIngredient> Recipe::getIngredients() const{ vector<RecipeIngredient> Recipe::getIngredients() const{
return this->ingredients; return this->ingredients;
} }
@ -74,6 +79,10 @@ void Recipe::setName(string newName){
this->name = newName; this->name = newName;
} }
void Recipe::setAuthor(string newName){
this->authorName = newName;
}
void Recipe::setIngredients(vector<RecipeIngredient> ingredients){ void Recipe::setIngredients(vector<RecipeIngredient> ingredients){
this->ingredients = ingredients; this->ingredients = ingredients;
} }
@ -111,8 +120,9 @@ void Recipe::setServings(float newServingsCount){
} }
void Recipe::print(){ 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->name.c_str(),
this->authorName.c_str(),
this->createdDate.toString().toStdString().c_str(), this->createdDate.toString().toStdString().c_str(),
this->prepTime.toString().toStdString().c_str(), this->prepTime.toString().toStdString().c_str(),
this->cookTime.toString().toStdString().c_str(), this->cookTime.toString().toStdString().c_str(),

View File

@ -32,12 +32,13 @@ class Recipe
{ {
public: public:
//Full constructor //Full constructor
Recipe(string name, vector<RecipeIngredient> ingredients, Instruction instruction, QImage image, vector<RecipeTag> tags, QDate createdDate, QTime prepTime, QTime cookTime, float servings); Recipe(string name, string author, vector<RecipeIngredient> ingredients, Instruction instruction, QImage image, vector<RecipeTag> tags, QDate createdDate, QTime prepTime, QTime cookTime, float servings);
//Constructor with default values. //Constructor with default values.
Recipe(); Recipe();
//Getters //Getters
string getName() const; string getName() const;
string getAuthor() const;
vector<RecipeIngredient> getIngredients() const; vector<RecipeIngredient> getIngredients() const;
vector<string> getFoodGroups() const; vector<string> getFoodGroups() const;
Instruction getInstruction() const; Instruction getInstruction() const;
@ -52,6 +53,7 @@ public:
//Setters //Setters
void setName(string newName); void setName(string newName);
void setAuthor(string newName);
void setIngredients(vector<RecipeIngredient> ingredients); void setIngredients(vector<RecipeIngredient> ingredients);
void setTags(vector<RecipeTag> tags); void setTags(vector<RecipeTag> tags);
void addIngredient(RecipeIngredient newIngredient); void addIngredient(RecipeIngredient newIngredient);
@ -66,6 +68,7 @@ public:
private: private:
//Main information. //Main information.
string name; //The name of the recipe. string name; //The name of the recipe.
string authorName; //The name of the author of this recipe.
vector<RecipeIngredient> ingredients; //The list of ingredients in the recipe. vector<RecipeIngredient> ingredients; //The list of ingredients in the recipe.
Instruction instruction; //The instruction HTML document. Instruction instruction; //The instruction HTML document.
QImage image; //An image displayed alongside the recipe. QImage image; //An image displayed alongside the recipe.