From cb3be5e1e2ae6abab3fbc006480293d5ca9f1949 Mon Sep 17 00:00:00 2001 From: andrewlalis Date: Sat, 10 Mar 2018 12:36:14 +0100 Subject: [PATCH] Added tags area to dialog, made it look better, and added tag model. --- RecipeDB.pro | 6 +- gui/newrecipedialog.cpp | 43 ++ gui/newrecipedialog.h | 13 + gui/newrecipedialog.ui | 467 +++++++++++++----- main.cpp | 17 +- model/database/recipedatabase.cpp | 25 + model/database/recipedatabase.h | 2 + .../recipe/ingredients/ingredientlistmodel.h | 1 + model/recipe/tags/recipetag.cpp | 2 +- model/recipe/tags/recipetag.h | 2 +- model/recipe/tags/taglistmodel.cpp | 44 ++ model/recipe/tags/taglistmodel.h | 24 + 12 files changed, 516 insertions(+), 130 deletions(-) create mode 100644 model/recipe/tags/taglistmodel.cpp create mode 100644 model/recipe/tags/taglistmodel.h diff --git a/RecipeDB.pro b/RecipeDB.pro index 0153b2b..0071690 100644 --- a/RecipeDB.pro +++ b/RecipeDB.pro @@ -26,7 +26,8 @@ SOURCES += model/recipe/instruction.cpp \ model/database/resulttable.cpp \ model/database/recipedatabase.cpp \ utils/fileutils.cpp \ - gui/newrecipedialog.cpp + gui/newrecipedialog.cpp \ + model/recipe/tags/taglistmodel.cpp HEADERS += model/recipe/instruction.h \ model/recipe/recipe.h \ @@ -42,7 +43,8 @@ HEADERS += model/recipe/instruction.h \ model/database/resulttable.h \ model/database/recipedatabase.h \ utils/fileutils.h \ - gui/newrecipedialog.h + gui/newrecipedialog.h \ + model/recipe/tags/taglistmodel.h LIBS += -ldl \ diff --git a/gui/newrecipedialog.cpp b/gui/newrecipedialog.cpp index 7467d30..7405d09 100644 --- a/gui/newrecipedialog.cpp +++ b/gui/newrecipedialog.cpp @@ -6,7 +6,10 @@ NewRecipeDialog::NewRecipeDialog(QWidget *parent) : ui(new Ui::NewRecipeDialog){ ui->setupUi(this); + setModal(true); + ui->ingredientsListView->setModel(&this->ingredientListModel); + ui->tagsListView->setModel(&this->tagsListModel); } NewRecipeDialog::NewRecipeDialog(RecipeDatabase *db, QWidget *parent) : NewRecipeDialog(parent){ @@ -15,12 +18,29 @@ NewRecipeDialog::NewRecipeDialog(RecipeDatabase *db, QWidget *parent) : NewRecip this->populateIngredientsBox(); this->populateUnitsBox(); + this->populateTagsBox(); } NewRecipeDialog::~NewRecipeDialog(){ delete ui; } +Recipe NewRecipeDialog::getRecipe(){ + Recipe r(ui->recipeNameEdit->text().toStdString(), + this->ingredientListModel.getIngredients(), + ui->instructionsTextEdit->toHtml().toStdString(), + QImage(),//Image + this->tagsListModel.getTags(),//Tags + QDate::currentDate(), + ui->prepTimeEdit->time(), + ui->cookTimeEdit->time(), + (float)ui->servingsSpinBox->value()); +} + +bool NewRecipeDialog::isAccepted() const{ + return this->accepted; +} + void NewRecipeDialog::populateIngredientsBox(){ this->ingredients = this->recipeDB->retrieveAllIngredients(); ui->ingredientNameBox->clear(); @@ -39,6 +59,15 @@ void NewRecipeDialog::populateUnitsBox(){ } } +void NewRecipeDialog::populateTagsBox(){ + this->tags = this->recipeDB->retrieveAllTags(); + ui->tagsComboBox->clear(); + for (unsigned int i = 0; i < this->tags.size(); i++){ + QString s = QString::fromStdString(this->tags[i].getValue()); + ui->tagsComboBox->insertItem(i, s); + } +} + void NewRecipeDialog::on_addIngredientButton_clicked(){ //Construct a recipe ingredient from the supplied data. Ingredient i = this->ingredients[ui->ingredientNameBox->currentIndex()]; @@ -58,3 +87,17 @@ void NewRecipeDialog::on_boldButton_clicked(){ ui->instructionsTextEdit->setFontWeight(QFont::Normal); } } + +void NewRecipeDialog::on_buttonBox_accepted(){ + this->accepted = true; + this->close(); +} + +void NewRecipeDialog::on_buttonBox_rejected(){ + this->close(); +} + +void NewRecipeDialog::on_addTagButton_clicked(){ + //Add a tag to the list of those prepared to be added. + this->tagsListModel.addTag(this->tags[ui->tagsComboBox->currentIndex()]); +} diff --git a/gui/newrecipedialog.h b/gui/newrecipedialog.h index 51322ed..47cd848 100644 --- a/gui/newrecipedialog.h +++ b/gui/newrecipedialog.h @@ -6,6 +6,7 @@ #include "model/database/recipedatabase.h" #include "model/recipe/ingredients/ingredientlistmodel.h" +#include "model/recipe/tags/taglistmodel.h" namespace Ui { class NewRecipeDialog; @@ -20,6 +21,8 @@ class NewRecipeDialog : public QDialog NewRecipeDialog(RecipeDatabase *db, QWidget *parent = 0); ~NewRecipeDialog(); + Recipe getRecipe(); + bool isAccepted() const; private slots: void on_addIngredientButton_clicked(); @@ -27,16 +30,26 @@ class NewRecipeDialog : public QDialog void on_boldButton_clicked(); + void on_buttonBox_accepted(); + + void on_buttonBox_rejected(); + + void on_addTagButton_clicked(); + private: Ui::NewRecipeDialog *ui; RecipeDatabase *recipeDB; vector ingredients; vector units; + vector tags; IngredientListModel ingredientListModel; + TagListModel tagsListModel; + bool accepted = false; //Helper functions to fill fields. void populateIngredientsBox(); void populateUnitsBox(); + void populateTagsBox(); }; #endif // NEWRECIPEDIALOG_H diff --git a/gui/newrecipedialog.ui b/gui/newrecipedialog.ui index 91c523e..78e7f57 100644 --- a/gui/newrecipedialog.ui +++ b/gui/newrecipedialog.ui @@ -23,149 +23,309 @@ New Recipe + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + - - + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + - - - - Noto Sans CJK KR - 14 - 50 - false - false - + + + Qt::LeftToRight - - Edit Recipe + + background-color: rgb(234, 235, 255); - - Qt::AlignCenter - - - - - - - Qt::AlignCenter - - - Recipe Name - - - - - - - - - - - - + - - - Prep Time - - - Qt::AlignCenter - + + + + + + + Noto Sans CJK KR + 14 + 50 + false + false + + + + Edit Recipe + + + Qt::AlignCenter + + + + + + + + PreferAntialias + + + + Qt::AlignCenter + + + Recipe Name + + + + - - - - 0 - 0 - 0 - 1999 - 12 - 27 - - - - QDateTimeEdit::HourSection - - - hh:mm:ss - - - Qt::UTC - - - - + + + + + + + + + Prep Time + + + Qt::AlignCenter + + + + + + + + 0 + 0 + 0 + 1999 + 12 + 27 + + + + QDateTimeEdit::HourSection + + + hh:mm:ss + + + Qt::UTC + + + + + + + + + + + + + + + + Cook Time + + + Qt::AlignCenter + + + + + + + QDateTimeEdit::HourSection + + + hh:mm:ss + + + Qt::UTC + + + + + + + + + + + + + + + + Servings + + + Qt::AlignCenter + + + + + + + 1 + + + 1.000000000000000 + + + + + + + - - - - - + + + + background-color: rgb(222, 226, 255); + + + + - Cook Time + Tags Qt::AlignCenter - - - - QDateTimeEdit::HourSection - - - hh:mm:ss - - - Qt::UTC - - - - - - - - - - - - - - - - Servings - - - Qt::AlignCenter - + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + New + + + + - - - 1 + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Add + + + + + + + Delete + + + + + + + + + + false - - 1.000000000000000 + + background-color: rgb(255, 255, 255); + + + QFrame::NoFrame @@ -183,10 +343,28 @@ 0 + + background-color: rgb(245, 245, 255); + + + 0 + QLayout::SetMaximumSize + + 0 + + + 0 + + + 0 + + + 0 + @@ -200,14 +378,20 @@ - + + + background-color: rgb(255, 255, 255); + + + QFrame::NoFrame + 100 - + @@ -239,7 +423,7 @@ - 0 + 2 0 @@ -286,7 +470,7 @@ - 0 + 2 0 @@ -368,10 +552,35 @@ - - - Add - + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Add + + + + + + + Delete + + + + @@ -456,6 +665,16 @@ + + + + Qt::LeftToRight + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + diff --git a/main.cpp b/main.cpp index 5d09adf..23f8db2 100644 --- a/main.cpp +++ b/main.cpp @@ -18,9 +18,18 @@ int main(int argc, char *argv[]) //TESTING CODE vector 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), "")); + ri.push_back(RecipeIngredient("baking powder", "additives", 1.0f, UnitOfMeasure("teaspoon", "teaspoons", "tsp", UnitOfMeasure::VOLUME, 1.0), "")); - Recipe rec("Example", ri, Instruction("BOLDiTaLiCs"), QImage(), vector(), QDate::currentDate(), QTime(0, 30), QTime(0, 25), 10.0f); + Recipe rec("Example", + ri, + Instruction("BOLDiTaLiCs"), + QImage(), + vector({RecipeTag("testing"), + RecipeTag("fake")}), + QDate::currentDate(), + QTime(0, 30), + QTime(0, 25), + 10.0f); bool success = recipeDB.storeRecipe(rec); printf("Storage successful: %d\n", success); @@ -38,5 +47,9 @@ int main(int argc, char *argv[]) d.show(); d.exec(); + if (d.isAccepted()){ + printf("Accepted the dialog.\n"); + } + return a.exec(); } diff --git a/model/database/recipedatabase.cpp b/model/database/recipedatabase.cpp index 37f23ce..b64a660 100644 --- a/model/database/recipedatabase.cpp +++ b/model/database/recipedatabase.cpp @@ -151,6 +151,7 @@ Recipe RecipeDatabase::retrieveRecipe(string name){ r.setInstruction(FileUtils::loadInstruction(id)); r.setImage(FileUtils::loadImage(id)); r.setIngredients(this->retrieveRecipeIngredients(id)); + r.setTags(this->retrieveTags(id)); return r; } @@ -198,6 +199,30 @@ vector RecipeDatabase::retrieveAllUnitsOfMeasure(){ return units; } +vector RecipeDatabase::retrieveTags(int recipeId){ + ResultTable t = this->selectFrom("recipeTag", "tagName", "WHERE recipeId="+std::to_string(recipeId)); + vector tags; + if (!t.isEmpty()){ + for (unsigned int row = 0; row < t.rowCount(); row++){ + RecipeTag tag(t.valueAt(row, 0)); + tags.push_back(tag); + } + } + return tags; +} + +vector RecipeDatabase::retrieveAllTags(){ + ResultTable t = this->selectFrom("recipeTag", "tagName", "ORDER BY tagName"); + vector tags; + if (!t.isEmpty()){ + for (unsigned int row = 0; row < t.rowCount(); row++){ + RecipeTag tag(t.valueAt(row, 0)); + tags.push_back(tag); + } + } + return tags; +} + void RecipeDatabase::ensureTablesExist(){ //Make sure that foreign keys are enabled. this->executeSQL("PRAGMA foreign_keys = ON;"); diff --git a/model/database/recipedatabase.h b/model/database/recipedatabase.h index 446536c..f1d9867 100644 --- a/model/database/recipedatabase.h +++ b/model/database/recipedatabase.h @@ -35,6 +35,8 @@ class RecipeDatabase : public Database vector retrieveRecipeIngredients(int recipeId); vector retrieveAllIngredients(); vector retrieveAllUnitsOfMeasure(); + vector retrieveTags(int recipeId); + vector retrieveAllTags(); private: //Utility methods. diff --git a/model/recipe/ingredients/ingredientlistmodel.h b/model/recipe/ingredients/ingredientlistmodel.h index 803c2ca..1f3605c 100644 --- a/model/recipe/ingredients/ingredientlistmodel.h +++ b/model/recipe/ingredients/ingredientlistmodel.h @@ -18,6 +18,7 @@ public: //Custom methods to handle ingredient data. void setIngredients(vector ingredients); bool addIngredient(RecipeIngredient ri); + vector getIngredients(); private: vector ingredients; diff --git a/model/recipe/tags/recipetag.cpp b/model/recipe/tags/recipetag.cpp index 22cd27d..3b1442a 100644 --- a/model/recipe/tags/recipetag.cpp +++ b/model/recipe/tags/recipetag.cpp @@ -8,7 +8,7 @@ RecipeTag::RecipeTag(string val){ this->value = val; } -string RecipeTag::getValue(){ +string RecipeTag::getValue() const{ return this->value; } diff --git a/model/recipe/tags/recipetag.h b/model/recipe/tags/recipetag.h index 5613af7..cd382fe 100644 --- a/model/recipe/tags/recipetag.h +++ b/model/recipe/tags/recipetag.h @@ -16,7 +16,7 @@ public: RecipeTag(string val); //Getters - string getValue(); + string getValue() const; //Setters void setValue(string newValue); private: diff --git a/model/recipe/tags/taglistmodel.cpp b/model/recipe/tags/taglistmodel.cpp new file mode 100644 index 0000000..dd70b3f --- /dev/null +++ b/model/recipe/tags/taglistmodel.cpp @@ -0,0 +1,44 @@ +#include "taglistmodel.h" + +TagListModel::TagListModel(){ + +} + +int TagListModel::rowCount(const QModelIndex &parent) const{ + return this->tags.size(); +} + +QVariant TagListModel::data(const QModelIndex &index, int role) const{ + string displayString = this->tags[index.row()].getValue(); + switch(role){ + case Qt::DisplayRole: + return QString::fromStdString(displayString); + } + + return QVariant(); +} + +void TagListModel::setTags(vector tags){ + this->tags = tags; + QModelIndex index = createIndex(0, 0); + QModelIndex bottomIndex = createIndex(this->tags.size()-1, 0); + emit dataChanged(index, bottomIndex); +} + +bool TagListModel::addTag(RecipeTag tag){ + //Add only if it's different. + for (unsigned int i = 0; i < this->tags.size(); i++){ + if (!this->tags[i].getValue().compare(tag.getValue())){ + return false; + } + } + this->tags.push_back(tag); + QModelIndex index = createIndex(this->tags.size()-1, 0); + QModelIndex bottomIndex = createIndex(this->tags.size()-1, 0); + emit dataChanged(index, bottomIndex); + return true; +} + +vector TagListModel::getTags(){ + return this->tags; +} diff --git a/model/recipe/tags/taglistmodel.h b/model/recipe/tags/taglistmodel.h new file mode 100644 index 0000000..e524e23 --- /dev/null +++ b/model/recipe/tags/taglistmodel.h @@ -0,0 +1,24 @@ +#ifndef TAGLISTMODEL_H +#define TAGLISTMODEL_H + +#include + +#include "model/recipe/tags/recipetag.h" + +class TagListModel : public QAbstractListModel +{ + public: + TagListModel(); + //Overridden methods. + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + + + void setTags(vector tags); + bool addTag(RecipeTag tag); + vector getTags(); + private: + vector tags; +}; + +#endif // TAGLISTMODEL_H