More security and less unexpected behaviour. #8
|
@ -195,6 +195,7 @@ void NewRecipeDialog::on_newUnitButton_clicked(){
|
|||
QMessageBox::critical(this, "Error", "Unable to store new unit.");
|
||||
} else {
|
||||
this->populateUnitsBox();
|
||||
ui->unitComboBox->setCurrentText(QString::fromStdString(u.getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
33
main.cpp
33
main.cpp
|
@ -6,6 +6,8 @@
|
|||
#include "model/database/recipedatabase.h"
|
||||
#include "utils/fileutils.h"
|
||||
|
||||
void test(RecipeDatabase *recipeDB);
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
RecipeDatabase recipeDB(QString(FileUtils::appDataPath+"recipes.db").toStdString());
|
||||
|
@ -14,6 +16,18 @@ int main(int argc, char *argv[])
|
|||
w.show();
|
||||
|
||||
//TESTING CODE
|
||||
test(&recipeDB);
|
||||
|
||||
//END TESTING CODE.
|
||||
|
||||
w.loadFromRecipe(recipeDB.retrieveRandomRecipe());
|
||||
|
||||
a.exec();
|
||||
recipeDB.closeConnection();
|
||||
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), ""));
|
||||
|
@ -29,12 +43,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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -228,8 +237,8 @@ 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));
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -257,6 +266,8 @@ bool RecipeDatabase::deleteRecipe(int recipeId){
|
|||
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;
|
||||
|
@ -334,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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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