Actually Usable Version #7
|
@ -58,7 +58,7 @@ void MainWindow::setCookTime(QTime cookTime){
|
|||
}
|
||||
|
||||
void MainWindow::setServings(float servings){
|
||||
ui->servingsLabel->setText(QString("Servings: ")+QString::fromStdString(StringUtils::toString(servings)));
|
||||
ui->servingsLabel->setText(QString(QString::fromStdString(StringUtils::toString(servings) + " Serving" + ((servings != 1.0f) ? "s" : ""))));
|
||||
}
|
||||
|
||||
void MainWindow::setTags(vector<RecipeTag> tags){
|
||||
|
@ -72,9 +72,10 @@ void MainWindow::on_newButton_clicked(){
|
|||
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."));
|
||||
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);
|
||||
}
|
||||
this->loadFromRecipe(r);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,4 +83,11 @@ void MainWindow::on_openButton_clicked(){
|
|||
OpenRecipeDialog d(this->recipeDB, this);
|
||||
d.show();
|
||||
d.exec();
|
||||
if (!d.getSelectedRecipe().isEmpty()){
|
||||
this->loadFromRecipe(d.getSelectedRecipe());
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_exitButton_clicked(){
|
||||
this->close();
|
||||
}
|
||||
|
|
|
@ -34,6 +34,8 @@ public:
|
|||
|
||||
void on_openButton_clicked();
|
||||
|
||||
void on_exitButton_clicked();
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
RecipeDatabase *recipeDB;
|
||||
|
|
|
@ -143,6 +143,12 @@ QPushButton#newButton:pressed{
|
|||
</item>
|
||||
<item alignment="Qt::AlignTop">
|
||||
<widget class="QPushButton" name="openButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
|
@ -175,6 +181,9 @@ QPushButton#openButton:pressed{
|
|||
</item>
|
||||
<item alignment="Qt::AlignTop">
|
||||
<widget class="QPushButton" name="browseButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
|
@ -211,6 +220,56 @@ QPushButton#browseButton:pressed{
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="exitButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>150</horstretch>
|
||||
<verstretch>80</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>80</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Noto Sans CJK KR Light</family>
|
||||
<pointsize>20</pointsize>
|
||||
<stylestrategy>PreferAntialias</stylestrategy>
|
||||
</font>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QPushButton#exitButton {
|
||||
background-color: rgb(255, 216, 216);
|
||||
border: 0px;
|
||||
}
|
||||
QPushButton#exitButton:hover{
|
||||
background-color: rgb(255, 191, 191);
|
||||
}
|
||||
QPushButton#exitButton:pressed{
|
||||
background-color: rgb(255, 147, 147);
|
||||
}</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Exit</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="default">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -367,6 +426,9 @@ font: "Noto Sans CJK KR";</string>
|
|||
<property name="text">
|
||||
<string>Prep Time:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -383,6 +445,9 @@ font: "Noto Sans CJK KR";</string>
|
|||
<property name="text">
|
||||
<string>Cook Time:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -396,6 +461,9 @@ font: "Noto Sans CJK KR";</string>
|
|||
<property name="text">
|
||||
<string>Servings:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
|
|
@ -119,7 +119,7 @@ void NewRecipeDialog::on_selectImageButton_clicked(){
|
|||
}
|
||||
}
|
||||
|
||||
void NewRecipeDialog::on_deleteIngredientButton_clicked(){
|
||||
void NewRecipeDialog::on_removeIngredientButton_clicked(){
|
||||
QModelIndexList indexList = ui->ingredientsListView->selectionModel()->selectedIndexes();
|
||||
for (QModelIndexList::iterator it = indexList.begin(); it != indexList.end(); ++it){
|
||||
QModelIndex i = *it;
|
||||
|
@ -127,6 +127,22 @@ void NewRecipeDialog::on_deleteIngredientButton_clicked(){
|
|||
}
|
||||
}
|
||||
|
||||
void NewRecipeDialog::on_deleteIngredientButton_clicked(){
|
||||
int index = ui->ingredientNameBox->currentIndex();
|
||||
Ingredient ing = this->ingredients.at(index);
|
||||
QMessageBox::StandardButton reply = QMessageBox::question(this,
|
||||
QString::fromStdString("Delete Ingredient"),
|
||||
QString::fromStdString("Are you sure you want to delete the ingredient " + ing.getName() + "?"));
|
||||
if (reply == QMessageBox::Yes){
|
||||
bool success = this->recipeDB->deleteIngredient(ing.getName());
|
||||
if (!success){
|
||||
QMessageBox::critical(this, QString::fromStdString("Error"), QString::fromStdString("Unable to delete ingredient: " + ing.getName() + ", some recipes use it!"));
|
||||
} else {
|
||||
this->populateIngredientsBox();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NewRecipeDialog::on_newIngredientButton_clicked(){
|
||||
NewIngredientDialog d(this);
|
||||
d.show();
|
||||
|
@ -155,8 +171,8 @@ void NewRecipeDialog::on_newTagButton_clicked(){
|
|||
}
|
||||
|
||||
void NewRecipeDialog::on_removeTagButton_clicked(){
|
||||
int index = ui->tagsComboBox->currentIndex();
|
||||
if (index < 0 || index >= this->tags.size()){
|
||||
unsigned int index = ui->tagsComboBox->currentIndex();
|
||||
if (index >= this->tags.size()){
|
||||
return;
|
||||
}
|
||||
RecipeTag tag = this->tags[ui->tagsComboBox->currentIndex()];
|
||||
|
@ -180,3 +196,18 @@ void NewRecipeDialog::on_newUnitButton_clicked(){
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NewRecipeDialog::on_deleteUnitButton_clicked(){
|
||||
int index = ui->unitComboBox->currentIndex();
|
||||
UnitOfMeasure unit = this->units[index];
|
||||
QMessageBox::StandardButton reply = QMessageBox::question(this,
|
||||
QString::fromStdString("Delete Unit Of Measure"),
|
||||
QString::fromStdString("Are you sure you want to delete the unit " + unit.getName() + "?"));
|
||||
if (reply == QMessageBox::Yes){
|
||||
if (!this->recipeDB->deleteUnitOfMeasure(unit.getName())){
|
||||
QMessageBox::critical(this, "Error", "Unable to delete unit. There may be recipes which still use it!");
|
||||
} else {
|
||||
this->populateUnitsBox();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,8 @@ class NewRecipeDialog : public QDialog
|
|||
|
||||
void on_selectImageButton_clicked();
|
||||
|
||||
void on_removeIngredientButton_clicked();
|
||||
|
||||
void on_deleteIngredientButton_clicked();
|
||||
|
||||
void on_newIngredientButton_clicked();
|
||||
|
@ -57,6 +59,8 @@ class NewRecipeDialog : public QDialog
|
|||
|
||||
void on_newUnitButton_clicked();
|
||||
|
||||
void on_deleteUnitButton_clicked();
|
||||
|
||||
private:
|
||||
Ui::NewRecipeDialog *ui;
|
||||
RecipeDatabase *recipeDB;
|
||||
|
|
|
@ -158,7 +158,7 @@
|
|||
<second>0</second>
|
||||
<year>1999</year>
|
||||
<month>12</month>
|
||||
<day>26</day>
|
||||
<day>25</day>
|
||||
</datetime>
|
||||
</property>
|
||||
<property name="currentSection">
|
||||
|
@ -504,6 +504,17 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="deleteIngredientButton">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../images.qrc">
|
||||
<normaloff>:/images/images/minus_icon.png</normaloff>:/images/images/minus_icon.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -579,6 +590,17 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="deleteUnitButton">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../images.qrc">
|
||||
<normaloff>:/images/images/minus_icon.png</normaloff>:/images/images/minus_icon.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -627,7 +649,7 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="deleteIngredientButton">
|
||||
<widget class="QPushButton" name="removeIngredientButton">
|
||||
<property name="text">
|
||||
<string>Delete</string>
|
||||
</property>
|
||||
|
|
|
@ -20,13 +20,45 @@ OpenRecipeDialog::~OpenRecipeDialog()
|
|||
delete ui;
|
||||
}
|
||||
|
||||
Recipe OpenRecipeDialog::getSelectedRecipe(){
|
||||
return this->selectedRecipe;
|
||||
}
|
||||
|
||||
void OpenRecipeDialog::populateRecipesTable(){
|
||||
this->recipeTableModel.clear();
|
||||
vector<Recipe> recipes = this->recipeDB->retrieveAllRecipes();
|
||||
// printf("Found %d recipes:\n", recipes.size());
|
||||
// for (Recipe r : recipes){
|
||||
// r.print();
|
||||
// printf("\n------------------\n");
|
||||
// }
|
||||
this->recipeTableModel.setRecipes(recipes);
|
||||
ui->recipeTableView->resizeColumnsToContents();
|
||||
ui->recipeTableView->show();
|
||||
}
|
||||
|
||||
void OpenRecipeDialog::on_deleteRecipeButton_clicked(){
|
||||
QItemSelectionModel *selectModel = ui->recipeTableView->selectionModel();
|
||||
if (!selectModel->hasSelection()){
|
||||
return;
|
||||
}
|
||||
vector<int> rows;
|
||||
QModelIndexList indexes = selectModel->selectedIndexes();
|
||||
for (int i = 0; i < indexes.count(); i++){
|
||||
rows.push_back(indexes.at(i).row());
|
||||
}
|
||||
string recipePlural = (rows.size() == 1) ? "recipe" : "recipes";
|
||||
QString title = QString::fromStdString("Delete " + recipePlural);
|
||||
QString content = QString::fromStdString("Are you sure you wish to delete the selected "+recipePlural+"?");
|
||||
QMessageBox::StandardButton reply = QMessageBox::question(this, title, content);
|
||||
if (reply == QMessageBox::Yes){
|
||||
for (int row : rows){
|
||||
Recipe r = this->recipeTableModel.getRecipeAt(row);
|
||||
bool success = this->recipeDB->deleteRecipe(r.getName());
|
||||
if (!success){
|
||||
QMessageBox::critical(this, QString::fromStdString("Unable to Delete"), QString::fromStdString("Could not delete recipe "+r.getName()));
|
||||
}
|
||||
}
|
||||
this->populateRecipesTable();
|
||||
}
|
||||
}
|
||||
|
||||
void OpenRecipeDialog::on_recipeTableView_doubleClicked(const QModelIndex &index){
|
||||
this->selectedRecipe = this->recipeTableModel.getRecipeAt(index.row());
|
||||
this->close();
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define OPENRECIPEDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "model/database/recipedatabase.h"
|
||||
#include "model/recipe/recipetablemodel.h"
|
||||
|
@ -19,10 +20,18 @@ class OpenRecipeDialog : public QDialog
|
|||
OpenRecipeDialog(RecipeDatabase *recipeDB, QWidget *parent = 0);
|
||||
~OpenRecipeDialog();
|
||||
|
||||
Recipe getSelectedRecipe();
|
||||
|
||||
private slots:
|
||||
void on_deleteRecipeButton_clicked();
|
||||
|
||||
void on_recipeTableView_doubleClicked(const QModelIndex &index);
|
||||
|
||||
private:
|
||||
Ui::OpenRecipeDialog *ui;
|
||||
RecipeDatabase *recipeDB;
|
||||
RecipeTableModel recipeTableModel;
|
||||
Recipe selectedRecipe;
|
||||
|
||||
void populateRecipesTable();
|
||||
};
|
||||
|
|
|
@ -86,6 +86,23 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item alignment="Qt::AlignLeft|Qt::AlignTop">
|
||||
<widget class="QWidget" name="interactionPanel" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<widget class="QPushButton" name="deleteRecipeButton">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../images.qrc">
|
||||
<normaloff>:/images/images/trash.png</normaloff>:/images/images/trash.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="contentPanel" native="true">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
|
@ -94,6 +111,9 @@
|
|||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
|
|
|
@ -5,5 +5,6 @@
|
|||
<file>images/plus_icon.png</file>
|
||||
<file>images/minus_icon.png</file>
|
||||
<file>images/search_icon.png</file>
|
||||
<file>images/trash.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
57
main.cpp
57
main.cpp
|
@ -13,45 +13,28 @@ int main(int argc, char *argv[])
|
|||
w.show();
|
||||
|
||||
//TESTING CODE
|
||||
// vector<RecipeIngredient> 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), ""));
|
||||
vector<RecipeIngredient> 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), ""));
|
||||
|
||||
// Recipe rec("Example",
|
||||
// ri,
|
||||
// Instruction("<b>BOLD</b><i>iTaLiCs</i>"),
|
||||
// QImage(),
|
||||
// vector<RecipeTag>({RecipeTag("testing"),
|
||||
// RecipeTag("fake")}),
|
||||
// QDate::currentDate(),
|
||||
// QTime(0, 30),
|
||||
// QTime(0, 25),
|
||||
// 10.0f);
|
||||
Recipe rec("Example",
|
||||
ri,
|
||||
Instruction("<b>BOLD</b><i>iTaLiCs</i>"),
|
||||
QImage(),
|
||||
vector<RecipeTag>({RecipeTag("testing"),
|
||||
RecipeTag("fake")}),
|
||||
QDate::currentDate(),
|
||||
QTime(0, 30),
|
||||
QTime(0, 25),
|
||||
10.0f);
|
||||
|
||||
// bool success = recipeDB.storeRecipe(rec);
|
||||
// printf("Storage successful: %d\n", success);
|
||||
bool success = recipeDB.storeRecipe(rec);
|
||||
printf("Storage successful: %d\n", success);
|
||||
|
||||
// recipeDB.storeUnitOfMeasure(UnitOfMeasure("tablespoon", "tablespoons", "tbsp", UnitOfMeasure::VOLUME, 1.0));
|
||||
// recipeDB.storeUnitOfMeasure(UnitOfMeasure("pinch", "pinches", "pch", UnitOfMeasure::VOLUME, 1.0));
|
||||
// recipeDB.storeUnitOfMeasure(UnitOfMeasure("gram", "grams", "g", UnitOfMeasure::MASS, 1.0));
|
||||
//recipeDB.selectFrom("recipe", "recipeId, name", "").printData();
|
||||
w.loadFromRecipe(recipeDB.retrieveRandomRecipe());
|
||||
|
||||
// Recipe reloadRec = recipeDB.retrieveRecipe("Example");
|
||||
// reloadRec.print();
|
||||
|
||||
// w.loadFromRecipe(reloadRec);
|
||||
|
||||
// NewRecipeDialog d(&recipeDB);
|
||||
// d.show();
|
||||
// d.exec();
|
||||
|
||||
// if (d.isAccepted()){
|
||||
// printf("Accepted the dialog.\n");
|
||||
// }
|
||||
|
||||
bool success = recipeDB.deleteRecipe(4);
|
||||
printf("Success: %d\n", success);
|
||||
recipeDB.selectFrom("recipe", "recipeId, name", "").printData();
|
||||
w.loadFromRecipe(recipeDB.retrieveRecipe("Generic Bread"));
|
||||
|
||||
return a.exec();
|
||||
a.exec();
|
||||
recipeDB.closeConnection();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -31,6 +31,8 @@ public:
|
|||
bool tableExists(string tableName);
|
||||
int getLastInsertedRowId();
|
||||
|
||||
void closeConnection();
|
||||
|
||||
protected:
|
||||
string surroundString(string s, string surround);
|
||||
|
||||
|
@ -44,7 +46,6 @@ private:
|
|||
char* errorMsg;
|
||||
|
||||
void openConnection();
|
||||
void closeConnection();
|
||||
std::string combineVector(std::vector<std::string> strings, std::string mid);
|
||||
};
|
||||
|
||||
|
|
|
@ -147,18 +147,16 @@ Recipe RecipeDatabase::retrieveRecipe(string name){
|
|||
fprintf(stderr, "Error: No recipe with name %s found!\n", name.c_str());
|
||||
return Recipe();
|
||||
}
|
||||
Recipe r;
|
||||
int id = std::stoi(t.valueAt(0, 0));
|
||||
r.setName(t.valueAt(0, 1));
|
||||
r.setCreatedDate(QDate::fromString(QString::fromStdString(t.valueAt(0, 2))));
|
||||
r.setPrepTime(QTime::fromString(QString::fromStdString(t.valueAt(0, 3))));
|
||||
r.setCookTime(QTime::fromString(QString::fromStdString(t.valueAt(0, 4))));
|
||||
r.setServings(std::stof(t.valueAt(0, 5)));
|
||||
r.setInstruction(FileUtils::loadInstruction(id));
|
||||
r.setImage(FileUtils::loadImage(id));
|
||||
r.setIngredients(this->retrieveRecipeIngredients(id));
|
||||
r.setTags(this->retrieveTags(id));
|
||||
return r;
|
||||
return this->readFromResultTable(t);
|
||||
}
|
||||
|
||||
Recipe RecipeDatabase::retrieveRandomRecipe(){
|
||||
ResultTable t = this->selectFrom("recipe", "*", "ORDER BY RANDOM() LIMIT 1");
|
||||
if (t.isEmpty()){
|
||||
fprintf(stderr, "Unable to find a random recipe.\n");
|
||||
return Recipe();
|
||||
}
|
||||
return this->readFromResultTable(t);
|
||||
}
|
||||
|
||||
vector<Recipe> RecipeDatabase::retrieveAllRecipes(){
|
||||
|
@ -239,7 +237,7 @@ vector<RecipeTag> RecipeDatabase::retrieveAllTags(){
|
|||
}
|
||||
|
||||
bool RecipeDatabase::deleteRecipe(string name){
|
||||
ResultTable t = this->selectFrom("recipe", "recipeId", "WHERE name="+name);
|
||||
ResultTable t = this->selectFrom("recipe", "recipeId", "WHERE name='"+name+"'");
|
||||
if (t.rowCount() != 1){
|
||||
return false;
|
||||
}
|
||||
|
@ -250,6 +248,7 @@ bool RecipeDatabase::deleteRecipe(string name){
|
|||
bool RecipeDatabase::deleteRecipe(int recipeId){
|
||||
string idString = std::to_string(recipeId);
|
||||
if (this->selectFrom("recipe", "recipeId", "WHERE recipeId="+idString).isEmpty()){
|
||||
printf("Cannot delete. No recipe with ID %d exists.\n", recipeId);
|
||||
return false;
|
||||
}
|
||||
this->executeSQL("BEGIN;");
|
||||
|
@ -266,27 +265,28 @@ bool RecipeDatabase::deleteRecipe(int recipeId){
|
|||
}
|
||||
|
||||
bool RecipeDatabase::deleteIngredient(string name){
|
||||
ResultTable t = this->selectFrom("recipeIngredient", "recipeId", "WHERE ingredientId=("
|
||||
"SELECT ingredientId"
|
||||
"FROM ingredient"
|
||||
"WHERE name="+name+")");
|
||||
ResultTable t = this->executeSQL("SELECT recipeId "
|
||||
"FROM recipeIngredient "
|
||||
"INNER JOIN ingredient "
|
||||
"ON recipeIngredient.ingredientId = ingredient.ingredientId "
|
||||
"WHERE ingredient.name='"+name+"';");
|
||||
if (!t.isEmpty()){
|
||||
//There is at least one recipe dependent on the ingredient.
|
||||
return false;
|
||||
}
|
||||
return this->deleteFrom("ingredient", "WHERE name="+name);
|
||||
return this->deleteFrom("ingredient", "WHERE name='"+name+"'");
|
||||
}
|
||||
|
||||
bool RecipeDatabase::deleteUnitOfMeasure(string name){
|
||||
ResultTable t = this->selectFrom("recipeIngredient", "recipeId", "WHERE unitName="+name);
|
||||
ResultTable t = this->selectFrom("recipeIngredient", "recipeId", "WHERE unitName='"+name+"'");
|
||||
if (!t.isEmpty()){
|
||||
return false;
|
||||
}
|
||||
return this->deleteFrom("unitOfMeasure", "WHERE name="+name);
|
||||
return this->deleteFrom("unitOfMeasure", "WHERE name='"+name+"'");
|
||||
}
|
||||
|
||||
bool RecipeDatabase::deleteTag(RecipeTag tag){
|
||||
return this->deleteFrom("recipeTag", "WHERE tagName="+tag.getValue());
|
||||
return this->deleteFrom("recipeTag", "WHERE tagName='"+tag.getValue()+"'");
|
||||
}
|
||||
|
||||
void RecipeDatabase::ensureTablesExist(){
|
||||
|
@ -331,3 +331,18 @@ void RecipeDatabase::ensureTablesExist(){
|
|||
"FOREIGN KEY (unitName) REFERENCES unitOfMeasure(name));");
|
||||
this->executeSQL("COMMIT;");
|
||||
}
|
||||
|
||||
Recipe RecipeDatabase::readFromResultTable(ResultTable t, int row){
|
||||
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)));
|
||||
r.setInstruction(FileUtils::loadInstruction(id));
|
||||
r.setImage(FileUtils::loadImage(id));
|
||||
r.setIngredients(this->retrieveRecipeIngredients(id));
|
||||
r.setTags(this->retrieveTags(id));
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ class RecipeDatabase : public Database
|
|||
|
||||
//Retrieval.
|
||||
Recipe retrieveRecipe(string name);
|
||||
Recipe retrieveRandomRecipe();
|
||||
vector<Recipe> retrieveAllRecipes();
|
||||
vector<RecipeIngredient> retrieveRecipeIngredients(int recipeId);
|
||||
vector<Ingredient> retrieveAllIngredients();
|
||||
|
@ -49,6 +50,8 @@ class RecipeDatabase : public Database
|
|||
|
||||
//Utility methods.
|
||||
void ensureTablesExist();
|
||||
//Read a recipe from a row of a result table.
|
||||
Recipe readFromResultTable(ResultTable t, int row=0);
|
||||
};
|
||||
|
||||
#endif // RECIPEDATABASE_H
|
||||
|
|
|
@ -50,7 +50,7 @@ string RecipeIngredient::toString(){
|
|||
result += StringUtils::toString(this->getQuantity());
|
||||
}
|
||||
result += " " + this->getUnit().getAbbreviation() + " " + this->getName();
|
||||
if (!this->getComment().empty()) result += " ~" + this->getComment();
|
||||
if (!this->getComment().empty()) result += " (" + this->getComment() + ")";
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ Recipe::Recipe(string name, vector<RecipeIngredient> ingredients, Instruction in
|
|||
setServings(servings);
|
||||
}
|
||||
|
||||
Recipe::Recipe() : Recipe::Recipe("Unnamed 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(1, 0), QTime(0, 30), 10.0f){
|
||||
//Set default values when none are specified.
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,11 @@ QTime Recipe::getTotalTime() const{
|
|||
}
|
||||
|
||||
float Recipe::getServings() const{
|
||||
return this->servings;
|
||||
return this->servings;
|
||||
}
|
||||
|
||||
bool Recipe::isEmpty() const{
|
||||
return this->name.empty();
|
||||
}
|
||||
|
||||
void Recipe::setName(string newName){
|
||||
|
|
|
@ -46,6 +46,7 @@ public:
|
|||
QTime getCookTime() const;
|
||||
QTime getTotalTime() const; //Derived method to add prep and cook times.
|
||||
float getServings() const;
|
||||
bool isEmpty() const;
|
||||
|
||||
//Setters
|
||||
void setName(string newName);
|
||||
|
|
|
@ -16,7 +16,7 @@ int RecipeTableModel::rowCount(const QModelIndex &parent) const{
|
|||
|
||||
int RecipeTableModel::columnCount(const QModelIndex &parent) const{
|
||||
Q_UNUSED(parent);
|
||||
return 2;//FIX THIS TO BE MORE ADAPTIVE EVENTUALLY.
|
||||
return 5;//FIX THIS TO BE MORE ADAPTIVE EVENTUALLY.
|
||||
}
|
||||
|
||||
QVariant RecipeTableModel::data(const QModelIndex &index, int role) const{
|
||||
|
@ -30,6 +30,12 @@ QVariant RecipeTableModel::data(const QModelIndex &index, int role) const{
|
|||
return QString::fromStdString(r.getName());
|
||||
case 1:
|
||||
return QString::fromStdString(r.getCreatedDate().toString().toStdString());
|
||||
case 2:
|
||||
return QString::fromStdString(StringUtils::toString(r.getServings()));
|
||||
case 3:
|
||||
return r.getPrepTime().toString("hh:mm:ss");
|
||||
case 4:
|
||||
return r.getCookTime().toString("hh:mm:ss");
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
|
@ -45,6 +51,12 @@ QVariant RecipeTableModel::headerData(int section, Qt::Orientation orientation,
|
|||
return "Name";
|
||||
case 1:
|
||||
return "Created On";
|
||||
case 2:
|
||||
return "Servings";
|
||||
case 3:
|
||||
return "Prep Time";
|
||||
case 4:
|
||||
return "Cook Time";
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
|
@ -59,3 +71,16 @@ void RecipeTableModel::setRecipes(vector<Recipe> recipes){
|
|||
this->recipes = recipes;
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
Recipe RecipeTableModel::getRecipeAt(int index){
|
||||
if (index < 0 || index >= this->recipes.size()){
|
||||
return Recipe();
|
||||
}
|
||||
return this->recipes[index];
|
||||
}
|
||||
|
||||
void RecipeTableModel::clear(){
|
||||
beginResetModel();
|
||||
this->recipes.clear();
|
||||
endResetModel();
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <QAbstractTableModel>
|
||||
|
||||
#include "model/recipe/recipe.h"
|
||||
#include "utils/stringutils.h"
|
||||
|
||||
class RecipeTableModel : public QAbstractTableModel
|
||||
{
|
||||
|
@ -19,7 +20,8 @@ class RecipeTableModel : public QAbstractTableModel
|
|||
|
||||
//Normal methods.
|
||||
void setRecipes(vector<Recipe> recipes);
|
||||
|
||||
Recipe getRecipeAt(int index);
|
||||
void clear();
|
||||
private:
|
||||
vector<Recipe> recipes;
|
||||
};
|
||||
|
|
|
@ -2,6 +2,14 @@
|
|||
|
||||
namespace StringUtils{
|
||||
|
||||
bool stringEndsWith(std::string const &fullString, std::string const &ending){
|
||||
if (fullString.length() >= ending.length()) {
|
||||
return (0 == fullString.compare (fullString.length() - ending.length(), ending.length(), ending));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::string toString(float val){
|
||||
float decimal = std::fmod(val, 1.0f);
|
||||
int places = 1;
|
||||
|
@ -13,6 +21,11 @@ std::string toString(float val){
|
|||
std::string arg = "%."+std::to_string(places)+"f";
|
||||
sprintf(buffer, arg.c_str(), val);
|
||||
std::string s = buffer;
|
||||
if (stringEndsWith(s, ".0")){
|
||||
while (s.find('.') != std::string::npos){
|
||||
s.pop_back();
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue