# HG changeset patch # User Michiel Broek # Date 1653939880 -7200 # Node ID 52efe638e79a002b23df0e3dd91a9416be954ffe # Parent bfd4e07c20cbc99b0cc8c5414047dcf4ba42bbbb Added print checklist diff -r bfd4e07c20cb -r 52efe638e79a src/EditProduct.h --- a/src/EditProduct.h Sat May 28 21:08:09 2022 +0200 +++ b/src/EditProduct.h Mon May 30 21:44:40 2022 +0200 @@ -306,6 +306,7 @@ void calcPack(); void exportBeerXML(); void printProduct(); + void printChecklist(); }; #endif diff -r bfd4e07c20cb -r 52efe638e79a src/EditProductExport.cpp --- a/src/EditProductExport.cpp Sat May 28 21:08:09 2022 +0200 +++ b/src/EditProductExport.cpp Mon May 30 21:44:40 2022 +0200 @@ -268,6 +268,12 @@ } +void EditProduct::printChecklist() +{ + PrinterDialog(PR_CHECKLIST, -1, this); +} + + void EditProduct::on_exportButton_clicked() { exportBeerXML(); @@ -276,7 +282,7 @@ void EditProduct::on_printButton_clicked() { - printProduct(); + printChecklist(); } diff -r bfd4e07c20cb -r 52efe638e79a src/PrinterDialog.cpp --- a/src/PrinterDialog.cpp Sat May 28 21:08:09 2022 +0200 +++ b/src/PrinterDialog.cpp Mon May 30 21:44:40 2022 +0200 @@ -1522,12 +1522,604 @@ y += 20; } } + + } else if (p_job == PR_CHECKLIST) { + + double factor = 1.0 / product->divide_factor; + double mashwater = 0; + int numsalts = 0; + qDebug() << "print checklist"; + printHeader(&painter); + y = 120; + + /* First item, a yeast starter if needed, days before brewday. */ + if (product->starter_enable && product->prop_volume[0]) { + checkHeader(&painter, &y, tr("Make a yeast starter")); + int days = 0; + int last = 0; + QString s = ""; + for (int i = 0; i < 4; i++) { + if (product->prop_volume[i]) { + last = i; + if (product->prop_type[i] == STARTERS_STIRRED) + days += 2; + else if (product->prop_type[i] == STARTERS_SHAKEN) + days += 4; + else + days += 6; // Simple starter + } + } + checkLine(&painter, &y, QString(tr("Start about %1 days before brewday with the starter.")).arg(days)); + for (int i = 0; i < 4; i++) { + if (product->prop_volume[i]) { + checkLine(&painter, &y, QString(tr("Starter step %1 of %2 liter with SG %3")).arg(i+1).arg(product->prop_volume[i], 1, 'f', 3). + arg(product->starter_sg, 1, 'f', 3)); + QString w = tr(" until there is enough yeast"); + if (product->prop_type[i] == STARTERS_STIRRED) + checkLine(&painter, &y, QString(tr("about 24 hours on a stirplate"))+w); + else if (product->prop_type[i] == STARTERS_SHAKEN) + checkLine(&painter, &y, QString(tr("shake often for a few days"))+w); + else + checkLine(&painter, &y, QString(tr("let it rest for almost a week"))+w); + if (i < last) { + checkLine(&painter, &y, QString(tr("place starter in the fridge for 24 hours"))); + checkLine(&painter, &y, QString(tr("remove starter from the fridge and decant"))); + } else { + checkLine(&painter, &y, QString(tr("place starter in the fridge until brewday"))); + checkLine(&painter, &y, QString(tr("remove starter from the fridge and decant"))); + } + } + } + y += 20; + } + + checkHeader(&painter, &y, tr("Mash water and treatment")); + checkLine(&painter, &y, QString("%1 liter water %2").arg(product->w1_amount * factor, 1, 'f', 1).arg(product->w1_name)); + mashwater += product->w1_amount * factor; + if (product->w2_name != "" && product->w2_amount > 0) { + checkLine(&painter, &y, QString("%1 liter water %2").arg(product->w2_amount * factor, 1, 'f', 1).arg(product->w2_name)); + mashwater += product->w2_amount * factor; + } + for (int i = 0; i < product->miscs.size(); i++) { + if (product->miscs.at(i).m_type == MISC_TYPES_WATER_AGENT) { + QString unit = (product->miscs.at(i).m_amount_is_weight) ? "gr":"ml"; + checkLine(&painter, &y, QString("%1 %2 %3").arg(product->miscs.at(i).m_amount * 1000 * factor, 1, 'f', 2).arg(unit).arg(product->miscs.at(i).m_name)); + numsalts++; + } + } + y += 20; + + checkHeader(&painter, &y, tr("Weight and mill the malts")); + for (int i = 0; i < product->fermentables.size(); i++) { + if (product->fermentables.at(i).f_added == FERMENTABLE_ADDED_MASH) { + checkLine(&painter, &y, QString("%1 kg `%2` (%3)").arg(product->fermentables.at(i).f_amount * factor, 1, 'f', 3). + arg(product->fermentables.at(i).f_name).arg(product->fermentables.at(i).f_supplier)); + } + } + checkLine(&painter, &y, QString(tr("Mill the malts"))); + y += 20; + + checkHeader(&painter, &y, tr("Mash")); + int loop = 0; + double l, mvol = 0, msugars = 0; + for (int i = 0; i < product->mashs.size(); i++) { + if (product->mashs.at(i).step_type == 0) + mvol += product->mashs.at(i).step_infuse_amount * factor; // We need this later + if (loop == 0) { + if (product->mashs.at(i).step_type == 0) + l = product->mashs.at(i).step_infuse_amount * factor; + else + l = mashwater; + checkLine(&painter, &y, QString(tr("Heat %1 liter water to %2°C (%3 cm below kettle top)")) + .arg(mashwater, 1, 'f', 1).arg(product->mashs.at(i).step_infuse_temp, 1, 'f', 1) + .arg(Utils::kettle_cm(l, product->eq_tun_volume, product->eq_tun_height), 1, 'f', 1)); + if (numsalts > 0) + checkLine(&painter, &y, QString(tr("Add brouwzouten"))); + checkLine(&painter, &y, QString(tr("Add malts and dough-in"))); + for (int j = 0; j < product->hops.size(); j++) { + if (product->hops.at(j).h_useat == HOP_USEAT_MASH) { + checkLine(&painter, &y, QString(tr("Add %1 gram `%2` hop")).arg(product->hops.at(j).h_amount * 1000 * factor, 1, 'f', 1) + .arg(product->hops.at(j).h_name)); + } + } + for (int j = 0; j < product->miscs.size(); j++) { + if ((product->miscs.at(j).m_use_use == MISC_USES_MASH) && (product->miscs.at(j).m_type != MISC_TYPES_WATER_AGENT)) { + QString unit = (product->miscs.at(j).m_amount_is_weight) ? "gr":"ml"; + checkLine(&painter, &y, QString(tr("Add %1 %2 `%3`")).arg(product->miscs.at(j).m_amount * 1000 * factor, 1, 'f', 2) + .arg(unit).arg(product->miscs.at(j).m_name)); + } + } + } else { // loop > 0 + if (product->mashs.at(i).step_type == 0) { // Infusion + checkLine(&painter, &y, QString(tr("Add %1 liter water of %2°C")).arg(product->mashs.at(i).step_infuse_amount * factor, 1, 'f', 1) + .arg(product->mashs.at(i).step_infuse_temp, 1, 'f', 1)); + } else if (product->mashs.at(i).step_type == 1) { // Direct heat + checkLine(&painter, &y, QString(tr("Heat upto %1°C")).arg(product->mashs.at(i).step_temp, 1, 'f', 1)); + } else { // Decoction + checkLine(&painter, &y, QString(tr("Take, heat, boil and return %1 part of the mash")) + .arg(product->mashs.at(i).step_infuse_amount * factor, 1, 'f', 1)); + } + } + if (product->mashs.at(i).step_temp != product->mashs.at(i).end_temp) { + checkInput(&painter, &y, QString(tr("%1 minutes from %2°C to %3°C")).arg(product->mashs.at(i).step_time) + .arg(product->mashs.at(i).step_temp, 1, 'f', 1).arg(product->mashs.at(i).end_temp, 1, 'f', 1), QString(tr("Brix"))); + } else { + checkInput(&painter, &y, QString(tr("%1 minutes at %2°C")).arg(product->mashs.at(i).step_time) + .arg(product->mashs.at(i).step_temp, 1, 'f', 1), QString(tr("Brix"))); + } + if (loop == 0) + checkInput(&painter, &y, QString(tr("Measure and adjust pH (target %1 pH)")).arg(product->mash_ph, 1, 'f', 2), QString(tr("pH"))); + loop++; + } + double est_masg_sg = 0, sugardensity = 1.611, grainabsorbtion = 0; + for (int i = 0; i < product->fermentables.size(); i++) { + if (product->fermentables.at(i).f_added == FERMENTABLE_ADDED_MASH) { + double d = product->fermentables.at(i).f_amount * factor * (product->fermentables.at(i).f_yield / 100) * + (1 - product->fermentables.at(i).f_moisture / 100); + mvol += product->fermentables.at(i).f_amount * factor * (product->fermentables.at(i).f_moisture / 100); + grainabsorbtion += my_grain_absorbtion * product->fermentables.at(i).f_amount * factor; + msugars += d; + } + } + double v = msugars / sugardensity + mvol; + double plato = 1000.0 * msugars / (v * 10.0); // deg. Plato + double mash_sg = Utils::plato_to_sg(plato); + checkInput(&painter, &y, QString(tr("Target SG end mash: ")) + strDensity(mash_sg), QString(tr("SG"))); + if ((y + 140) > painter.device()->height()) { + printer->newPage(); + printHeader(&painter); + y = 120; + } else { + y += 20; + } + + checkHeader(&painter, &y, tr("Lauter and Sparge")); + checkLine(&painter, &y, QString(tr("Heat %1 liter sparge water to %2°C")).arg(product->sparge_volume * factor, 1, 'f', 1) + .arg(product->sparge_temp, 1, 'f', 1)); + checkInput(&painter, &y, QString(tr("Bring to %1 pH with %2 ml. `%3`")).arg(product->sparge_ph, 1, 'f', 2) + .arg(product->sparge_acid_amount * 1000 * factor, 1, 'f', 2).arg(my_acids.at(product->sparge_acid_type).name_en), QString(tr("pH"))); + checkLine(&painter, &y, QString(tr("Sparge with close to %1 liter water")) + .arg(((product->boil_size * factor) - mashwater + grainabsorbtion + product->eq_lauter_deadspace) * 1.03, 1, 'f', 1)); + checkInput(&painter, &y, QString(tr("Target volume in boil kettle: %1 liter (%2 cm below kettle top)")) + .arg(product->boil_size * factor * 1.04, 1, 'f', 1) + .arg(Utils::kettle_cm(product->boil_size * factor * 1.04, product->eq_kettle_volume, product->eq_kettle_height), 1, 'f', 1), + QString(tr("cm"))); + checkInput(&painter, &y, QString(tr("Target SG in boil kettle: ")) + strDensity(product->preboil_sg), QString(tr("SG"))); + checkInput(&painter, &y, "", QString(tr("pH"))); + for (int i = 0; i < product->hops.size(); i++) { + if (product->hops.at(i).h_useat == HOP_USEAT_FWH) { + checkLine(&painter, &y, QString(tr("Add %1 gr `%2` hop after sparge")).arg(product->hops.at(i).h_amount * 1000 * factor, 1, 'f', 1) + .arg(product->hops.at(i).h_name)); + } + } + + if (checkSplit(&painter, &y, 1)) + factor = 1; + /* Boil, how much space do we need */ + int lines = 0; + if (product->boil_time == 0) { + lines = 3; + } else { + lines = 5; + if (product->brew_cooling_method == 1) + lines++; + for (int i = 0; i < product->fermentables.size(); i++) { + if (product->fermentables.at(i).f_added == FERMENTABLE_ADDED_BOIL) + lines++; + } + for (int i = 0; i < product->hops.size(); i++) { + if (product->hops.at(i).h_useat == HOP_USEAT_BOIL || product->hops.at(i).h_useat == HOP_USEAT_AROMA) + lines++; + } + for (int i = 0; i < product->miscs.size(); i++) { + if (product->miscs.at(i).m_use_use == MISC_USES_BOIL) + lines++; + } + } + qDebug() << "check" << lines << y + (lines * 20) << painter.device()->height(); + if ((y + (lines * 20)) > painter.device()->height()) { + printer->newPage(); + printHeader(&painter); + y = 120; + } else { + y += 20; + } + checkHeader(&painter, &y, tr("Boil")); + if (product->boil_time > 0) { + checkLine(&painter, &y, QString(tr("Total boiltime: %1 minutes")).arg(product->boil_time, 1, 'f', 0)); + for (int i = product->boil_time; i >= 0; i--) { + if (i == 10) { + for (int j = 0; j < product->fermentables.size(); j++) { + if (product->fermentables.at(j).f_added == FERMENTABLE_ADDED_BOIL) + checkLine(&painter, &y, QString(tr("%1 kg `%2` at 10 minutes before end of boil")) + .arg(product->fermentables.at(j).f_amount * factor, 1, 'f', 3) + .arg(product->fermentables.at(j).f_name)); + } + if (product->brew_cooling_method == 1) + checkLine(&painter, &y, QString(tr("Place emersion chiller at 10 minutes before end of boil"))); + } + for (int j = 0; j < product->hops.size(); j++) { + if ((product->hops.at(j).h_useat == HOP_USEAT_BOIL || product->hops.at(j).h_useat == HOP_USEAT_AROMA) && product->hops.at(j).h_time == i) { + if (i == 0) + checkLine(&painter, &y, QString(tr("%1 gr `%2` at flameout")).arg(product->hops.at(j).h_amount * 1000 * factor, 1, 'f', 2) + .arg(product->hops.at(j).h_name)); + else + checkLine(&painter, &y, QString(tr("%1 gr `%2` at %3 minutes before end of boil")) + .arg(product->hops.at(j).h_amount * 1000 * factor, 1, 'f', 2).arg(product->hops.at(j).h_name).arg(i)); + } + } + for (int j = 0; j < product->miscs.size(); j++) { + if (product->miscs.at(j).m_use_use == MISC_USES_BOIL && product->miscs.at(j).m_time == i) { + QString unit = (product->miscs.at(j).m_amount_is_weight) ? "gr":"ml"; + if (i == 0) + checkLine(&painter, &y, QString(tr("%1 %2 `%3` at flameout")) + .arg(product->miscs.at(j).m_amount * 1000 * factor, 1, 'f', 2).arg(unit).arg(product->miscs.at(j).m_name)); + else + checkLine(&painter, &y, QString(tr("%1 %2 `%3` at %4 minutes before end of boil")) + .arg(product->miscs.at(j).m_amount * 1000 * factor, 1, 'f', 2).arg(unit).arg(product->miscs.at(j).m_name).arg(i)); + } + } + } + checkInput(&painter, &y, QString(tr("Target volume at end of boil: %1 liter (%2 cm below kettle top)")) + .arg(product->batch_size * 1.04 * factor, 1, 'f', 1) + .arg(Utils::kettle_cm(product->batch_size * 1.04 * factor, product->eq_kettle_volume, product->eq_kettle_height)), + QString(tr("cm"))); + checkInput(&painter, &y, QString(tr("Target SG at end of boil: ")) + strDensity(product->est_og3), QString(tr("SG"))); + checkInput(&painter, &y, "", QString(tr("pH"))); + if (checkSplit(&painter, &y, 2)) + factor = 1; + } else { + checkLine(&painter, &y, QString(tr("This is a `no-boil` recipe"))); + } + + /* Whirlpools and chilling */ + lines = 5; + if (product->brew_whirlpool9) + lines++; + if (product->brew_whirlpool7) + lines++; + if (product->brew_whirlpool6) + lines++; + if (product->brew_whirlpool2) + lines++; + for (int i = 0; i < product->hops.size(); i++) { + if (product->hops.at(i).h_useat == HOP_USEAT_WHIRLPOOL) + lines++; + } + if ((y + (lines * 20)) > painter.device()->height()) { + printer->newPage(); + printHeader(&painter); + y = 120; + } else { + y += 20; + } + if ((product->brew_whirlpool9 + product->brew_whirlpool7 + product->brew_whirlpool6 + product->brew_whirlpool2) > 0) { + checkHeader(&painter, &y, tr("Whirlpool(s) and cooling")); + if (product->brew_whirlpool9 > 0) + checkLine(&painter, &y, QString(tr("Wirlpool for %1 minutes. Keep temp above 85°C")).arg(product->brew_whirlpool9, 1, 'f', 0)); + if (product->brew_whirlpool7 > 0) + checkLine(&painter, &y, QString(tr("Wirlpool for %1 minutes. Keep temp between 72 and 79°C")).arg(product->brew_whirlpool7, 1, 'f', 0)); + if (product->brew_whirlpool6 > 0) + checkLine(&painter, &y, QString(tr("Wirlpool for %1 minutes. Keep temp between 60 and 66°C")).arg(product->brew_whirlpool6, 1, 'f', 0)); + for (int i = 0; i < product->hops.size(); i++) { + if (product->hops.at(i).h_useat == HOP_USEAT_WHIRLPOOL) + checkLine(&painter, &y, QString(tr("%1 gr `%2` for %3 minutes in the whirlpool")) + .arg(product->hops.at(i).h_amount * 1000 * factor, 1, 'f', 1).arg(product->hops.at(i).h_name) + .arg(product->hops.at(i).h_time)); + } + checkLine(&painter, &y, QString(tr("Cool to %1°C")).arg(product->brew_cooling_to, 1, 'f', 1)); + if (product->brew_whirlpool2 > 0) + checkLine(&painter, &y, QString(tr("Wirlpool for %1 minutes.")).arg(product->brew_whirlpool2, 1, 'f', 0)); + } else { + checkHeader(&painter, &y, tr("Cooling")); + checkLine(&painter, &y, QString(tr("Cool to %1°C")).arg(product->brew_cooling_to, 1, 'f', 1)); + } + checkLine(&painter, &y, QString(tr("Desinfect fermenter and pump and hoses if needed"))); + checkInput(&painter, &y, QString(tr("Transfer wort to fermenter")), QString(tr("Liter"))); + if (checkSplit(&painter, &y, 3)) + factor = 1; + + double climate = product->brew_cooling_to; + lines = 3; + for (int i = 0; i < product->yeasts.size(); i++) { + if (product->yeasts.at(i).y_use == YEAST_USE_PRIMARY) { + lines++; + if (product->yeasts.at(i).y_type == YEAST_TYPES_KVEIK && (product->yeasts.at(i).y_pitch_temperature > 0)) + lines++; + } + } + if (product->brew_aeration_type > 0) + lines++; + if (product->brew_fermenter_extrawater > 0) + lines++; + if ((y + (lines * 20)) > painter.device()->height()) { + printer->newPage(); + printHeader(&painter); + y = 120; + } else { + y += 20; + } + double dry = 0; + checkHeader(&painter, &y, tr("Yeast pitching and fermentation")); + for (int i = 0; i < product->yeasts.size(); i++) { + if (product->yeasts.at(i).y_use == YEAST_USE_PRIMARY) { + switch (product->yeasts.at(i).y_form) { + case YEAST_FORMS_LIQUID: checkLine(&painter, &y, QString(tr("%1 pack %2, `%3` yeast")).arg(product->yeasts.at(i).y_amount) + .arg(product->yeasts.at(i).y_product_id).arg(product->yeasts.at(i).y_name)); + break; + case YEAST_FORMS_DRY: dry += product->yeasts.at(i).y_amount * 1000 * factor; + case YEAST_FORMS_DRIED: checkLine(&painter, &y, QString(tr("%1 gram %2, `%3` yeast")) + .arg(product->yeasts.at(i).y_amount * 1000 * factor, 1, 'f', 1) + .arg(product->yeasts.at(i).y_product_id).arg(product->yeasts.at(i).y_name)); + break; + default: checkLine(&painter, &y, QString(tr("%1 ml %2, `%3` yeast")) + .arg(product->yeasts.at(i).y_amount * 1000 * factor, 1, 'f', 0) + .arg(product->yeasts.at(i).y_product_id).arg(product->yeasts.at(i).y_name)); + break; + } + if (product->yeasts.at(i).y_type == YEAST_TYPES_KVEIK && (product->yeasts.at(i).y_pitch_temperature > 0)) { + checkLine(&painter, &y, QString(tr("Pitch yeast at %1°C")).arg(product->yeasts.at(i).y_pitch_temperature, 1, 'f', 1)); + climate = product->yeasts.at(i).y_pitch_temperature; + } + } + } + if (dry > 0) { + checkLine(&painter, &y, QString(tr("Pitch yeast dry into the wort"))); + } else { + if (product->starter_enable && product->prop_volume[0]) + checkLine(&painter, &y, QString(tr("Add decanted yeast starter"))); + else + checkLine(&painter, &y, QString(tr("Add the yeast"))); + } + if (product->brew_fermenter_extrawater) + checkLine(&painter, &y, QString(tr("Add %1 liter water in the fermenter")).arg(product->brew_fermenter_extrawater * factor, 1, 'f', 1)); + if (product->brew_aeration_type > 0) + checkLine(&painter, &y, QString(tr("Aerate %1 minutes with %2")).arg(product->brew_aeration_time) + .arg((product->brew_aeration_type == 1) ? "air":"oxygen")); + checkLine(&painter, &y, QString(tr("Set fermentation start temperature to %1°C")).arg(climate, 1, 'f', 1)); + checkLine(&painter, &y, QString(tr("Start fermentation"))); + + /* During primary fermentation */ + lines = 0; + for (int i = 0; i < product->fermentables.size(); i++) + if (product->fermentables.at(i).f_added == FERMENTABLE_ADDED_FERMENTATION) + lines++; + for (int i = 0; i < product->miscs.size(); i++) + if (product->miscs.at(i).m_use_use == MISC_USES_PRIMARY) + lines++; + if (lines) { + if ((y + 20 + (lines * 20)) > painter.device()->height()) { + printer->newPage(); + printHeader(&painter); + y = 120; + } else { + y += 20; + } + checkHeader(&painter, &y, tr("Primary fermentation")); + for (int i = 0; i < product->fermentables.size(); i++) { + if (product->fermentables.at(i).f_added == FERMENTABLE_ADDED_FERMENTATION) + checkLine(&painter, &y, QString(tr("Add %1 kg `%2` on day 3 or 4")).arg(product->fermentables.at(i).f_amount * factor, 1, 'f', 3) + .arg(product->fermentables.at(i).f_name)); + } + for (int i = 0; i < product->miscs.size(); i++) { + if (product->miscs.at(i).m_use_use == MISC_USES_PRIMARY) { + QString unit = (product->miscs.at(i).m_amount_is_weight) ? "gr":"ml"; + checkLine(&painter, &y, QString(tr("Add %1 %2 `%3` on day 3 or 4")).arg(product->miscs.at(i).m_amount * factor, 1, 'f', 3) + .arg(unit).arg(product->miscs.at(i).m_name)); + } + } + } + if (checkSplit(&painter, &y, 4)) + factor = 1; + + /* During secondary fermentation, yeast */ + lines = 0; + for (int i = 0; i < product->yeasts.size(); i++) { + if (product->yeasts.at(i).y_use == YEAST_USE_SECONDARY) + lines++; + if (product->yeasts.at(i).y_harvest_time > 0) + lines++; + } + if (lines) { + if ((y + 20 + (lines * 20)) > painter.device()->height()) { + printer->newPage(); + printHeader(&painter); + y = 120; + } else { + y += 20; + } + checkHeader(&painter, &y, tr("Secondary fermentation")); + for (int i = 0; i < product->yeasts.size(); i++) { + if (product->yeasts.at(i).y_use == YEAST_USE_SECONDARY) { + if (product->yeasts.at(i).y_form == YEAST_FORMS_LIQUID) { + checkLine(&painter, &y, QString(tr("Add %1 pack %2, `%3` yeast (with starter if needed)")) + .arg(product->yeasts.at(i).y_amount).arg(product->yeasts.at(i).y_product_id).arg(product->yeasts.at(i).y_name)); + } else if (product->yeasts.at(i).y_form == YEAST_FORMS_DRY) { + checkLine(&painter, &y, QString(tr("Add %1 gram %2, `%3`")).arg(product->yeasts.at(i).y_amount * 1000 * factor, 1, 'f', 1) + .arg(product->yeasts.at(i).y_product_id).arg(product->yeasts.at(i).y_name)); + } else { + checkLine(&painter, &y, QString(tr("Add %1 gram %2, `%3` yeast (with starter if needed)")) + .arg(product->yeasts.at(i).y_amount * 1000 * factor, 1, 'f', 1) + .arg(product->yeasts.at(i).y_product_id).arg(product->yeasts.at(i).y_name)); + } + } + if (product->yeasts.at(i).y_harvest_time > 0) { + checkLine(&painter, &y, QString(tr("After %1 hours harvest yeast from the %2")).arg(product->yeasts.at(i).y_harvest_time) + .arg((product->yeasts.at(i).y_harvest_top > 0) ? "top":"bottom")); + } + } + } + if (checkSplit(&painter, &y, 5)) + factor = 1; + + /* During tertiary fermentation */ + lines = 0; + for (int i = 0; i < product->fermentables.size(); i++) + if (product->fermentables.at(i).f_added == FERMENTABLE_ADDED_LAGERING) + lines++; + for (int i = 0; i < product->hops.size(); i++) + if (product->hops.at(i).h_useat == HOP_USEAT_DRY_HOP) + lines++; + for (int i = 0; i < product->miscs.size(); i++) + if (product->miscs.at(i).m_use_use == MISC_USES_SECONDARY) + lines++; + for (int i = 0; i < product->yeasts.size(); i++) { + if (product->yeasts.at(i).y_use == YEAST_USE_TERTIARY) + lines++; + } + if (lines) { + if ((y + 20 + (lines * 20)) > painter.device()->height()) { + printer->newPage(); + printHeader(&painter); + y = 120; + } else { + y += 20; + } + checkHeader(&painter, &y, tr("Tertiary fermentation")); + for (int i = 0; i < product->fermentables.size(); i++) { + if (product->fermentables.at(i).f_added == FERMENTABLE_ADDED_LAGERING) + checkLine(&painter, &y, QString(tr("Add %1 kg `%2`")).arg(product->fermentables.at(i).f_amount * factor, 1, 'f', 3) + .arg(product->fermentables.at(i).f_name)); + } + for (int i = 0; i < product->hops.size(); i++) { + if (product->hops.at(i).h_useat == HOP_USEAT_DRY_HOP) { + checkLine(&painter, &y, QString(tr("Add %1 gram `%2` for %3 days")).arg(product->hops.at(i).h_amount * 1000 * factor, 1, 'f', 1) + .arg(product->hops.at(i).h_name).arg(product->hops.at(i).h_time / 1440)); + } + } + for (int i = 0; i < product->yeasts.size(); i++) { + if (product->yeasts.at(i).y_use == YEAST_USE_TERTIARY) { + if (product->yeasts.at(i).y_form == YEAST_FORMS_LIQUID) { + checkLine(&painter, &y, QString(tr("Add %1 pack %2, `%3` yeast (with starter if needed)")) + .arg(product->yeasts.at(i).y_amount).arg(product->yeasts.at(i).y_product_id).arg(product->yeasts.at(i).y_name)); + } else if (product->yeasts.at(i).y_form == YEAST_FORMS_DRY) { + checkLine(&painter, &y, QString(tr("Add %1 gram %2, `%3`")).arg(product->yeasts.at(i).y_amount * 1000 * factor, 1, 'f', 1) + .arg(product->yeasts.at(i).y_product_id).arg(product->yeasts.at(i).y_name)); + } else { + checkLine(&painter, &y, QString(tr("Add %1 ml %2, `%3` yeast (with starter if needed)")) + .arg(product->yeasts.at(i).y_amount * 1000 * factor, 1, 'f', 1) + .arg(product->yeasts.at(i).y_product_id).arg(product->yeasts.at(i).y_name)); + } + } + } + for (int i = 0; i < product->miscs.size(); i++) { + if (product->miscs.at(i).m_use_use == MISC_USES_SECONDARY) { + QString unit = (product->miscs.at(i).m_amount_is_weight) ? "gr":"ml"; + checkLine(&painter, &y, QString(tr("Add %1 %2 `%3` for %4 days")).arg(product->miscs.at(i).m_amount * factor, 1, 'f', 3) + .arg(unit).arg(product->miscs.at(i).m_name).arg(product->miscs.at(i).m_time / 1440)); + } + } + } + if (checkSplit(&painter, &y, 6)) + factor = 1; + + /* During packaging */ + lines = 0; + for (int i = 0; i < product->fermentables.size(); i++) + if (product->fermentables.at(i).f_added >= FERMENTABLE_ADDED_BOTTLE) + lines++; + for (int i = 0; i < product->miscs.size(); i++) + if (product->miscs.at(i).m_use_use == MISC_USES_BOTTLING) + lines++; + for (int i = 0; i < product->yeasts.size(); i++) + if (product->yeasts.at(i).y_use == YEAST_USE_BOTTLE) + lines++; + if (lines) { + if ((y + 20 + (lines * 20)) > painter.device()->height()) { + printer->newPage(); + printHeader(&painter); + y = 120; + } else { + y += 20; + } + checkHeader(&painter, &y, tr("Packaging")); + for (int i = 0; i < product->fermentables.size(); i++) { + if (product->fermentables.at(i).f_added == FERMENTABLE_ADDED_BOTTLE) + checkLine(&painter, &y, QString(tr("Bottling add %1 kg `%2` with %3 liter water")) + .arg(product->fermentables.at(i).f_amount * factor, 1, 'f', 3) + .arg(product->fermentables.at(i).f_name).arg(product->bottle_priming_water * factor, 1, 'f', 3)); + if (product->fermentables.at(i).f_added == FERMENTABLE_ADDED_KEGS) + checkLine(&painter, &y, QString(tr("Kegging add %1 kg `%2` with %3 liter water")) + .arg(product->fermentables.at(i).f_amount * factor, 1, 'f', 3) + .arg(product->fermentables.at(i).f_name).arg(product->keg_priming_water * factor, 1, 'f', 3)); + } + for (int i = 0; i < product->yeasts.size(); i++) { + if (product->yeasts.at(i).y_use == YEAST_USE_BOTTLE) { + if (product->yeasts.at(i).y_form == YEAST_FORMS_LIQUID) { + checkLine(&painter, &y, QString(tr("Add %1, `%2` as bottle yeast")) + .arg(product->yeasts.at(i).y_product_id).arg(product->yeasts.at(i).y_name)); + } else if (product->yeasts.at(i).y_form == YEAST_FORMS_DRY) { + checkLine(&painter, &y, QString(tr("Add %1 gram %2, `%3` as bottle yeast")) + .arg(product->yeasts.at(i).y_amount * 1000 * factor, 1, 'f', 1) + .arg(product->yeasts.at(i).y_product_id).arg(product->yeasts.at(i).y_name)); + } else { + checkLine(&painter, &y, QString(tr("Add %1 ml %2, `%3` as bottle yeast")) + .arg(product->yeasts.at(i).y_amount * 1000 * factor, 1, 'f', 1) + .arg(product->yeasts.at(i).y_product_id).arg(product->yeasts.at(i).y_name)); + } + } + } + for (int i = 0; i < product->miscs.size(); i++) { + if (product->miscs.at(i).m_use_use == MISC_USES_BOTTLING) { + QString unit = (product->miscs.at(i).m_amount_is_weight) ? "gr":"ml"; + checkLine(&painter, &y, QString(tr("Add %1 %2 `%3` during bottling")).arg(product->miscs.at(i).m_amount * factor, 1, 'f', 3) + .arg(unit).arg(product->miscs.at(i).m_name)); + } + } + } } painter.end(); } +void PrinterDialog::checkHeader(QPainter *painter, qreal *y, QString text) +{ + painter->setFont(QFont("Arial", 10, QFont::Bold)); + painter->setPen(Qt::black); + painter->drawText(30, *y, 700, 20, Qt::AlignLeft, text); + painter->setFont(QFont("Arial", 10, QFont::Normal)); + *y += 20; +} + + +/* + * Draw a checkbox and text. + */ +void PrinterDialog::checkLine(QPainter *painter, qreal *y, QString text) +{ + painter->drawRect( 4, *y, 16, 16); + painter->drawText(30, *y,650, 20, Qt::AlignLeft, text); + *y += 20; +} + + +void PrinterDialog::checkInput(QPainter *painter, qreal *y, QString text, QString prompt) +{ + if (text != "") { + painter->drawRect( 4, *y, 16, 16); + painter->drawText(30, *y,500, 20, Qt::AlignLeft, text); + } + painter->drawText(515, *y, 150, 20, Qt::AlignRight, QString(tr("Measured:")) + QString(" _________")); + painter->drawText(675, *y, 60, 20, Qt::AlignLeft, prompt); + *y += 20; +} + + +bool PrinterDialog::checkSplit(QPainter *painter, qreal *y, int moment) +{ + if (product->divide_type && product->divide_type == moment) { + *y += 20; + painter->setFont(QFont("Helvetica", 14, QFont::Bold)); + painter->drawText(0, *y, 735, 20, Qt::AlignCenter, QString(tr("%1 split the batch here!")).arg(prod_split[product->divide_type])); + painter->setFont(QFont("Arial", 10, QFont::Normal)); + *y += 26; + return true; + } + return false; +} + + QString PrinterDialog::strDiff(double v1, double v2, int decimals, QString suffix) { return QString("%1%2%3").arg((v2 > v1) ? "+":"").arg(v2 - v1, 1, 'f', decimals).arg(suffix); @@ -1563,7 +2155,7 @@ painter->drawText(120, 0, 500, 40, Qt::AlignLeft, tr("Yeastbank") + " " + my_brewery_name); } else if (p_job == PR_RECIPE) { painter->drawText(120, 0, 500, 40, Qt::AlignLeft, recipe->name); - } else if (p_job == PR_PRODUCT) { + } else if (p_job == PR_PRODUCT || p_job == PR_CHECKLIST) { painter->drawText(120, 0, 500, 40, Qt::AlignLeft, product->code + " " + product->name); } else { painter->drawText(120, 0, 500, 40, Qt::AlignLeft, "?? " + my_brewery_name); @@ -1576,7 +2168,7 @@ painter->drawText(120,55, 80, 20, Qt::AlignLeft, tr("Beer style")); painter->drawText(200,55, 400, 20, Qt::AlignLeft, ": " + recipe->st_name); } - if (p_job == PR_PRODUCT) { + if (p_job == PR_PRODUCT || p_job == PR_CHECKLIST) { painter->drawText(120,55, 80, 20, Qt::AlignLeft, tr("Beer style")); painter->drawText(200,55, 400, 20, Qt::AlignLeft, ": " + product->st_name); } diff -r bfd4e07c20cb -r 52efe638e79a src/PrinterDialog.h --- a/src/PrinterDialog.h Sat May 28 21:08:09 2022 +0200 +++ b/src/PrinterDialog.h Mon May 30 21:44:40 2022 +0200 @@ -6,7 +6,7 @@ #include -enum JobType { PR_SUPPLIES, PR_YEASTBANK, PR_RECIPE, PR_PRODUCT }; +enum JobType { PR_SUPPLIES, PR_YEASTBANK, PR_RECIPE, PR_PRODUCT, PR_CHECKLIST }; namespace Ui { class PrinterDialog; @@ -39,6 +39,10 @@ void printHeader(QPainter *painter); QString strDensity(double density); QString strDiff(double v1, double v2, int decimals, QString suffix); + void checkHeader(QPainter *painter, qreal *y, QString text); + void checkLine(QPainter *painter, qreal *y, QString text); + void checkInput(QPainter *painter, qreal *y, QString text, QString prompt); + bool checkSplit(QPainter *painter, qreal *y, int moment); }; #endif