Fri, 20 May 2022 20:43:33 +0200
Implemented the tasting tab. On the generic tab, show the ingredients check or the read only prompt on the same place depending on the product stage. Fixed the yeasts ingredients in stock check. Reordered the tab order of all edit fields. It looks like this module is ready and needs testing.
/** * EditProduct.cpp is part of bmsapp. * * Export product. * * bmsapp is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * bmsapp is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ void EditProduct::on_exportButton_clicked() { qDebug() << "export"; const QStringList styletype({ "Lager", "Ale", "Mead", "Wheat", "Mixed", "Cider" }); const QStringList producttypes({ "Extract", "Partial Mash", "All Grain" }); const QStringList color_method({ "Morey", "Mosher", "Daniels", "Halberstadt", "Naudts" }); const QStringList ibu_method({ "Tinseth", "Rager", "Daniels", "Garetz", "Mosher", "Noonan" }); const QStringList hop_types({ "Bittering", "Aroma", "Both" }); const QStringList hop_forms({ "Pellet", "Plug", "Leaf", "Leaf", "Pellet" }); /* "Leaf Wet", "Cryo" */ /* We use more hop forms then beerxml knows about, so we send known names */ /* instead of what we internally use. */ const QStringList hop_use({ "Mash", "First wort", "Boil", "Aroma", "Whirlpool", "Dry hop" }); const QStringList fermentable_type({ "Grain", "Sugar", "Extract", "Dry extract", "Adjunct" }); const QStringList fermentable_graintype({ "Base", "Roast", "Crystal", "Kilned", "Sour malt", "Special", "No malt" }); const QStringList yeast_type({ "Lager", "Ale", "Wheat", "Wine", "Champagne", "Other", "Other", "Other", "Other", "Other" }); const QStringList yeast_form({ "Liquid", "Dry", "Slant", "Culture", "Frozen", "Bottle", "Dry" }); const QStringList yeast_use({ "Primary", "Secondary", "Tertiary", "Bottle" }); const QStringList misc_type({ "Spice", "Herb", "Flavor", "Fining", "Water agent", "Yeast nutrient", "Other" }); const QStringList misc_use({ "Starter", "Mash", "Boil", "Primary", "Secondary", "Bottling" }); const QStringList step_type({ "Infusion", "Temperature", "Decoction" }); QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"), QDir::homePath() + "/" + product->name + ".xml", tr("Files (*.xml)")); if (fileName == 0) { QMessageBox::warning(this, tr("Save File"), tr("No XML file selected.")); return; } QFile file(fileName); file.open(QIODevice::WriteOnly); QXmlStreamWriter *xmlWriter = new QXmlStreamWriter(&file); xmlWriter->writeStartDocument(); xmlWriter->setAutoFormatting(true); xmlWriter->setAutoFormattingIndent(1); xmlWriter->writeStartElement("RECIPES"); xmlWriter->writeStartElement("RECIPE"); /* * Product basics */ xmlWriter->writeTextElement("VERSION", "1"); xmlWriter->writeTextElement("NAME", product->name); if (product->notes != "") xmlWriter->writeTextElement("NOTES", product->notes); xmlWriter->writeTextElement("TYPE", producttypes[product->type]); xmlWriter->writeTextElement("BREWER", "Anonymous"); xmlWriter->writeTextElement("BATCH_SIZE", QString::number(product->batch_size, 'f', 4)); xmlWriter->writeTextElement("BOIL_SIZE", QString::number(product->boil_size, 'f', 4)); xmlWriter->writeTextElement("BOIL_TIME", QString::number(product->boil_time, 'f', 3)); xmlWriter->writeTextElement("EFFICIENCY", QString::number(product->efficiency, 'f', 4)); xmlWriter->writeTextElement("EST_OG", QString::number(product->est_og, 'f', 3)); xmlWriter->writeTextElement("EST_FG", QString::number(product->est_fg, 'f', 3)); if (product->est_abv > 0) xmlWriter->writeTextElement("EST_ABV", QString::number(product->est_abv, 'f', 1)); if (product->est_color > 0) { xmlWriter->writeTextElement("EST_COLOR", QString::number(Utils::ebc_to_srm(product->est_color), 'f', 6)); xmlWriter->writeTextElement("COLOR_METHOD", color_method[product->color_method]); } if (product->est_ibu > 0) { xmlWriter->writeTextElement("EST_IBU", QString::number(product->est_ibu, 'f', 1)); xmlWriter->writeTextElement("IBU_METHOD", ibu_method[product->ibu_method]); } xmlWriter->writeStartElement("STYLE"); xmlWriter->writeTextElement("VERSION", "1"); xmlWriter->writeTextElement("NAME", product->st_name); xmlWriter->writeTextElement("CATEGORY", product->st_category); xmlWriter->writeTextElement("CATEGORY_NUMBER", QString::number(product->st_category_number, 'f', 0)); xmlWriter->writeTextElement("STYLE_LETTER", product->st_letter); xmlWriter->writeTextElement("STYLE_GUIDE", product->st_guide); xmlWriter->writeTextElement("TYPE", styletype[product->st_type]); xmlWriter->writeTextElement("OG_MIN", QString::number(product->st_og_min, 'f', 3)); xmlWriter->writeTextElement("OG_MAX", QString::number(product->st_og_max, 'f', 3)); xmlWriter->writeTextElement("FG_MIN", QString::number(product->st_fg_min, 'f', 3)); xmlWriter->writeTextElement("FG_MAX", QString::number(product->st_fg_max, 'f', 3)); xmlWriter->writeTextElement("IBU_MIN", QString::number(product->st_ibu_min, 'f', 0)); xmlWriter->writeTextElement("IBU_MAX", QString::number(product->st_ibu_max, 'f', 0)); xmlWriter->writeTextElement("COLOR_MIN", QString::number(Utils::ebc_to_srm(product->st_color_min), 'f', 2)); xmlWriter->writeTextElement("COLOR_MAX", QString::number(Utils::ebc_to_srm(product->st_color_max), 'f', 2)); xmlWriter->writeTextElement("CARB_MIN", QString::number(product->st_carb_min, 'f', 1)); xmlWriter->writeTextElement("CARB_MAX", QString::number(product->st_carb_max, 'f', 1)); xmlWriter->writeTextElement("ABV_MIN", QString::number(product->st_abv_min, 'f', 1)); xmlWriter->writeTextElement("ABV_MAX", QString::number(product->st_abv_max, 'f', 1)); xmlWriter->writeEndElement(); // STYLE xmlWriter->writeStartElement("EQUIPMENT"); xmlWriter->writeTextElement("VERSION", "1"); xmlWriter->writeTextElement("NAME", "Dummy Brewery"); xmlWriter->writeTextElement("BATCH_SIZE", QString::number(product->batch_size, 'f', 2)); xmlWriter->writeTextElement("BOIL_SIZE", QString::number(product->boil_size, 'f', 2)); xmlWriter->writeTextElement("BOIL_TIME", QString::number(product->boil_time, 'f', 0)); xmlWriter->writeEndElement(); // EQUIPMENT xmlWriter->writeStartElement("HOPS"); for (int i = 0; i < product->hops.size(); i++) { xmlWriter->writeStartElement("HOP"); xmlWriter->writeTextElement("VERSION", "1"); xmlWriter->writeTextElement("NAME", product->hops.at(i).h_name); xmlWriter->writeTextElement("ALPHA", QString::number(product->hops.at(i).h_alpha, 'f', 1)); xmlWriter->writeTextElement("AMOUNT", QString::number(product->hops.at(i).h_amount, 'f', 4)); xmlWriter->writeTextElement("USE", hop_use[product->hops.at(i).h_useat]); xmlWriter->writeTextElement("TIME", QString::number(product->hops.at(i).h_time, 'f', 0)); xmlWriter->writeTextElement("TYPE", hop_types[product->hops.at(i).h_type]); xmlWriter->writeTextElement("FORM", hop_forms[product->hops.at(i).h_form]); xmlWriter->writeTextElement("BETA", QString::number(product->hops.at(i).h_beta, 'f', 1)); xmlWriter->writeTextElement("HSI", QString::number(product->hops.at(i).h_hsi, 'f', 1)); xmlWriter->writeTextElement("ORIGIN", product->hops.at(i).h_origin); xmlWriter->writeEndElement(); } xmlWriter->writeEndElement(); // HOPS xmlWriter->writeStartElement("FERMENTABLES"); for (int i = 0; i < product->fermentables.size(); i++) { xmlWriter->writeStartElement("FERMENTABLE"); xmlWriter->writeTextElement("VERSION", "1"); xmlWriter->writeTextElement("NAME", product->fermentables.at(i).f_name); xmlWriter->writeTextElement("TYPE", fermentable_type[product->fermentables.at(i).f_type]); xmlWriter->writeTextElement("AMOUNT", QString::number(product->fermentables.at(i).f_amount, 'f', 4)); xmlWriter->writeTextElement("YIELD", QString::number(product->fermentables.at(i).f_yield, 'f', 1)); xmlWriter->writeTextElement("COLOR", QString::number(Utils::ebc_to_srm(product->fermentables.at(i).f_color), 'f', 1)); xmlWriter->writeTextElement("ADD_AFTER_BOIL", product->fermentables.at(i).f_add_after_boil ? "TRUE":"FALSE"); xmlWriter->writeTextElement("ORIGIN", product->fermentables.at(i).f_origin); xmlWriter->writeTextElement("SUPPLIER", product->fermentables.at(i).f_supplier); if (product->fermentables.at(i).f_coarse_fine_diff) xmlWriter->writeTextElement("COARSE_FINE_DIFF", QString::number(product->fermentables.at(i).f_coarse_fine_diff, 'f', 4)); if (product->fermentables.at(i).f_moisture) xmlWriter->writeTextElement("MOISTURE", QString::number(product->fermentables.at(i).f_moisture, 'f', 4)); if (product->fermentables.at(i).f_diastatic_power) xmlWriter->writeTextElement("DIASTATIC_POWER", QString::number(product->fermentables.at(i).f_diastatic_power, 'f', 4)); if (product->fermentables.at(i).f_protein) xmlWriter->writeTextElement("PROTEIN", QString::number(product->fermentables.at(i).f_protein, 'f', 4)); if (product->fermentables.at(i).f_max_in_batch) xmlWriter->writeTextElement("MAX_IN_BATCH", QString::number(product->fermentables.at(i).f_max_in_batch, 'f', 1)); xmlWriter->writeTextElement("RECOMMEND_MASH", product->fermentables.at(i).f_recommend_mash ? "TRUE":"FALSE"); xmlWriter->writeTextElement("GRAINTYPE", fermentable_graintype[product->fermentables.at(i).f_graintype]); xmlWriter->writeEndElement(); } xmlWriter->writeEndElement(); // FERMENTABLES xmlWriter->writeStartElement("MISCS"); for (int i = 0; i < product->miscs.size(); i++) { xmlWriter->writeStartElement("MISC"); xmlWriter->writeTextElement("VERSION", "1"); xmlWriter->writeTextElement("NAME", product->miscs.at(i).m_name); xmlWriter->writeTextElement("TYPE", misc_type[product->miscs.at(i).m_type]); xmlWriter->writeTextElement("AMOUNT", QString::number(product->miscs.at(i).m_amount, 'f', 5)); xmlWriter->writeTextElement("AMOUNT_IS_WEIGHT", product->miscs.at(i).m_amount_is_weight ? "TRUE":"FALSE"); xmlWriter->writeTextElement("USE", misc_use[product->miscs.at(i).m_use_use]); xmlWriter->writeTextElement("TIME", QString::number(product->miscs.at(i).m_time, 'f', 0)); xmlWriter->writeEndElement(); } xmlWriter->writeEndElement(); // MISCS xmlWriter->writeStartElement("YEASTS"); for (int i = 0; i < product->yeasts.size(); i++) { xmlWriter->writeStartElement("YEAST"); xmlWriter->writeTextElement("VERSION", "1"); xmlWriter->writeTextElement("NAME", product->yeasts.at(i).y_name); xmlWriter->writeTextElement("TYPE", yeast_type[product->yeasts.at(i).y_type]); xmlWriter->writeTextElement("FORM", yeast_form[product->yeasts.at(i).y_form]); xmlWriter->writeTextElement("AMOUNT", QString::number(product->yeasts.at(i).y_amount, 'f', 5)); xmlWriter->writeTextElement("AMOUNT_IS_WEIGHT", (product->yeasts.at(i).y_form == 1) ? "TRUE":"FALSE"); xmlWriter->writeTextElement("LABORATORY", product->yeasts.at(i).y_laboratory); xmlWriter->writeTextElement("PRODUCT_ID", product->yeasts.at(i).y_product_id); xmlWriter->writeTextElement("MIN_TEMPERATURE", QString::number(product->yeasts.at(i).y_min_temperature, 'f', 1)); xmlWriter->writeTextElement("MAX_TEMPERATURE", QString::number(product->yeasts.at(i).y_max_temperature, 'f', 1)); xmlWriter->writeTextElement("ATTENUATION", QString::number(product->yeasts.at(i).y_attenuation, 'f', 1)); xmlWriter->writeTextElement("ADD_TO_SECONDARY", (product->yeasts.at(i).y_use == 0) ? "FALSE":"TRUE"); xmlWriter->writeEndElement(); } xmlWriter->writeEndElement(); // YEASTS xmlWriter->writeStartElement("WATERS"); if (product->w1_amount > 0) { xmlWriter->writeStartElement("WATER"); xmlWriter->writeTextElement("VERSION", "1"); xmlWriter->writeTextElement("NAME", product->w1_name); xmlWriter->writeTextElement("AMOUNT", QString::number(product->w1_amount, 'f', 2)); xmlWriter->writeTextElement("CALCIUM", QString::number(product->w1_calcium, 'f', 2)); xmlWriter->writeTextElement("MAGNESIUM", QString::number(product->w1_magnesium, 'f', 2)); xmlWriter->writeTextElement("BICARBONATE", QString::number(product->w1_total_alkalinity * 1.22, 'f', 2)); xmlWriter->writeTextElement("SULFATE", QString::number(product->w1_sulfate, 'f', 2)); xmlWriter->writeTextElement("CHLORIDE", QString::number(product->w1_chloride, 'f', 2)); xmlWriter->writeTextElement("SODIUM", QString::number(product->w1_sodium, 'f', 2)); xmlWriter->writeTextElement("PH", QString::number(product->w1_ph, 'f', 2)); xmlWriter->writeTextElement("TOTAL_ALKALINITY", QString::number(product->w1_total_alkalinity, 'f', 2)); xmlWriter->writeEndElement(); if (product->w2_amount > 0) { xmlWriter->writeStartElement("WATER"); xmlWriter->writeTextElement("VERSION", "1"); xmlWriter->writeTextElement("NAME", product->w2_name); xmlWriter->writeTextElement("AMOUNT", QString::number(product->w2_amount, 'f', 2)); xmlWriter->writeTextElement("CALCIUM", QString::number(product->w2_calcium, 'f', 2)); xmlWriter->writeTextElement("MAGNESIUM", QString::number(product->w2_magnesium, 'f', 2)); xmlWriter->writeTextElement("BICARBONATE", QString::number(product->w2_total_alkalinity * 1.22, 'f', 2)); xmlWriter->writeTextElement("SULFATE", QString::number(product->w2_sulfate, 'f', 2)); xmlWriter->writeTextElement("CHLORIDE", QString::number(product->w2_chloride, 'f', 2)); xmlWriter->writeTextElement("SODIUM", QString::number(product->w2_sodium, 'f', 2)); xmlWriter->writeTextElement("PH", QString::number(product->w2_ph, 'f', 2)); xmlWriter->writeTextElement("TOTAL_ALKALINITY", QString::number(product->w2_total_alkalinity, 'f', 2)); xmlWriter->writeEndElement(); } } xmlWriter->writeEndElement(); // WATERS xmlWriter->writeStartElement("MASH"); xmlWriter->writeTextElement("VERSION", "1"); xmlWriter->writeTextElement("NAME", product->mash_name); xmlWriter->writeTextElement("GRAIN_TEMP", "10.0"); xmlWriter->writeTextElement("PH", QString::number(product->sparge_ph, 'f', 2)); xmlWriter->writeTextElement("SPARGE_TEMP", QString::number(product->sparge_temp, 'f', 2)); xmlWriter->writeStartElement("MASH_STEPS"); for (int i = 0; i < product->mashs.size(); i++) { xmlWriter->writeStartElement("MASH_STEP"); xmlWriter->writeTextElement("VERSION", "1"); xmlWriter->writeTextElement("NAME", product->mashs.at(i).step_name); xmlWriter->writeTextElement("TYPE", step_type[product->mashs.at(i).step_type]); if (product->mashs.at(i).step_type == 0) { xmlWriter->writeTextElement("INFUSE_AMOUNT", QString::number(product->mashs.at(i).step_infuse_amount, 'f', 3)); xmlWriter->writeTextElement("INFUSE_TEMP", QString::number(product->mashs.at(i).step_infuse_temp, 'f', 3)); } if (product->mashs.at(i).step_type == 2) { xmlWriter->writeTextElement("DECOCTION_AMT", QString::number(product->mashs.at(i).step_infuse_amount, 'f', 3)); } xmlWriter->writeTextElement("STEP_TEMP", QString::number(product->mashs.at(i).step_temp, 'f', 1)); xmlWriter->writeTextElement("STEP_TIME", QString::number(product->mashs.at(i).step_time, 'f', 1)); xmlWriter->writeTextElement("RAMP_TIME", QString::number(product->mashs.at(i).ramp_time, 'f', 1)); xmlWriter->writeTextElement("END_TEMP", QString::number(product->mashs.at(i).end_temp, 'f', 1)); xmlWriter->writeTextElement("PH", QString::number(product->mash_ph, 'f', 1)); xmlWriter->writeEndElement(); } xmlWriter->writeEndElement(); // MASH_STEPS xmlWriter->writeEndElement(); // MASH xmlWriter->writeEndElement(); // RECIPE xmlWriter->writeEndElement(); // RECIPES xmlWriter->writeEndDocument(); QMessageBox::information(this, tr("Save File"), tr("XML export ready")); file.close(); } void EditProduct::on_printButton_clicked() { PrinterDialog(PR_RECIPE, -1, this); }