More security and less unexpected behaviour. #8
			
				
			
		
		
		
	
							
								
								
									
										11
									
								
								RecipeDB.pro
								
								
								
								
							
							
						
						
									
										11
									
								
								RecipeDB.pro
								
								
								
								
							| 
						 | 
				
			
			@ -34,7 +34,9 @@ SOURCES += model/recipe/instruction.cpp \
 | 
			
		|||
    utils/stringutils.cpp \
 | 
			
		||||
    gui/openrecipedialog.cpp \
 | 
			
		||||
    model/recipe/recipetablemodel.cpp \
 | 
			
		||||
    gui/mainwindow.cpp
 | 
			
		||||
    gui/mainwindow.cpp \
 | 
			
		||||
    gui/newDialogs/newfoodgroupdialog.cpp \
 | 
			
		||||
    model/recipe/ingredients/recipeingredientlistmodel.cpp
 | 
			
		||||
 | 
			
		||||
HEADERS  += model/recipe/instruction.h \
 | 
			
		||||
    model/recipe/recipe.h \
 | 
			
		||||
| 
						 | 
				
			
			@ -58,7 +60,9 @@ HEADERS  += model/recipe/instruction.h \
 | 
			
		|||
    utils/stringutils.h \
 | 
			
		||||
    gui/openrecipedialog.h \
 | 
			
		||||
    model/recipe/recipetablemodel.h \
 | 
			
		||||
    gui/mainwindow.h
 | 
			
		||||
    gui/mainwindow.h \
 | 
			
		||||
    gui/newDialogs/newfoodgroupdialog.h \
 | 
			
		||||
    model/recipe/ingredients/recipeingredientlistmodel.h
 | 
			
		||||
 | 
			
		||||
LIBS += -ldl \
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -68,7 +72,8 @@ FORMS    += gui/mainwindow.ui \
 | 
			
		|||
    gui/newDialogs/newtagdialog.ui \
 | 
			
		||||
    gui/newDialogs/newunitdialog.ui \
 | 
			
		||||
    gui/openrecipedialog.ui \
 | 
			
		||||
    gui/mainwindow.ui
 | 
			
		||||
    gui/mainwindow.ui \
 | 
			
		||||
    gui/newDialogs/newfoodgroupdialog.ui
 | 
			
		||||
 | 
			
		||||
DISTFILES += \
 | 
			
		||||
    .gitignore
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,7 +6,7 @@
 | 
			
		|||
#include <QAbstractListModel>
 | 
			
		||||
 | 
			
		||||
#include "model/recipe/recipe.h"
 | 
			
		||||
#include "model/recipe/ingredients/ingredientlistmodel.h"
 | 
			
		||||
#include "model/recipe/ingredients/recipeingredientlistmodel.h"
 | 
			
		||||
#include "gui/newrecipedialog.h"
 | 
			
		||||
#include "gui/openrecipedialog.h"
 | 
			
		||||
#include "utils/stringutils.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -39,7 +39,7 @@ public:
 | 
			
		|||
	private:
 | 
			
		||||
    Ui::MainWindow *ui;
 | 
			
		||||
	RecipeDatabase *recipeDB;
 | 
			
		||||
    IngredientListModel ingredientModel;
 | 
			
		||||
	RecipeIngredientListModel ingredientModel;
 | 
			
		||||
	TagListModel tagsListModel;
 | 
			
		||||
 | 
			
		||||
    //Hidden manipulation methods.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -329,10 +329,10 @@ font: "Noto Sans CJK KR";</string>
 | 
			
		|||
          <property name="bottomMargin">
 | 
			
		||||
           <number>0</number>
 | 
			
		||||
          </property>
 | 
			
		||||
          <item>
 | 
			
		||||
          <item alignment="Qt::AlignRight">
 | 
			
		||||
           <widget class="QLabel" name="recipeNameLabel">
 | 
			
		||||
            <property name="sizePolicy">
 | 
			
		||||
             <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
 | 
			
		||||
             <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
 | 
			
		||||
              <horstretch>0</horstretch>
 | 
			
		||||
              <verstretch>0</verstretch>
 | 
			
		||||
             </sizepolicy>
 | 
			
		||||
| 
						 | 
				
			
			@ -361,6 +361,26 @@ font: "Noto Sans CJK KR";</string>
 | 
			
		|||
            </property>
 | 
			
		||||
           </widget>
 | 
			
		||||
          </item>
 | 
			
		||||
          <item alignment="Qt::AlignLeft|Qt::AlignBottom">
 | 
			
		||||
           <widget class="QLabel" name="authorLabel">
 | 
			
		||||
            <property name="sizePolicy">
 | 
			
		||||
             <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
 | 
			
		||||
              <horstretch>0</horstretch>
 | 
			
		||||
              <verstretch>0</verstretch>
 | 
			
		||||
             </sizepolicy>
 | 
			
		||||
            </property>
 | 
			
		||||
            <property name="font">
 | 
			
		||||
             <font>
 | 
			
		||||
              <family>Noto Sans CJK KR Light</family>
 | 
			
		||||
              <pointsize>14</pointsize>
 | 
			
		||||
              <stylestrategy>PreferAntialias</stylestrategy>
 | 
			
		||||
             </font>
 | 
			
		||||
            </property>
 | 
			
		||||
            <property name="text">
 | 
			
		||||
             <string>By Unknown Author</string>
 | 
			
		||||
            </property>
 | 
			
		||||
           </widget>
 | 
			
		||||
          </item>
 | 
			
		||||
         </layout>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
| 
						 | 
				
			
			@ -584,6 +604,9 @@ font: "Noto Sans CJK KR";</string>
 | 
			
		|||
                  <property name="horizontalScrollBarPolicy">
 | 
			
		||||
                   <enum>Qt::ScrollBarAlwaysOff</enum>
 | 
			
		||||
                  </property>
 | 
			
		||||
                  <property name="editTriggers">
 | 
			
		||||
                   <set>QAbstractItemView::NoEditTriggers</set>
 | 
			
		||||
                  </property>
 | 
			
		||||
                  <property name="selectionMode">
 | 
			
		||||
                   <enum>QAbstractItemView::ExtendedSelection</enum>
 | 
			
		||||
                  </property>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,18 @@
 | 
			
		|||
#include "newfoodgroupdialog.h"
 | 
			
		||||
#include "ui_newfoodgroupdialog.h"
 | 
			
		||||
 | 
			
		||||
newFoodGroupDialog::newFoodGroupDialog(QWidget *parent) :
 | 
			
		||||
	QDialog(parent),
 | 
			
		||||
	ui(new Ui::newFoodGroupDialog)
 | 
			
		||||
{
 | 
			
		||||
	ui->setupUi(this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
newFoodGroupDialog::~newFoodGroupDialog()
 | 
			
		||||
{
 | 
			
		||||
	delete ui;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
string newFoodGroupDialog::getFoodGroup() const{
 | 
			
		||||
	return ui->lineEdit->text().toStdString();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,27 @@
 | 
			
		|||
#ifndef NEWFOODGROUPDIALOG_H
 | 
			
		||||
#define NEWFOODGROUPDIALOG_H
 | 
			
		||||
 | 
			
		||||
#include <QDialog>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
using namespace std;
 | 
			
		||||
 | 
			
		||||
namespace Ui {
 | 
			
		||||
class newFoodGroupDialog;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class newFoodGroupDialog : public QDialog
 | 
			
		||||
{
 | 
			
		||||
		Q_OBJECT
 | 
			
		||||
 | 
			
		||||
	public:
 | 
			
		||||
		explicit newFoodGroupDialog(QWidget *parent = 0);
 | 
			
		||||
		~newFoodGroupDialog();
 | 
			
		||||
 | 
			
		||||
		string getFoodGroup() const;
 | 
			
		||||
 | 
			
		||||
	private:
 | 
			
		||||
		Ui::newFoodGroupDialog *ui;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // NEWFOODGROUPDIALOG_H
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,101 @@
 | 
			
		|||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<ui version="4.0">
 | 
			
		||||
 <class>newFoodGroupDialog</class>
 | 
			
		||||
 <widget class="QDialog" name="newFoodGroupDialog">
 | 
			
		||||
  <property name="geometry">
 | 
			
		||||
   <rect>
 | 
			
		||||
    <x>0</x>
 | 
			
		||||
    <y>0</y>
 | 
			
		||||
    <width>240</width>
 | 
			
		||||
    <height>114</height>
 | 
			
		||||
   </rect>
 | 
			
		||||
  </property>
 | 
			
		||||
  <property name="font">
 | 
			
		||||
   <font>
 | 
			
		||||
    <pointsize>11</pointsize>
 | 
			
		||||
   </font>
 | 
			
		||||
  </property>
 | 
			
		||||
  <property name="windowTitle">
 | 
			
		||||
   <string>New Food Group</string>
 | 
			
		||||
  </property>
 | 
			
		||||
  <property name="windowIcon">
 | 
			
		||||
   <iconset resource="../../images.qrc">
 | 
			
		||||
    <normaloff>:/images/images/icon.png</normaloff>:/images/images/icon.png</iconset>
 | 
			
		||||
  </property>
 | 
			
		||||
  <layout class="QVBoxLayout" name="verticalLayout">
 | 
			
		||||
   <item>
 | 
			
		||||
    <widget class="QLabel" name="label">
 | 
			
		||||
     <property name="font">
 | 
			
		||||
      <font>
 | 
			
		||||
       <family>Noto Sans CJK KR Light</family>
 | 
			
		||||
       <pointsize>12</pointsize>
 | 
			
		||||
      </font>
 | 
			
		||||
     </property>
 | 
			
		||||
     <property name="text">
 | 
			
		||||
      <string>Add New Food Group</string>
 | 
			
		||||
     </property>
 | 
			
		||||
     <property name="alignment">
 | 
			
		||||
      <set>Qt::AlignCenter</set>
 | 
			
		||||
     </property>
 | 
			
		||||
    </widget>
 | 
			
		||||
   </item>
 | 
			
		||||
   <item>
 | 
			
		||||
    <widget class="QLineEdit" name="lineEdit">
 | 
			
		||||
     <property name="font">
 | 
			
		||||
      <font>
 | 
			
		||||
       <family>Noto Sans CJK KR Light</family>
 | 
			
		||||
       <pointsize>12</pointsize>
 | 
			
		||||
      </font>
 | 
			
		||||
     </property>
 | 
			
		||||
    </widget>
 | 
			
		||||
   </item>
 | 
			
		||||
   <item>
 | 
			
		||||
    <widget class="QDialogButtonBox" name="buttonBox">
 | 
			
		||||
     <property name="orientation">
 | 
			
		||||
      <enum>Qt::Horizontal</enum>
 | 
			
		||||
     </property>
 | 
			
		||||
     <property name="standardButtons">
 | 
			
		||||
      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
 | 
			
		||||
     </property>
 | 
			
		||||
    </widget>
 | 
			
		||||
   </item>
 | 
			
		||||
  </layout>
 | 
			
		||||
 </widget>
 | 
			
		||||
 <resources>
 | 
			
		||||
  <include location="../../images.qrc"/>
 | 
			
		||||
 </resources>
 | 
			
		||||
 <connections>
 | 
			
		||||
  <connection>
 | 
			
		||||
   <sender>buttonBox</sender>
 | 
			
		||||
   <signal>accepted()</signal>
 | 
			
		||||
   <receiver>newFoodGroupDialog</receiver>
 | 
			
		||||
   <slot>accept()</slot>
 | 
			
		||||
   <hints>
 | 
			
		||||
    <hint type="sourcelabel">
 | 
			
		||||
     <x>248</x>
 | 
			
		||||
     <y>254</y>
 | 
			
		||||
    </hint>
 | 
			
		||||
    <hint type="destinationlabel">
 | 
			
		||||
     <x>157</x>
 | 
			
		||||
     <y>274</y>
 | 
			
		||||
    </hint>
 | 
			
		||||
   </hints>
 | 
			
		||||
  </connection>
 | 
			
		||||
  <connection>
 | 
			
		||||
   <sender>buttonBox</sender>
 | 
			
		||||
   <signal>rejected()</signal>
 | 
			
		||||
   <receiver>newFoodGroupDialog</receiver>
 | 
			
		||||
   <slot>reject()</slot>
 | 
			
		||||
   <hints>
 | 
			
		||||
    <hint type="sourcelabel">
 | 
			
		||||
     <x>316</x>
 | 
			
		||||
     <y>260</y>
 | 
			
		||||
    </hint>
 | 
			
		||||
    <hint type="destinationlabel">
 | 
			
		||||
     <x>286</x>
 | 
			
		||||
     <y>274</y>
 | 
			
		||||
    </hint>
 | 
			
		||||
   </hints>
 | 
			
		||||
  </connection>
 | 
			
		||||
 </connections>
 | 
			
		||||
</ui>
 | 
			
		||||
| 
						 | 
				
			
			@ -8,11 +8,42 @@ NewIngredientDialog::NewIngredientDialog(QWidget *parent) :
 | 
			
		|||
	ui->setupUi(this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NewIngredientDialog::NewIngredientDialog(RecipeDatabase *recipeDB, QWidget *parent) : NewIngredientDialog(parent){
 | 
			
		||||
	this->recipeDB = recipeDB;
 | 
			
		||||
	this->populateFoodGroupBox();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NewIngredientDialog::~NewIngredientDialog()
 | 
			
		||||
{
 | 
			
		||||
	delete ui;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Ingredient NewIngredientDialog::getIngredient(){
 | 
			
		||||
	return Ingredient(ui->nameEdit->text().toLower().toStdString(), ui->foodGroupEdit->text().toLower().toStdString());
 | 
			
		||||
	return Ingredient(ui->nameEdit->text().toLower().toStdString(), ui->foodGroupBox->currentText().toStdString());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void NewIngredientDialog::populateFoodGroupBox(){
 | 
			
		||||
	vector<string> foodGroups = this->recipeDB->retrieveAllFoodGroups();
 | 
			
		||||
	ui->foodGroupBox->clear();
 | 
			
		||||
	for (unsigned int i = 0; i < foodGroups.size(); i++){
 | 
			
		||||
		QString s = QString::fromStdString(foodGroups[i]);
 | 
			
		||||
		ui->foodGroupBox->insertItem(i, s);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void NewIngredientDialog::on_addFoodGroupButton_clicked(){
 | 
			
		||||
	newFoodGroupDialog d(this);
 | 
			
		||||
	if (d.exec() == QDialog::Accepted){
 | 
			
		||||
		string s = d.getFoodGroup();
 | 
			
		||||
		if (!s.empty()){
 | 
			
		||||
			ui->foodGroupBox->addItem(QString::fromStdString(s));
 | 
			
		||||
			ui->foodGroupBox->setCurrentText(QString::fromStdString(s));
 | 
			
		||||
		} else {
 | 
			
		||||
			QMessageBox::warning(this, "Empty Food Group", "The food group you entered is empty!");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void NewIngredientDialog::on_deleteFoodGroupButton_clicked(){
 | 
			
		||||
	ui->foodGroupBox->removeItem(ui->foodGroupBox->currentIndex());
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,11 @@
 | 
			
		|||
#define NEWINGREDIENTDIALOG_H
 | 
			
		||||
 | 
			
		||||
#include <QDialog>
 | 
			
		||||
#include <QMessageBox>
 | 
			
		||||
 | 
			
		||||
#include "model/recipe/ingredients/ingredient.h"
 | 
			
		||||
#include "model/database/recipedatabase.h"
 | 
			
		||||
#include "gui/newDialogs/newfoodgroupdialog.h"
 | 
			
		||||
 | 
			
		||||
namespace Ui {
 | 
			
		||||
class NewIngredientDialog;
 | 
			
		||||
| 
						 | 
				
			
			@ -14,13 +18,22 @@ class NewIngredientDialog : public QDialog
 | 
			
		|||
 | 
			
		||||
	public:
 | 
			
		||||
		explicit NewIngredientDialog(QWidget *parent = 0);
 | 
			
		||||
		NewIngredientDialog(RecipeDatabase *recipeDB, QWidget *parent = 0);
 | 
			
		||||
		~NewIngredientDialog();
 | 
			
		||||
 | 
			
		||||
		//Access values.
 | 
			
		||||
		Ingredient getIngredient();
 | 
			
		||||
 | 
			
		||||
	private slots:
 | 
			
		||||
		void on_addFoodGroupButton_clicked();
 | 
			
		||||
 | 
			
		||||
		void on_deleteFoodGroupButton_clicked();
 | 
			
		||||
 | 
			
		||||
	private:
 | 
			
		||||
		Ui::NewIngredientDialog *ui;
 | 
			
		||||
		RecipeDatabase *recipeDB;
 | 
			
		||||
 | 
			
		||||
		void populateFoodGroupBox();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // NEWINGREDIENTDIALOG_H
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,8 +6,8 @@
 | 
			
		|||
   <rect>
 | 
			
		||||
    <x>0</x>
 | 
			
		||||
    <y>0</y>
 | 
			
		||||
    <width>240</width>
 | 
			
		||||
    <height>320</height>
 | 
			
		||||
    <width>367</width>
 | 
			
		||||
    <height>228</height>
 | 
			
		||||
   </rect>
 | 
			
		||||
  </property>
 | 
			
		||||
  <property name="windowTitle">
 | 
			
		||||
| 
						 | 
				
			
			@ -60,7 +60,45 @@
 | 
			
		|||
          </widget>
 | 
			
		||||
         </item>
 | 
			
		||||
         <item>
 | 
			
		||||
          <widget class="QLineEdit" name="foodGroupEdit"/>
 | 
			
		||||
          <widget class="QWidget" name="foodGroupSelectionWidget" native="true">
 | 
			
		||||
           <layout class="QHBoxLayout" name="horizontalLayout">
 | 
			
		||||
            <item>
 | 
			
		||||
             <widget class="QComboBox" name="foodGroupBox">
 | 
			
		||||
              <property name="sizePolicy">
 | 
			
		||||
               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
 | 
			
		||||
                <horstretch>0</horstretch>
 | 
			
		||||
                <verstretch>0</verstretch>
 | 
			
		||||
               </sizepolicy>
 | 
			
		||||
              </property>
 | 
			
		||||
              <property name="insertPolicy">
 | 
			
		||||
               <enum>QComboBox::InsertAlphabetically</enum>
 | 
			
		||||
              </property>
 | 
			
		||||
             </widget>
 | 
			
		||||
            </item>
 | 
			
		||||
            <item alignment="Qt::AlignRight">
 | 
			
		||||
             <widget class="QPushButton" name="addFoodGroupButton">
 | 
			
		||||
              <property name="text">
 | 
			
		||||
               <string/>
 | 
			
		||||
              </property>
 | 
			
		||||
              <property name="icon">
 | 
			
		||||
               <iconset resource="../../images.qrc">
 | 
			
		||||
                <normaloff>:/images/images/plus_icon.png</normaloff>:/images/images/plus_icon.png</iconset>
 | 
			
		||||
              </property>
 | 
			
		||||
             </widget>
 | 
			
		||||
            </item>
 | 
			
		||||
            <item alignment="Qt::AlignRight">
 | 
			
		||||
             <widget class="QPushButton" name="deleteFoodGroupButton">
 | 
			
		||||
              <property name="text">
 | 
			
		||||
               <string/>
 | 
			
		||||
              </property>
 | 
			
		||||
              <property name="icon">
 | 
			
		||||
               <iconset resource="../../images.qrc">
 | 
			
		||||
                <normaloff>:/images/images/minus_icon.png</normaloff>:/images/images/minus_icon.png</iconset>
 | 
			
		||||
              </property>
 | 
			
		||||
             </widget>
 | 
			
		||||
            </item>
 | 
			
		||||
           </layout>
 | 
			
		||||
          </widget>
 | 
			
		||||
         </item>
 | 
			
		||||
        </layout>
 | 
			
		||||
       </widget>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,16 +7,19 @@
 | 
			
		|||
    <x>0</x>
 | 
			
		||||
    <y>0</y>
 | 
			
		||||
    <width>240</width>
 | 
			
		||||
    <height>320</height>
 | 
			
		||||
    <height>121</height>
 | 
			
		||||
   </rect>
 | 
			
		||||
  </property>
 | 
			
		||||
  <property name="windowTitle">
 | 
			
		||||
   <string>Dialog</string>
 | 
			
		||||
   <string>New Tag</string>
 | 
			
		||||
  </property>
 | 
			
		||||
  <property name="windowIcon">
 | 
			
		||||
   <iconset resource="../../images.qrc">
 | 
			
		||||
    <normaloff>:/images/images/icon.png</normaloff>:/images/images/icon.png</iconset>
 | 
			
		||||
  </property>
 | 
			
		||||
  <property name="styleSheet">
 | 
			
		||||
   <string notr="true">font: 25 "Noto Sans CJK KR Light";</string>
 | 
			
		||||
  </property>
 | 
			
		||||
  <property name="modal">
 | 
			
		||||
   <bool>true</bool>
 | 
			
		||||
  </property>
 | 
			
		||||
| 
						 | 
				
			
			@ -26,6 +29,14 @@
 | 
			
		|||
     <layout class="QVBoxLayout" name="verticalLayout_2">
 | 
			
		||||
      <item>
 | 
			
		||||
       <widget class="QLabel" name="tagLabel">
 | 
			
		||||
        <property name="font">
 | 
			
		||||
         <font>
 | 
			
		||||
          <pointsize>13</pointsize>
 | 
			
		||||
          <weight>3</weight>
 | 
			
		||||
          <italic>false</italic>
 | 
			
		||||
          <bold>false</bold>
 | 
			
		||||
         </font>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string>New Tag</string>
 | 
			
		||||
        </property>
 | 
			
		||||
| 
						 | 
				
			
			@ -35,7 +46,16 @@
 | 
			
		|||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item>
 | 
			
		||||
       <widget class="QLineEdit" name="tagEdit"/>
 | 
			
		||||
       <widget class="QLineEdit" name="tagEdit">
 | 
			
		||||
        <property name="font">
 | 
			
		||||
         <font>
 | 
			
		||||
          <pointsize>12</pointsize>
 | 
			
		||||
          <weight>3</weight>
 | 
			
		||||
          <italic>false</italic>
 | 
			
		||||
          <bold>false</bold>
 | 
			
		||||
         </font>
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
     </layout>
 | 
			
		||||
    </widget>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,8 +6,8 @@
 | 
			
		|||
   <rect>
 | 
			
		||||
    <x>0</x>
 | 
			
		||||
    <y>0</y>
 | 
			
		||||
    <width>240</width>
 | 
			
		||||
    <height>350</height>
 | 
			
		||||
    <width>195</width>
 | 
			
		||||
    <height>340</height>
 | 
			
		||||
   </rect>
 | 
			
		||||
  </property>
 | 
			
		||||
  <property name="windowTitle">
 | 
			
		||||
| 
						 | 
				
			
			@ -17,6 +17,9 @@
 | 
			
		|||
   <iconset resource="../../images.qrc">
 | 
			
		||||
    <normaloff>:/images/images/icon.png</normaloff>:/images/images/icon.png</iconset>
 | 
			
		||||
  </property>
 | 
			
		||||
  <property name="styleSheet">
 | 
			
		||||
   <string notr="true">font: 25 "Noto Sans CJK KR Light";</string>
 | 
			
		||||
  </property>
 | 
			
		||||
  <property name="modal">
 | 
			
		||||
   <bool>true</bool>
 | 
			
		||||
  </property>
 | 
			
		||||
| 
						 | 
				
			
			@ -26,6 +29,14 @@
 | 
			
		|||
     <layout class="QVBoxLayout" name="verticalLayout_2">
 | 
			
		||||
      <item>
 | 
			
		||||
       <widget class="QLabel" name="label">
 | 
			
		||||
        <property name="font">
 | 
			
		||||
         <font>
 | 
			
		||||
          <pointsize>12</pointsize>
 | 
			
		||||
          <weight>3</weight>
 | 
			
		||||
          <italic>false</italic>
 | 
			
		||||
          <bold>false</bold>
 | 
			
		||||
         </font>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string>Unit Name</string>
 | 
			
		||||
        </property>
 | 
			
		||||
| 
						 | 
				
			
			@ -39,6 +50,14 @@
 | 
			
		|||
      </item>
 | 
			
		||||
      <item>
 | 
			
		||||
       <widget class="QLabel" name="label_2">
 | 
			
		||||
        <property name="font">
 | 
			
		||||
         <font>
 | 
			
		||||
          <pointsize>12</pointsize>
 | 
			
		||||
          <weight>3</weight>
 | 
			
		||||
          <italic>false</italic>
 | 
			
		||||
          <bold>false</bold>
 | 
			
		||||
         </font>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string>Plural Name</string>
 | 
			
		||||
        </property>
 | 
			
		||||
| 
						 | 
				
			
			@ -52,6 +71,14 @@
 | 
			
		|||
      </item>
 | 
			
		||||
      <item>
 | 
			
		||||
       <widget class="QLabel" name="label_3">
 | 
			
		||||
        <property name="font">
 | 
			
		||||
         <font>
 | 
			
		||||
          <pointsize>12</pointsize>
 | 
			
		||||
          <weight>3</weight>
 | 
			
		||||
          <italic>false</italic>
 | 
			
		||||
          <bold>false</bold>
 | 
			
		||||
         </font>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string>Abbreviation</string>
 | 
			
		||||
        </property>
 | 
			
		||||
| 
						 | 
				
			
			@ -86,6 +113,14 @@
 | 
			
		|||
             <verstretch>0</verstretch>
 | 
			
		||||
            </sizepolicy>
 | 
			
		||||
           </property>
 | 
			
		||||
           <property name="font">
 | 
			
		||||
            <font>
 | 
			
		||||
             <pointsize>12</pointsize>
 | 
			
		||||
             <weight>3</weight>
 | 
			
		||||
             <italic>false</italic>
 | 
			
		||||
             <bold>false</bold>
 | 
			
		||||
            </font>
 | 
			
		||||
           </property>
 | 
			
		||||
           <property name="text">
 | 
			
		||||
            <string>Type:</string>
 | 
			
		||||
           </property>
 | 
			
		||||
| 
						 | 
				
			
			@ -109,6 +144,14 @@
 | 
			
		|||
        <layout class="QVBoxLayout" name="verticalLayout_3">
 | 
			
		||||
         <item>
 | 
			
		||||
          <widget class="QLabel" name="label_5">
 | 
			
		||||
           <property name="font">
 | 
			
		||||
            <font>
 | 
			
		||||
             <pointsize>12</pointsize>
 | 
			
		||||
             <weight>3</weight>
 | 
			
		||||
             <italic>false</italic>
 | 
			
		||||
             <bold>false</bold>
 | 
			
		||||
            </font>
 | 
			
		||||
           </property>
 | 
			
		||||
           <property name="text">
 | 
			
		||||
            <string>Metric Coefficient</string>
 | 
			
		||||
           </property>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -75,6 +75,7 @@ void NewRecipeDialog::on_addIngredientButton_clicked(){
 | 
			
		|||
	UnitOfMeasure u = this->units[ui->unitComboBox->currentIndex()];
 | 
			
		||||
	RecipeIngredient ri(i, ui->quantitySpinBox->value(), u, ui->commentsLineEdit->text().toStdString());
 | 
			
		||||
	this->ingredientListModel.addIngredient(ri);
 | 
			
		||||
	ui->commentsLineEdit->clear();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void NewRecipeDialog::on_italicsButton_clicked(){
 | 
			
		||||
| 
						 | 
				
			
			@ -144,12 +145,17 @@ void NewRecipeDialog::on_deleteIngredientButton_clicked(){
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void NewRecipeDialog::on_newIngredientButton_clicked(){
 | 
			
		||||
	NewIngredientDialog d(this);
 | 
			
		||||
	NewIngredientDialog d(this->recipeDB, this);
 | 
			
		||||
	d.show();
 | 
			
		||||
	if (d.exec() == QDialog::Accepted){
 | 
			
		||||
		Ingredient i = d.getIngredient();
 | 
			
		||||
		this->recipeDB->storeIngredient(i);
 | 
			
		||||
		this->populateIngredientsBox();
 | 
			
		||||
		if (!i.getName().empty() && !i.getFoodGroup().empty() && this->recipeDB->storeIngredient(i)){
 | 
			
		||||
			this->populateIngredientsBox();
 | 
			
		||||
			ui->ingredientNameBox->setCurrentText(QString::fromStdString(i.getName()));
 | 
			
		||||
		} else {
 | 
			
		||||
			QMessageBox::critical(this, "Error", "Unable to add ingredient.");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -159,12 +165,16 @@ void NewRecipeDialog::on_newTagButton_clicked(){
 | 
			
		|||
	if (d.exec() == QDialog::Accepted){
 | 
			
		||||
		RecipeTag tag = d.getTag();
 | 
			
		||||
		//Temporarily add this to the tags list, and it will be saved if the recipe is saved.
 | 
			
		||||
		this->tags.push_back(tag);
 | 
			
		||||
		this->tagsListModel.addTag(tag);
 | 
			
		||||
		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);
 | 
			
		||||
		if (!tag.getValue().empty()){
 | 
			
		||||
			this->tags.push_back(tag);
 | 
			
		||||
			this->tagsListModel.addTag(tag);
 | 
			
		||||
			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);
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			QMessageBox::warning(this, "Empty Tag", "The tag you entered is blank!");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -189,10 +199,11 @@ void NewRecipeDialog::on_newUnitButton_clicked(){
 | 
			
		|||
	d.show();
 | 
			
		||||
	if (d.exec() == QDialog::Accepted){
 | 
			
		||||
		UnitOfMeasure u = d.getUnit();
 | 
			
		||||
		if (!this->recipeDB->storeUnitOfMeasure(u) || u.getName().empty() || u.getNamePlural().empty() || u.getAbbreviation().empty()){
 | 
			
		||||
			QMessageBox::critical(this, "Error", "Unable to store new unit.");
 | 
			
		||||
		if (u.getName().empty() || u.getNamePlural().empty() || u.getAbbreviation().empty() || !this->recipeDB->storeUnitOfMeasure(u)){
 | 
			
		||||
			QMessageBox::critical(this, "Error", "Unable to store new unit. Make sure all the information is filled in!");
 | 
			
		||||
		} else {
 | 
			
		||||
			this->populateUnitsBox();
 | 
			
		||||
			ui->unitComboBox->setCurrentText(QString::fromStdString(u.getName()));
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,7 +8,7 @@
 | 
			
		|||
#include <QMessageBox>
 | 
			
		||||
 | 
			
		||||
#include "model/database/recipedatabase.h"
 | 
			
		||||
#include "model/recipe/ingredients/ingredientlistmodel.h"
 | 
			
		||||
#include "model/recipe/ingredients/recipeingredientlistmodel.h"
 | 
			
		||||
#include "model/recipe/tags/taglistmodel.h"
 | 
			
		||||
 | 
			
		||||
#include "gui/newDialogs/newingredientdialog.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -67,7 +67,7 @@ class NewRecipeDialog : public QDialog
 | 
			
		|||
		vector<Ingredient> ingredients;
 | 
			
		||||
		vector<UnitOfMeasure> units;
 | 
			
		||||
		vector<RecipeTag> tags;
 | 
			
		||||
		IngredientListModel ingredientListModel;
 | 
			
		||||
		RecipeIngredientListModel ingredientListModel;
 | 
			
		||||
		TagListModel tagsListModel;
 | 
			
		||||
		QImage img;
 | 
			
		||||
		bool accepted = false;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -96,27 +96,11 @@
 | 
			
		|||
            <item>
 | 
			
		||||
             <widget class="QWidget" name="recipeNamePanel" native="true">
 | 
			
		||||
              <layout class="QVBoxLayout" name="verticalLayout_9">
 | 
			
		||||
               <item>
 | 
			
		||||
                <widget class="QLabel" name="recipeNameLabel">
 | 
			
		||||
                 <property name="font">
 | 
			
		||||
                  <font>
 | 
			
		||||
                   <weight>3</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>
 | 
			
		||||
                   <pointsize>16</pointsize>
 | 
			
		||||
                   <weight>3</weight>
 | 
			
		||||
                   <italic>false</italic>
 | 
			
		||||
                   <bold>false</bold>
 | 
			
		||||
| 
						 | 
				
			
			@ -158,7 +142,7 @@
 | 
			
		|||
                      <second>0</second>
 | 
			
		||||
                      <year>1999</year>
 | 
			
		||||
                      <month>12</month>
 | 
			
		||||
                      <day>25</day>
 | 
			
		||||
                      <day>24</day>
 | 
			
		||||
                     </datetime>
 | 
			
		||||
                    </property>
 | 
			
		||||
                    <property name="currentSection">
 | 
			
		||||
| 
						 | 
				
			
			@ -289,6 +273,12 @@
 | 
			
		|||
                   <verstretch>0</verstretch>
 | 
			
		||||
                  </sizepolicy>
 | 
			
		||||
                 </property>
 | 
			
		||||
                 <property name="styleSheet">
 | 
			
		||||
                  <string notr="true">background-color: rgb(113, 119, 255);</string>
 | 
			
		||||
                 </property>
 | 
			
		||||
                 <property name="insertPolicy">
 | 
			
		||||
                  <enum>QComboBox::InsertAlphabetically</enum>
 | 
			
		||||
                 </property>
 | 
			
		||||
                </widget>
 | 
			
		||||
               </item>
 | 
			
		||||
               <item alignment="Qt::AlignRight">
 | 
			
		||||
| 
						 | 
				
			
			@ -418,16 +408,6 @@
 | 
			
		|||
            <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="QVBoxLayout" name="verticalLayout_12">
 | 
			
		||||
| 
						 | 
				
			
			@ -485,12 +465,21 @@
 | 
			
		|||
                         <verstretch>0</verstretch>
 | 
			
		||||
                        </sizepolicy>
 | 
			
		||||
                       </property>
 | 
			
		||||
                       <property name="styleSheet">
 | 
			
		||||
                        <string notr="true">background-color: rgb(113, 119, 255);</string>
 | 
			
		||||
                       </property>
 | 
			
		||||
                       <property name="editable">
 | 
			
		||||
                        <bool>false</bool>
 | 
			
		||||
                       </property>
 | 
			
		||||
                       <property name="currentText">
 | 
			
		||||
                        <string/>
 | 
			
		||||
                       </property>
 | 
			
		||||
                       <property name="insertPolicy">
 | 
			
		||||
                        <enum>QComboBox::InsertAlphabetically</enum>
 | 
			
		||||
                       </property>
 | 
			
		||||
                       <property name="frame">
 | 
			
		||||
                        <bool>true</bool>
 | 
			
		||||
                       </property>
 | 
			
		||||
                      </widget>
 | 
			
		||||
                     </item>
 | 
			
		||||
                     <item>
 | 
			
		||||
| 
						 | 
				
			
			@ -580,6 +569,12 @@
 | 
			
		|||
                         <verstretch>0</verstretch>
 | 
			
		||||
                        </sizepolicy>
 | 
			
		||||
                       </property>
 | 
			
		||||
                       <property name="styleSheet">
 | 
			
		||||
                        <string notr="true">background-color: rgb(113, 119, 255);</string>
 | 
			
		||||
                       </property>
 | 
			
		||||
                       <property name="insertPolicy">
 | 
			
		||||
                        <enum>QComboBox::InsertAlphabetically</enum>
 | 
			
		||||
                       </property>
 | 
			
		||||
                      </widget>
 | 
			
		||||
                     </item>
 | 
			
		||||
                     <item alignment="Qt::AlignRight">
 | 
			
		||||
| 
						 | 
				
			
			@ -832,7 +827,10 @@
 | 
			
		|||
         <enum>Qt::LeftToRight</enum>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="autoFillBackground">
 | 
			
		||||
         <bool>false</bool>
 | 
			
		||||
         <bool>true</bool>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="styleSheet">
 | 
			
		||||
         <string notr="true">background-color: rgb(255, 255, 255);</string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="standardButtons">
 | 
			
		||||
         <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,10 +8,19 @@ OpenRecipeDialog::OpenRecipeDialog(QWidget *parent) :
 | 
			
		|||
	ui->setupUi(this);
 | 
			
		||||
 | 
			
		||||
	ui->recipeTableView->setModel(&this->recipeTableModel);
 | 
			
		||||
	ui->ingredientsListView->setModel(&this->ingredientsModel);
 | 
			
		||||
	ui->tagsListView->setModel(&this->tagsModel);
 | 
			
		||||
 | 
			
		||||
	connect(ui->ingredientsListView->selectionModel(),
 | 
			
		||||
			SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
 | 
			
		||||
			this,
 | 
			
		||||
			SLOT(on_ingredientsListView_selectionChanged(QItemSelection)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
OpenRecipeDialog::OpenRecipeDialog(RecipeDatabase *recipeDB, QWidget *parent) : OpenRecipeDialog(parent){
 | 
			
		||||
	this->recipeDB = recipeDB;
 | 
			
		||||
	this->populateIngredientsList();
 | 
			
		||||
	this->populateTagsList();
 | 
			
		||||
	this->populateRecipesTable();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -32,13 +41,21 @@ void OpenRecipeDialog::populateRecipesTable(){
 | 
			
		|||
	ui->recipeTableView->show();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OpenRecipeDialog::populateIngredientsList(){
 | 
			
		||||
	this->ingredientsModel.setIngredients(this->recipeDB->retrieveAllIngredients());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OpenRecipeDialog::populateTagsList(){
 | 
			
		||||
	this->tagsModel.setTags(this->recipeDB->retrieveAllTags());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OpenRecipeDialog::on_deleteRecipeButton_clicked(){
 | 
			
		||||
	QItemSelectionModel *selectModel = ui->recipeTableView->selectionModel();
 | 
			
		||||
	if (!selectModel->hasSelection()){
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	vector<int> rows;
 | 
			
		||||
	QModelIndexList indexes = selectModel->selectedIndexes();
 | 
			
		||||
	QModelIndexList indexes = selectModel->selectedRows();
 | 
			
		||||
	for (int i = 0; i < indexes.count(); i++){
 | 
			
		||||
		rows.push_back(indexes.at(i).row());
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -62,3 +79,14 @@ void OpenRecipeDialog::on_recipeTableView_doubleClicked(const QModelIndex &index
 | 
			
		|||
	this->selectedRecipe = this->recipeTableModel.getRecipeAt(index.row());
 | 
			
		||||
	this->close();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OpenRecipeDialog::on_ingredientsListView_selectionChanged(const QItemSelection &selection){
 | 
			
		||||
	printf("Selection changed!\n");
 | 
			
		||||
	vector<Ingredient> ingredients;
 | 
			
		||||
	for (QModelIndex index : selection.indexes()){
 | 
			
		||||
		Ingredient i = this->ingredientsModel.getIngredients().at(index.row());
 | 
			
		||||
		ingredients.push_back(i);
 | 
			
		||||
		printf("Selected: %s\n", i.getName().c_str());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,9 +3,12 @@
 | 
			
		|||
 | 
			
		||||
#include <QDialog>
 | 
			
		||||
#include <QMessageBox>
 | 
			
		||||
#include <QItemSelection>
 | 
			
		||||
 | 
			
		||||
#include "model/database/recipedatabase.h"
 | 
			
		||||
#include "model/recipe/recipetablemodel.h"
 | 
			
		||||
#include "model/recipe/ingredients/ingredientlistmodel.h"
 | 
			
		||||
#include "model/recipe/tags/taglistmodel.h"
 | 
			
		||||
 | 
			
		||||
namespace Ui {
 | 
			
		||||
class OpenRecipeDialog;
 | 
			
		||||
| 
						 | 
				
			
			@ -27,13 +30,20 @@ class OpenRecipeDialog : public QDialog
 | 
			
		|||
 | 
			
		||||
		void on_recipeTableView_doubleClicked(const QModelIndex &index);
 | 
			
		||||
 | 
			
		||||
		void on_ingredientsListView_selectionChanged(const QItemSelection &selection);
 | 
			
		||||
 | 
			
		||||
	private:
 | 
			
		||||
		Ui::OpenRecipeDialog *ui;
 | 
			
		||||
		RecipeDatabase *recipeDB;
 | 
			
		||||
		RecipeTableModel recipeTableModel;
 | 
			
		||||
		Recipe selectedRecipe;
 | 
			
		||||
 | 
			
		||||
		IngredientListModel ingredientsModel;
 | 
			
		||||
		TagListModel tagsModel;
 | 
			
		||||
 | 
			
		||||
		void populateRecipesTable();
 | 
			
		||||
		void populateIngredientsList();
 | 
			
		||||
		void populateTagsList();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // OPENRECIPEDIALOG_H
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,7 +6,7 @@
 | 
			
		|||
   <rect>
 | 
			
		||||
    <x>0</x>
 | 
			
		||||
    <y>0</y>
 | 
			
		||||
    <width>640</width>
 | 
			
		||||
    <width>1000</width>
 | 
			
		||||
    <height>480</height>
 | 
			
		||||
   </rect>
 | 
			
		||||
  </property>
 | 
			
		||||
| 
						 | 
				
			
			@ -20,10 +20,80 @@
 | 
			
		|||
  <property name="modal">
 | 
			
		||||
   <bool>true</bool>
 | 
			
		||||
  </property>
 | 
			
		||||
  <layout class="QVBoxLayout" name="verticalLayout">
 | 
			
		||||
   <item alignment="Qt::AlignTop">
 | 
			
		||||
  <layout class="QHBoxLayout" name="horizontalLayout_6">
 | 
			
		||||
   <item alignment="Qt::AlignLeft|Qt::AlignTop">
 | 
			
		||||
    <widget class="QWidget" name="searchPanel" native="true">
 | 
			
		||||
     <layout class="QHBoxLayout" name="horizontalLayout">
 | 
			
		||||
     <layout class="QVBoxLayout" name="verticalLayout">
 | 
			
		||||
      <item alignment="Qt::AlignLeft">
 | 
			
		||||
       <widget class="QWidget" name="tagsSearchpanel" native="true">
 | 
			
		||||
        <layout class="QVBoxLayout" name="verticalLayout_3">
 | 
			
		||||
         <item>
 | 
			
		||||
          <widget class="QLabel" name="tagLabel">
 | 
			
		||||
           <property name="text">
 | 
			
		||||
            <string>Tag</string>
 | 
			
		||||
           </property>
 | 
			
		||||
          </widget>
 | 
			
		||||
         </item>
 | 
			
		||||
         <item>
 | 
			
		||||
          <widget class="QListView" name="tagsListView">
 | 
			
		||||
           <property name="sizePolicy">
 | 
			
		||||
            <sizepolicy hsizetype="Minimum" vsizetype="Expanding">
 | 
			
		||||
             <horstretch>0</horstretch>
 | 
			
		||||
             <verstretch>0</verstretch>
 | 
			
		||||
            </sizepolicy>
 | 
			
		||||
           </property>
 | 
			
		||||
           <property name="frameShape">
 | 
			
		||||
            <enum>QFrame::NoFrame</enum>
 | 
			
		||||
           </property>
 | 
			
		||||
           <property name="selectionMode">
 | 
			
		||||
            <enum>QAbstractItemView::ExtendedSelection</enum>
 | 
			
		||||
           </property>
 | 
			
		||||
           <property name="isWrapping" stdset="0">
 | 
			
		||||
            <bool>false</bool>
 | 
			
		||||
           </property>
 | 
			
		||||
           <property name="wordWrap">
 | 
			
		||||
            <bool>false</bool>
 | 
			
		||||
           </property>
 | 
			
		||||
          </widget>
 | 
			
		||||
         </item>
 | 
			
		||||
        </layout>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item alignment="Qt::AlignLeft">
 | 
			
		||||
       <widget class="QWidget" name="ingredientSearchPanel" native="true">
 | 
			
		||||
        <layout class="QVBoxLayout" name="verticalLayout_4">
 | 
			
		||||
         <item>
 | 
			
		||||
          <widget class="QLabel" name="ingredientLabel">
 | 
			
		||||
           <property name="text">
 | 
			
		||||
            <string>Ingredient</string>
 | 
			
		||||
           </property>
 | 
			
		||||
          </widget>
 | 
			
		||||
         </item>
 | 
			
		||||
         <item>
 | 
			
		||||
          <widget class="QListView" name="ingredientsListView">
 | 
			
		||||
           <property name="sizePolicy">
 | 
			
		||||
            <sizepolicy hsizetype="Minimum" vsizetype="Expanding">
 | 
			
		||||
             <horstretch>0</horstretch>
 | 
			
		||||
             <verstretch>0</verstretch>
 | 
			
		||||
            </sizepolicy>
 | 
			
		||||
           </property>
 | 
			
		||||
           <property name="frameShape">
 | 
			
		||||
            <enum>QFrame::NoFrame</enum>
 | 
			
		||||
           </property>
 | 
			
		||||
           <property name="selectionMode">
 | 
			
		||||
            <enum>QAbstractItemView::ExtendedSelection</enum>
 | 
			
		||||
           </property>
 | 
			
		||||
           <property name="isWrapping" stdset="0">
 | 
			
		||||
            <bool>false</bool>
 | 
			
		||||
           </property>
 | 
			
		||||
           <property name="wordWrap">
 | 
			
		||||
            <bool>true</bool>
 | 
			
		||||
           </property>
 | 
			
		||||
          </widget>
 | 
			
		||||
         </item>
 | 
			
		||||
        </layout>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item>
 | 
			
		||||
       <widget class="QWidget" name="nameSearchPanel" native="true">
 | 
			
		||||
        <layout class="QHBoxLayout" name="horizontalLayout_2">
 | 
			
		||||
| 
						 | 
				
			
			@ -40,38 +110,6 @@
 | 
			
		|||
        </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">
 | 
			
		||||
| 
						 | 
				
			
			@ -86,26 +124,26 @@
 | 
			
		|||
     </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 alignment="Qt::AlignLeft">
 | 
			
		||||
       <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="QTableView" name="recipeTableView">
 | 
			
		||||
        <property name="frameShape">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										41
									
								
								main.cpp
								
								
								
								
							
							
						
						
									
										41
									
								
								main.cpp
								
								
								
								
							| 
						 | 
				
			
			@ -4,22 +4,39 @@
 | 
			
		|||
 | 
			
		||||
#include "model/database/database.h"
 | 
			
		||||
#include "model/database/recipedatabase.h"
 | 
			
		||||
#include "utils/fileutils.h"
 | 
			
		||||
 | 
			
		||||
void test(RecipeDatabase *recipeDB);
 | 
			
		||||
 | 
			
		||||
int main(int argc, char *argv[])
 | 
			
		||||
{
 | 
			
		||||
	RecipeDatabase recipeDB("recipes");
 | 
			
		||||
	RecipeDatabase recipeDB(QString(FileUtils::appDataPath+"recipes.db").toStdString());
 | 
			
		||||
    QApplication a(argc, argv);
 | 
			
		||||
	MainWindow w(&recipeDB);
 | 
			
		||||
    w.show();
 | 
			
		||||
 | 
			
		||||
	//TESTING CODE
 | 
			
		||||
	test(&recipeDB);
 | 
			
		||||
 | 
			
		||||
	//END TESTING CODE.
 | 
			
		||||
 | 
			
		||||
	w.loadFromRecipe(recipeDB.retrieveRandomRecipe());
 | 
			
		||||
 | 
			
		||||
	a.exec();
 | 
			
		||||
	recipeDB.closeConnection();
 | 
			
		||||
	printf("Total queries: %lu\n", recipeDB.getQueryCount());
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void test(RecipeDatabase *recipeDB){
 | 
			
		||||
	vector<RecipeIngredient> ri;
 | 
			
		||||
	ri.push_back(RecipeIngredient("flour", "grains", 3.0f, UnitOfMeasure("cup", "cups", "c", UnitOfMeasure::VOLUME, 1.0), ""));
 | 
			
		||||
	ri.push_back(RecipeIngredient("baking powder", "additives", 1.0f, UnitOfMeasure("teaspoon", "teaspoons", "tsp", UnitOfMeasure::VOLUME, 1.0), ""));
 | 
			
		||||
 | 
			
		||||
	Recipe rec("Example",
 | 
			
		||||
			   ri,
 | 
			
		||||
			   Instruction("<b>BOLD</b><i>iTaLiCs</i>"),
 | 
			
		||||
			   Instruction("Placeholder Text"),
 | 
			
		||||
			   QImage(),
 | 
			
		||||
			   vector<RecipeTag>({RecipeTag("testing"),
 | 
			
		||||
								  RecipeTag("fake")}),
 | 
			
		||||
| 
						 | 
				
			
			@ -28,13 +45,21 @@ int main(int argc, char *argv[])
 | 
			
		|||
			   QTime(0, 25),
 | 
			
		||||
			   10.0f);
 | 
			
		||||
 | 
			
		||||
	bool success = recipeDB.storeRecipe(rec);
 | 
			
		||||
	bool success = recipeDB->storeRecipe(rec);
 | 
			
		||||
	printf("Storage successful: %d\n", success);
 | 
			
		||||
 | 
			
		||||
	//recipeDB.selectFrom("recipe", "recipeId, name", "").printData();
 | 
			
		||||
	w.loadFromRecipe(recipeDB.retrieveRandomRecipe());
 | 
			
		||||
	vector<string> foodGroups = recipeDB->retrieveAllFoodGroups();
 | 
			
		||||
	printf("Food Groups:\n");
 | 
			
		||||
	for (string s : foodGroups){
 | 
			
		||||
		printf("\t%s\n", s.c_str());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	//Get food groups from recipe.
 | 
			
		||||
	Recipe r = recipeDB->retrieveRecipe("Pannenkoeken");
 | 
			
		||||
	vector<string> foodGroupsR = r.getFoodGroups();
 | 
			
		||||
	printf("Pannenkoeken Food Groups:\n");
 | 
			
		||||
	for (string s : foodGroupsR){
 | 
			
		||||
		printf("\t%s\n", s.c_str());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	a.exec();
 | 
			
		||||
	recipeDB.closeConnection();
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,7 @@
 | 
			
		|||
 | 
			
		||||
Database::Database(string filename){
 | 
			
		||||
    this->filename = filename;
 | 
			
		||||
	this->queryCount = 0;
 | 
			
		||||
    openConnection();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -22,6 +23,7 @@ ResultTable Database::executeSQL(string statement){
 | 
			
		|||
	t.extractData(stmt);
 | 
			
		||||
 | 
			
		||||
	this->returnCode = sqlite3_finalize(stmt);
 | 
			
		||||
	this->queryCount++;
 | 
			
		||||
 | 
			
		||||
	return t;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -99,6 +101,10 @@ bool Database::tableExists(string tableName){
 | 
			
		|||
	return !t.isEmpty();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int Database::getLastInsertedRowId(){
 | 
			
		||||
int Database::getLastInsertedRowId() const{
 | 
			
		||||
	return sqlite3_last_insert_rowid(this->db);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned long Database::getQueryCount() const{
 | 
			
		||||
	return this->queryCount;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,7 +29,9 @@ public:
 | 
			
		|||
	bool deleteFrom(string tableName, string conditions);
 | 
			
		||||
 | 
			
		||||
	bool tableExists(string tableName);
 | 
			
		||||
	int getLastInsertedRowId();
 | 
			
		||||
	int getLastInsertedRowId() const;
 | 
			
		||||
 | 
			
		||||
	unsigned long getQueryCount() const;
 | 
			
		||||
 | 
			
		||||
	void closeConnection();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -45,6 +47,9 @@ private:
 | 
			
		|||
    string sql;
 | 
			
		||||
    char* errorMsg;
 | 
			
		||||
 | 
			
		||||
	//Data tracking.
 | 
			
		||||
	unsigned long queryCount;
 | 
			
		||||
 | 
			
		||||
    void openConnection();
 | 
			
		||||
	std::string combineVector(std::vector<std::string> strings, std::string mid);
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -88,7 +88,7 @@ int RecipeDatabase::storeIngredient(Ingredient ingredient){
 | 
			
		|||
			return -1;
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		return std::stoi(t.valueAt(0, 0));
 | 
			
		||||
		return std::stoi(t.at(0, 0));
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -162,12 +162,21 @@ Recipe RecipeDatabase::retrieveRandomRecipe(){
 | 
			
		|||
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)));
 | 
			
		||||
	for (TableRow row : t.rows()){
 | 
			
		||||
		recipes.push_back(this->retrieveRecipe(row.at(0)));
 | 
			
		||||
	}
 | 
			
		||||
	return recipes;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
vector<string> RecipeDatabase::retrieveAllFoodGroups(){
 | 
			
		||||
	ResultTable t = this->executeSQL("SELECT DISTINCT foodGroup FROM ingredient ORDER BY foodGroup;");
 | 
			
		||||
	vector<string> foodGroups;
 | 
			
		||||
	for (TableRow row : t.rows()){
 | 
			
		||||
		foodGroups.push_back(row.at(0));
 | 
			
		||||
	}
 | 
			
		||||
	return foodGroups;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
vector<RecipeIngredient> RecipeDatabase::retrieveRecipeIngredients(int recipeId){
 | 
			
		||||
	ResultTable t = this->executeSQL("SELECT ingredient.name, ingredient.foodGroup, "//0, 1
 | 
			
		||||
									 "recipeIngredient.quantity, recipeIngredient.unitName, recipeIngredient.comment,"//2, 3, 4
 | 
			
		||||
| 
						 | 
				
			
			@ -179,33 +188,33 @@ vector<RecipeIngredient> RecipeDatabase::retrieveRecipeIngredients(int recipeId)
 | 
			
		|||
									 "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, 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));
 | 
			
		||||
	for (TableRow row : t.rows()){
 | 
			
		||||
		RecipeIngredient r(row.at(0),
 | 
			
		||||
						   row.at(1),
 | 
			
		||||
						   std::stof(row.at(2)),
 | 
			
		||||
						   UnitOfMeasure(row.at(5), row.at(6), row.at(7), std::stoi(row.at(8)), std::stod(row.at(9))),
 | 
			
		||||
						   row.at(4));
 | 
			
		||||
		ings.push_back(r);
 | 
			
		||||
	}
 | 
			
		||||
	return ings;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
vector<Ingredient> RecipeDatabase::retrieveAllIngredients(){
 | 
			
		||||
	ResultTable t = this->selectFrom("ingredient", "*", "ORDER BY name");
 | 
			
		||||
	ResultTable t = this->selectFrom("ingredient", "name, foodGroup", "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));
 | 
			
		||||
	for (TableRow row : t.rows()){
 | 
			
		||||
		Ingredient i(row.at(0), row.at(1));
 | 
			
		||||
		ings.push_back(i);
 | 
			
		||||
	}
 | 
			
		||||
	return ings;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
vector<UnitOfMeasure> RecipeDatabase::retrieveAllUnitsOfMeasure(){
 | 
			
		||||
	ResultTable t = this->selectFrom("unitOfMeasure", "*", "ORDER BY name");
 | 
			
		||||
	ResultTable t = this->selectFrom("unitOfMeasure", "name, plural, abbreviation, type, metricCoefficient", "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)));
 | 
			
		||||
		for (TableRow row : t.rows()){
 | 
			
		||||
			UnitOfMeasure u(row.at(0), row.at(1), row.at(2), std::stoi(row.at(3)), std::stod(row.at(4)));
 | 
			
		||||
			units.push_back(u);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -213,11 +222,11 @@ vector<UnitOfMeasure> RecipeDatabase::retrieveAllUnitsOfMeasure(){
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
vector<RecipeTag> RecipeDatabase::retrieveTags(int recipeId){
 | 
			
		||||
	ResultTable t = this->selectFrom("recipeTag", "tagName", "WHERE recipeId="+std::to_string(recipeId));
 | 
			
		||||
	ResultTable t = this->selectFrom("recipeTag", "tagName", "WHERE recipeId="+std::to_string(recipeId)+" ORDER BY tagName");
 | 
			
		||||
	vector<RecipeTag> tags;
 | 
			
		||||
	if (!t.isEmpty()){
 | 
			
		||||
		for (unsigned int row = 0; row < t.rowCount(); row++){
 | 
			
		||||
			RecipeTag tag(t.valueAt(row, 0));
 | 
			
		||||
		for (TableRow row : t.rows()){
 | 
			
		||||
			RecipeTag tag(row.at(0));
 | 
			
		||||
			tags.push_back(tag);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -225,11 +234,11 @@ vector<RecipeTag> RecipeDatabase::retrieveTags(int recipeId){
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
vector<RecipeTag> RecipeDatabase::retrieveAllTags(){
 | 
			
		||||
	ResultTable t = this->selectFrom("recipeTag", "tagName", "ORDER BY tagName");
 | 
			
		||||
	ResultTable t = this->executeSQL("SELECT DISTINCT tagName FROM recipeTag ORDER BY tagName;");
 | 
			
		||||
	vector<RecipeTag> tags;
 | 
			
		||||
	if (!t.isEmpty()){
 | 
			
		||||
		for (unsigned int row = 0; row < t.rowCount(); row++){
 | 
			
		||||
			RecipeTag tag(t.valueAt(row, 0));
 | 
			
		||||
		for (TableRow row : t.rows()){
 | 
			
		||||
			RecipeTag tag(row.at(0));
 | 
			
		||||
			tags.push_back(tag);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -241,7 +250,7 @@ bool RecipeDatabase::deleteRecipe(string name){
 | 
			
		|||
	if (t.rowCount() != 1){
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	string recipeId = t.valueAt(0, 0);
 | 
			
		||||
	string recipeId = t.at(0, 0);
 | 
			
		||||
	return this->deleteRecipe(std::stoi(recipeId));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -255,6 +264,10 @@ bool RecipeDatabase::deleteRecipe(int recipeId){
 | 
			
		|||
	bool tagsDeleted = this->deleteFrom("recipeTag", "WHERE recipeId="+idString);
 | 
			
		||||
	bool recipeIngredientDeleted = this->deleteFrom("recipeIngredient", "WHERE recipeId="+idString);
 | 
			
		||||
	bool recipeDeleted = this->deleteFrom("recipe", "WHERE recipeId="+idString);
 | 
			
		||||
	bool instructionDeleted = FileUtils::deleteInstruction(recipeId);
 | 
			
		||||
	bool imageDeleted = FileUtils::deleteImage(recipeId);
 | 
			
		||||
	Q_UNUSED(instructionDeleted);
 | 
			
		||||
	Q_UNUSED(imageDeleted);
 | 
			
		||||
	if (tagsDeleted && recipeIngredientDeleted && recipeDeleted){
 | 
			
		||||
		this->executeSQL("COMMIT;");
 | 
			
		||||
		return true;
 | 
			
		||||
| 
						 | 
				
			
			@ -332,14 +345,15 @@ void RecipeDatabase::ensureTablesExist(){
 | 
			
		|||
	this->executeSQL("COMMIT;");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Recipe RecipeDatabase::readFromResultTable(ResultTable t, int row){
 | 
			
		||||
Recipe RecipeDatabase::readFromResultTable(ResultTable t, int tRow){
 | 
			
		||||
	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)));
 | 
			
		||||
	TableRow row = t.rows().at(tRow);
 | 
			
		||||
	int id = std::stoi(row.at(0));
 | 
			
		||||
	r.setName(row.at(1));
 | 
			
		||||
	r.setCreatedDate(QDate::fromString(QString::fromStdString(row.at(2))));
 | 
			
		||||
	r.setPrepTime(QTime::fromString(QString::fromStdString(row.at(3))));
 | 
			
		||||
	r.setCookTime(QTime::fromString(QString::fromStdString(row.at(4))));
 | 
			
		||||
	r.setServings(std::stof(row.at(5)));
 | 
			
		||||
	r.setInstruction(FileUtils::loadInstruction(id));
 | 
			
		||||
	r.setImage(FileUtils::loadImage(id));
 | 
			
		||||
	r.setIngredients(this->retrieveRecipeIngredients(id));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
#ifndef RECIPEDATABASE_H
 | 
			
		||||
#define RECIPEDATABASE_H
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <map>
 | 
			
		||||
 | 
			
		||||
#include "database.h"
 | 
			
		||||
#include "model/recipe/recipe.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -34,6 +34,7 @@ class RecipeDatabase : public Database
 | 
			
		|||
		Recipe retrieveRecipe(string name);
 | 
			
		||||
		Recipe retrieveRandomRecipe();
 | 
			
		||||
		vector<Recipe> retrieveAllRecipes();
 | 
			
		||||
		vector<string> retrieveAllFoodGroups();
 | 
			
		||||
		vector<RecipeIngredient> retrieveRecipeIngredients(int recipeId);
 | 
			
		||||
		vector<Ingredient> retrieveAllIngredients();
 | 
			
		||||
		vector<UnitOfMeasure> retrieveAllUnitsOfMeasure();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -47,7 +47,7 @@ bool ResultTable::isEmpty(){
 | 
			
		|||
	return this->values.empty();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
string ResultTable::valueAt(unsigned int row, unsigned int col){
 | 
			
		||||
string ResultTable::at(unsigned int row, unsigned int col){
 | 
			
		||||
	if (isIndexValid(row, col)){
 | 
			
		||||
		return this->values[row][col];
 | 
			
		||||
	} else {
 | 
			
		||||
| 
						 | 
				
			
			@ -78,6 +78,10 @@ unsigned int ResultTable::rowCount(){
 | 
			
		|||
	return this->values.size();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
vector<vector<string> > ResultTable::rows(){
 | 
			
		||||
	return this->values;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
string ResultTable::convertToString(sqlite3_value *val){
 | 
			
		||||
	const unsigned char* raw_text = sqlite3_value_text(val);
 | 
			
		||||
	if (raw_text == 0){
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,6 +12,8 @@ using namespace std;
 | 
			
		|||
 * @brief The ResultTable class is an object that contains the results of an SQL query, in string form.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
typedef vector<string> TableRow;
 | 
			
		||||
 | 
			
		||||
class ResultTable
 | 
			
		||||
{
 | 
			
		||||
	public:
 | 
			
		||||
| 
						 | 
				
			
			@ -28,11 +30,12 @@ class ResultTable
 | 
			
		|||
		void printData();
 | 
			
		||||
 | 
			
		||||
		bool isEmpty();
 | 
			
		||||
		string valueAt(unsigned int row, unsigned int col);
 | 
			
		||||
		string at(unsigned int row, unsigned int col);
 | 
			
		||||
		int getReturnCode();
 | 
			
		||||
		string getOriginalQuery();
 | 
			
		||||
		unsigned int columnCount();
 | 
			
		||||
		unsigned int rowCount();
 | 
			
		||||
		vector<vector<string>> rows();
 | 
			
		||||
	private:
 | 
			
		||||
		vector<vector<string>> values;
 | 
			
		||||
		int queryCode;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,5 +23,9 @@ void Ingredient::setName(string newName){
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void Ingredient::setFoodGroup(string newFoodGroup){
 | 
			
		||||
    this->foodGroup = newFoodGroup;
 | 
			
		||||
	this->foodGroup = newFoodGroup;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
string Ingredient::toString(){
 | 
			
		||||
	return this->getName();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,6 +23,8 @@ public:
 | 
			
		|||
    //Setters
 | 
			
		||||
    void setName(string newName);
 | 
			
		||||
    void setFoodGroup(string newFoodGroup);
 | 
			
		||||
 | 
			
		||||
	string toString();
 | 
			
		||||
protected:
 | 
			
		||||
    string name;
 | 
			
		||||
    string foodGroup;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
#include "model/recipe/ingredients/ingredientlistmodel.h"
 | 
			
		||||
 | 
			
		||||
IngredientListModel::IngredientListModel(){
 | 
			
		||||
    this->ingredients = vector<RecipeIngredient>();
 | 
			
		||||
	this->ingredients = vector<Ingredient>();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int IngredientListModel::rowCount(const QModelIndex &parent) const{
 | 
			
		||||
| 
						 | 
				
			
			@ -10,7 +10,7 @@ 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];
 | 
			
		||||
	Ingredient i = this->ingredients[row];
 | 
			
		||||
 | 
			
		||||
	string displayStr = i.toString();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -22,14 +22,14 @@ QVariant IngredientListModel::data(const QModelIndex &index, int role) const{
 | 
			
		|||
    return QVariant();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void IngredientListModel::setIngredients(vector<RecipeIngredient> ingredients){
 | 
			
		||||
void IngredientListModel::setIngredients(vector<Ingredient> ingredients){
 | 
			
		||||
    this->ingredients = ingredients;
 | 
			
		||||
    QModelIndex index = createIndex(0, 0);
 | 
			
		||||
    QModelIndex bottomIndex = createIndex(ingredients.size()-1, 0);
 | 
			
		||||
	emit dataChanged(index, bottomIndex);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool IngredientListModel::addIngredient(RecipeIngredient ri){
 | 
			
		||||
bool IngredientListModel::addIngredient(Ingredient 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())){
 | 
			
		||||
| 
						 | 
				
			
			@ -48,6 +48,6 @@ void IngredientListModel::deleteIngredient(int index){
 | 
			
		|||
	emit dataChanged(createIndex(0, 0), createIndex(this->ingredients.size()-1, 0));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
vector<RecipeIngredient> IngredientListModel::getIngredients(){
 | 
			
		||||
vector<Ingredient> IngredientListModel::getIngredients(){
 | 
			
		||||
	return this->ingredients;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,13 +16,13 @@ public:
 | 
			
		|||
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
 | 
			
		||||
 | 
			
		||||
    //Custom methods to handle ingredient data.
 | 
			
		||||
    void setIngredients(vector<RecipeIngredient> ingredients);
 | 
			
		||||
	bool addIngredient(RecipeIngredient ri);
 | 
			
		||||
	void setIngredients(vector<Ingredient> ingredients);
 | 
			
		||||
	bool addIngredient(Ingredient ri);
 | 
			
		||||
	void deleteIngredient(int index);
 | 
			
		||||
	vector<RecipeIngredient> getIngredients();
 | 
			
		||||
	vector<Ingredient> getIngredients();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    vector<RecipeIngredient> ingredients;
 | 
			
		||||
	vector<Ingredient> ingredients;
 | 
			
		||||
 | 
			
		||||
	//Helper for printing.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,6 +14,10 @@ RecipeIngredient::RecipeIngredient(Ingredient i, float quantity, UnitOfMeasure u
 | 
			
		|||
	setComment(comment);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RecipeIngredient::RecipeIngredient(Ingredient &i) : RecipeIngredient(i, 0.0f, UnitOfMeasure("bleh"), "Fuck"){
 | 
			
		||||
	//Constructs recipe ingredient from ingredient which is a hidden recipe ingredient.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RecipeIngredient::RecipeIngredient(){
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,6 +21,7 @@ public:
 | 
			
		|||
	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, string comment);
 | 
			
		||||
	RecipeIngredient(Ingredient &i);
 | 
			
		||||
	RecipeIngredient();
 | 
			
		||||
 | 
			
		||||
    //Getters
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,53 @@
 | 
			
		|||
#include "recipeingredientlistmodel.h"
 | 
			
		||||
 | 
			
		||||
RecipeIngredientListModel::RecipeIngredientListModel(){
 | 
			
		||||
	this->ingredients = vector<RecipeIngredient>();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int RecipeIngredientListModel::rowCount(const QModelIndex &parent) const{
 | 
			
		||||
	return this->ingredients.size();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QVariant RecipeIngredientListModel::data(const QModelIndex &index, int role) const{
 | 
			
		||||
	int row = index.row();
 | 
			
		||||
	RecipeIngredient i = this->ingredients[row];
 | 
			
		||||
 | 
			
		||||
	string displayStr = i.toString();
 | 
			
		||||
 | 
			
		||||
	switch(role){
 | 
			
		||||
	case Qt::DisplayRole:
 | 
			
		||||
		return QString::fromStdString(displayStr);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return QVariant();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RecipeIngredientListModel::setIngredients(vector<RecipeIngredient> ingredients){
 | 
			
		||||
	this->ingredients = ingredients;
 | 
			
		||||
	QModelIndex index = createIndex(0, 0);
 | 
			
		||||
	QModelIndex bottomIndex = createIndex(ingredients.size()-1, 0);
 | 
			
		||||
	emit dataChanged(index, bottomIndex);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RecipeIngredientListModel::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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RecipeIngredientListModel::deleteIngredient(int index){
 | 
			
		||||
	this->ingredients.erase(this->ingredients.begin() + index);
 | 
			
		||||
	emit dataChanged(createIndex(0, 0), createIndex(this->ingredients.size()-1, 0));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
vector<RecipeIngredient> RecipeIngredientListModel::getIngredients(){
 | 
			
		||||
	return this->ingredients;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,28 @@
 | 
			
		|||
#ifndef RECIPEINGREDIENTLISTMODEL_H
 | 
			
		||||
#define RECIPEINGREDIENTLISTMODEL_H
 | 
			
		||||
 | 
			
		||||
#include <QAbstractListModel>
 | 
			
		||||
 | 
			
		||||
#include "model/recipe/ingredients/recipeingredient.h"
 | 
			
		||||
 | 
			
		||||
class RecipeIngredientListModel : public QAbstractListModel
 | 
			
		||||
{
 | 
			
		||||
	public:
 | 
			
		||||
		RecipeIngredientListModel();
 | 
			
		||||
 | 
			
		||||
		//Overridden methods.
 | 
			
		||||
		int rowCount(const QModelIndex &parent = QModelIndex()) const override;
 | 
			
		||||
		QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
 | 
			
		||||
 | 
			
		||||
		//Custom methods to handle ingredient data.
 | 
			
		||||
		void setIngredients(vector<RecipeIngredient> ingredients);
 | 
			
		||||
		bool addIngredient(RecipeIngredient ri);
 | 
			
		||||
		void deleteIngredient(int index);
 | 
			
		||||
		vector<RecipeIngredient> getIngredients();
 | 
			
		||||
 | 
			
		||||
	private:
 | 
			
		||||
		vector<RecipeIngredient> ingredients;
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // RECIPEINGREDIENTLISTMODEL_H
 | 
			
		||||
| 
						 | 
				
			
			@ -21,7 +21,17 @@ string Recipe::getName() const{
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
vector<RecipeIngredient> Recipe::getIngredients() const{
 | 
			
		||||
    return this->ingredients;
 | 
			
		||||
	return this->ingredients;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
vector<string> Recipe::getFoodGroups() const{
 | 
			
		||||
	vector<string> foodGroups;
 | 
			
		||||
	for (RecipeIngredient ri : this->ingredients){
 | 
			
		||||
		if (find(foodGroups.begin(), foodGroups.end(), ri.getFoodGroup()) == foodGroups.end()){
 | 
			
		||||
			foodGroups.push_back(ri.getFoodGroup());
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return foodGroups;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Instruction Recipe::getInstruction() const{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,6 +6,7 @@
 | 
			
		|||
#include <QDate>
 | 
			
		||||
#include <QTime>
 | 
			
		||||
#include <QImage>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
 | 
			
		||||
#include "model/recipe/ingredients/recipeingredient.h"
 | 
			
		||||
#include "model/recipe/instruction.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -38,6 +39,7 @@ public:
 | 
			
		|||
    //Getters
 | 
			
		||||
    string getName() const;
 | 
			
		||||
    vector<RecipeIngredient> getIngredients() const;
 | 
			
		||||
	vector<string> getFoodGroups() const;
 | 
			
		||||
    Instruction getInstruction() const;
 | 
			
		||||
    QImage getImage() const;
 | 
			
		||||
    vector<RecipeTag> getTags() const;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -72,8 +72,8 @@ void RecipeTableModel::setRecipes(vector<Recipe> recipes){
 | 
			
		|||
	endInsertRows();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Recipe RecipeTableModel::getRecipeAt(int index){
 | 
			
		||||
	if (index < 0 || index >= this->recipes.size()){
 | 
			
		||||
Recipe RecipeTableModel::getRecipeAt(unsigned int index){
 | 
			
		||||
	if (index >= this->recipes.size()){
 | 
			
		||||
		return Recipe();
 | 
			
		||||
	}
 | 
			
		||||
	return this->recipes[index];
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,7 +20,7 @@ class RecipeTableModel : public QAbstractTableModel
 | 
			
		|||
 | 
			
		||||
		//Normal methods.
 | 
			
		||||
		void setRecipes(vector<Recipe> recipes);
 | 
			
		||||
		Recipe getRecipeAt(int index);
 | 
			
		||||
		Recipe getRecipeAt(unsigned int index);
 | 
			
		||||
		void clear();
 | 
			
		||||
	private:
 | 
			
		||||
		vector<Recipe> recipes;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -61,4 +61,18 @@ QImage loadImage(int nr){
 | 
			
		|||
	return img;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool deleteInstruction(int nr){
 | 
			
		||||
	ensureAppDataFolderExists();
 | 
			
		||||
	QString filename = appDataPath + QString::fromStdString(std::to_string(nr)) +".html";
 | 
			
		||||
	QFile file(filename);
 | 
			
		||||
	return file.remove();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool deleteImage(int nr){
 | 
			
		||||
	ensureAppDataFolderExists();
 | 
			
		||||
	QString filename = appDataPath + QString::fromStdString(std::to_string(nr)) +".png";
 | 
			
		||||
	QFile file(filename);
 | 
			
		||||
	return file.remove();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,6 +6,7 @@
 | 
			
		|||
#include <QDir>
 | 
			
		||||
#include <QTextStream>
 | 
			
		||||
#include <QImage>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
#include "model/recipe/instruction.h"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -19,9 +20,13 @@ namespace FileUtils{
 | 
			
		|||
 | 
			
		||||
	Instruction loadInstruction(int nr);
 | 
			
		||||
 | 
			
		||||
	bool deleteInstruction(int nr);
 | 
			
		||||
 | 
			
		||||
	bool saveImage(int nr, QImage image);
 | 
			
		||||
 | 
			
		||||
	QImage loadImage(int nr);
 | 
			
		||||
 | 
			
		||||
	bool deleteImage(int nr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // FILEUTILS_H
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,4 +29,13 @@ std::string toString(float val){
 | 
			
		|||
	return s;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void printVector(std::vector<std::string> &vect){
 | 
			
		||||
	std::printf("Vector of %ld elements:\n", vect.size());
 | 
			
		||||
	int c = 0;
 | 
			
		||||
	for (std::string s : vect){
 | 
			
		||||
		std::printf("\t[%d] = %s\n", c, s.c_str());
 | 
			
		||||
		c++;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,7 @@
 | 
			
		|||
#define STRINGUTILS_H
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <cmath>
 | 
			
		||||
 | 
			
		||||
namespace StringUtils{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue