diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index 78b64db..7db6bbe 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -58,7 +58,7 @@ void MainWindow::setCookTime(QTime cookTime){ } void MainWindow::setServings(float servings){ - ui->servingsLabel->setText(QString("Servings: ")+QString::fromStdString(StringUtils::toString(servings))); + ui->servingsLabel->setText(QString(QString::fromStdString(StringUtils::toString(servings) + " Serving" + ((servings != 1.0f) ? "s" : "")))); } void MainWindow::setTags(vector tags){ @@ -72,9 +72,10 @@ void MainWindow::on_newButton_clicked(){ if (d.isAccepted()){ Recipe r = d.getRecipe(); if (!this->recipeDB->storeRecipe(r)){ - QMessageBox::critical(this, QString("Unable to Save Recipe"), QString("The program was not able to successfully save the recipe.")); + QMessageBox::critical(this, QString("Unable to Save Recipe"), QString("The program was not able to successfully save the recipe. Make sure to give the recipe a name, instructions, and some ingredients!")); + } else { + this->loadFromRecipe(r); } - this->loadFromRecipe(r); } } @@ -82,4 +83,11 @@ void MainWindow::on_openButton_clicked(){ OpenRecipeDialog d(this->recipeDB, this); d.show(); d.exec(); + if (!d.getSelectedRecipe().isEmpty()){ + this->loadFromRecipe(d.getSelectedRecipe()); + } +} + +void MainWindow::on_exitButton_clicked(){ + this->close(); } diff --git a/gui/mainwindow.h b/gui/mainwindow.h index 0dd91b9..2b62cc3 100644 --- a/gui/mainwindow.h +++ b/gui/mainwindow.h @@ -34,6 +34,8 @@ public: void on_openButton_clicked(); + void on_exitButton_clicked(); + private: Ui::MainWindow *ui; RecipeDatabase *recipeDB; diff --git a/gui/mainwindow.ui b/gui/mainwindow.ui index 430cb1e..0925f75 100644 --- a/gui/mainwindow.ui +++ b/gui/mainwindow.ui @@ -143,6 +143,12 @@ QPushButton#newButton:pressed{ + + + 0 + 0 + + 150 @@ -175,6 +181,9 @@ QPushButton#openButton:pressed{ + + false + 150 @@ -211,6 +220,56 @@ QPushButton#browseButton:pressed{ + + + + + 150 + 80 + + + + + 150 + 80 + + + + + Noto Sans CJK KR Light + 20 + PreferAntialias + + + + false + + + QPushButton#exitButton { + background-color: rgb(255, 216, 216); + border: 0px; +} +QPushButton#exitButton:hover{ + background-color: rgb(255, 191, 191); +} +QPushButton#exitButton:pressed{ + background-color: rgb(255, 147, 147); +} + + + Exit + + + false + + + false + + + false + + + @@ -367,6 +426,9 @@ font: "Noto Sans CJK KR"; Prep Time: + + Qt::AlignCenter + @@ -383,6 +445,9 @@ font: "Noto Sans CJK KR"; Cook Time: + + Qt::AlignCenter + @@ -396,6 +461,9 @@ font: "Noto Sans CJK KR"; Servings: + + Qt::AlignCenter + diff --git a/gui/newrecipedialog.cpp b/gui/newrecipedialog.cpp index ac0c89e..a0681f2 100644 --- a/gui/newrecipedialog.cpp +++ b/gui/newrecipedialog.cpp @@ -119,7 +119,7 @@ void NewRecipeDialog::on_selectImageButton_clicked(){ } } -void NewRecipeDialog::on_deleteIngredientButton_clicked(){ +void NewRecipeDialog::on_removeIngredientButton_clicked(){ QModelIndexList indexList = ui->ingredientsListView->selectionModel()->selectedIndexes(); for (QModelIndexList::iterator it = indexList.begin(); it != indexList.end(); ++it){ QModelIndex i = *it; @@ -127,6 +127,22 @@ void NewRecipeDialog::on_deleteIngredientButton_clicked(){ } } +void NewRecipeDialog::on_deleteIngredientButton_clicked(){ + int index = ui->ingredientNameBox->currentIndex(); + Ingredient ing = this->ingredients.at(index); + QMessageBox::StandardButton reply = QMessageBox::question(this, + QString::fromStdString("Delete Ingredient"), + QString::fromStdString("Are you sure you want to delete the ingredient " + ing.getName() + "?")); + if (reply == QMessageBox::Yes){ + bool success = this->recipeDB->deleteIngredient(ing.getName()); + if (!success){ + QMessageBox::critical(this, QString::fromStdString("Error"), QString::fromStdString("Unable to delete ingredient: " + ing.getName() + ", some recipes use it!")); + } else { + this->populateIngredientsBox(); + } + } +} + void NewRecipeDialog::on_newIngredientButton_clicked(){ NewIngredientDialog d(this); d.show(); @@ -155,8 +171,8 @@ void NewRecipeDialog::on_newTagButton_clicked(){ } void NewRecipeDialog::on_removeTagButton_clicked(){ - int index = ui->tagsComboBox->currentIndex(); - if (index < 0 || index >= this->tags.size()){ + unsigned int index = ui->tagsComboBox->currentIndex(); + if (index >= this->tags.size()){ return; } RecipeTag tag = this->tags[ui->tagsComboBox->currentIndex()]; @@ -180,3 +196,18 @@ void NewRecipeDialog::on_newUnitButton_clicked(){ } } } + +void NewRecipeDialog::on_deleteUnitButton_clicked(){ + int index = ui->unitComboBox->currentIndex(); + UnitOfMeasure unit = this->units[index]; + QMessageBox::StandardButton reply = QMessageBox::question(this, + QString::fromStdString("Delete Unit Of Measure"), + QString::fromStdString("Are you sure you want to delete the unit " + unit.getName() + "?")); + if (reply == QMessageBox::Yes){ + if (!this->recipeDB->deleteUnitOfMeasure(unit.getName())){ + QMessageBox::critical(this, "Error", "Unable to delete unit. There may be recipes which still use it!"); + } else { + this->populateUnitsBox(); + } + } +} diff --git a/gui/newrecipedialog.h b/gui/newrecipedialog.h index d272f3e..bfeae1f 100644 --- a/gui/newrecipedialog.h +++ b/gui/newrecipedialog.h @@ -47,6 +47,8 @@ class NewRecipeDialog : public QDialog void on_selectImageButton_clicked(); + void on_removeIngredientButton_clicked(); + void on_deleteIngredientButton_clicked(); void on_newIngredientButton_clicked(); @@ -57,6 +59,8 @@ class NewRecipeDialog : public QDialog void on_newUnitButton_clicked(); + void on_deleteUnitButton_clicked(); + private: Ui::NewRecipeDialog *ui; RecipeDatabase *recipeDB; diff --git a/gui/newrecipedialog.ui b/gui/newrecipedialog.ui index a470909..7a57690 100644 --- a/gui/newrecipedialog.ui +++ b/gui/newrecipedialog.ui @@ -158,7 +158,7 @@ 0 1999 12 - 26 + 25 @@ -504,6 +504,17 @@ + + + + + + + + :/images/images/minus_icon.png:/images/images/minus_icon.png + + + @@ -579,6 +590,17 @@ + + + + + + + + :/images/images/minus_icon.png:/images/images/minus_icon.png + + + @@ -627,7 +649,7 @@ - + Delete diff --git a/gui/openrecipedialog.cpp b/gui/openrecipedialog.cpp index 5991297..fb34703 100644 --- a/gui/openrecipedialog.cpp +++ b/gui/openrecipedialog.cpp @@ -20,13 +20,45 @@ OpenRecipeDialog::~OpenRecipeDialog() delete ui; } +Recipe OpenRecipeDialog::getSelectedRecipe(){ + return this->selectedRecipe; +} + void OpenRecipeDialog::populateRecipesTable(){ + this->recipeTableModel.clear(); vector recipes = this->recipeDB->retrieveAllRecipes(); -// printf("Found %d recipes:\n", recipes.size()); -// for (Recipe r : recipes){ -// r.print(); -// printf("\n------------------\n"); -// } this->recipeTableModel.setRecipes(recipes); + ui->recipeTableView->resizeColumnsToContents(); ui->recipeTableView->show(); } + +void OpenRecipeDialog::on_deleteRecipeButton_clicked(){ + QItemSelectionModel *selectModel = ui->recipeTableView->selectionModel(); + if (!selectModel->hasSelection()){ + return; + } + vector rows; + QModelIndexList indexes = selectModel->selectedIndexes(); + for (int i = 0; i < indexes.count(); i++){ + rows.push_back(indexes.at(i).row()); + } + string recipePlural = (rows.size() == 1) ? "recipe" : "recipes"; + QString title = QString::fromStdString("Delete " + recipePlural); + QString content = QString::fromStdString("Are you sure you wish to delete the selected "+recipePlural+"?"); + QMessageBox::StandardButton reply = QMessageBox::question(this, title, content); + if (reply == QMessageBox::Yes){ + for (int row : rows){ + Recipe r = this->recipeTableModel.getRecipeAt(row); + bool success = this->recipeDB->deleteRecipe(r.getName()); + if (!success){ + QMessageBox::critical(this, QString::fromStdString("Unable to Delete"), QString::fromStdString("Could not delete recipe "+r.getName())); + } + } + this->populateRecipesTable(); + } +} + +void OpenRecipeDialog::on_recipeTableView_doubleClicked(const QModelIndex &index){ + this->selectedRecipe = this->recipeTableModel.getRecipeAt(index.row()); + this->close(); +} diff --git a/gui/openrecipedialog.h b/gui/openrecipedialog.h index 51c7a18..974b6cf 100644 --- a/gui/openrecipedialog.h +++ b/gui/openrecipedialog.h @@ -2,6 +2,7 @@ #define OPENRECIPEDIALOG_H #include +#include #include "model/database/recipedatabase.h" #include "model/recipe/recipetablemodel.h" @@ -19,10 +20,18 @@ class OpenRecipeDialog : public QDialog OpenRecipeDialog(RecipeDatabase *recipeDB, QWidget *parent = 0); ~OpenRecipeDialog(); + Recipe getSelectedRecipe(); + + private slots: + void on_deleteRecipeButton_clicked(); + + void on_recipeTableView_doubleClicked(const QModelIndex &index); + private: Ui::OpenRecipeDialog *ui; RecipeDatabase *recipeDB; RecipeTableModel recipeTableModel; + Recipe selectedRecipe; void populateRecipesTable(); }; diff --git a/gui/openrecipedialog.ui b/gui/openrecipedialog.ui index be20dd9..d689a16 100644 --- a/gui/openrecipedialog.ui +++ b/gui/openrecipedialog.ui @@ -86,6 +86,23 @@ + + + + + + + + + + + :/images/images/trash.png:/images/images/trash.png + + + + + + @@ -94,6 +111,9 @@ QFrame::NoFrame + + QAbstractItemView::SelectRows + true diff --git a/images.qrc b/images.qrc index 8b12ebf..a5261a4 100644 --- a/images.qrc +++ b/images.qrc @@ -5,5 +5,6 @@ images/plus_icon.png images/minus_icon.png images/search_icon.png + images/trash.png diff --git a/main.cpp b/main.cpp index 418b03d..3d4bfdb 100644 --- a/main.cpp +++ b/main.cpp @@ -13,45 +13,28 @@ int main(int argc, char *argv[]) w.show(); //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), "")); + 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), "")); -// Recipe rec("Example", -// ri, -// Instruction("BOLDiTaLiCs"), -// QImage(), -// vector({RecipeTag("testing"), -// RecipeTag("fake")}), -// 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); + bool success = recipeDB.storeRecipe(rec); + printf("Storage successful: %d\n", success); -// recipeDB.storeUnitOfMeasure(UnitOfMeasure("tablespoon", "tablespoons", "tbsp", UnitOfMeasure::VOLUME, 1.0)); -// recipeDB.storeUnitOfMeasure(UnitOfMeasure("pinch", "pinches", "pch", UnitOfMeasure::VOLUME, 1.0)); -// recipeDB.storeUnitOfMeasure(UnitOfMeasure("gram", "grams", "g", UnitOfMeasure::MASS, 1.0)); + //recipeDB.selectFrom("recipe", "recipeId, name", "").printData(); + w.loadFromRecipe(recipeDB.retrieveRandomRecipe()); -// Recipe reloadRec = recipeDB.retrieveRecipe("Example"); -// reloadRec.print(); - -// w.loadFromRecipe(reloadRec); - -// NewRecipeDialog d(&recipeDB); -// d.show(); -// d.exec(); - -// if (d.isAccepted()){ -// printf("Accepted the dialog.\n"); -// } - - bool success = recipeDB.deleteRecipe(4); - printf("Success: %d\n", success); - recipeDB.selectFrom("recipe", "recipeId, name", "").printData(); - w.loadFromRecipe(recipeDB.retrieveRecipe("Generic Bread")); - - return a.exec(); + a.exec(); + recipeDB.closeConnection(); + return 0; } diff --git a/model/database/database.h b/model/database/database.h index a110db7..ab149d5 100644 --- a/model/database/database.h +++ b/model/database/database.h @@ -31,6 +31,8 @@ public: bool tableExists(string tableName); int getLastInsertedRowId(); + void closeConnection(); + protected: string surroundString(string s, string surround); @@ -44,7 +46,6 @@ private: char* errorMsg; void openConnection(); - void closeConnection(); std::string combineVector(std::vector strings, std::string mid); }; diff --git a/model/database/recipedatabase.cpp b/model/database/recipedatabase.cpp index 54f9bcc..1650579 100644 --- a/model/database/recipedatabase.cpp +++ b/model/database/recipedatabase.cpp @@ -147,18 +147,16 @@ Recipe RecipeDatabase::retrieveRecipe(string name){ fprintf(stderr, "Error: No recipe with name %s found!\n", name.c_str()); return Recipe(); } - Recipe r; - int id = std::stoi(t.valueAt(0, 0)); - r.setName(t.valueAt(0, 1)); - r.setCreatedDate(QDate::fromString(QString::fromStdString(t.valueAt(0, 2)))); - r.setPrepTime(QTime::fromString(QString::fromStdString(t.valueAt(0, 3)))); - r.setCookTime(QTime::fromString(QString::fromStdString(t.valueAt(0, 4)))); - r.setServings(std::stof(t.valueAt(0, 5))); - r.setInstruction(FileUtils::loadInstruction(id)); - r.setImage(FileUtils::loadImage(id)); - r.setIngredients(this->retrieveRecipeIngredients(id)); - r.setTags(this->retrieveTags(id)); - return r; + return this->readFromResultTable(t); +} + +Recipe RecipeDatabase::retrieveRandomRecipe(){ + ResultTable t = this->selectFrom("recipe", "*", "ORDER BY RANDOM() LIMIT 1"); + if (t.isEmpty()){ + fprintf(stderr, "Unable to find a random recipe.\n"); + return Recipe(); + } + return this->readFromResultTable(t); } vector RecipeDatabase::retrieveAllRecipes(){ @@ -239,7 +237,7 @@ vector RecipeDatabase::retrieveAllTags(){ } bool RecipeDatabase::deleteRecipe(string name){ - ResultTable t = this->selectFrom("recipe", "recipeId", "WHERE name="+name); + ResultTable t = this->selectFrom("recipe", "recipeId", "WHERE name='"+name+"'"); if (t.rowCount() != 1){ return false; } @@ -250,6 +248,7 @@ bool RecipeDatabase::deleteRecipe(string name){ bool RecipeDatabase::deleteRecipe(int recipeId){ string idString = std::to_string(recipeId); if (this->selectFrom("recipe", "recipeId", "WHERE recipeId="+idString).isEmpty()){ + printf("Cannot delete. No recipe with ID %d exists.\n", recipeId); return false; } this->executeSQL("BEGIN;"); @@ -266,27 +265,28 @@ bool RecipeDatabase::deleteRecipe(int recipeId){ } bool RecipeDatabase::deleteIngredient(string name){ - ResultTable t = this->selectFrom("recipeIngredient", "recipeId", "WHERE ingredientId=(" - "SELECT ingredientId" - "FROM ingredient" - "WHERE name="+name+")"); + ResultTable t = this->executeSQL("SELECT recipeId " + "FROM recipeIngredient " + "INNER JOIN ingredient " + "ON recipeIngredient.ingredientId = ingredient.ingredientId " + "WHERE ingredient.name='"+name+"';"); if (!t.isEmpty()){ //There is at least one recipe dependent on the ingredient. return false; } - return this->deleteFrom("ingredient", "WHERE name="+name); + return this->deleteFrom("ingredient", "WHERE name='"+name+"'"); } bool RecipeDatabase::deleteUnitOfMeasure(string name){ - ResultTable t = this->selectFrom("recipeIngredient", "recipeId", "WHERE unitName="+name); + ResultTable t = this->selectFrom("recipeIngredient", "recipeId", "WHERE unitName='"+name+"'"); if (!t.isEmpty()){ return false; } - return this->deleteFrom("unitOfMeasure", "WHERE name="+name); + return this->deleteFrom("unitOfMeasure", "WHERE name='"+name+"'"); } bool RecipeDatabase::deleteTag(RecipeTag tag){ - return this->deleteFrom("recipeTag", "WHERE tagName="+tag.getValue()); + return this->deleteFrom("recipeTag", "WHERE tagName='"+tag.getValue()+"'"); } void RecipeDatabase::ensureTablesExist(){ @@ -331,3 +331,18 @@ void RecipeDatabase::ensureTablesExist(){ "FOREIGN KEY (unitName) REFERENCES unitOfMeasure(name));"); this->executeSQL("COMMIT;"); } + +Recipe RecipeDatabase::readFromResultTable(ResultTable t, int row){ + Recipe r; + int id = std::stoi(t.valueAt(row, 0)); + r.setName(t.valueAt(row, 1)); + r.setCreatedDate(QDate::fromString(QString::fromStdString(t.valueAt(row, 2)))); + r.setPrepTime(QTime::fromString(QString::fromStdString(t.valueAt(row, 3)))); + r.setCookTime(QTime::fromString(QString::fromStdString(t.valueAt(row, 4)))); + r.setServings(std::stof(t.valueAt(row, 5))); + r.setInstruction(FileUtils::loadInstruction(id)); + r.setImage(FileUtils::loadImage(id)); + r.setIngredients(this->retrieveRecipeIngredients(id)); + r.setTags(this->retrieveTags(id)); + return r; +} diff --git a/model/database/recipedatabase.h b/model/database/recipedatabase.h index b240166..c5466b7 100644 --- a/model/database/recipedatabase.h +++ b/model/database/recipedatabase.h @@ -32,6 +32,7 @@ class RecipeDatabase : public Database //Retrieval. Recipe retrieveRecipe(string name); + Recipe retrieveRandomRecipe(); vector retrieveAllRecipes(); vector retrieveRecipeIngredients(int recipeId); vector retrieveAllIngredients(); @@ -49,6 +50,8 @@ class RecipeDatabase : public Database //Utility methods. void ensureTablesExist(); + //Read a recipe from a row of a result table. + Recipe readFromResultTable(ResultTable t, int row=0); }; #endif // RECIPEDATABASE_H diff --git a/model/recipe/ingredients/recipeingredient.cpp b/model/recipe/ingredients/recipeingredient.cpp index d8f115b..34de9d1 100644 --- a/model/recipe/ingredients/recipeingredient.cpp +++ b/model/recipe/ingredients/recipeingredient.cpp @@ -50,7 +50,7 @@ string RecipeIngredient::toString(){ result += StringUtils::toString(this->getQuantity()); } result += " " + this->getUnit().getAbbreviation() + " " + this->getName(); - if (!this->getComment().empty()) result += " ~" + this->getComment(); + if (!this->getComment().empty()) result += " (" + this->getComment() + ")"; return result; } diff --git a/model/recipe/recipe.cpp b/model/recipe/recipe.cpp index f99e1a2..0859bd8 100644 --- a/model/recipe/recipe.cpp +++ b/model/recipe/recipe.cpp @@ -12,7 +12,7 @@ Recipe::Recipe(string name, vector ingredients, Instruction in setServings(servings); } -Recipe::Recipe() : Recipe::Recipe("Unnamed Recipe", vector(), Instruction(), QImage(), vector(), QDate::currentDate(), QTime(1, 0), QTime(0, 30), 10.0f){ +Recipe::Recipe() : Recipe::Recipe("", vector(), Instruction(), QImage(), vector(), QDate::currentDate(), QTime(1, 0), QTime(0, 30), 10.0f){ //Set default values when none are specified. } @@ -53,7 +53,11 @@ QTime Recipe::getTotalTime() const{ } float Recipe::getServings() const{ - return this->servings; + return this->servings; +} + +bool Recipe::isEmpty() const{ + return this->name.empty(); } void Recipe::setName(string newName){ diff --git a/model/recipe/recipe.h b/model/recipe/recipe.h index d013659..048b09a 100644 --- a/model/recipe/recipe.h +++ b/model/recipe/recipe.h @@ -46,6 +46,7 @@ public: QTime getCookTime() const; QTime getTotalTime() const; //Derived method to add prep and cook times. float getServings() const; + bool isEmpty() const; //Setters void setName(string newName); diff --git a/model/recipe/recipetablemodel.cpp b/model/recipe/recipetablemodel.cpp index a22c7b6..521fa51 100644 --- a/model/recipe/recipetablemodel.cpp +++ b/model/recipe/recipetablemodel.cpp @@ -16,7 +16,7 @@ int RecipeTableModel::rowCount(const QModelIndex &parent) const{ int RecipeTableModel::columnCount(const QModelIndex &parent) const{ Q_UNUSED(parent); - return 2;//FIX THIS TO BE MORE ADAPTIVE EVENTUALLY. + return 5;//FIX THIS TO BE MORE ADAPTIVE EVENTUALLY. } QVariant RecipeTableModel::data(const QModelIndex &index, int role) const{ @@ -30,6 +30,12 @@ QVariant RecipeTableModel::data(const QModelIndex &index, int role) const{ return QString::fromStdString(r.getName()); case 1: return QString::fromStdString(r.getCreatedDate().toString().toStdString()); + case 2: + return QString::fromStdString(StringUtils::toString(r.getServings())); + case 3: + return r.getPrepTime().toString("hh:mm:ss"); + case 4: + return r.getCookTime().toString("hh:mm:ss"); } } return QVariant(); @@ -45,6 +51,12 @@ QVariant RecipeTableModel::headerData(int section, Qt::Orientation orientation, return "Name"; case 1: return "Created On"; + case 2: + return "Servings"; + case 3: + return "Prep Time"; + case 4: + return "Cook Time"; default: return QVariant(); } @@ -59,3 +71,16 @@ void RecipeTableModel::setRecipes(vector recipes){ this->recipes = recipes; endInsertRows(); } + +Recipe RecipeTableModel::getRecipeAt(int index){ + if (index < 0 || index >= this->recipes.size()){ + return Recipe(); + } + return this->recipes[index]; +} + +void RecipeTableModel::clear(){ + beginResetModel(); + this->recipes.clear(); + endResetModel(); +} diff --git a/model/recipe/recipetablemodel.h b/model/recipe/recipetablemodel.h index 04285f5..7449619 100644 --- a/model/recipe/recipetablemodel.h +++ b/model/recipe/recipetablemodel.h @@ -4,6 +4,7 @@ #include #include "model/recipe/recipe.h" +#include "utils/stringutils.h" class RecipeTableModel : public QAbstractTableModel { @@ -19,7 +20,8 @@ class RecipeTableModel : public QAbstractTableModel //Normal methods. void setRecipes(vector recipes); - + Recipe getRecipeAt(int index); + void clear(); private: vector recipes; }; diff --git a/utils/stringutils.cpp b/utils/stringutils.cpp index 3ed578b..f6115e8 100644 --- a/utils/stringutils.cpp +++ b/utils/stringutils.cpp @@ -2,6 +2,14 @@ namespace StringUtils{ +bool stringEndsWith(std::string const &fullString, std::string const &ending){ + if (fullString.length() >= ending.length()) { + return (0 == fullString.compare (fullString.length() - ending.length(), ending.length(), ending)); + } else { + return false; + } +} + std::string toString(float val){ float decimal = std::fmod(val, 1.0f); int places = 1; @@ -13,6 +21,11 @@ std::string toString(float val){ std::string arg = "%."+std::to_string(places)+"f"; sprintf(buffer, arg.c_str(), val); std::string s = buffer; + if (stringEndsWith(s, ".0")){ + while (s.find('.') != std::string::npos){ + s.pop_back(); + } + } return s; }