Merge pull request #7 from andrewlalis/development
Actually Usable Version
This commit is contained in:
commit
626fe91bb1
13
RecipeDB.pro
13
RecipeDB.pro
|
@ -14,7 +14,6 @@ TEMPLATE = app
|
||||||
|
|
||||||
SOURCES += model/recipe/instruction.cpp \
|
SOURCES += model/recipe/instruction.cpp \
|
||||||
model/recipe/recipe.cpp \
|
model/recipe/recipe.cpp \
|
||||||
userInterface/mainwindow.cpp \
|
|
||||||
main.cpp \
|
main.cpp \
|
||||||
model/database/database.cpp \
|
model/database/database.cpp \
|
||||||
model/recipe/ingredients/unitofmeasure.cpp \
|
model/recipe/ingredients/unitofmeasure.cpp \
|
||||||
|
@ -33,11 +32,12 @@ SOURCES += model/recipe/instruction.cpp \
|
||||||
gui/newDialogs/newunitdialog.cpp \
|
gui/newDialogs/newunitdialog.cpp \
|
||||||
utils/aspectratiopixmaplabel.cpp \
|
utils/aspectratiopixmaplabel.cpp \
|
||||||
utils/stringutils.cpp \
|
utils/stringutils.cpp \
|
||||||
openrecipedialog.cpp
|
gui/openrecipedialog.cpp \
|
||||||
|
model/recipe/recipetablemodel.cpp \
|
||||||
|
gui/mainwindow.cpp
|
||||||
|
|
||||||
HEADERS += model/recipe/instruction.h \
|
HEADERS += model/recipe/instruction.h \
|
||||||
model/recipe/recipe.h \
|
model/recipe/recipe.h \
|
||||||
userInterface/mainwindow.h \
|
|
||||||
model/database/database.h \
|
model/database/database.h \
|
||||||
model/recipe/ingredients/unitofmeasure.h \
|
model/recipe/ingredients/unitofmeasure.h \
|
||||||
model/recipe/ingredients/ingredient.h \
|
model/recipe/ingredients/ingredient.h \
|
||||||
|
@ -56,7 +56,9 @@ HEADERS += model/recipe/instruction.h \
|
||||||
gui/newDialogs/newunitdialog.h \
|
gui/newDialogs/newunitdialog.h \
|
||||||
utils/aspectratiopixmaplabel.h \
|
utils/aspectratiopixmaplabel.h \
|
||||||
utils/stringutils.h \
|
utils/stringutils.h \
|
||||||
openrecipedialog.h
|
gui/openrecipedialog.h \
|
||||||
|
model/recipe/recipetablemodel.h \
|
||||||
|
gui/mainwindow.h
|
||||||
|
|
||||||
LIBS += -ldl \
|
LIBS += -ldl \
|
||||||
|
|
||||||
|
@ -65,7 +67,8 @@ FORMS += gui/mainwindow.ui \
|
||||||
gui/newDialogs/newingredientdialog.ui \
|
gui/newDialogs/newingredientdialog.ui \
|
||||||
gui/newDialogs/newtagdialog.ui \
|
gui/newDialogs/newtagdialog.ui \
|
||||||
gui/newDialogs/newunitdialog.ui \
|
gui/newDialogs/newunitdialog.ui \
|
||||||
openrecipedialog.ui
|
gui/openrecipedialog.ui \
|
||||||
|
gui/mainwindow.ui
|
||||||
|
|
||||||
DISTFILES += \
|
DISTFILES += \
|
||||||
.gitignore
|
.gitignore
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "userInterface/mainwindow.h"
|
#include "gui/mainwindow.h"
|
||||||
#include "ui_mainwindow.h"
|
#include "ui_mainwindow.h"
|
||||||
|
|
||||||
MainWindow::MainWindow(QWidget *parent) :
|
MainWindow::MainWindow(QWidget *parent) :
|
||||||
|
@ -58,7 +58,7 @@ void MainWindow::setCookTime(QTime cookTime){
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::setServings(float servings){
|
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){
|
void MainWindow::setTags(vector<RecipeTag> tags){
|
||||||
|
@ -72,8 +72,22 @@ void MainWindow::on_newButton_clicked(){
|
||||||
if (d.isAccepted()){
|
if (d.isAccepted()){
|
||||||
Recipe r = d.getRecipe();
|
Recipe r = d.getRecipe();
|
||||||
if (!this->recipeDB->storeRecipe(r)){
|
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
|
@ -8,6 +8,7 @@
|
||||||
#include "model/recipe/recipe.h"
|
#include "model/recipe/recipe.h"
|
||||||
#include "model/recipe/ingredients/ingredientlistmodel.h"
|
#include "model/recipe/ingredients/ingredientlistmodel.h"
|
||||||
#include "gui/newrecipedialog.h"
|
#include "gui/newrecipedialog.h"
|
||||||
|
#include "gui/openrecipedialog.h"
|
||||||
#include "utils/stringutils.h"
|
#include "utils/stringutils.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -27,9 +28,14 @@ public:
|
||||||
|
|
||||||
//Loads all data from a recipe into the GUI components.
|
//Loads all data from a recipe into the GUI components.
|
||||||
void loadFromRecipe(Recipe recipe);
|
void loadFromRecipe(Recipe recipe);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void on_newButton_clicked();
|
void on_newButton_clicked();
|
||||||
|
|
||||||
|
void on_openButton_clicked();
|
||||||
|
|
||||||
|
void on_exitButton_clicked();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::MainWindow *ui;
|
Ui::MainWindow *ui;
|
||||||
RecipeDatabase *recipeDB;
|
RecipeDatabase *recipeDB;
|
|
@ -143,6 +143,12 @@ QPushButton#newButton:pressed{
|
||||||
</item>
|
</item>
|
||||||
<item alignment="Qt::AlignTop">
|
<item alignment="Qt::AlignTop">
|
||||||
<widget class="QPushButton" name="openButton">
|
<widget class="QPushButton" name="openButton">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>150</width>
|
<width>150</width>
|
||||||
|
@ -175,6 +181,9 @@ QPushButton#openButton:pressed{
|
||||||
</item>
|
</item>
|
||||||
<item alignment="Qt::AlignTop">
|
<item alignment="Qt::AlignTop">
|
||||||
<widget class="QPushButton" name="browseButton">
|
<widget class="QPushButton" name="browseButton">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>150</width>
|
<width>150</width>
|
||||||
|
@ -211,6 +220,56 @@ QPushButton#browseButton:pressed{
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</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>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -367,6 +426,9 @@ font: "Noto Sans CJK KR";</string>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Prep Time:</string>
|
<string>Prep Time:</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
@ -383,6 +445,9 @@ font: "Noto Sans CJK KR";</string>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Cook Time:</string>
|
<string>Cook Time:</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
@ -396,6 +461,9 @@ font: "Noto Sans CJK KR";</string>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Servings:</string>
|
<string>Servings:</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
|
|
@ -8,10 +8,8 @@ NewUnitDialog::NewUnitDialog(QWidget *parent) :
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
ui->typeComboBox->clear();
|
ui->typeComboBox->clear();
|
||||||
ui->typeComboBox->setItemData(0, "Mass");
|
QStringList list({"Mass", "Volume", "Length", "Misc"});
|
||||||
ui->typeComboBox->setItemData(1, "Volume");
|
ui->typeComboBox->insertItems(0, list);
|
||||||
ui->typeComboBox->setItemData(2, "Length");
|
|
||||||
ui->typeComboBox->setItemData(3, "Misc");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +21,7 @@ NewUnitDialog::~NewUnitDialog()
|
||||||
UnitOfMeasure NewUnitDialog::getUnit(){
|
UnitOfMeasure NewUnitDialog::getUnit(){
|
||||||
return UnitOfMeasure(ui->unitNameEdit->text().toLower().toStdString(),
|
return UnitOfMeasure(ui->unitNameEdit->text().toLower().toStdString(),
|
||||||
ui->pluralNameEdit->text().toLower().toStdString(),
|
ui->pluralNameEdit->text().toLower().toStdString(),
|
||||||
ui->abbreviationEdit->text().toLower().toStdString(),
|
ui->abbreviationEdit->text().toStdString(),
|
||||||
this->getSelectedType(),
|
this->getSelectedType(),
|
||||||
ui->coefficientSpinBox->value());
|
ui->coefficientSpinBox->value());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
QModelIndexList indexList = ui->ingredientsListView->selectionModel()->selectedIndexes();
|
||||||
for (QModelIndexList::iterator it = indexList.begin(); it != indexList.end(); ++it){
|
for (QModelIndexList::iterator it = indexList.begin(); it != indexList.end(); ++it){
|
||||||
QModelIndex i = *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(){
|
void NewRecipeDialog::on_newIngredientButton_clicked(){
|
||||||
NewIngredientDialog d(this);
|
NewIngredientDialog d(this);
|
||||||
d.show();
|
d.show();
|
||||||
|
@ -155,12 +171,12 @@ void NewRecipeDialog::on_newTagButton_clicked(){
|
||||||
}
|
}
|
||||||
|
|
||||||
void NewRecipeDialog::on_removeTagButton_clicked(){
|
void NewRecipeDialog::on_removeTagButton_clicked(){
|
||||||
int index = ui->tagsComboBox->currentIndex();
|
unsigned int index = ui->tagsComboBox->currentIndex();
|
||||||
if (index < 0 || index >= this->tags.size()){
|
if (index >= this->tags.size()){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
RecipeTag tag = this->tags[ui->tagsComboBox->currentIndex()];
|
RecipeTag tag = this->tags[ui->tagsComboBox->currentIndex()];
|
||||||
string content = "Are you sure you wish to delete the following tag:\n"+tag.getValue();
|
string content = "Are you sure you wish to delete the following tag:\n"+tag.getValue()+"\nThis will delete the tag for all recipes that use it.";
|
||||||
QMessageBox::StandardButton reply = QMessageBox::question(this, QString("Delete Tag"), QString(content.c_str()));
|
QMessageBox::StandardButton reply = QMessageBox::question(this, QString("Delete Tag"), QString(content.c_str()));
|
||||||
if (reply == QMessageBox::Yes){
|
if (reply == QMessageBox::Yes){
|
||||||
this->recipeDB->deleteTag(tag);
|
this->recipeDB->deleteTag(tag);
|
||||||
|
@ -173,10 +189,25 @@ void NewRecipeDialog::on_newUnitButton_clicked(){
|
||||||
d.show();
|
d.show();
|
||||||
if (d.exec() == QDialog::Accepted){
|
if (d.exec() == QDialog::Accepted){
|
||||||
UnitOfMeasure u = d.getUnit();
|
UnitOfMeasure u = d.getUnit();
|
||||||
if (!this->recipeDB->storeUnitOfMeasure(u)){
|
if (!this->recipeDB->storeUnitOfMeasure(u) || u.getName().empty() || u.getNamePlural().empty() || u.getAbbreviation().empty()){
|
||||||
QMessageBox::critical(this, "Error", "Unable to store new unit.");
|
QMessageBox::critical(this, "Error", "Unable to store new unit.");
|
||||||
} else {
|
} else {
|
||||||
this->populateUnitsBox();
|
this->populateUnitsBox();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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_selectImageButton_clicked();
|
||||||
|
|
||||||
|
void on_removeIngredientButton_clicked();
|
||||||
|
|
||||||
void on_deleteIngredientButton_clicked();
|
void on_deleteIngredientButton_clicked();
|
||||||
|
|
||||||
void on_newIngredientButton_clicked();
|
void on_newIngredientButton_clicked();
|
||||||
|
@ -57,6 +59,8 @@ class NewRecipeDialog : public QDialog
|
||||||
|
|
||||||
void on_newUnitButton_clicked();
|
void on_newUnitButton_clicked();
|
||||||
|
|
||||||
|
void on_deleteUnitButton_clicked();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::NewRecipeDialog *ui;
|
Ui::NewRecipeDialog *ui;
|
||||||
RecipeDatabase *recipeDB;
|
RecipeDatabase *recipeDB;
|
||||||
|
|
|
@ -26,6 +26,9 @@
|
||||||
<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 "Noto Sans CJK KR";</string>
|
||||||
|
</property>
|
||||||
<property name="modal">
|
<property name="modal">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
@ -97,9 +100,7 @@
|
||||||
<widget class="QLabel" name="recipeNameLabel">
|
<widget class="QLabel" name="recipeNameLabel">
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
<family>Noto Sans CJK KR</family>
|
<weight>3</weight>
|
||||||
<pointsize>14</pointsize>
|
|
||||||
<weight>50</weight>
|
|
||||||
<italic>false</italic>
|
<italic>false</italic>
|
||||||
<bold>false</bold>
|
<bold>false</bold>
|
||||||
</font>
|
</font>
|
||||||
|
@ -116,7 +117,9 @@
|
||||||
<widget class="QLineEdit" name="recipeNameEdit">
|
<widget class="QLineEdit" name="recipeNameEdit">
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
<stylestrategy>PreferAntialias</stylestrategy>
|
<weight>3</weight>
|
||||||
|
<italic>false</italic>
|
||||||
|
<bold>false</bold>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="alignment">
|
<property name="alignment">
|
||||||
|
@ -155,7 +158,7 @@
|
||||||
<second>0</second>
|
<second>0</second>
|
||||||
<year>1999</year>
|
<year>1999</year>
|
||||||
<month>12</month>
|
<month>12</month>
|
||||||
<day>26</day>
|
<day>25</day>
|
||||||
</datetime>
|
</datetime>
|
||||||
</property>
|
</property>
|
||||||
<property name="currentSection">
|
<property name="currentSection">
|
||||||
|
@ -501,6 +504,17 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</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>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -532,9 +546,7 @@
|
||||||
<widget class="QLabel" name="amountLabel">
|
<widget class="QLabel" name="amountLabel">
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
<family>Noto Sans CJK KR</family>
|
<weight>3</weight>
|
||||||
<pointsize>14</pointsize>
|
|
||||||
<weight>50</weight>
|
|
||||||
<italic>false</italic>
|
<italic>false</italic>
|
||||||
<bold>false</bold>
|
<bold>false</bold>
|
||||||
</font>
|
</font>
|
||||||
|
@ -578,6 +590,17 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</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>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -626,7 +649,7 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="deleteIngredientButton">
|
<widget class="QPushButton" name="removeIngredientButton">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Delete</string>
|
<string>Delete</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -745,9 +768,9 @@
|
||||||
<widget class="QToolButton" name="italicsButton">
|
<widget class="QToolButton" name="italicsButton">
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
<family>Liberation Serif</family>
|
<weight>3</weight>
|
||||||
<pointsize>12</pointsize>
|
<italic>false</italic>
|
||||||
<italic>true</italic>
|
<bold>false</bold>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
@ -765,10 +788,9 @@
|
||||||
<widget class="QToolButton" name="boldButton">
|
<widget class="QToolButton" name="boldButton">
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
<family>Liberation Serif</family>
|
<weight>3</weight>
|
||||||
<pointsize>12</pointsize>
|
<italic>false</italic>
|
||||||
<weight>75</weight>
|
<bold>false</bold>
|
||||||
<bold>true</bold>
|
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
#include "openrecipedialog.h"
|
||||||
|
#include "ui_openrecipedialog.h"
|
||||||
|
|
||||||
|
OpenRecipeDialog::OpenRecipeDialog(QWidget *parent) :
|
||||||
|
QDialog(parent),
|
||||||
|
ui(new Ui::OpenRecipeDialog)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
ui->recipeTableView->setModel(&this->recipeTableModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenRecipeDialog::OpenRecipeDialog(RecipeDatabase *recipeDB, QWidget *parent) : OpenRecipeDialog(parent){
|
||||||
|
this->recipeDB = recipeDB;
|
||||||
|
this->populateRecipesTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenRecipeDialog::~OpenRecipeDialog()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
Recipe OpenRecipeDialog::getSelectedRecipe(){
|
||||||
|
return this->selectedRecipe;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenRecipeDialog::populateRecipesTable(){
|
||||||
|
this->recipeTableModel.clear();
|
||||||
|
vector<Recipe> recipes = this->recipeDB->retrieveAllRecipes();
|
||||||
|
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();
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
#ifndef OPENRECIPEDIALOG_H
|
||||||
|
#define OPENRECIPEDIALOG_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
|
#include "model/database/recipedatabase.h"
|
||||||
|
#include "model/recipe/recipetablemodel.h"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class OpenRecipeDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
class OpenRecipeDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit OpenRecipeDialog(QWidget *parent = 0);
|
||||||
|
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();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // OPENRECIPEDIALOG_H
|
|
@ -0,0 +1,134 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>OpenRecipeDialog</class>
|
||||||
|
<widget class="QDialog" name="OpenRecipeDialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>640</width>
|
||||||
|
<height>480</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Open Recipe</string>
|
||||||
|
</property>
|
||||||
|
<property name="windowIcon">
|
||||||
|
<iconset resource="../images.qrc">
|
||||||
|
<normaloff>:/images/images/icon.png</normaloff>:/images/images/icon.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="modal">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item alignment="Qt::AlignTop">
|
||||||
|
<widget class="QWidget" name="searchPanel" native="true">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="nameSearchPanel" native="true">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="nameLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Name</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="nameEdit"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="tagsSearchpanel" native="true">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="tagLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Tag</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="tagEdit"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="ingredientSearchPanel" native="true">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="ingredientLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Ingredient</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="ingredientEdit"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="searchButton">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../images.qrc">
|
||||||
|
<normaloff>:/images/images/search_icon.png</normaloff>:/images/images/search_icon.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</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">
|
||||||
|
<item>
|
||||||
|
<widget class="QTableView" name="recipeTableView">
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::NoFrame</enum>
|
||||||
|
</property>
|
||||||
|
<property name="selectionBehavior">
|
||||||
|
<enum>QAbstractItemView::SelectRows</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sortingEnabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<attribute name="verticalHeaderVisible">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources>
|
||||||
|
<include location="../images.qrc"/>
|
||||||
|
</resources>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
|
@ -4,5 +4,7 @@
|
||||||
<file>images/icon.png</file>
|
<file>images/icon.png</file>
|
||||||
<file>images/plus_icon.png</file>
|
<file>images/plus_icon.png</file>
|
||||||
<file>images/minus_icon.png</file>
|
<file>images/minus_icon.png</file>
|
||||||
|
<file>images/search_icon.png</file>
|
||||||
|
<file>images/trash.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 9.7 KiB |
Binary file not shown.
After Width: | Height: | Size: 724 B |
56
main.cpp
56
main.cpp
|
@ -1,4 +1,4 @@
|
||||||
#include "userInterface/mainwindow.h"
|
#include "gui/mainwindow.h"
|
||||||
#include "gui/newrecipedialog.h"
|
#include "gui/newrecipedialog.h"
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
|
||||||
|
@ -13,42 +13,28 @@ int main(int argc, char *argv[])
|
||||||
w.show();
|
w.show();
|
||||||
|
|
||||||
//TESTING CODE
|
//TESTING CODE
|
||||||
// vector<RecipeIngredient> ri;
|
vector<RecipeIngredient> ri;
|
||||||
// ri.push_back(RecipeIngredient("flour", "grains", 3.0f, UnitOfMeasure("cup", "cups", "c", UnitOfMeasure::VOLUME, 1.0), ""));
|
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), ""));
|
ri.push_back(RecipeIngredient("baking powder", "additives", 1.0f, UnitOfMeasure("teaspoon", "teaspoons", "tsp", UnitOfMeasure::VOLUME, 1.0), ""));
|
||||||
|
|
||||||
// Recipe rec("Example",
|
Recipe rec("Example",
|
||||||
// ri,
|
ri,
|
||||||
// Instruction("<b>BOLD</b><i>iTaLiCs</i>"),
|
Instruction("<b>BOLD</b><i>iTaLiCs</i>"),
|
||||||
// QImage(),
|
QImage(),
|
||||||
// vector<RecipeTag>({RecipeTag("testing"),
|
vector<RecipeTag>({RecipeTag("testing"),
|
||||||
// RecipeTag("fake")}),
|
RecipeTag("fake")}),
|
||||||
// QDate::currentDate(),
|
QDate::currentDate(),
|
||||||
// QTime(0, 30),
|
QTime(0, 30),
|
||||||
// QTime(0, 25),
|
QTime(0, 25),
|
||||||
// 10.0f);
|
10.0f);
|
||||||
|
|
||||||
// bool success = recipeDB.storeRecipe(rec);
|
bool success = recipeDB.storeRecipe(rec);
|
||||||
// printf("Storage successful: %d\n", success);
|
printf("Storage successful: %d\n", success);
|
||||||
|
|
||||||
// recipeDB.storeUnitOfMeasure(UnitOfMeasure("tablespoon", "tablespoons", "tbsp", UnitOfMeasure::VOLUME, 1.0));
|
//recipeDB.selectFrom("recipe", "recipeId, name", "").printData();
|
||||||
// recipeDB.storeUnitOfMeasure(UnitOfMeasure("pinch", "pinches", "pch", UnitOfMeasure::VOLUME, 1.0));
|
w.loadFromRecipe(recipeDB.retrieveRandomRecipe());
|
||||||
// recipeDB.storeUnitOfMeasure(UnitOfMeasure("gram", "grams", "g", UnitOfMeasure::MASS, 1.0));
|
|
||||||
|
|
||||||
// Recipe reloadRec = recipeDB.retrieveRecipe("Example");
|
a.exec();
|
||||||
// reloadRec.print();
|
recipeDB.closeConnection();
|
||||||
|
return 0;
|
||||||
// w.loadFromRecipe(reloadRec);
|
|
||||||
|
|
||||||
// NewRecipeDialog d(&recipeDB);
|
|
||||||
// d.show();
|
|
||||||
// d.exec();
|
|
||||||
|
|
||||||
// if (d.isAccepted()){
|
|
||||||
// printf("Accepted the dialog.\n");
|
|
||||||
// }
|
|
||||||
|
|
||||||
w.loadFromRecipe(recipeDB.retrieveRecipe("Generic Bread"));
|
|
||||||
|
|
||||||
return a.exec();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,20 @@ ResultTable Database::selectFrom(string tableName, string columnNames, string co
|
||||||
return this->executeSQL(query);
|
return this->executeSQL(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Database::deleteFrom(string tableName, string conditions){
|
||||||
|
if (tableName.empty()){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
string query = "DELETE FROM " + tableName + " " + conditions + ";";
|
||||||
|
ResultTable t = this->executeSQL(query);
|
||||||
|
if (t.getReturnCode() != SQLITE_DONE){
|
||||||
|
fprintf(stderr, "Can't delete from table %s.Return code: %d\n%s\n", tableName.c_str(), t.getReturnCode(), sqlite3_errmsg(this->db));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Database::openConnection(){
|
void Database::openConnection(){
|
||||||
this->returnCode = sqlite3_open(this->filename.c_str(), &this->db);
|
this->returnCode = sqlite3_open(this->filename.c_str(), &this->db);
|
||||||
if (this->returnCode || this->db == NULL){
|
if (this->returnCode || this->db == NULL){
|
||||||
|
|
|
@ -26,10 +26,13 @@ public:
|
||||||
ResultTable executeSQL(string statement);
|
ResultTable executeSQL(string statement);
|
||||||
bool insertInto(string tableName, vector<string> columnNames, vector<string> values);
|
bool insertInto(string tableName, vector<string> columnNames, vector<string> values);
|
||||||
ResultTable selectFrom(string tableName, string columnNames, string conditions);
|
ResultTable selectFrom(string tableName, string columnNames, string conditions);
|
||||||
|
bool deleteFrom(string tableName, string conditions);
|
||||||
|
|
||||||
bool tableExists(string tableName);
|
bool tableExists(string tableName);
|
||||||
int getLastInsertedRowId();
|
int getLastInsertedRowId();
|
||||||
|
|
||||||
|
void closeConnection();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
string surroundString(string s, string surround);
|
string surroundString(string s, string surround);
|
||||||
|
|
||||||
|
@ -43,7 +46,6 @@ private:
|
||||||
char* errorMsg;
|
char* errorMsg;
|
||||||
|
|
||||||
void openConnection();
|
void openConnection();
|
||||||
void closeConnection();
|
|
||||||
std::string combineVector(std::vector<std::string> strings, std::string mid);
|
std::string combineVector(std::vector<std::string> strings, std::string mid);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,12 @@ RecipeDatabase::RecipeDatabase(string filename) : Database(filename){
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RecipeDatabase::storeRecipe(Recipe recipe){
|
bool RecipeDatabase::storeRecipe(Recipe recipe){
|
||||||
|
//Some primary checks to avoid garbage in the database.
|
||||||
|
if (recipe.getName().empty() ||
|
||||||
|
recipe.getInstruction().getHTML().empty() ||
|
||||||
|
recipe.getIngredients().empty()){
|
||||||
|
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->executeSQL("BEGIN;");
|
||||||
ResultTable t = this->selectFrom("recipe", "*", "WHERE name="+surroundString(recipe.getName(), "'"));
|
ResultTable t = this->selectFrom("recipe", "*", "WHERE name="+surroundString(recipe.getName(), "'"));
|
||||||
|
@ -141,18 +147,25 @@ Recipe RecipeDatabase::retrieveRecipe(string name){
|
||||||
fprintf(stderr, "Error: No recipe with name %s found!\n", name.c_str());
|
fprintf(stderr, "Error: No recipe with name %s found!\n", name.c_str());
|
||||||
return Recipe();
|
return Recipe();
|
||||||
}
|
}
|
||||||
Recipe r;
|
return this->readFromResultTable(t);
|
||||||
int id = std::stoi(t.valueAt(0, 0));
|
}
|
||||||
r.setName(t.valueAt(0, 1));
|
|
||||||
r.setCreatedDate(QDate::fromString(QString::fromStdString(t.valueAt(0, 2))));
|
Recipe RecipeDatabase::retrieveRandomRecipe(){
|
||||||
r.setPrepTime(QTime::fromString(QString::fromStdString(t.valueAt(0, 3))));
|
ResultTable t = this->selectFrom("recipe", "*", "ORDER BY RANDOM() LIMIT 1");
|
||||||
r.setCookTime(QTime::fromString(QString::fromStdString(t.valueAt(0, 4))));
|
if (t.isEmpty()){
|
||||||
r.setServings(std::stof(t.valueAt(0, 5)));
|
fprintf(stderr, "Unable to find a random recipe.\n");
|
||||||
r.setInstruction(FileUtils::loadInstruction(id));
|
return Recipe();
|
||||||
r.setImage(FileUtils::loadImage(id));
|
}
|
||||||
r.setIngredients(this->retrieveRecipeIngredients(id));
|
return this->readFromResultTable(t);
|
||||||
r.setTags(this->retrieveTags(id));
|
}
|
||||||
return r;
|
|
||||||
|
vector<Recipe> RecipeDatabase::retrieveAllRecipes(){
|
||||||
|
ResultTable t = this->selectFrom("recipe", "name", "ORDER BY name");
|
||||||
|
vector<Recipe> recipes;
|
||||||
|
for (unsigned int row = 0; row < t.rowCount(); row++){
|
||||||
|
recipes.push_back(this->retrieveRecipe(t.valueAt(row, 0)));
|
||||||
|
}
|
||||||
|
return recipes;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<RecipeIngredient> RecipeDatabase::retrieveRecipeIngredients(int recipeId){
|
vector<RecipeIngredient> RecipeDatabase::retrieveRecipeIngredients(int recipeId){
|
||||||
|
@ -223,8 +236,57 @@ vector<RecipeTag> RecipeDatabase::retrieveAllTags(){
|
||||||
return tags;
|
return tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RecipeDatabase::deleteTag(RecipeTag tag){
|
bool RecipeDatabase::deleteRecipe(string name){
|
||||||
ResultTable t = this->executeSQL("DELETE FROM recipeTag WHERE tagName="+surroundString(tag.getValue(), "'"));
|
ResultTable t = this->selectFrom("recipe", "recipeId", "WHERE name='"+name+"'");
|
||||||
|
if (t.rowCount() != 1){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
string recipeId = t.valueAt(0, 0);
|
||||||
|
return this->deleteRecipe(std::stoi(recipeId));
|
||||||
|
}
|
||||||
|
|
||||||
|
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;");
|
||||||
|
bool tagsDeleted = this->deleteFrom("recipeTag", "WHERE recipeId="+idString);
|
||||||
|
bool recipeIngredientDeleted = this->deleteFrom("recipeIngredient", "WHERE recipeId="+idString);
|
||||||
|
bool recipeDeleted = this->deleteFrom("recipe", "WHERE recipeId="+idString);
|
||||||
|
if (tagsDeleted && recipeIngredientDeleted && recipeDeleted){
|
||||||
|
this->executeSQL("COMMIT;");
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
this->executeSQL("ROLLBACK;");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RecipeDatabase::deleteIngredient(string 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+"'");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RecipeDatabase::deleteUnitOfMeasure(string name){
|
||||||
|
ResultTable t = this->selectFrom("recipeIngredient", "recipeId", "WHERE unitName='"+name+"'");
|
||||||
|
if (!t.isEmpty()){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return this->deleteFrom("unitOfMeasure", "WHERE name='"+name+"'");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RecipeDatabase::deleteTag(RecipeTag tag){
|
||||||
|
return this->deleteFrom("recipeTag", "WHERE tagName='"+tag.getValue()+"'");
|
||||||
}
|
}
|
||||||
|
|
||||||
void RecipeDatabase::ensureTablesExist(){
|
void RecipeDatabase::ensureTablesExist(){
|
||||||
|
@ -269,3 +331,18 @@ void RecipeDatabase::ensureTablesExist(){
|
||||||
"FOREIGN KEY (unitName) REFERENCES unitOfMeasure(name));");
|
"FOREIGN KEY (unitName) REFERENCES unitOfMeasure(name));");
|
||||||
this->executeSQL("COMMIT;");
|
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,8 @@ class RecipeDatabase : public Database
|
||||||
|
|
||||||
//Retrieval.
|
//Retrieval.
|
||||||
Recipe retrieveRecipe(string name);
|
Recipe retrieveRecipe(string name);
|
||||||
|
Recipe retrieveRandomRecipe();
|
||||||
|
vector<Recipe> retrieveAllRecipes();
|
||||||
vector<RecipeIngredient> retrieveRecipeIngredients(int recipeId);
|
vector<RecipeIngredient> retrieveRecipeIngredients(int recipeId);
|
||||||
vector<Ingredient> retrieveAllIngredients();
|
vector<Ingredient> retrieveAllIngredients();
|
||||||
vector<UnitOfMeasure> retrieveAllUnitsOfMeasure();
|
vector<UnitOfMeasure> retrieveAllUnitsOfMeasure();
|
||||||
|
@ -39,11 +41,17 @@ class RecipeDatabase : public Database
|
||||||
vector<RecipeTag> retrieveAllTags();
|
vector<RecipeTag> retrieveAllTags();
|
||||||
|
|
||||||
//Deletion.
|
//Deletion.
|
||||||
void deleteTag(RecipeTag tag);
|
bool deleteRecipe(string name);
|
||||||
|
bool deleteRecipe(int recipeId);
|
||||||
|
bool deleteIngredient(string name);
|
||||||
|
bool deleteUnitOfMeasure(string name);
|
||||||
|
bool deleteTag(RecipeTag tag);
|
||||||
private:
|
private:
|
||||||
|
|
||||||
//Utility methods.
|
//Utility methods.
|
||||||
void ensureTablesExist();
|
void ensureTablesExist();
|
||||||
|
//Read a recipe from a row of a result table.
|
||||||
|
Recipe readFromResultTable(ResultTable t, int row=0);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // RECIPEDATABASE_H
|
#endif // RECIPEDATABASE_H
|
||||||
|
|
|
@ -50,7 +50,7 @@ string RecipeIngredient::toString(){
|
||||||
result += StringUtils::toString(this->getQuantity());
|
result += StringUtils::toString(this->getQuantity());
|
||||||
}
|
}
|
||||||
result += " " + this->getUnit().getAbbreviation() + " " + this->getName();
|
result += " " + this->getUnit().getAbbreviation() + " " + this->getName();
|
||||||
if (!this->getComment().empty()) result += " ~" + this->getComment();
|
if (!this->getComment().empty()) result += " (" + this->getComment() + ")";
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ Recipe::Recipe(string name, vector<RecipeIngredient> ingredients, Instruction in
|
||||||
setServings(servings);
|
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.
|
//Set default values when none are specified.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +53,11 @@ QTime Recipe::getTotalTime() const{
|
||||||
}
|
}
|
||||||
|
|
||||||
float Recipe::getServings() const{
|
float Recipe::getServings() const{
|
||||||
return this->servings;
|
return this->servings;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Recipe::isEmpty() const{
|
||||||
|
return this->name.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Recipe::setName(string newName){
|
void Recipe::setName(string newName){
|
||||||
|
|
|
@ -46,6 +46,7 @@ public:
|
||||||
QTime getCookTime() const;
|
QTime getCookTime() const;
|
||||||
QTime getTotalTime() const; //Derived method to add prep and cook times.
|
QTime getTotalTime() const; //Derived method to add prep and cook times.
|
||||||
float getServings() const;
|
float getServings() const;
|
||||||
|
bool isEmpty() const;
|
||||||
|
|
||||||
//Setters
|
//Setters
|
||||||
void setName(string newName);
|
void setName(string newName);
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
#include "recipetablemodel.h"
|
||||||
|
|
||||||
|
RecipeTableModel::RecipeTableModel()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
RecipeTableModel::RecipeTableModel(vector<Recipe> recipes){
|
||||||
|
this->setRecipes(recipes);
|
||||||
|
}
|
||||||
|
|
||||||
|
int RecipeTableModel::rowCount(const QModelIndex &parent) const{
|
||||||
|
Q_UNUSED(parent);
|
||||||
|
return this->recipes.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
int RecipeTableModel::columnCount(const QModelIndex &parent) const{
|
||||||
|
Q_UNUSED(parent);
|
||||||
|
return 5;//FIX THIS TO BE MORE ADAPTIVE EVENTUALLY.
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant RecipeTableModel::data(const QModelIndex &index, int role) const{
|
||||||
|
int row = index.row();
|
||||||
|
int col = index.column();
|
||||||
|
Recipe r = this->recipes[row];
|
||||||
|
|
||||||
|
if (role == Qt::DisplayRole){
|
||||||
|
switch(col){
|
||||||
|
case 0:
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant RecipeTableModel::headerData(int section, Qt::Orientation orientation, int role) const{
|
||||||
|
if (role != Qt::DisplayRole){
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
if (orientation == Qt::Horizontal){
|
||||||
|
switch (section){
|
||||||
|
case 0:
|
||||||
|
return "Name";
|
||||||
|
case 1:
|
||||||
|
return "Created On";
|
||||||
|
case 2:
|
||||||
|
return "Servings";
|
||||||
|
case 3:
|
||||||
|
return "Prep Time";
|
||||||
|
case 4:
|
||||||
|
return "Cook Time";
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
} else if (orientation == Qt::Vertical){
|
||||||
|
return QString::fromStdString(std::to_string(section));
|
||||||
|
}
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RecipeTableModel::setRecipes(vector<Recipe> recipes){
|
||||||
|
beginInsertRows({}, 0, recipes.size()-1);
|
||||||
|
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();
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
#ifndef RECIPETABLEMODEL_H
|
||||||
|
#define RECIPETABLEMODEL_H
|
||||||
|
|
||||||
|
#include <QAbstractTableModel>
|
||||||
|
|
||||||
|
#include "model/recipe/recipe.h"
|
||||||
|
#include "utils/stringutils.h"
|
||||||
|
|
||||||
|
class RecipeTableModel : public QAbstractTableModel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RecipeTableModel();
|
||||||
|
RecipeTableModel(vector<Recipe> recipes);
|
||||||
|
|
||||||
|
//Overridden methods.
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||||
|
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||||
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
||||||
|
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
||||||
|
|
||||||
|
//Normal methods.
|
||||||
|
void setRecipes(vector<Recipe> recipes);
|
||||||
|
Recipe getRecipeAt(int index);
|
||||||
|
void clear();
|
||||||
|
private:
|
||||||
|
vector<Recipe> recipes;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // RECIPETABLEMODEL_H
|
|
@ -1,14 +0,0 @@
|
||||||
#include "openrecipedialog.h"
|
|
||||||
#include "ui_openrecipedialog.h"
|
|
||||||
|
|
||||||
OpenRecipeDialog::OpenRecipeDialog(QWidget *parent) :
|
|
||||||
QDialog(parent),
|
|
||||||
ui(new Ui::OpenRecipeDialog)
|
|
||||||
{
|
|
||||||
ui->setupUi(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
OpenRecipeDialog::~OpenRecipeDialog()
|
|
||||||
{
|
|
||||||
delete ui;
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
#ifndef OPENRECIPEDIALOG_H
|
|
||||||
#define OPENRECIPEDIALOG_H
|
|
||||||
|
|
||||||
#include <QDialog>
|
|
||||||
|
|
||||||
namespace Ui {
|
|
||||||
class OpenRecipeDialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
class OpenRecipeDialog : public QDialog
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit OpenRecipeDialog(QWidget *parent = 0);
|
|
||||||
~OpenRecipeDialog();
|
|
||||||
|
|
||||||
private:
|
|
||||||
Ui::OpenRecipeDialog *ui;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // OPENRECIPEDIALOG_H
|
|
|
@ -1,19 +0,0 @@
|
||||||
<?xml version='1.0'?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>OpenRecipeDialog</class>
|
|
||||||
<widget name="OpenRecipeDialog" class="QDialog">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>640</width>
|
|
||||||
<height>480</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>Dialog</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
<resources/>
|
|
||||||
<connections/>
|
|
||||||
</ui>
|
|
|
@ -2,6 +2,14 @@
|
||||||
|
|
||||||
namespace StringUtils{
|
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){
|
std::string toString(float val){
|
||||||
float decimal = std::fmod(val, 1.0f);
|
float decimal = std::fmod(val, 1.0f);
|
||||||
int places = 1;
|
int places = 1;
|
||||||
|
@ -13,6 +21,11 @@ std::string toString(float val){
|
||||||
std::string arg = "%."+std::to_string(places)+"f";
|
std::string arg = "%."+std::to_string(places)+"f";
|
||||||
sprintf(buffer, arg.c_str(), val);
|
sprintf(buffer, arg.c_str(), val);
|
||||||
std::string s = buffer;
|
std::string s = buffer;
|
||||||
|
if (stringEndsWith(s, ".0")){
|
||||||
|
while (s.find('.') != std::string::npos){
|
||||||
|
s.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue