Stable first release #10
|
@ -95,11 +95,12 @@ void MainWindow::on_exitButton_clicked(){
|
|||
|
||||
void MainWindow::on_editButton_clicked(){
|
||||
NewRecipeDialog d(this->recipeDB, this->currentRecipe, this);
|
||||
string originalName = this->currentRecipe.getName();
|
||||
d.show();
|
||||
d.exec();
|
||||
if (d.isAccepted()){
|
||||
Recipe r = d.getRecipe();
|
||||
if (!this->recipeDB->storeRecipe(r)){
|
||||
if (!this->recipeDB->updateRecipe(r, originalName)){
|
||||
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);
|
||||
|
|
|
@ -100,7 +100,6 @@
|
|||
<widget class="QLineEdit" name="recipeNameEdit">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>3</weight>
|
||||
<italic>false</italic>
|
||||
<bold>false</bold>
|
||||
|
@ -142,7 +141,7 @@
|
|||
<second>0</second>
|
||||
<year>1999</year>
|
||||
<month>12</month>
|
||||
<day>24</day>
|
||||
<day>23</day>
|
||||
</datetime>
|
||||
</property>
|
||||
<property name="currentSection">
|
||||
|
@ -352,6 +351,9 @@
|
|||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::MultiSelection</enum>
|
||||
</property>
|
||||
<property name="verticalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
@ -667,6 +669,9 @@
|
|||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::MultiSelection</enum>
|
||||
</property>
|
||||
<property name="verticalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<property name="batchSize">
|
||||
<number>100</number>
|
||||
</property>
|
||||
|
@ -746,16 +751,6 @@
|
|||
<string notr="true">background-color: rgb(250, 250, 255);</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||
<item>
|
||||
<widget class="QLabel" name="instructionsLabel">
|
||||
<property name="text">
|
||||
<string>Instructions</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item alignment="Qt::AlignLeft|Qt::AlignTop">
|
||||
<widget class="QWidget" name="textControlPanel" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
|
@ -769,7 +764,7 @@
|
|||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>I</string>
|
||||
<string>Italic</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
|
@ -789,7 +784,7 @@
|
|||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>B</string>
|
||||
<string>Bold</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
|
@ -827,7 +822,7 @@
|
|||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: rgb(255, 255, 255);</string>
|
||||
|
|
|
@ -127,3 +127,11 @@ void OpenRecipeDialog::on_foodGroupsListWidget_itemSelectionChanged(){
|
|||
}
|
||||
this->populateRecipesTable(this->recipeDB->retrieveRecipesWithFoodGroups(groups));
|
||||
}
|
||||
|
||||
void OpenRecipeDialog::on_clearSearchButton_clicked(){
|
||||
ui->nameEdit->clear();
|
||||
ui->foodGroupsListWidget->selectionModel()->clearSelection();
|
||||
ui->tagsListView->selectionModel()->clearSelection();
|
||||
ui->ingredientsListView->selectionModel()->clearSelection();
|
||||
this->populateRecipesTable(this->recipeDB->retrieveAllRecipes());
|
||||
}
|
||||
|
|
|
@ -38,6 +38,8 @@ class OpenRecipeDialog : public QDialog
|
|||
|
||||
void on_foodGroupsListWidget_itemSelectionChanged();
|
||||
|
||||
void on_clearSearchButton_clicked();
|
||||
|
||||
private:
|
||||
Ui::OpenRecipeDialog *ui;
|
||||
RecipeDatabase *recipeDB;
|
||||
|
|
|
@ -147,13 +147,9 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="searchButton">
|
||||
<widget class="QPushButton" name="clearSearchButton">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../images.qrc">
|
||||
<normaloff>:/images/images/search_icon.png</normaloff>:/images/images/search_icon.png</iconset>
|
||||
<string>Clear search criteria</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
@ -14,12 +14,11 @@ ResultTable Database::executeSQL(string statement){
|
|||
sqlite3_stmt* stmt;
|
||||
this->sql = statement;
|
||||
this->returnCode = sqlite3_prepare_v2(this->db, statement.c_str(), -1, &stmt, NULL);
|
||||
ResultTable t(statement);
|
||||
if (this->returnCode != SQLITE_OK){
|
||||
fprintf(stderr, "Unable to successfully prepare SQL statement. Error code: %d\n\tError Message: %s\n", this->returnCode, sqlite3_errmsg(this->db));
|
||||
return t;
|
||||
return ResultTable(this->returnCode);
|
||||
}
|
||||
|
||||
ResultTable t(statement);
|
||||
t.extractData(stmt);
|
||||
|
||||
this->returnCode = sqlite3_finalize(stmt);
|
||||
|
@ -78,6 +77,18 @@ void Database::closeConnection(){
|
|||
this->dbIsOpen = false;
|
||||
}
|
||||
|
||||
void Database::beginTransaction(){
|
||||
this->executeSQL("BEGIN;");
|
||||
}
|
||||
|
||||
void Database::commitTransaction(){
|
||||
this->executeSQL("COMMIT;");
|
||||
}
|
||||
|
||||
void Database::rollbackTransaction(){
|
||||
this->executeSQL("ROLLBACK;");
|
||||
}
|
||||
|
||||
string Database::combineVector(std::vector<string> strings, string mid){
|
||||
if (strings.empty()){
|
||||
return "";
|
||||
|
|
|
@ -35,6 +35,10 @@ public:
|
|||
|
||||
void closeConnection();
|
||||
|
||||
void beginTransaction();
|
||||
void commitTransaction();
|
||||
void rollbackTransaction();
|
||||
|
||||
protected:
|
||||
string surroundString(string s, string surround);
|
||||
|
||||
|
|
|
@ -253,6 +253,18 @@ vector<RecipeIngredient> RecipeDatabase::retrieveRecipeIngredients(int recipeId)
|
|||
return ings;
|
||||
}
|
||||
|
||||
int RecipeDatabase::retrieveIngredientId(string ingredientName){
|
||||
return std::stoi(this->selectFrom("ingredient", "ingredientId", "WHERE name = '"+ingredientName+"'").at(0, 0));
|
||||
}
|
||||
|
||||
bool RecipeDatabase::deleteRecipeTags(int recipeId){
|
||||
return this->deleteFrom("recipeTag", "WHERE recipeId = "+std::to_string(recipeId));
|
||||
}
|
||||
|
||||
bool RecipeDatabase::deleteRecipeIngredients(int recipeId){
|
||||
return this->deleteFrom("recipeIngredient", "WHERE recipeId = "+std::to_string(recipeId));
|
||||
}
|
||||
|
||||
vector<Ingredient> RecipeDatabase::retrieveAllIngredients(){
|
||||
ResultTable t = this->selectFrom("ingredient", "name, foodGroup", "ORDER BY name");
|
||||
vector<Ingredient> ings;
|
||||
|
@ -356,8 +368,71 @@ bool RecipeDatabase::deleteTag(RecipeTag tag){
|
|||
return this->deleteFrom("recipeTag", "WHERE tagName='"+tag.getValue()+"'");
|
||||
}
|
||||
|
||||
bool RecipeDatabase::updateRecipe(Recipe recipe){
|
||||
|
||||
bool RecipeDatabase::updateRecipe(Recipe recipe, string originalName) {
|
||||
string idS = this->selectFrom("recipe", "recipeId", "WHERE name="+surroundString(originalName, "'")).at(0, 0);
|
||||
int id = std::stoi(idS);
|
||||
this->beginTransaction();
|
||||
ResultTable t = this->executeSQL("UPDATE recipe "
|
||||
"SET name = '"+recipe.getName()+"', "
|
||||
"createdDate = '"+recipe.getCreatedDate().toString().toStdString()+"', "
|
||||
"prepTime = '"+recipe.getPrepTime().toString().toStdString()+"', "
|
||||
"cookTime = '"+recipe.getCookTime().toString().toStdString()+"', "
|
||||
"servingCount = "+std::to_string(recipe.getServings())+" "
|
||||
"WHERE recipeId = "+idS+";");
|
||||
bool recipeSuccess = t.getReturnCode() == SQLITE_DONE;
|
||||
if (!recipeSuccess){
|
||||
this->rollbackTransaction();
|
||||
return false;
|
||||
}
|
||||
bool tagsSuccess = this->deleteRecipeTags(id);
|
||||
for (RecipeTag tag : recipe.getTags()){
|
||||
tagsSuccess = tagsSuccess && this->insertInto(
|
||||
"recipeTag",
|
||||
vector<string>({
|
||||
"recipeId",
|
||||
"tagName"
|
||||
}),
|
||||
vector<string>({
|
||||
idS,
|
||||
tag.getValue()
|
||||
}));
|
||||
}
|
||||
if (!tagsSuccess){
|
||||
this->rollbackTransaction();
|
||||
return false;
|
||||
}
|
||||
bool ingredientsSuccess = this->deleteRecipeIngredients(id);
|
||||
for (RecipeIngredient ri : recipe.getIngredients()){
|
||||
ingredientsSuccess = ingredientsSuccess && this->insertInto(
|
||||
"recipeIngredient",
|
||||
vector<string>({
|
||||
"recipeId",
|
||||
"ingredientId",
|
||||
"unitName",
|
||||
"quantity",
|
||||
"comment"
|
||||
}),
|
||||
vector<string>({
|
||||
idS,
|
||||
std::to_string(this->retrieveIngredientId(ri.getName())),
|
||||
ri.getUnit().getName(),
|
||||
std::to_string(ri.getQuantity()),
|
||||
ri.getComment()
|
||||
}));
|
||||
}
|
||||
if (!ingredientsSuccess){
|
||||
this->rollbackTransaction();
|
||||
return false;
|
||||
}
|
||||
bool instructionSuccess = FileUtils::saveInstruction(id, recipe.getInstruction());
|
||||
bool imageSuccess = FileUtils::saveImage(id, recipe.getImage());
|
||||
if (!(instructionSuccess && imageSuccess)){
|
||||
this->rollbackTransaction();
|
||||
return false;
|
||||
} else {
|
||||
this->commitTransaction();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void RecipeDatabase::ensureTablesExist(){
|
||||
|
|
|
@ -26,9 +26,6 @@ class RecipeDatabase : public Database
|
|||
bool storeRecipeIngredient(RecipeIngredient ri, int recipeId);
|
||||
int storeIngredient(Ingredient ingredient);
|
||||
bool storeUnitOfMeasure(UnitOfMeasure u);
|
||||
bool storeInstruction(Instruction instruction, int recipeId);
|
||||
bool storeImage(QImage image, int recipeId);
|
||||
bool storeTags(vector<RecipeTag> tags, int recipeId);
|
||||
|
||||
//Retrieval.
|
||||
Recipe retrieveRecipe(string name);
|
||||
|
@ -39,10 +36,8 @@ class RecipeDatabase : public Database
|
|||
vector<Recipe> retrieveRecipesWithSubstring(string s);
|
||||
vector<Recipe> retrieveRecipesWithFoodGroups(vector<string> groups);
|
||||
vector<string> retrieveAllFoodGroups();
|
||||
vector<RecipeIngredient> retrieveRecipeIngredients(int recipeId);
|
||||
vector<Ingredient> retrieveAllIngredients();
|
||||
vector<UnitOfMeasure> retrieveAllUnitsOfMeasure();
|
||||
vector<RecipeTag> retrieveTags(int recipeId);
|
||||
vector<RecipeTag> retrieveAllTags();
|
||||
|
||||
//Deletion.
|
||||
|
@ -53,7 +48,7 @@ class RecipeDatabase : public Database
|
|||
bool deleteTag(RecipeTag tag);
|
||||
|
||||
//Updating.
|
||||
bool updateRecipe(Recipe recipe);
|
||||
bool updateRecipe(Recipe recipe, string originalName);
|
||||
private:
|
||||
|
||||
//Utility methods.
|
||||
|
@ -61,6 +56,20 @@ class RecipeDatabase : public Database
|
|||
//Read a recipe from a row of a result table.
|
||||
Recipe readFromResultTable(ResultTable t, int row=0);
|
||||
vector<Recipe> readRecipesFromTable(ResultTable t);
|
||||
|
||||
//Storage
|
||||
bool storeInstruction(Instruction instruction, int recipeId);
|
||||
bool storeImage(QImage image, int recipeId);
|
||||
bool storeTags(vector<RecipeTag> tags, int recipeId);
|
||||
|
||||
//Retrieval
|
||||
vector<RecipeTag> retrieveTags(int recipeId);
|
||||
vector<RecipeIngredient> retrieveRecipeIngredients(int recipeId);
|
||||
int retrieveIngredientId(string ingredientName);
|
||||
|
||||
//Deletion
|
||||
bool deleteRecipeTags(int recipeId);
|
||||
bool deleteRecipeIngredients(int recipeId);
|
||||
};
|
||||
|
||||
#endif // RECIPEDATABASE_H
|
||||
|
|
|
@ -8,6 +8,10 @@ ResultTable::ResultTable(string query){
|
|||
this->originalQuery = query;
|
||||
}
|
||||
|
||||
ResultTable::ResultTable(int resultCode){
|
||||
this->queryCode = resultCode;
|
||||
}
|
||||
|
||||
void ResultTable::extractData(sqlite3_stmt *stmt){
|
||||
this->values.clear();
|
||||
int res = sqlite3_step(stmt);
|
||||
|
@ -30,6 +34,7 @@ void ResultTable::processRow(sqlite3_stmt *stmt){
|
|||
}
|
||||
|
||||
void ResultTable::printData(){
|
||||
printf("--> Result Code: [%d] <--\n", this->getReturnCode());
|
||||
if (this->isEmpty()){
|
||||
printf("Result table is empty.\n");
|
||||
return;
|
||||
|
|
|
@ -21,6 +21,8 @@ class ResultTable
|
|||
ResultTable();
|
||||
//Constructs a table with the original query saved.
|
||||
ResultTable(string query);
|
||||
//Constructs an empty table with a result code.
|
||||
ResultTable(int resultCode);
|
||||
|
||||
//Gets all the data from the result set and stores it internally as strings.
|
||||
void extractData(sqlite3_stmt* stmt);
|
||||
|
|
Loading…
Reference in New Issue