Periodic update of progress. #4
			
				
			
		
		
		
	
							
								
								
									
										11
									
								
								RecipeDB.pro
								
								
								
								
							
							
						
						
									
										11
									
								
								RecipeDB.pro
								
								
								
								
							| 
						 | 
				
			
			@ -25,7 +25,9 @@ SOURCES += model/recipe/instruction.cpp \
 | 
			
		|||
    SQLite/sqlite3.c \
 | 
			
		||||
    model/database/resulttable.cpp \
 | 
			
		||||
    model/database/recipedatabase.cpp \
 | 
			
		||||
    utils/fileutils.cpp
 | 
			
		||||
    utils/fileutils.cpp \
 | 
			
		||||
    gui/newrecipedialog.cpp \
 | 
			
		||||
    model/recipe/tags/taglistmodel.cpp
 | 
			
		||||
 | 
			
		||||
HEADERS  += model/recipe/instruction.h \
 | 
			
		||||
    model/recipe/recipe.h \
 | 
			
		||||
| 
						 | 
				
			
			@ -40,11 +42,14 @@ HEADERS  += model/recipe/instruction.h \
 | 
			
		|||
    SQLite/sqlite3ext.h \
 | 
			
		||||
    model/database/resulttable.h \
 | 
			
		||||
    model/database/recipedatabase.h \
 | 
			
		||||
    utils/fileutils.h
 | 
			
		||||
    utils/fileutils.h \
 | 
			
		||||
    gui/newrecipedialog.h \
 | 
			
		||||
    model/recipe/tags/taglistmodel.h
 | 
			
		||||
 | 
			
		||||
LIBS += -ldl \
 | 
			
		||||
 | 
			
		||||
FORMS    += gui/mainwindow.ui
 | 
			
		||||
FORMS    += gui/mainwindow.ui \
 | 
			
		||||
    gui/newrecipedialog.ui
 | 
			
		||||
 | 
			
		||||
DISTFILES += \
 | 
			
		||||
    .gitignore
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -109,12 +109,25 @@
 | 
			
		|||
            </property>
 | 
			
		||||
            <property name="font">
 | 
			
		||||
             <font>
 | 
			
		||||
              <family>Source Sans Pro Light</family>
 | 
			
		||||
              <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">background-color: rgb(83, 75, 255);</string>
 | 
			
		||||
             <string notr="true">QPushButton#newButton {
 | 
			
		||||
	background-color: rgb(235, 235, 255);
 | 
			
		||||
	border: 0px;
 | 
			
		||||
}
 | 
			
		||||
QPushButton#newButton:hover{
 | 
			
		||||
	background-color: rgb(245, 245, 255);
 | 
			
		||||
}
 | 
			
		||||
QPushButton#newButton:pressed{
 | 
			
		||||
	background-color: rgb(255, 255, 255);
 | 
			
		||||
}</string>
 | 
			
		||||
            </property>
 | 
			
		||||
            <property name="text">
 | 
			
		||||
             <string>New</string>
 | 
			
		||||
| 
						 | 
				
			
			@ -134,12 +147,22 @@
 | 
			
		|||
            </property>
 | 
			
		||||
            <property name="font">
 | 
			
		||||
             <font>
 | 
			
		||||
              <family>Source Sans Pro Light</family>
 | 
			
		||||
              <family>Noto Sans CJK KR Light</family>
 | 
			
		||||
              <pointsize>20</pointsize>
 | 
			
		||||
              <stylestrategy>PreferAntialias</stylestrategy>
 | 
			
		||||
             </font>
 | 
			
		||||
            </property>
 | 
			
		||||
            <property name="styleSheet">
 | 
			
		||||
             <string notr="true">background-color: rgb(112, 105, 255);</string>
 | 
			
		||||
             <string notr="true">QPushButton#openButton {
 | 
			
		||||
	background-color: rgb(222, 226, 255);
 | 
			
		||||
	border: 0px;
 | 
			
		||||
}
 | 
			
		||||
QPushButton#openButton:hover{
 | 
			
		||||
	background-color: rgb(232, 236, 255);
 | 
			
		||||
}
 | 
			
		||||
QPushButton#openButton:pressed{
 | 
			
		||||
	background-color: rgb(255, 255, 255);
 | 
			
		||||
}</string>
 | 
			
		||||
            </property>
 | 
			
		||||
            <property name="text">
 | 
			
		||||
             <string>Open</string>
 | 
			
		||||
| 
						 | 
				
			
			@ -156,16 +179,32 @@
 | 
			
		|||
            </property>
 | 
			
		||||
            <property name="font">
 | 
			
		||||
             <font>
 | 
			
		||||
              <family>Source Sans Pro Light</family>
 | 
			
		||||
              <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">background-color: rgb(137, 131, 255);</string>
 | 
			
		||||
             <string notr="true">QPushButton#browseButton {
 | 
			
		||||
	background-color: rgb(215, 215, 255);
 | 
			
		||||
	border: 0px;
 | 
			
		||||
}
 | 
			
		||||
QPushButton#browseButton:hover{
 | 
			
		||||
	background-color: rgb(225, 225, 255);
 | 
			
		||||
}
 | 
			
		||||
QPushButton#browseButton:pressed{
 | 
			
		||||
	background-color: rgb(255, 255, 255);
 | 
			
		||||
}</string>
 | 
			
		||||
            </property>
 | 
			
		||||
            <property name="text">
 | 
			
		||||
             <string>Browse</string>
 | 
			
		||||
            </property>
 | 
			
		||||
            <property name="flat">
 | 
			
		||||
             <bool>false</bool>
 | 
			
		||||
            </property>
 | 
			
		||||
           </widget>
 | 
			
		||||
          </item>
 | 
			
		||||
         </layout>
 | 
			
		||||
| 
						 | 
				
			
			@ -214,8 +253,13 @@
 | 
			
		|||
         </property>
 | 
			
		||||
         <property name="font">
 | 
			
		||||
          <font>
 | 
			
		||||
           <family>Source Sans Pro Light</family>
 | 
			
		||||
           <family>Noto Sans CJK KR Light</family>
 | 
			
		||||
           <pointsize>24</pointsize>
 | 
			
		||||
           <weight>50</weight>
 | 
			
		||||
           <italic>false</italic>
 | 
			
		||||
           <bold>false</bold>
 | 
			
		||||
           <stylestrategy>PreferAntialias</stylestrategy>
 | 
			
		||||
           <kerning>true</kerning>
 | 
			
		||||
          </font>
 | 
			
		||||
         </property>
 | 
			
		||||
         <property name="styleSheet">
 | 
			
		||||
| 
						 | 
				
			
			@ -299,7 +343,7 @@
 | 
			
		|||
               </property>
 | 
			
		||||
               <property name="font">
 | 
			
		||||
                <font>
 | 
			
		||||
                 <family>Source Sans Pro Light</family>
 | 
			
		||||
                 <family>Noto Sans CJK KR Thin</family>
 | 
			
		||||
                 <pointsize>18</pointsize>
 | 
			
		||||
                </font>
 | 
			
		||||
               </property>
 | 
			
		||||
| 
						 | 
				
			
			@ -324,8 +368,9 @@
 | 
			
		|||
               </property>
 | 
			
		||||
               <property name="font">
 | 
			
		||||
                <font>
 | 
			
		||||
                 <family>Source Sans Pro Light</family>
 | 
			
		||||
                 <pointsize>16</pointsize>
 | 
			
		||||
                 <family>Noto Sans CJK KR Light</family>
 | 
			
		||||
                 <pointsize>12</pointsize>
 | 
			
		||||
                 <stylestrategy>PreferAntialias</stylestrategy>
 | 
			
		||||
                </font>
 | 
			
		||||
               </property>
 | 
			
		||||
               <property name="styleSheet">
 | 
			
		||||
| 
						 | 
				
			
			@ -343,6 +388,9 @@
 | 
			
		|||
               <property name="horizontalScrollBarPolicy">
 | 
			
		||||
                <enum>Qt::ScrollBarAlwaysOff</enum>
 | 
			
		||||
               </property>
 | 
			
		||||
               <property name="selectionMode">
 | 
			
		||||
                <enum>QAbstractItemView::NoSelection</enum>
 | 
			
		||||
               </property>
 | 
			
		||||
               <property name="isWrapping" stdset="0">
 | 
			
		||||
                <bool>true</bool>
 | 
			
		||||
               </property>
 | 
			
		||||
| 
						 | 
				
			
			@ -397,7 +445,7 @@
 | 
			
		|||
               </property>
 | 
			
		||||
               <property name="font">
 | 
			
		||||
                <font>
 | 
			
		||||
                 <family>Source Sans Pro Light</family>
 | 
			
		||||
                 <family>Noto Sans CJK KR Thin</family>
 | 
			
		||||
                 <pointsize>18</pointsize>
 | 
			
		||||
                </font>
 | 
			
		||||
               </property>
 | 
			
		||||
| 
						 | 
				
			
			@ -414,6 +462,12 @@
 | 
			
		|||
             </item>
 | 
			
		||||
             <item>
 | 
			
		||||
              <widget class="QTextEdit" name="instructionsTextEdit">
 | 
			
		||||
               <property name="font">
 | 
			
		||||
                <font>
 | 
			
		||||
                 <family>Noto Sans CJK KR Medium</family>
 | 
			
		||||
                 <stylestrategy>PreferAntialias</stylestrategy>
 | 
			
		||||
                </font>
 | 
			
		||||
               </property>
 | 
			
		||||
               <property name="styleSheet">
 | 
			
		||||
                <string notr="true">background-color: rgb(244, 244, 244);</string>
 | 
			
		||||
               </property>
 | 
			
		||||
| 
						 | 
				
			
			@ -445,11 +499,11 @@
 | 
			
		|||
                <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
 | 
			
		||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
 | 
			
		||||
p, li { white-space: pre-wrap; }
 | 
			
		||||
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
 | 
			
		||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#00ff40;">This is some </span><span style=" font-size:16pt; color:#a33c3e;">colored text and </span><a href="https://www.google.com"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">link</span></a></p></body></html></string>
 | 
			
		||||
</style></head><body style=" font-family:'Noto Sans CJK KR Medium'; font-size:11pt; font-weight:400; font-style:normal;">
 | 
			
		||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; color:#00ff40;">This is some </span><span style=" font-family:'MS Shell Dlg 2'; font-size:16pt; color:#a33c3e;">colored text and </span><a href="https://www.google.com"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;">link</span></a></p></body></html></string>
 | 
			
		||||
               </property>
 | 
			
		||||
               <property name="textInteractionFlags">
 | 
			
		||||
                <set>Qt::LinksAccessibleByMouse</set>
 | 
			
		||||
                <set>Qt::TextSelectableByMouse</set>
 | 
			
		||||
               </property>
 | 
			
		||||
              </widget>
 | 
			
		||||
             </item>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,103 @@
 | 
			
		|||
#include "newrecipedialog.h"
 | 
			
		||||
#include "ui_newrecipedialog.h"
 | 
			
		||||
 | 
			
		||||
NewRecipeDialog::NewRecipeDialog(QWidget *parent) :
 | 
			
		||||
	QDialog(parent),
 | 
			
		||||
	ui(new Ui::NewRecipeDialog){
 | 
			
		||||
	ui->setupUi(this);
 | 
			
		||||
 | 
			
		||||
	setModal(true);
 | 
			
		||||
 | 
			
		||||
	ui->ingredientsListView->setModel(&this->ingredientListModel);
 | 
			
		||||
	ui->tagsListView->setModel(&this->tagsListModel);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NewRecipeDialog::NewRecipeDialog(RecipeDatabase *db, QWidget *parent) : NewRecipeDialog(parent){
 | 
			
		||||
	this->recipeDB = db;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	this->populateIngredientsBox();
 | 
			
		||||
	this->populateUnitsBox();
 | 
			
		||||
	this->populateTagsBox();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NewRecipeDialog::~NewRecipeDialog(){
 | 
			
		||||
	delete ui;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Recipe NewRecipeDialog::getRecipe(){
 | 
			
		||||
	Recipe r(ui->recipeNameEdit->text().toStdString(),
 | 
			
		||||
			 this->ingredientListModel.getIngredients(),
 | 
			
		||||
			 ui->instructionsTextEdit->toHtml().toStdString(),
 | 
			
		||||
			 QImage(),//Image
 | 
			
		||||
			 this->tagsListModel.getTags(),//Tags
 | 
			
		||||
			 QDate::currentDate(),
 | 
			
		||||
			 ui->prepTimeEdit->time(),
 | 
			
		||||
			 ui->cookTimeEdit->time(),
 | 
			
		||||
			 (float)ui->servingsSpinBox->value());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool NewRecipeDialog::isAccepted() const{
 | 
			
		||||
	return this->accepted;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void NewRecipeDialog::populateIngredientsBox(){
 | 
			
		||||
	this->ingredients = this->recipeDB->retrieveAllIngredients();
 | 
			
		||||
	ui->ingredientNameBox->clear();
 | 
			
		||||
	for (unsigned int i = 0; i < this->ingredients.size(); i++){
 | 
			
		||||
		QString s = QString::fromStdString(this->ingredients[i].getName());
 | 
			
		||||
		ui->ingredientNameBox->insertItem(i, s);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void NewRecipeDialog::populateUnitsBox(){
 | 
			
		||||
	this->units = this->recipeDB->retrieveAllUnitsOfMeasure();
 | 
			
		||||
	ui->unitComboBox->clear();
 | 
			
		||||
	for (unsigned int i = 0; i < this->units.size(); i++){
 | 
			
		||||
		QString s = QString::fromStdString(this->units[i].getName());
 | 
			
		||||
		ui->unitComboBox->insertItem(i, s);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void NewRecipeDialog::populateTagsBox(){
 | 
			
		||||
	this->tags = this->recipeDB->retrieveAllTags();
 | 
			
		||||
	ui->tagsComboBox->clear();
 | 
			
		||||
	for (unsigned int i = 0; i < this->tags.size(); i++){
 | 
			
		||||
		QString s = QString::fromStdString(this->tags[i].getValue());
 | 
			
		||||
		ui->tagsComboBox->insertItem(i, s);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void NewRecipeDialog::on_addIngredientButton_clicked(){
 | 
			
		||||
	//Construct a recipe ingredient from the supplied data.
 | 
			
		||||
	Ingredient i = this->ingredients[ui->ingredientNameBox->currentIndex()];
 | 
			
		||||
	UnitOfMeasure u = this->units[ui->unitComboBox->currentIndex()];
 | 
			
		||||
	RecipeIngredient ri(i, ui->quantitySpinBox->value(), u, ui->commentsLineEdit->text().toStdString());
 | 
			
		||||
	this->ingredientListModel.addIngredient(ri);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void NewRecipeDialog::on_italicsButton_clicked(){
 | 
			
		||||
	ui->instructionsTextEdit->setFontItalic(ui->italicsButton->isChecked());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void NewRecipeDialog::on_boldButton_clicked(){
 | 
			
		||||
	if (ui->boldButton->isChecked()){
 | 
			
		||||
		ui->instructionsTextEdit->setFontWeight(QFont::Bold);
 | 
			
		||||
	} else {
 | 
			
		||||
		ui->instructionsTextEdit->setFontWeight(QFont::Normal);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void NewRecipeDialog::on_buttonBox_accepted(){
 | 
			
		||||
	this->accepted = true;
 | 
			
		||||
	this->close();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void NewRecipeDialog::on_buttonBox_rejected(){
 | 
			
		||||
	this->close();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void NewRecipeDialog::on_addTagButton_clicked(){
 | 
			
		||||
	//Add a tag to the list of those prepared to be added.
 | 
			
		||||
	this->tagsListModel.addTag(this->tags[ui->tagsComboBox->currentIndex()]);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,55 @@
 | 
			
		|||
#ifndef NEWRECIPEDIALOG_H
 | 
			
		||||
#define NEWRECIPEDIALOG_H
 | 
			
		||||
 | 
			
		||||
#include <QDialog>
 | 
			
		||||
#include <QTextCharFormat>
 | 
			
		||||
 | 
			
		||||
#include "model/database/recipedatabase.h"
 | 
			
		||||
#include "model/recipe/ingredients/ingredientlistmodel.h"
 | 
			
		||||
#include "model/recipe/tags/taglistmodel.h"
 | 
			
		||||
 | 
			
		||||
namespace Ui {
 | 
			
		||||
class NewRecipeDialog;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class NewRecipeDialog : public QDialog
 | 
			
		||||
{
 | 
			
		||||
		Q_OBJECT
 | 
			
		||||
 | 
			
		||||
	public:
 | 
			
		||||
		explicit NewRecipeDialog(QWidget *parent = 0);
 | 
			
		||||
		NewRecipeDialog(RecipeDatabase *db, QWidget *parent = 0);
 | 
			
		||||
		~NewRecipeDialog();
 | 
			
		||||
 | 
			
		||||
		Recipe getRecipe();
 | 
			
		||||
		bool isAccepted() const;
 | 
			
		||||
	private slots:
 | 
			
		||||
		void on_addIngredientButton_clicked();
 | 
			
		||||
 | 
			
		||||
		void on_italicsButton_clicked();
 | 
			
		||||
 | 
			
		||||
		void on_boldButton_clicked();
 | 
			
		||||
 | 
			
		||||
		void on_buttonBox_accepted();
 | 
			
		||||
 | 
			
		||||
		void on_buttonBox_rejected();
 | 
			
		||||
 | 
			
		||||
		void on_addTagButton_clicked();
 | 
			
		||||
 | 
			
		||||
	private:
 | 
			
		||||
		Ui::NewRecipeDialog *ui;
 | 
			
		||||
		RecipeDatabase *recipeDB;
 | 
			
		||||
		vector<Ingredient> ingredients;
 | 
			
		||||
		vector<UnitOfMeasure> units;
 | 
			
		||||
		vector<RecipeTag> tags;
 | 
			
		||||
		IngredientListModel ingredientListModel;
 | 
			
		||||
		TagListModel tagsListModel;
 | 
			
		||||
		bool accepted = false;
 | 
			
		||||
 | 
			
		||||
		//Helper functions to fill fields.
 | 
			
		||||
		void populateIngredientsBox();
 | 
			
		||||
		void populateUnitsBox();
 | 
			
		||||
		void populateTagsBox();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // NEWRECIPEDIALOG_H
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,685 @@
 | 
			
		|||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<ui version="4.0">
 | 
			
		||||
 <class>NewRecipeDialog</class>
 | 
			
		||||
 <widget class="QDialog" name="NewRecipeDialog">
 | 
			
		||||
  <property name="enabled">
 | 
			
		||||
   <bool>true</bool>
 | 
			
		||||
  </property>
 | 
			
		||||
  <property name="geometry">
 | 
			
		||||
   <rect>
 | 
			
		||||
    <x>0</x>
 | 
			
		||||
    <y>0</y>
 | 
			
		||||
    <width>640</width>
 | 
			
		||||
    <height>689</height>
 | 
			
		||||
   </rect>
 | 
			
		||||
  </property>
 | 
			
		||||
  <property name="sizePolicy">
 | 
			
		||||
   <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
 | 
			
		||||
    <horstretch>0</horstretch>
 | 
			
		||||
    <verstretch>0</verstretch>
 | 
			
		||||
   </sizepolicy>
 | 
			
		||||
  </property>
 | 
			
		||||
  <property name="windowTitle">
 | 
			
		||||
   <string>New Recipe</string>
 | 
			
		||||
  </property>
 | 
			
		||||
  <layout class="QVBoxLayout" name="verticalLayout">
 | 
			
		||||
   <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::AlignTop">
 | 
			
		||||
    <widget class="QWidget" name="mainContentPanel" 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>
 | 
			
		||||
       <widget class="QWidget" name="tagsAndBasicPanel" native="true">
 | 
			
		||||
        <layout class="QHBoxLayout" name="horizontalLayout_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>
 | 
			
		||||
          <widget class="QWidget" name="basicRecipePanel" native="true">
 | 
			
		||||
           <property name="layoutDirection">
 | 
			
		||||
            <enum>Qt::LeftToRight</enum>
 | 
			
		||||
           </property>
 | 
			
		||||
           <property name="styleSheet">
 | 
			
		||||
            <string notr="true">background-color: rgb(234, 235, 255);</string>
 | 
			
		||||
           </property>
 | 
			
		||||
           <layout class="QVBoxLayout" name="verticalLayout_10">
 | 
			
		||||
            <item>
 | 
			
		||||
             <widget class="QWidget" name="recipeNamePanel" native="true">
 | 
			
		||||
              <layout class="QVBoxLayout" name="verticalLayout_9">
 | 
			
		||||
               <item>
 | 
			
		||||
                <widget class="QLabel" name="recipeNameLabel">
 | 
			
		||||
                 <property name="font">
 | 
			
		||||
                  <font>
 | 
			
		||||
                   <family>Noto Sans CJK KR</family>
 | 
			
		||||
                   <pointsize>14</pointsize>
 | 
			
		||||
                   <weight>50</weight>
 | 
			
		||||
                   <italic>false</italic>
 | 
			
		||||
                   <bold>false</bold>
 | 
			
		||||
                  </font>
 | 
			
		||||
                 </property>
 | 
			
		||||
                 <property name="text">
 | 
			
		||||
                  <string>Edit Recipe</string>
 | 
			
		||||
                 </property>
 | 
			
		||||
                 <property name="alignment">
 | 
			
		||||
                  <set>Qt::AlignCenter</set>
 | 
			
		||||
                 </property>
 | 
			
		||||
                </widget>
 | 
			
		||||
               </item>
 | 
			
		||||
               <item>
 | 
			
		||||
                <widget class="QLineEdit" name="recipeNameEdit">
 | 
			
		||||
                 <property name="font">
 | 
			
		||||
                  <font>
 | 
			
		||||
                   <stylestrategy>PreferAntialias</stylestrategy>
 | 
			
		||||
                  </font>
 | 
			
		||||
                 </property>
 | 
			
		||||
                 <property name="alignment">
 | 
			
		||||
                  <set>Qt::AlignCenter</set>
 | 
			
		||||
                 </property>
 | 
			
		||||
                 <property name="placeholderText">
 | 
			
		||||
                  <string>Recipe Name</string>
 | 
			
		||||
                 </property>
 | 
			
		||||
                </widget>
 | 
			
		||||
               </item>
 | 
			
		||||
              </layout>
 | 
			
		||||
             </widget>
 | 
			
		||||
            </item>
 | 
			
		||||
            <item>
 | 
			
		||||
             <widget class="QWidget" name="basicInfoPanel" native="true">
 | 
			
		||||
              <layout class="QHBoxLayout" name="horizontalLayout">
 | 
			
		||||
               <item alignment="Qt::AlignTop">
 | 
			
		||||
                <widget class="QWidget" name="prepTimePanel" native="true">
 | 
			
		||||
                 <layout class="QVBoxLayout" name="verticalLayout_3">
 | 
			
		||||
                  <item>
 | 
			
		||||
                   <widget class="QLabel" name="label">
 | 
			
		||||
                    <property name="text">
 | 
			
		||||
                     <string>Prep Time</string>
 | 
			
		||||
                    </property>
 | 
			
		||||
                    <property name="alignment">
 | 
			
		||||
                     <set>Qt::AlignCenter</set>
 | 
			
		||||
                    </property>
 | 
			
		||||
                   </widget>
 | 
			
		||||
                  </item>
 | 
			
		||||
                  <item>
 | 
			
		||||
                   <widget class="QTimeEdit" name="prepTimeEdit">
 | 
			
		||||
                    <property name="dateTime">
 | 
			
		||||
                     <datetime>
 | 
			
		||||
                      <hour>0</hour>
 | 
			
		||||
                      <minute>0</minute>
 | 
			
		||||
                      <second>0</second>
 | 
			
		||||
                      <year>1999</year>
 | 
			
		||||
                      <month>12</month>
 | 
			
		||||
                      <day>27</day>
 | 
			
		||||
                     </datetime>
 | 
			
		||||
                    </property>
 | 
			
		||||
                    <property name="currentSection">
 | 
			
		||||
                     <enum>QDateTimeEdit::HourSection</enum>
 | 
			
		||||
                    </property>
 | 
			
		||||
                    <property name="displayFormat">
 | 
			
		||||
                     <string>hh:mm:ss</string>
 | 
			
		||||
                    </property>
 | 
			
		||||
                    <property name="timeSpec">
 | 
			
		||||
                     <enum>Qt::UTC</enum>
 | 
			
		||||
                    </property>
 | 
			
		||||
                    <property name="time">
 | 
			
		||||
                     <time>
 | 
			
		||||
                      <hour>0</hour>
 | 
			
		||||
                      <minute>0</minute>
 | 
			
		||||
                      <second>0</second>
 | 
			
		||||
                     </time>
 | 
			
		||||
                    </property>
 | 
			
		||||
                   </widget>
 | 
			
		||||
                  </item>
 | 
			
		||||
                 </layout>
 | 
			
		||||
                </widget>
 | 
			
		||||
               </item>
 | 
			
		||||
               <item alignment="Qt::AlignTop">
 | 
			
		||||
                <widget class="QWidget" name="cookTimePanel" native="true">
 | 
			
		||||
                 <layout class="QVBoxLayout" name="verticalLayout_4">
 | 
			
		||||
                  <item>
 | 
			
		||||
                   <widget class="QLabel" name="label_2">
 | 
			
		||||
                    <property name="text">
 | 
			
		||||
                     <string>Cook Time</string>
 | 
			
		||||
                    </property>
 | 
			
		||||
                    <property name="alignment">
 | 
			
		||||
                     <set>Qt::AlignCenter</set>
 | 
			
		||||
                    </property>
 | 
			
		||||
                   </widget>
 | 
			
		||||
                  </item>
 | 
			
		||||
                  <item>
 | 
			
		||||
                   <widget class="QTimeEdit" name="cookTimeEdit">
 | 
			
		||||
                    <property name="currentSection">
 | 
			
		||||
                     <enum>QDateTimeEdit::HourSection</enum>
 | 
			
		||||
                    </property>
 | 
			
		||||
                    <property name="displayFormat">
 | 
			
		||||
                     <string>hh:mm:ss</string>
 | 
			
		||||
                    </property>
 | 
			
		||||
                    <property name="timeSpec">
 | 
			
		||||
                     <enum>Qt::UTC</enum>
 | 
			
		||||
                    </property>
 | 
			
		||||
                    <property name="time">
 | 
			
		||||
                     <time>
 | 
			
		||||
                      <hour>0</hour>
 | 
			
		||||
                      <minute>0</minute>
 | 
			
		||||
                      <second>0</second>
 | 
			
		||||
                     </time>
 | 
			
		||||
                    </property>
 | 
			
		||||
                   </widget>
 | 
			
		||||
                  </item>
 | 
			
		||||
                 </layout>
 | 
			
		||||
                </widget>
 | 
			
		||||
               </item>
 | 
			
		||||
               <item alignment="Qt::AlignTop">
 | 
			
		||||
                <widget class="QWidget" name="servingsWidget" native="true">
 | 
			
		||||
                 <layout class="QVBoxLayout" name="verticalLayout_5">
 | 
			
		||||
                  <item>
 | 
			
		||||
                   <widget class="QLabel" name="label_3">
 | 
			
		||||
                    <property name="text">
 | 
			
		||||
                     <string>Servings</string>
 | 
			
		||||
                    </property>
 | 
			
		||||
                    <property name="alignment">
 | 
			
		||||
                     <set>Qt::AlignCenter</set>
 | 
			
		||||
                    </property>
 | 
			
		||||
                   </widget>
 | 
			
		||||
                  </item>
 | 
			
		||||
                  <item>
 | 
			
		||||
                   <widget class="QDoubleSpinBox" name="servingsSpinBox">
 | 
			
		||||
                    <property name="decimals">
 | 
			
		||||
                     <number>1</number>
 | 
			
		||||
                    </property>
 | 
			
		||||
                    <property name="value">
 | 
			
		||||
                     <double>1.000000000000000</double>
 | 
			
		||||
                    </property>
 | 
			
		||||
                   </widget>
 | 
			
		||||
                  </item>
 | 
			
		||||
                 </layout>
 | 
			
		||||
                </widget>
 | 
			
		||||
               </item>
 | 
			
		||||
              </layout>
 | 
			
		||||
             </widget>
 | 
			
		||||
            </item>
 | 
			
		||||
           </layout>
 | 
			
		||||
          </widget>
 | 
			
		||||
         </item>
 | 
			
		||||
         <item>
 | 
			
		||||
          <widget class="QWidget" name="tagsPanel" native="true">
 | 
			
		||||
           <property name="styleSheet">
 | 
			
		||||
            <string notr="true">background-color: rgb(222, 226, 255);</string>
 | 
			
		||||
           </property>
 | 
			
		||||
           <layout class="QVBoxLayout" name="verticalLayout_11">
 | 
			
		||||
            <item alignment="Qt::AlignTop">
 | 
			
		||||
             <widget class="QLabel" name="tagsPanelLabel">
 | 
			
		||||
              <property name="text">
 | 
			
		||||
               <string>Tags</string>
 | 
			
		||||
              </property>
 | 
			
		||||
              <property name="alignment">
 | 
			
		||||
               <set>Qt::AlignCenter</set>
 | 
			
		||||
              </property>
 | 
			
		||||
             </widget>
 | 
			
		||||
            </item>
 | 
			
		||||
            <item alignment="Qt::AlignTop">
 | 
			
		||||
             <widget class="QWidget" name="newTagBoxPanel" native="true">
 | 
			
		||||
              <layout class="QHBoxLayout" name="horizontalLayout_7">
 | 
			
		||||
               <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>
 | 
			
		||||
                <widget class="QComboBox" name="tagsComboBox"/>
 | 
			
		||||
               </item>
 | 
			
		||||
               <item>
 | 
			
		||||
                <widget class="QPushButton" name="newTagButton">
 | 
			
		||||
                 <property name="text">
 | 
			
		||||
                  <string>New</string>
 | 
			
		||||
                 </property>
 | 
			
		||||
                </widget>
 | 
			
		||||
               </item>
 | 
			
		||||
              </layout>
 | 
			
		||||
             </widget>
 | 
			
		||||
            </item>
 | 
			
		||||
            <item>
 | 
			
		||||
             <widget class="QWidget" name="tagsListControlPanel" native="true">
 | 
			
		||||
              <layout class="QHBoxLayout" name="horizontalLayout_8">
 | 
			
		||||
               <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>
 | 
			
		||||
                <widget class="QPushButton" name="addTagButton">
 | 
			
		||||
                 <property name="text">
 | 
			
		||||
                  <string>Add</string>
 | 
			
		||||
                 </property>
 | 
			
		||||
                </widget>
 | 
			
		||||
               </item>
 | 
			
		||||
               <item>
 | 
			
		||||
                <widget class="QPushButton" name="deleteTagButton">
 | 
			
		||||
                 <property name="text">
 | 
			
		||||
                  <string>Delete</string>
 | 
			
		||||
                 </property>
 | 
			
		||||
                </widget>
 | 
			
		||||
               </item>
 | 
			
		||||
              </layout>
 | 
			
		||||
             </widget>
 | 
			
		||||
            </item>
 | 
			
		||||
            <item>
 | 
			
		||||
             <widget class="QListView" name="tagsListView">
 | 
			
		||||
              <property name="autoFillBackground">
 | 
			
		||||
               <bool>false</bool>
 | 
			
		||||
              </property>
 | 
			
		||||
              <property name="styleSheet">
 | 
			
		||||
               <string notr="true">background-color: rgb(255, 255, 255);</string>
 | 
			
		||||
              </property>
 | 
			
		||||
              <property name="frameShape">
 | 
			
		||||
               <enum>QFrame::NoFrame</enum>
 | 
			
		||||
              </property>
 | 
			
		||||
             </widget>
 | 
			
		||||
            </item>
 | 
			
		||||
           </layout>
 | 
			
		||||
          </widget>
 | 
			
		||||
         </item>
 | 
			
		||||
        </layout>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item alignment="Qt::AlignTop">
 | 
			
		||||
       <widget class="QWidget" name="ingredientsPanel" native="true">
 | 
			
		||||
        <property name="sizePolicy">
 | 
			
		||||
         <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
 | 
			
		||||
          <horstretch>0</horstretch>
 | 
			
		||||
          <verstretch>0</verstretch>
 | 
			
		||||
         </sizepolicy>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="styleSheet">
 | 
			
		||||
         <string notr="true">background-color: rgb(245, 245, 255);</string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <layout class="QVBoxLayout" name="verticalLayout_6">
 | 
			
		||||
         <property name="spacing">
 | 
			
		||||
          <number>0</number>
 | 
			
		||||
         </property>
 | 
			
		||||
         <property name="sizeConstraint">
 | 
			
		||||
          <enum>QLayout::SetMaximumSize</enum>
 | 
			
		||||
         </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>
 | 
			
		||||
          <widget class="QLabel" name="ingredientsPanelLabel">
 | 
			
		||||
           <property name="text">
 | 
			
		||||
            <string>Ingredients</string>
 | 
			
		||||
           </property>
 | 
			
		||||
           <property name="alignment">
 | 
			
		||||
            <set>Qt::AlignCenter</set>
 | 
			
		||||
           </property>
 | 
			
		||||
          </widget>
 | 
			
		||||
         </item>
 | 
			
		||||
         <item>
 | 
			
		||||
          <widget class="QWidget" name="ingredientsSubPanel" native="true">
 | 
			
		||||
           <layout class="QHBoxLayout" name="horizontalLayout_2">
 | 
			
		||||
            <item>
 | 
			
		||||
             <widget class="QListView" name="ingredientsListView">
 | 
			
		||||
              <property name="styleSheet">
 | 
			
		||||
               <string notr="true">background-color: rgb(255, 255, 255);</string>
 | 
			
		||||
              </property>
 | 
			
		||||
              <property name="frameShape">
 | 
			
		||||
               <enum>QFrame::NoFrame</enum>
 | 
			
		||||
              </property>
 | 
			
		||||
              <property name="batchSize">
 | 
			
		||||
               <number>100</number>
 | 
			
		||||
              </property>
 | 
			
		||||
             </widget>
 | 
			
		||||
            </item>
 | 
			
		||||
            <item alignment="Qt::AlignRight|Qt::AlignTop">
 | 
			
		||||
             <widget class="QWidget" name="addIngredientPanel" native="true">
 | 
			
		||||
              <layout class="QVBoxLayout" name="verticalLayout_7">
 | 
			
		||||
               <property name="spacing">
 | 
			
		||||
                <number>5</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>
 | 
			
		||||
                <widget class="QLabel" name="addIngredientLabel">
 | 
			
		||||
                 <property name="text">
 | 
			
		||||
                  <string>Add Ingredient</string>
 | 
			
		||||
                 </property>
 | 
			
		||||
                 <property name="alignment">
 | 
			
		||||
                  <set>Qt::AlignCenter</set>
 | 
			
		||||
                 </property>
 | 
			
		||||
                </widget>
 | 
			
		||||
               </item>
 | 
			
		||||
               <item>
 | 
			
		||||
                <widget class="QWidget" name="ingredientNamePanel" native="true">
 | 
			
		||||
                 <layout class="QHBoxLayout" name="horizontalLayout_4">
 | 
			
		||||
                  <property name="spacing">
 | 
			
		||||
                   <number>2</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>
 | 
			
		||||
                   <widget class="QComboBox" name="ingredientNameBox">
 | 
			
		||||
                    <property name="sizePolicy">
 | 
			
		||||
                     <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
 | 
			
		||||
                      <horstretch>0</horstretch>
 | 
			
		||||
                      <verstretch>0</verstretch>
 | 
			
		||||
                     </sizepolicy>
 | 
			
		||||
                    </property>
 | 
			
		||||
                    <property name="currentText">
 | 
			
		||||
                     <string/>
 | 
			
		||||
                    </property>
 | 
			
		||||
                   </widget>
 | 
			
		||||
                  </item>
 | 
			
		||||
                  <item>
 | 
			
		||||
                   <widget class="QPushButton" name="newIngredientButton">
 | 
			
		||||
                    <property name="text">
 | 
			
		||||
                     <string>New</string>
 | 
			
		||||
                    </property>
 | 
			
		||||
                   </widget>
 | 
			
		||||
                  </item>
 | 
			
		||||
                 </layout>
 | 
			
		||||
                </widget>
 | 
			
		||||
               </item>
 | 
			
		||||
               <item>
 | 
			
		||||
                <widget class="QWidget" name="quantityPanel" native="true">
 | 
			
		||||
                 <property name="minimumSize">
 | 
			
		||||
                  <size>
 | 
			
		||||
                   <width>0</width>
 | 
			
		||||
                   <height>36</height>
 | 
			
		||||
                  </size>
 | 
			
		||||
                 </property>
 | 
			
		||||
                 <layout class="QHBoxLayout" name="horizontalLayout_3">
 | 
			
		||||
                  <property name="spacing">
 | 
			
		||||
                   <number>2</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>
 | 
			
		||||
                   <widget class="QLabel" name="amountLabel">
 | 
			
		||||
                    <property name="font">
 | 
			
		||||
                     <font>
 | 
			
		||||
                      <family>Noto Sans CJK KR</family>
 | 
			
		||||
                      <pointsize>14</pointsize>
 | 
			
		||||
                      <weight>50</weight>
 | 
			
		||||
                      <italic>false</italic>
 | 
			
		||||
                      <bold>false</bold>
 | 
			
		||||
                     </font>
 | 
			
		||||
                    </property>
 | 
			
		||||
                    <property name="text">
 | 
			
		||||
                     <string>Amount</string>
 | 
			
		||||
                    </property>
 | 
			
		||||
                   </widget>
 | 
			
		||||
                  </item>
 | 
			
		||||
                  <item>
 | 
			
		||||
                   <widget class="QDoubleSpinBox" name="quantitySpinBox">
 | 
			
		||||
                    <property name="sizePolicy">
 | 
			
		||||
                     <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
 | 
			
		||||
                      <horstretch>0</horstretch>
 | 
			
		||||
                      <verstretch>0</verstretch>
 | 
			
		||||
                     </sizepolicy>
 | 
			
		||||
                    </property>
 | 
			
		||||
                    <property name="maximum">
 | 
			
		||||
                     <double>10000.000000000000000</double>
 | 
			
		||||
                    </property>
 | 
			
		||||
                    <property name="value">
 | 
			
		||||
                     <double>1.000000000000000</double>
 | 
			
		||||
                    </property>
 | 
			
		||||
                   </widget>
 | 
			
		||||
                  </item>
 | 
			
		||||
                  <item>
 | 
			
		||||
                   <widget class="QComboBox" name="unitComboBox"/>
 | 
			
		||||
                  </item>
 | 
			
		||||
                  <item>
 | 
			
		||||
                   <widget class="QPushButton" name="newUnitButton">
 | 
			
		||||
                    <property name="text">
 | 
			
		||||
                     <string>New</string>
 | 
			
		||||
                    </property>
 | 
			
		||||
                   </widget>
 | 
			
		||||
                  </item>
 | 
			
		||||
                 </layout>
 | 
			
		||||
                </widget>
 | 
			
		||||
               </item>
 | 
			
		||||
               <item>
 | 
			
		||||
                <widget class="QLineEdit" name="commentsLineEdit">
 | 
			
		||||
                 <property name="minimumSize">
 | 
			
		||||
                  <size>
 | 
			
		||||
                   <width>0</width>
 | 
			
		||||
                   <height>0</height>
 | 
			
		||||
                  </size>
 | 
			
		||||
                 </property>
 | 
			
		||||
                 <property name="frame">
 | 
			
		||||
                  <bool>false</bool>
 | 
			
		||||
                 </property>
 | 
			
		||||
                 <property name="alignment">
 | 
			
		||||
                  <set>Qt::AlignCenter</set>
 | 
			
		||||
                 </property>
 | 
			
		||||
                 <property name="placeholderText">
 | 
			
		||||
                  <string>Comments</string>
 | 
			
		||||
                 </property>
 | 
			
		||||
                 <property name="clearButtonEnabled">
 | 
			
		||||
                  <bool>false</bool>
 | 
			
		||||
                 </property>
 | 
			
		||||
                </widget>
 | 
			
		||||
               </item>
 | 
			
		||||
               <item>
 | 
			
		||||
                <widget class="QWidget" name="ingredientsListControlPanel" native="true">
 | 
			
		||||
                 <layout class="QHBoxLayout" name="horizontalLayout_9">
 | 
			
		||||
                  <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>
 | 
			
		||||
                   <widget class="QPushButton" name="addIngredientButton">
 | 
			
		||||
                    <property name="text">
 | 
			
		||||
                     <string>Add</string>
 | 
			
		||||
                    </property>
 | 
			
		||||
                   </widget>
 | 
			
		||||
                  </item>
 | 
			
		||||
                  <item>
 | 
			
		||||
                   <widget class="QPushButton" name="deleteIngredientButton">
 | 
			
		||||
                    <property name="text">
 | 
			
		||||
                     <string>Delete</string>
 | 
			
		||||
                    </property>
 | 
			
		||||
                   </widget>
 | 
			
		||||
                  </item>
 | 
			
		||||
                 </layout>
 | 
			
		||||
                </widget>
 | 
			
		||||
               </item>
 | 
			
		||||
              </layout>
 | 
			
		||||
             </widget>
 | 
			
		||||
            </item>
 | 
			
		||||
           </layout>
 | 
			
		||||
          </widget>
 | 
			
		||||
         </item>
 | 
			
		||||
        </layout>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item>
 | 
			
		||||
       <widget class="QWidget" name="instructionsPanel" native="true">
 | 
			
		||||
        <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">
 | 
			
		||||
          <widget class="QWidget" name="textControlPanel" native="true">
 | 
			
		||||
           <layout class="QHBoxLayout" name="horizontalLayout_5">
 | 
			
		||||
            <item>
 | 
			
		||||
             <widget class="QToolButton" name="italicsButton">
 | 
			
		||||
              <property name="font">
 | 
			
		||||
               <font>
 | 
			
		||||
                <family>Liberation Serif</family>
 | 
			
		||||
                <pointsize>12</pointsize>
 | 
			
		||||
                <italic>true</italic>
 | 
			
		||||
               </font>
 | 
			
		||||
              </property>
 | 
			
		||||
              <property name="text">
 | 
			
		||||
               <string>I</string>
 | 
			
		||||
              </property>
 | 
			
		||||
              <property name="checkable">
 | 
			
		||||
               <bool>true</bool>
 | 
			
		||||
              </property>
 | 
			
		||||
              <property name="toolButtonStyle">
 | 
			
		||||
               <enum>Qt::ToolButtonIconOnly</enum>
 | 
			
		||||
              </property>
 | 
			
		||||
             </widget>
 | 
			
		||||
            </item>
 | 
			
		||||
            <item>
 | 
			
		||||
             <widget class="QToolButton" name="boldButton">
 | 
			
		||||
              <property name="font">
 | 
			
		||||
               <font>
 | 
			
		||||
                <family>Liberation Serif</family>
 | 
			
		||||
                <pointsize>12</pointsize>
 | 
			
		||||
                <weight>75</weight>
 | 
			
		||||
                <bold>true</bold>
 | 
			
		||||
               </font>
 | 
			
		||||
              </property>
 | 
			
		||||
              <property name="text">
 | 
			
		||||
               <string>B</string>
 | 
			
		||||
              </property>
 | 
			
		||||
              <property name="checkable">
 | 
			
		||||
               <bool>true</bool>
 | 
			
		||||
              </property>
 | 
			
		||||
              <property name="checked">
 | 
			
		||||
               <bool>false</bool>
 | 
			
		||||
              </property>
 | 
			
		||||
              <property name="autoRaise">
 | 
			
		||||
               <bool>false</bool>
 | 
			
		||||
              </property>
 | 
			
		||||
             </widget>
 | 
			
		||||
            </item>
 | 
			
		||||
           </layout>
 | 
			
		||||
          </widget>
 | 
			
		||||
         </item>
 | 
			
		||||
         <item>
 | 
			
		||||
          <widget class="QTextEdit" name="instructionsTextEdit">
 | 
			
		||||
           <property name="placeholderText">
 | 
			
		||||
            <string>Enter instructions here.</string>
 | 
			
		||||
           </property>
 | 
			
		||||
          </widget>
 | 
			
		||||
         </item>
 | 
			
		||||
        </layout>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item>
 | 
			
		||||
       <widget class="QDialogButtonBox" name="buttonBox">
 | 
			
		||||
        <property name="layoutDirection">
 | 
			
		||||
         <enum>Qt::LeftToRight</enum>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="standardButtons">
 | 
			
		||||
         <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
     </layout>
 | 
			
		||||
    </widget>
 | 
			
		||||
   </item>
 | 
			
		||||
  </layout>
 | 
			
		||||
 </widget>
 | 
			
		||||
 <resources/>
 | 
			
		||||
 <connections/>
 | 
			
		||||
</ui>
 | 
			
		||||
							
								
								
									
										34
									
								
								main.cpp
								
								
								
								
							
							
						
						
									
										34
									
								
								main.cpp
								
								
								
								
							| 
						 | 
				
			
			@ -1,4 +1,5 @@
 | 
			
		|||
#include "userInterface/mainwindow.h"
 | 
			
		||||
#include "gui/newrecipedialog.h"
 | 
			
		||||
#include <QApplication>
 | 
			
		||||
 | 
			
		||||
#include "model/database/database.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -13,27 +14,42 @@ int main(int argc, char *argv[])
 | 
			
		|||
	//TESTING CODE
 | 
			
		||||
 | 
			
		||||
	RecipeDatabase recipeDB("recipes");
 | 
			
		||||
//	recipeDB.storeIngredient(Ingredient("Apple", "Fruit"));
 | 
			
		||||
//	recipeDB.storeIngredient(Ingredient("Corn", "Vegetable"));
 | 
			
		||||
//	recipeDB.storeIngredient(Ingredient("Lettuce", "Vegetable"));
 | 
			
		||||
//	recipeDB.storeIngredient(Ingredient("Carrot", "Vegetable"));
 | 
			
		||||
 | 
			
		||||
//	recipeDB.executeSQL("SELECT * FROM ingredient;").printData();
 | 
			
		||||
 | 
			
		||||
	//TESTING CODE
 | 
			
		||||
	vector<RecipeIngredient> ri;
 | 
			
		||||
	ri.push_back(RecipeIngredient("flour", "grains", 3.0f, UnitOfMeasure("cup", "cups", "c")));
 | 
			
		||||
	ri.push_back(RecipeIngredient("Baking Powder", "Additives", 1.0f, UnitOfMeasure("Teaspoon", "Teaspoons", "Tsp")));
 | 
			
		||||
	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>(), 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);
 | 
			
		||||
 | 
			
		||||
	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));
 | 
			
		||||
 | 
			
		||||
	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");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return a.exec();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -42,7 +42,7 @@ ResultTable Database::selectFrom(string tableName, string columnNames, string co
 | 
			
		|||
	if (columnNames.size() == 0 || tableName.empty()){
 | 
			
		||||
		return ResultTable();
 | 
			
		||||
	}
 | 
			
		||||
	string query = "SELECT " + columnNames + " FROM " + tableName + " WHERE " + conditions + ";";
 | 
			
		||||
	string query = "SELECT " + columnNames + " FROM " + tableName + " " + conditions + ";";
 | 
			
		||||
	return this->executeSQL(query);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -81,8 +81,7 @@ bool Database::tableExists(string tableName){
 | 
			
		|||
	if (tableName.empty() || this->db == NULL || !this->dbIsOpen){
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	ResultTable t = this->selectFrom("sqlite_master", "name", "type='table' AND name='"+tableName+"'");
 | 
			
		||||
	//ResultTable t = executeSQL("SELECT name FROM sqlite_master WHERE type='table' AND name='"+tableName+"';");
 | 
			
		||||
	ResultTable t = this->selectFrom("sqlite_master", "name", "WHERE type='table' AND name='"+tableName+"'");
 | 
			
		||||
	return !t.isEmpty();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,9 +5,9 @@ RecipeDatabase::RecipeDatabase(string filename) : Database(filename){
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
bool RecipeDatabase::storeRecipe(Recipe recipe){
 | 
			
		||||
	///TODO: Implement this in a smart way using transaction.
 | 
			
		||||
	//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;");
 | 
			
		||||
	ResultTable t = this->selectFrom("recipe", "*", "name="+surroundString(recipe.getName(), "'"));
 | 
			
		||||
	ResultTable t = this->selectFrom("recipe", "*", "WHERE name="+surroundString(recipe.getName(), "'"));
 | 
			
		||||
	if (!t.isEmpty()){
 | 
			
		||||
		fprintf(stderr, "Error storing recipe: Recipe with name %s already exists.\n", recipe.getName().c_str());
 | 
			
		||||
	} else {
 | 
			
		||||
| 
						 | 
				
			
			@ -50,17 +50,11 @@ bool RecipeDatabase::storeRecipe(Recipe recipe){
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
bool RecipeDatabase::storeRecipeIngredient(RecipeIngredient ri, int recipeId){
 | 
			
		||||
	//First check if the base ingredient has been added to the database. This is done within storeIngredient().
 | 
			
		||||
	ResultTable t = this->selectFrom("ingredient", "ingredientId", "name="+surroundString(ri.getName(), "'"));
 | 
			
		||||
	int ingId = 0;
 | 
			
		||||
	if (t.isEmpty()){
 | 
			
		||||
		if (!this->insertInto("ingredient", vector<string>({"foodGroup", "name"}), vector<string>({ri.getFoodGroup(), ri.getName()}))){
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
		ingId = this->getLastInsertedRowId();
 | 
			
		||||
	} else {
 | 
			
		||||
		ingId = std::stoi(t.valueAt(0, 0));
 | 
			
		||||
	}
 | 
			
		||||
	int ingId = this->storeIngredient(ri);
 | 
			
		||||
	if (ingId < 0) return false;
 | 
			
		||||
 | 
			
		||||
	if (!this->storeUnitOfMeasure(ri.getUnit())) return false;
 | 
			
		||||
 | 
			
		||||
	return this->insertInto("recipeIngredient",
 | 
			
		||||
					 vector<string>({
 | 
			
		||||
										"ingredientId",
 | 
			
		||||
| 
						 | 
				
			
			@ -78,13 +72,43 @@ bool RecipeDatabase::storeRecipeIngredient(RecipeIngredient ri, int recipeId){
 | 
			
		|||
									}));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RecipeDatabase::storeIngredient(Ingredient ingredient){
 | 
			
		||||
	ResultTable t = this->selectFrom("ingredient", "*", "name="+surroundString(ingredient.getName(), "'"));
 | 
			
		||||
int RecipeDatabase::storeIngredient(Ingredient ingredient){
 | 
			
		||||
	ResultTable t = this->selectFrom("ingredient", "*", "WHERE name="+surroundString(ingredient.getName(), "'"));
 | 
			
		||||
	if (t.isEmpty()){
 | 
			
		||||
		this->insertInto("ingredient", vector<string>({"foodGroup", "name"}), vector<string>({ingredient.getFoodGroup(), ingredient.getName()}));
 | 
			
		||||
		bool success = this->insertInto("ingredient", vector<string>({"foodGroup", "name"}), vector<string>({ingredient.getFoodGroup(), ingredient.getName()}));
 | 
			
		||||
		if (success){
 | 
			
		||||
			return this->getLastInsertedRowId();
 | 
			
		||||
		} else {
 | 
			
		||||
			return -1;
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		return std::stoi(t.valueAt(0, 0));
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RecipeDatabase::storeUnitOfMeasure(UnitOfMeasure u){
 | 
			
		||||
	ResultTable t = this->selectFrom("unitOfMeasure", "name", "WHERE name="+surroundString(u.getName(), "'"));
 | 
			
		||||
	if (!t.isEmpty()){
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
	bool success = this->insertInto("unitOfMeasure",
 | 
			
		||||
									vector<string>({
 | 
			
		||||
													   "name",
 | 
			
		||||
													   "plural",
 | 
			
		||||
													   "abbreviation",
 | 
			
		||||
													   "type",
 | 
			
		||||
													   "metricCoefficient"
 | 
			
		||||
												   }),
 | 
			
		||||
									vector<string>({
 | 
			
		||||
													   u.getName(),
 | 
			
		||||
													   u.getNamePlural(),
 | 
			
		||||
													   u.getAbbreviation(),
 | 
			
		||||
													   std::to_string(u.getType()),
 | 
			
		||||
													   std::to_string(u.getMetricCoefficient())
 | 
			
		||||
												   }));
 | 
			
		||||
	return success;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RecipeDatabase::storeInstruction(Instruction instruction, int recipeId){
 | 
			
		||||
	return FileUtils::saveInstruction(recipeId, instruction);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -112,12 +136,11 @@ bool RecipeDatabase::storeTags(vector<RecipeTag> tags, int recipeId){
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
Recipe RecipeDatabase::retrieveRecipe(string name){
 | 
			
		||||
	ResultTable t = this->selectFrom("recipe", "*", "name="+surroundString(name, "'"));
 | 
			
		||||
	ResultTable t = this->selectFrom("recipe", "*", "WHERE name="+surroundString(name, "'"));
 | 
			
		||||
	if (t.isEmpty()){
 | 
			
		||||
		fprintf(stderr, "Error: No recipe with name %s found!\n", name.c_str());
 | 
			
		||||
		return Recipe();
 | 
			
		||||
	}
 | 
			
		||||
	t.printData();
 | 
			
		||||
	Recipe r;
 | 
			
		||||
	int id = std::stoi(t.valueAt(0, 0));
 | 
			
		||||
	r.setName(t.valueAt(0, 1));
 | 
			
		||||
| 
						 | 
				
			
			@ -128,24 +151,78 @@ Recipe RecipeDatabase::retrieveRecipe(string name){
 | 
			
		|||
	r.setInstruction(FileUtils::loadInstruction(id));
 | 
			
		||||
	r.setImage(FileUtils::loadImage(id));
 | 
			
		||||
	r.setIngredients(this->retrieveRecipeIngredients(id));
 | 
			
		||||
	r.setTags(this->retrieveTags(id));
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
vector<RecipeIngredient> RecipeDatabase::retrieveRecipeIngredients(int recipeId){
 | 
			
		||||
	ResultTable t = this->executeSQL("SELECT ingredient.name, ingredient.foodGroup, recipeIngredient.quantity, recipeIngredient.unitName, recipeIngredient.comment "
 | 
			
		||||
	ResultTable t = this->executeSQL("SELECT ingredient.name, ingredient.foodGroup, "//0, 1
 | 
			
		||||
									 "recipeIngredient.quantity, recipeIngredient.unitName, recipeIngredient.comment,"//2, 3, 4
 | 
			
		||||
									 "unitOfMeasure.name, unitOfMeasure.plural, unitOfMeasure.abbreviation, unitOfMeasure.type, unitOfMeasure.metricCoefficient "//5, 6, 7, 8, 9
 | 
			
		||||
									 "FROM ingredient "
 | 
			
		||||
									 "INNER JOIN recipeIngredient "
 | 
			
		||||
									 "ON ingredient.ingredientId = recipeIngredient.ingredientId "
 | 
			
		||||
									 "AND recipeIngredient.recipeId = "+std::to_string(recipeId)+";");
 | 
			
		||||
	t.printData();
 | 
			
		||||
									 "INNER JOIN unitOfMeasure "
 | 
			
		||||
									 "ON recipeIngredient.unitName = unitOfMeasure.name "
 | 
			
		||||
									 "WHERE recipeIngredient.recipeId = "+std::to_string(recipeId)+";");
 | 
			
		||||
	vector<RecipeIngredient> ings;
 | 
			
		||||
	for (unsigned int row = 0; row < t.rowCount(); row++){
 | 
			
		||||
		RecipeIngredient r(t.valueAt(row, 0), t.valueAt(row, 1), std::stof(t.valueAt(row, 2)), UnitOfMeasure(t.valueAt(row, 3)));
 | 
			
		||||
		RecipeIngredient r(t.valueAt(row, 0),
 | 
			
		||||
						   t.valueAt(row, 1),
 | 
			
		||||
						   std::stof(t.valueAt(row, 2)),
 | 
			
		||||
						   UnitOfMeasure(t.valueAt(row, 5), t.valueAt(row, 6), t.valueAt(row, 7), std::stoi(t.valueAt(row, 8)), std::stod(t.valueAt(row, 9))),
 | 
			
		||||
						   t.valueAt(row, 4));
 | 
			
		||||
		ings.push_back(r);
 | 
			
		||||
	}
 | 
			
		||||
	return ings;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
vector<Ingredient> RecipeDatabase::retrieveAllIngredients(){
 | 
			
		||||
	ResultTable t = this->selectFrom("ingredient", "*", "ORDER BY name");
 | 
			
		||||
	vector<Ingredient> ings;
 | 
			
		||||
	for (unsigned int row = 0; row < t.rowCount(); row++){
 | 
			
		||||
		Ingredient i(t.valueAt(row, 2), t.valueAt(row, 1));
 | 
			
		||||
		ings.push_back(i);
 | 
			
		||||
	}
 | 
			
		||||
	return ings;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
vector<UnitOfMeasure> RecipeDatabase::retrieveAllUnitsOfMeasure(){
 | 
			
		||||
	ResultTable t = this->selectFrom("unitOfMeasure", "*", "ORDER BY name");
 | 
			
		||||
	vector<UnitOfMeasure> units;
 | 
			
		||||
	if (!t.isEmpty()){
 | 
			
		||||
		for (unsigned int row = 0; row < t.rowCount(); row++){
 | 
			
		||||
			UnitOfMeasure u(t.valueAt(row, 0), t.valueAt(row, 1), t.valueAt(row, 2), std::stoi(t.valueAt(row, 3)), std::stod(t.valueAt(row, 4)));
 | 
			
		||||
			units.push_back(u);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return units;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
vector<RecipeTag> RecipeDatabase::retrieveTags(int recipeId){
 | 
			
		||||
	ResultTable t = this->selectFrom("recipeTag", "tagName", "WHERE recipeId="+std::to_string(recipeId));
 | 
			
		||||
	vector<RecipeTag> tags;
 | 
			
		||||
	if (!t.isEmpty()){
 | 
			
		||||
		for (unsigned int row = 0; row < t.rowCount(); row++){
 | 
			
		||||
			RecipeTag tag(t.valueAt(row, 0));
 | 
			
		||||
			tags.push_back(tag);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return tags;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
vector<RecipeTag> RecipeDatabase::retrieveAllTags(){
 | 
			
		||||
	ResultTable t = this->selectFrom("recipeTag", "tagName", "ORDER BY tagName");
 | 
			
		||||
	vector<RecipeTag> tags;
 | 
			
		||||
	if (!t.isEmpty()){
 | 
			
		||||
		for (unsigned int row = 0; row < t.rowCount(); row++){
 | 
			
		||||
			RecipeTag tag(t.valueAt(row, 0));
 | 
			
		||||
			tags.push_back(tag);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return tags;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RecipeDatabase::ensureTablesExist(){
 | 
			
		||||
	//Make sure that foreign keys are enabled.
 | 
			
		||||
	this->executeSQL("PRAGMA foreign_keys = ON;");
 | 
			
		||||
| 
						 | 
				
			
			@ -156,6 +233,13 @@ void RecipeDatabase::ensureTablesExist(){
 | 
			
		|||
					 "ingredientId INTEGER PRIMARY KEY,"
 | 
			
		||||
					 "foodGroup varchar,"
 | 
			
		||||
					 "name varchar UNIQUE);");
 | 
			
		||||
	//Unit of Measure table.
 | 
			
		||||
	this->executeSQL("CREATE TABLE IF NOT EXISTS unitOfMeasure("
 | 
			
		||||
					 "name varchar UNIQUE PRIMARY KEY,"
 | 
			
		||||
					 "plural varchar,"
 | 
			
		||||
					 "abbreviation varchar,"
 | 
			
		||||
					 "type int,"
 | 
			
		||||
					 "metricCoefficient real);");
 | 
			
		||||
	//Recipe table. Each recipe can have at most one instruction, and one image.
 | 
			
		||||
	this->executeSQL("CREATE TABLE IF NOT EXISTS recipe("
 | 
			
		||||
					 "recipeId INTEGER PRIMARY KEY,"
 | 
			
		||||
| 
						 | 
				
			
			@ -177,6 +261,7 @@ void RecipeDatabase::ensureTablesExist(){
 | 
			
		|||
					 "unitName varchar,"
 | 
			
		||||
					 "comment varchar,"
 | 
			
		||||
					 "FOREIGN KEY (ingredientId) REFERENCES ingredient(ingredientId),"
 | 
			
		||||
					 "FOREIGN KEY (recipeId) REFERENCES recipe(recipeId));");
 | 
			
		||||
					 "FOREIGN KEY (recipeId) REFERENCES recipe(recipeId),"
 | 
			
		||||
					 "FOREIGN KEY (unitName) REFERENCES unitOfMeasure(name));");
 | 
			
		||||
	this->executeSQL("COMMIT;");
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,14 +22,21 @@ class RecipeDatabase : public Database
 | 
			
		|||
		bool storeRecipe(Recipe recipe);
 | 
			
		||||
 | 
			
		||||
		//SQL Helper methods.
 | 
			
		||||
		//Storage.
 | 
			
		||||
		bool storeRecipeIngredient(RecipeIngredient ri, int recipeId);
 | 
			
		||||
		void storeIngredient(Ingredient ingredient);
 | 
			
		||||
		int storeIngredient(Ingredient ingredient);
 | 
			
		||||
		bool storeUnitOfMeasure(UnitOfMeasure u);
 | 
			
		||||
		bool storeInstruction(Instruction instruction, int recipeId);
 | 
			
		||||
		bool storeImage(QImage image, int recipeId);
 | 
			
		||||
		bool storeTags(vector<RecipeTag> tags, int recipeId);
 | 
			
		||||
 | 
			
		||||
		//Retrieval.
 | 
			
		||||
		Recipe retrieveRecipe(string name);
 | 
			
		||||
		vector<RecipeIngredient> retrieveRecipeIngredients(int recipeId);
 | 
			
		||||
		vector<Ingredient> retrieveAllIngredients();
 | 
			
		||||
		vector<UnitOfMeasure> retrieveAllUnitsOfMeasure();
 | 
			
		||||
		vector<RecipeTag> retrieveTags(int recipeId);
 | 
			
		||||
		vector<RecipeTag> retrieveAllTags();
 | 
			
		||||
	private:
 | 
			
		||||
 | 
			
		||||
		//Utility methods.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,10 +10,23 @@ int IngredientListModel::rowCount(const QModelIndex &parent) const{
 | 
			
		|||
 | 
			
		||||
QVariant IngredientListModel::data(const QModelIndex &index, int role) const{
 | 
			
		||||
    int row = index.row();
 | 
			
		||||
	RecipeIngredient i = this->ingredients[row];
 | 
			
		||||
 | 
			
		||||
	string displayStr;
 | 
			
		||||
 | 
			
		||||
	if (std::ceil(i.getQuantity()) == i.getQuantity()){
 | 
			
		||||
		//The quantity is an integer and should be casted.
 | 
			
		||||
		displayStr += std::to_string((int)i.getQuantity());
 | 
			
		||||
	} else {
 | 
			
		||||
		float q = i.getQuantity();
 | 
			
		||||
		displayStr += toString(q);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	displayStr += " " + i.getUnit().getAbbreviation() + " " + i.getName();
 | 
			
		||||
 | 
			
		||||
    switch(role){
 | 
			
		||||
    case Qt::DisplayRole:
 | 
			
		||||
        return QString::fromStdString(ingredients[row].getName());
 | 
			
		||||
		return QString::fromStdString(displayStr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return QVariant();
 | 
			
		||||
| 
						 | 
				
			
			@ -23,5 +36,37 @@ void IngredientListModel::setIngredients(vector<RecipeIngredient> ingredients){
 | 
			
		|||
    this->ingredients = ingredients;
 | 
			
		||||
    QModelIndex index = createIndex(0, 0);
 | 
			
		||||
    QModelIndex bottomIndex = createIndex(ingredients.size()-1, 0);
 | 
			
		||||
    emit dataChanged(index, bottomIndex);
 | 
			
		||||
	emit dataChanged(index, bottomIndex);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool IngredientListModel::addIngredient(RecipeIngredient ri){
 | 
			
		||||
	//Add only if it doesn't exist already.
 | 
			
		||||
	for (unsigned int i = 0; i < this->ingredients.size(); i++){
 | 
			
		||||
		if (!this->ingredients[i].getName().compare(ri.getName())){
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	this->ingredients.push_back(ri);
 | 
			
		||||
	QModelIndex index = createIndex(this->ingredients.size()-1, 0);
 | 
			
		||||
	QModelIndex bottomIndex = createIndex(this->ingredients.size()-1, 0);
 | 
			
		||||
	emit dataChanged(index, bottomIndex);
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
vector<RecipeIngredient> IngredientListModel::getIngredients(){
 | 
			
		||||
	return this->ingredients;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
string toString(float val){
 | 
			
		||||
	float decimal = std::fmod(val, 1.0f);
 | 
			
		||||
	int places = 1;
 | 
			
		||||
	while (std::fmod(decimal * 10, 1.0f) > 0){
 | 
			
		||||
		decimal *= 10;
 | 
			
		||||
		places++;
 | 
			
		||||
	}
 | 
			
		||||
	char buffer[50];
 | 
			
		||||
	string arg = "%."+std::to_string(places)+"f";
 | 
			
		||||
	sprintf(buffer, arg.c_str(), val);
 | 
			
		||||
	string s = buffer;
 | 
			
		||||
	return s;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,9 +17,16 @@ public:
 | 
			
		|||
 | 
			
		||||
    //Custom methods to handle ingredient data.
 | 
			
		||||
    void setIngredients(vector<RecipeIngredient> ingredients);
 | 
			
		||||
	bool addIngredient(RecipeIngredient ri);
 | 
			
		||||
	vector<RecipeIngredient> getIngredients();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    vector<RecipeIngredient> ingredients;
 | 
			
		||||
 | 
			
		||||
	//Helper for printing.
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
string toString(float val);
 | 
			
		||||
 | 
			
		||||
#endif // INGREDIENTLISTMODEL_H
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,15 +1,17 @@
 | 
			
		|||
#include "model/recipe/ingredients/recipeingredient.h"
 | 
			
		||||
 | 
			
		||||
RecipeIngredient::RecipeIngredient(string name, string foodGroup, float quantity, UnitOfMeasure unit) : Ingredient(name, foodGroup){
 | 
			
		||||
RecipeIngredient::RecipeIngredient(string name, string foodGroup, float quantity, UnitOfMeasure unit, string comment) : Ingredient(name, foodGroup){
 | 
			
		||||
    setQuantity(quantity);
 | 
			
		||||
    setUnit(unit);
 | 
			
		||||
	setComment(comment);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RecipeIngredient::RecipeIngredient(Ingredient i, float quantity, UnitOfMeasure unit){
 | 
			
		||||
RecipeIngredient::RecipeIngredient(Ingredient i, float quantity, UnitOfMeasure unit, string comment){
 | 
			
		||||
    setName(i.getName());
 | 
			
		||||
    setFoodGroup(i.getFoodGroup());
 | 
			
		||||
    setQuantity(quantity);
 | 
			
		||||
	setUnit(unit);
 | 
			
		||||
	setComment(comment);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RecipeIngredient::RecipeIngredient(){
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,9 +16,9 @@ class RecipeIngredient : public Ingredient
 | 
			
		|||
{
 | 
			
		||||
public:
 | 
			
		||||
    //Constructor for new RecipeIngredient without starting child ingredient.
 | 
			
		||||
    RecipeIngredient(string name, string foodGroup, float quantity, UnitOfMeasure unit);
 | 
			
		||||
	RecipeIngredient(string name, string foodGroup, float quantity, UnitOfMeasure unit, string comment);
 | 
			
		||||
    //Constructor using data from a child ingredient.
 | 
			
		||||
    RecipeIngredient(Ingredient i, float quantity, UnitOfMeasure unit);
 | 
			
		||||
	RecipeIngredient(Ingredient i, float quantity, UnitOfMeasure unit, string comment);
 | 
			
		||||
	RecipeIngredient();
 | 
			
		||||
 | 
			
		||||
    //Getters
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,19 +1,23 @@
 | 
			
		|||
#include "unitofmeasure.h"
 | 
			
		||||
 | 
			
		||||
UnitOfMeasure::UnitOfMeasure(string name, string plural, string abbreviation){
 | 
			
		||||
UnitOfMeasure::UnitOfMeasure(string name, string plural, string abbreviation, int type, double coef){
 | 
			
		||||
    this->name = name;
 | 
			
		||||
    this->plural = plural;
 | 
			
		||||
	this->abbreviation = abbreviation;
 | 
			
		||||
	this->type = type;
 | 
			
		||||
	this->metricCoefficient = coef;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
UnitOfMeasure::UnitOfMeasure(string name){
 | 
			
		||||
	this->name = name;
 | 
			
		||||
	this->plural = name + "s";
 | 
			
		||||
	this->abbreviation = "NULL";
 | 
			
		||||
	this->type = MISC;
 | 
			
		||||
	this->metricCoefficient = 1;
 | 
			
		||||
	///TODO: Make actual guessing of this stuff.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
UnitOfMeasure::UnitOfMeasure() : UnitOfMeasure::UnitOfMeasure("", "", ""){
 | 
			
		||||
UnitOfMeasure::UnitOfMeasure() : UnitOfMeasure::UnitOfMeasure("", "", "", MISC, 1.0){
 | 
			
		||||
    //Default constructor initializes all fields to empty strings.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -26,5 +30,13 @@ string UnitOfMeasure::getNamePlural() const{
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
string UnitOfMeasure::getAbbreviation() const{
 | 
			
		||||
    return this->abbreviation;
 | 
			
		||||
	return this->abbreviation;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int UnitOfMeasure::getType() const{
 | 
			
		||||
	return this->type;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
double UnitOfMeasure::getMetricCoefficient() const{
 | 
			
		||||
	return this->metricCoefficient;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,8 +12,14 @@ using namespace std;
 | 
			
		|||
class UnitOfMeasure
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	//Constants Declarations.
 | 
			
		||||
	static const int MASS = 1;
 | 
			
		||||
	static const int VOLUME = 2;
 | 
			
		||||
	static const int LENGTH = 3;
 | 
			
		||||
	static const int MISC = 4;
 | 
			
		||||
 | 
			
		||||
    //Full constructor.
 | 
			
		||||
    UnitOfMeasure(string name, string plural, string abbreviation);
 | 
			
		||||
	UnitOfMeasure(string name, string plural, string abbreviation, int type, double coef);
 | 
			
		||||
	//Attempt to guess unit from just a string.
 | 
			
		||||
	UnitOfMeasure(string name);
 | 
			
		||||
    //Constructor with default values.
 | 
			
		||||
| 
						 | 
				
			
			@ -23,10 +29,14 @@ public:
 | 
			
		|||
    string getName() const;
 | 
			
		||||
    string getNamePlural() const;
 | 
			
		||||
    string getAbbreviation() const;
 | 
			
		||||
	int getType() const;
 | 
			
		||||
	double getMetricCoefficient() const;
 | 
			
		||||
private:
 | 
			
		||||
    string name;                //The name of the unit of measure.
 | 
			
		||||
    string plural;              //The plural name.
 | 
			
		||||
    string abbreviation;        //A short version of the unit.
 | 
			
		||||
	int type;					//The type of unit, as one of the constants above.
 | 
			
		||||
	double metricCoefficient;	//The conversion from this unit to the standard metric unit.
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // UNITOFMEASURE_H
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,7 +8,7 @@ RecipeTag::RecipeTag(string val){
 | 
			
		|||
    this->value = val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
string RecipeTag::getValue(){
 | 
			
		||||
string RecipeTag::getValue() const{
 | 
			
		||||
    return this->value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@ public:
 | 
			
		|||
    RecipeTag(string val);
 | 
			
		||||
 | 
			
		||||
    //Getters
 | 
			
		||||
    string getValue();
 | 
			
		||||
	string getValue() const;
 | 
			
		||||
    //Setters
 | 
			
		||||
    void setValue(string newValue);
 | 
			
		||||
private:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,44 @@
 | 
			
		|||
#include "taglistmodel.h"
 | 
			
		||||
 | 
			
		||||
TagListModel::TagListModel(){
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int TagListModel::rowCount(const QModelIndex &parent) const{
 | 
			
		||||
	return this->tags.size();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QVariant TagListModel::data(const QModelIndex &index, int role) const{
 | 
			
		||||
	string displayString = this->tags[index.row()].getValue();
 | 
			
		||||
	switch(role){
 | 
			
		||||
	case Qt::DisplayRole:
 | 
			
		||||
		return QString::fromStdString(displayString);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return QVariant();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TagListModel::setTags(vector<RecipeTag> tags){
 | 
			
		||||
	this->tags = tags;
 | 
			
		||||
	QModelIndex index = createIndex(0, 0);
 | 
			
		||||
	QModelIndex bottomIndex = createIndex(this->tags.size()-1, 0);
 | 
			
		||||
	emit dataChanged(index, bottomIndex);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool TagListModel::addTag(RecipeTag tag){
 | 
			
		||||
	//Add only if it's different.
 | 
			
		||||
	for (unsigned int i = 0; i < this->tags.size(); i++){
 | 
			
		||||
		if (!this->tags[i].getValue().compare(tag.getValue())){
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	this->tags.push_back(tag);
 | 
			
		||||
	QModelIndex index = createIndex(this->tags.size()-1, 0);
 | 
			
		||||
	QModelIndex bottomIndex = createIndex(this->tags.size()-1, 0);
 | 
			
		||||
	emit dataChanged(index, bottomIndex);
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
vector<RecipeTag> TagListModel::getTags(){
 | 
			
		||||
	return this->tags;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
#ifndef TAGLISTMODEL_H
 | 
			
		||||
#define TAGLISTMODEL_H
 | 
			
		||||
 | 
			
		||||
#include <QAbstractListModel>
 | 
			
		||||
 | 
			
		||||
#include "model/recipe/tags/recipetag.h"
 | 
			
		||||
 | 
			
		||||
class TagListModel : public QAbstractListModel
 | 
			
		||||
{
 | 
			
		||||
	public:
 | 
			
		||||
		TagListModel();
 | 
			
		||||
		//Overridden methods.
 | 
			
		||||
		int rowCount(const QModelIndex &parent = QModelIndex()) const override;
 | 
			
		||||
		QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		void setTags(vector<RecipeTag> tags);
 | 
			
		||||
		bool addTag(RecipeTag tag);
 | 
			
		||||
		vector<RecipeTag> getTags();
 | 
			
		||||
	private:
 | 
			
		||||
		vector<RecipeTag> tags;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // TAGLISTMODEL_H
 | 
			
		||||
		Loading…
	
		Reference in New Issue