|
1 /** |
|
2 * EditProduct.cpp is part of bmsapp. |
|
3 * |
|
4 * tab 6, yeasts. |
|
5 * |
|
6 * bmsapp is free software: you can redistribute it and/or modify |
|
7 * it under the terms of the GNU General Public License as published by |
|
8 * the Free Software Foundation, either version 3 of the License, or |
|
9 * (at your option) any later version. |
|
10 * |
|
11 * bmsapp is distributed in the yeaste that it will be useful, |
|
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14 * GNU General Public License for more details. |
|
15 * |
|
16 * You should have received a copy of the GNU General Public License |
|
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
18 */ |
|
19 |
|
20 |
|
21 bool EditProduct::yeast_sort_test(const Yeasts &D1, const Yeasts &D2) |
|
22 { |
|
23 if (D1.y_use > D2.y_use) |
|
24 return false; |
|
25 if (D1.y_use < D2.y_use) |
|
26 return true; |
|
27 return (D1.y_amount > D2.y_amount); |
|
28 } |
|
29 |
|
30 |
|
31 void EditProduct::refreshYeasts() |
|
32 { |
|
33 QString w; |
|
34 QWidget* pWidget; |
|
35 QHBoxLayout* pLayout; |
|
36 QTableWidgetItem *item; |
|
37 |
|
38 qDebug() << "refreshYeasts" << product->yeasts.size(); |
|
39 std::sort(product->yeasts.begin(), product->yeasts.end(), yeast_sort_test); |
|
40 |
|
41 const QStringList labels({tr("Yeast"), tr("Laboratory"), tr("Code"), tr("Type"), tr("Use for"), tr("Min. °C"), tr("Max. °C"), |
|
42 tr("Tol. %"), tr("Attn. %"), tr("Amount"), tr("Delete"), tr("Edit") }); |
|
43 |
|
44 ui->yeastsTable->setColumnCount(12); |
|
45 ui->yeastsTable->setColumnWidth(0, 200); /* Yeast */ |
|
46 ui->yeastsTable->setColumnWidth(1, 125); /* Laboratory */ |
|
47 ui->yeastsTable->setColumnWidth(2, 80); /* Code */ |
|
48 ui->yeastsTable->setColumnWidth(3, 80); /* Type */ |
|
49 ui->yeastsTable->setColumnWidth(4, 100); /* Usage */ |
|
50 ui->yeastsTable->setColumnWidth(5, 60); /* Min. */ |
|
51 ui->yeastsTable->setColumnWidth(6, 60); /* Max. */ |
|
52 ui->yeastsTable->setColumnWidth(7, 60); /* Tolerance */ |
|
53 ui->yeastsTable->setColumnWidth(8, 60); /* Attenuation */ |
|
54 ui->yeastsTable->setColumnWidth(9, 90); /* Amount */ |
|
55 ui->yeastsTable->setColumnWidth(10, 80); /* Delete */ |
|
56 ui->yeastsTable->setColumnWidth(11, 80); /* Edit */ |
|
57 ui->yeastsTable->setHorizontalHeaderLabels(labels); |
|
58 ui->yeastsTable->verticalHeader()->hide(); |
|
59 ui->yeastsTable->setRowCount(product->yeasts.size()); |
|
60 |
|
61 for (int i = 0; i < product->yeasts.size(); i++) { |
|
62 |
|
63 ui->yeastsTable->setItem(i, 0, new QTableWidgetItem(product->yeasts.at(i).y_name)); |
|
64 ui->yeastsTable->setItem(i, 1, new QTableWidgetItem(product->yeasts.at(i).y_laboratory)); |
|
65 ui->yeastsTable->setItem(i, 2, new QTableWidgetItem(product->yeasts.at(i).y_product_id)); |
|
66 |
|
67 item = new QTableWidgetItem(yeast_forms[product->yeasts.at(i).y_form]); |
|
68 item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter); |
|
69 ui->yeastsTable->setItem(i, 3, item); |
|
70 |
|
71 item = new QTableWidgetItem(yeast_use[product->yeasts.at(i).y_use]); |
|
72 item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter); |
|
73 ui->yeastsTable->setItem(i, 4, item); |
|
74 |
|
75 item = new QTableWidgetItem(QString("%1").arg(product->yeasts.at(i).y_min_temperature, 2, 'f', 1, '0')); |
|
76 item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); |
|
77 ui->yeastsTable->setItem(i, 5, item); |
|
78 |
|
79 item = new QTableWidgetItem(QString("%1").arg(product->yeasts.at(i).y_max_temperature, 2, 'f', 1, '0')); |
|
80 item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); |
|
81 ui->yeastsTable->setItem(i, 6, item); |
|
82 |
|
83 item = new QTableWidgetItem(QString("%1").arg(product->yeasts.at(i).y_tolerance, 2, 'f', 1, '0')); |
|
84 item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); |
|
85 ui->yeastsTable->setItem(i, 7, item); |
|
86 |
|
87 item = new QTableWidgetItem(QString("%1").arg(product->yeasts.at(i).y_attenuation, 2, 'f', 1, '0')); |
|
88 item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); |
|
89 ui->yeastsTable->setItem(i, 8, item); |
|
90 |
|
91 if (product->yeasts.at(i).y_form == 0) |
|
92 item = new QTableWidgetItem(QString("%1 pack").arg(product->yeasts.at(i).y_amount, 1, 'f', 0, '0')); |
|
93 else if (product->yeasts.at(i).y_form == 1) |
|
94 item = new QTableWidgetItem(QString("%1 gr").arg(product->yeasts.at(i).y_amount * 1000.0, 3, 'f', 2, '0')); |
|
95 else |
|
96 item = new QTableWidgetItem(QString("%1 ml").arg(product->yeasts.at(i).y_amount * 1000.0, 3, 'f', 2, '0')); |
|
97 item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); |
|
98 ui->yeastsTable->setItem(i, 9, item); |
|
99 |
|
100 pWidget = new QWidget(); |
|
101 QPushButton* btn_dele = new QPushButton(); |
|
102 btn_dele->setObjectName(QString("%1").arg(i)); /* Send row with the button */ |
|
103 btn_dele->setText(tr("Delete")); |
|
104 connect(btn_dele, SIGNAL(clicked()), this, SLOT(deleteYeastRow_clicked())); |
|
105 pLayout = new QHBoxLayout(pWidget); |
|
106 pLayout->addWidget(btn_dele); |
|
107 pLayout->setContentsMargins(5, 0, 5, 0); |
|
108 pWidget->setLayout(pLayout); |
|
109 ui->yeastsTable->setCellWidget(i, 10, pWidget); |
|
110 |
|
111 pWidget = new QWidget(); |
|
112 QPushButton* btn_edit = new QPushButton(); |
|
113 btn_edit->setObjectName(QString("%1").arg(i)); /* Send row with the button */ |
|
114 btn_edit->setText(tr("Edit")); |
|
115 connect(btn_edit, SIGNAL(clicked()), this, SLOT(editYeastRow_clicked())); |
|
116 pLayout = new QHBoxLayout(pWidget); |
|
117 pLayout->addWidget(btn_edit); |
|
118 pLayout->setContentsMargins(5, 0, 5, 0); |
|
119 pWidget->setLayout(pLayout); |
|
120 ui->yeastsTable->setCellWidget(i, 11, pWidget); |
|
121 } |
|
122 } |
|
123 |
|
124 |
|
125 /* |
|
126 * The results are not stored line in EditProduct. This is just a hint. |
|
127 */ |
|
128 void EditProduct::calcYeast() |
|
129 { |
|
130 double sg = product->est_og; |
|
131 double plato = Utils::sg_to_plato(sg); |
|
132 double volume = product->batch_size * 0.9; // Volume min trub chiller loss. |
|
133 bool maybe_starter = false; |
|
134 double pitchrate = 0.75; |
|
135 double initcells = 0; |
|
136 |
|
137 qDebug() << "calcYeast()"; |
|
138 ui->yeastProcedure->setCurrentIndex(0); |
|
139 |
|
140 if (product->yeasts.size() == 0) |
|
141 return; // No yeast in product. |
|
142 |
|
143 for (int i = 0; i < product->yeasts.size(); i++) { |
|
144 if (product->yeasts.at(i).y_use == 0) { // Primary |
|
145 if (product->yeasts.at(i).y_form == 1) { |
|
146 /* |
|
147 * Dry yeast, build the formule with the yeast parameters. |
|
148 * Based on https://www.lallemandbrewing.com/en/canada/brewers-corner/brewing-tools/pitching-rate-calculator/ |
|
149 */ |
|
150 ui->yeastProcedure->setCurrentIndex(2); |
|
151 ui->lo_gr_hlEdit->setValue(product->yeasts.at(i).y_gr_hl_lo); |
|
152 ui->hi_gr_hlEdit->setValue(product->yeasts.at(i).y_gr_hl_hi); |
|
153 ui->lo_sgEdit->setValue(product->yeasts.at(i).y_sg_lo); |
|
154 ui->hi_sgEdit->setValue(product->yeasts.at(i).y_sg_hi); |
|
155 double og = product->yeasts.at(i).y_sg_lo; |
|
156 double f1 = product->yeasts.at(i).y_gr_hl_lo / 100.0; |
|
157 double f2 = round(f1 / 5 * 1000000.0) / 1000000.0; |
|
158 double multiplier = (sg <= og) ? f1 : (f1 + f2 * (sg - og) / 0.008); |
|
159 qDebug() << " sg:" << sg << "og:" << og << "f1:" << f1 << "f2:" << f2 << "multiplier:" << multiplier; |
|
160 double yeast_grams = round(volume * multiplier * 100.0) / 100.0; // * (100 / dataRecord.starter_viability), 2); |
|
161 double yeast_gr_hl = round((yeast_grams / (volume * 0.01)) * 100.0) / 100.0; |
|
162 ui->need_grEdit->setValue(yeast_grams); |
|
163 ui->pitch_grEdit->setValue(yeast_gr_hl); |
|
164 qDebug() << " need" << yeast_grams << "grams, gr/hl:" << yeast_gr_hl; |
|
165 return; |
|
166 } else { |
|
167 /* |
|
168 * Liquid, slant, culture etc. |
|
169 * pitchrate see https://www.brewersfriend.com/yeast-pitch-rate-and-starter-calculator/ |
|
170 * and http://braukaiser.com/blog/blog/2012/11/03/estimating-yeast-growth/ |
|
171 */ |
|
172 ui->yeastProcedure->setCurrentIndex(1); |
|
173 if (product->yeasts.at(i).y_type == 0) { // Lager yeast |
|
174 pitchrate = 1.5; |
|
175 if (sg > 1.060) |
|
176 pitchrate = 2.0; |
|
177 } else if (product->yeasts.at(i).y_type == 6) { // Real Kveik |
|
178 pitchrate = 0.075; |
|
179 } else { |
|
180 pitchrate = 0.75; |
|
181 if (sg > 1.060) |
|
182 pitchrate = 1.0; |
|
183 } |
|
184 if (product->yeasts.at(i).y_form == 0) |
|
185 initcells = (product->yeasts.at(i).y_cells / 1000000000) * product->yeasts.at(i).y_amount * 0.97; // 97% viability assumed. |
|
186 else |
|
187 initcells = (product->yeasts.at(i).y_cells / 1000000) * product->yeasts.at(i).y_amount * 0.97; |
|
188 |
|
189 double needed = round(pitchrate * volume * plato * 10.0) / 10.0; |
|
190 double starter = 0; |
|
191 if (needed > initcells) { |
|
192 maybe_starter = true; |
|
193 starter = round(needed / 2.0) / 100.0; // A very rough starter size estimate. |
|
194 } |
|
195 |
|
196 ui->pitchrateEdit->setValue(pitchrate); |
|
197 ui->initcellsEdit->setValue(initcells); |
|
198 ui->targetcellsEdit->setValue(needed); |
|
199 ui->starterEdit->setValue(starter); |
|
200 |
|
201 qDebug() << " pitchrate:" << pitchrate << "needed:" << needed << "initcells:" << initcells << "starter" << maybe_starter << "size" << starter; |
|
202 } |
|
203 break; |
|
204 } |
|
205 } |
|
206 } |
|
207 |
|
208 |
|
209 void EditProduct::addYeastRow_clicked() |
|
210 { |
|
211 Yeasts newy; |
|
212 |
|
213 qDebug() << "Add yeast row"; |
|
214 |
|
215 for (int i = 0; i < product->yeasts.size(); i++) { |
|
216 if (product->yeasts.at(i).y_amount == 0) |
|
217 return; // Add only one at a time. |
|
218 } |
|
219 |
|
220 newy.y_name = "Select one"; |
|
221 newy.y_laboratory = ""; |
|
222 newy.y_product_id = ""; |
|
223 newy.y_amount = 0; |
|
224 newy.y_type = 0; |
|
225 newy.y_form = 0; |
|
226 newy.y_min_temperature = 0; |
|
227 newy.y_max_temperature = 0; |
|
228 newy.y_flocculation = 0; |
|
229 newy.y_attenuation = 0; |
|
230 newy.y_cells = 0; |
|
231 newy.y_tolerance = 0; |
|
232 newy.y_inventory = 0; |
|
233 newy.y_use = 0; |
|
234 newy.y_sta1 = false; |
|
235 newy.y_bacteria = false; |
|
236 newy.y_harvest_top = false; |
|
237 newy.y_harvest_time = 0; |
|
238 newy.y_pitch_temperature = 0; |
|
239 newy.y_pofpos = false; |
|
240 newy.y_zymocide = 0; |
|
241 newy.y_gr_hl_lo = 0; |
|
242 newy.y_sg_lo = 0; |
|
243 newy.y_gr_hl_hi = 0; |
|
244 newy.y_sg_hi = 0; |
|
245 newy.y_cost = 0; |
|
246 |
|
247 product->yeasts.append(newy); |
|
248 emit refreshAll(); |
|
249 } |
|
250 |
|
251 |
|
252 void EditProduct::deleteYeastRow_clicked() |
|
253 { |
|
254 if (product->locked || product->yeasts.size() < 1) |
|
255 return; |
|
256 |
|
257 QPushButton *pb = qobject_cast<QPushButton *>(QObject::sender()); |
|
258 int row = pb->objectName().toInt(); |
|
259 qDebug() << "Delete yeast row" << row << product->yeasts.size(); |
|
260 |
|
261 int rc = QMessageBox::warning(this, tr("Delete yeast"), tr("Delete %1").arg(product->yeasts.at(row).y_name), |
|
262 QMessageBox::Yes | QMessageBox::No, QMessageBox::No); |
|
263 if (rc == QMessageBox::No) |
|
264 return; |
|
265 |
|
266 product->yeasts.removeAt(row); |
|
267 is_changed(); |
|
268 emit refreshAll(); |
|
269 } |
|
270 |
|
271 |
|
272 void EditProduct::yeast_amount_changed(double val) |
|
273 { |
|
274 QTableWidgetItem *item; |
|
275 |
|
276 qDebug() << "yeast_amount_changed()" << product->yeasts_row << val; |
|
277 |
|
278 if (product->yeasts.at(product->yeasts_row).y_form == 0) { |
|
279 product->yeasts[product->yeasts_row].y_amount = val; |
|
280 item = new QTableWidgetItem(QString("%1 pack").arg(val, 1, 'f', 0, '0')); |
|
281 } else if (product->yeasts.at(product->yeasts_row).y_form == 1) { |
|
282 product->yeasts[product->yeasts_row].y_amount = val / 1000.0; |
|
283 item = new QTableWidgetItem(QString("%1 gr").arg(val, 3, 'f', 2, '0')); |
|
284 } else { |
|
285 product->yeasts[product->yeasts_row].y_amount = val / 1000.0; |
|
286 item = new QTableWidgetItem(QString("%1 ml").arg(val, 3, 'f', 2, '0')); |
|
287 } |
|
288 item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); |
|
289 ui->yeastsTable->setItem(product->yeasts_row, 9, item); |
|
290 |
|
291 calcYeast(); |
|
292 is_changed(); |
|
293 } |
|
294 |
|
295 |
|
296 void EditProduct::yeast_select_changed(int val) |
|
297 { |
|
298 QSqlQuery query; |
|
299 bool instock = yinstockEdit->isChecked(); |
|
300 QString w; |
|
301 QTableWidgetItem *item; |
|
302 |
|
303 if (val < 1) |
|
304 return; |
|
305 |
|
306 qDebug() << "yeast_select_changed()" << product->yeasts_row << val << instock; |
|
307 |
|
308 /* |
|
309 * Search the yeast pointed by the index and instock flag. |
|
310 */ |
|
311 QString sql = "SELECT name,laboratory,product_id,type,form,min_temperature,max_temperature,flocculation,attenuation," |
|
312 "cells,tolerance,sta1,bacteria,harvest_top,harvest_time,pitch_temperature,pofpos,zymocide," |
|
313 "gr_hl_lo,sg_lo,gr_hl_hi,sg_hi,cost FROM inventory_yeasts "; |
|
314 if (instock) |
|
315 sql.append("WHERE inventory > 0 "); |
|
316 sql.append("ORDER BY laboratory,product_id,name"); |
|
317 query.prepare(sql); |
|
318 query.exec(); |
|
319 query.first(); |
|
320 for (int i = 0; i < (val - 1); i++) { |
|
321 query.next(); |
|
322 } |
|
323 qDebug() << "found" << query.value(0).toString() << query.value(2).toString(); |
|
324 |
|
325 /* |
|
326 * Replace the yeast record contents |
|
327 */ |
|
328 product->yeasts[product->yeasts_row].y_name = query.value(0).toString(); |
|
329 product->yeasts[product->yeasts_row].y_laboratory = query.value(1).toString(); |
|
330 product->yeasts[product->yeasts_row].y_product_id = query.value(2).toString(); |
|
331 product->yeasts[product->yeasts_row].y_type = query.value(3).toInt(); |
|
332 product->yeasts[product->yeasts_row].y_form = query.value(4).toInt(); |
|
333 product->yeasts[product->yeasts_row].y_min_temperature = query.value(5).toDouble(); |
|
334 product->yeasts[product->yeasts_row].y_max_temperature = query.value(6).toDouble(); |
|
335 product->yeasts[product->yeasts_row].y_flocculation = query.value(7).toInt(); |
|
336 product->yeasts[product->yeasts_row].y_attenuation = query.value(8).toDouble(); |
|
337 product->yeasts[product->yeasts_row].y_cells = query.value(9).toDouble(); |
|
338 product->yeasts[product->yeasts_row].y_tolerance = query.value(10).toDouble(); |
|
339 product->yeasts[product->yeasts_row].y_sta1 = query.value(11).toInt() ? true:false; |
|
340 product->yeasts[product->yeasts_row].y_bacteria = query.value(12).toInt() ? true:false; |
|
341 product->yeasts[product->yeasts_row].y_harvest_top = query.value(13).toInt() ? true:false; |
|
342 product->yeasts[product->yeasts_row].y_harvest_time = query.value(14).toInt(); |
|
343 product->yeasts[product->yeasts_row].y_pitch_temperature = query.value(15).toDouble(); |
|
344 product->yeasts[product->yeasts_row].y_pofpos = query.value(16).toInt() ? true:false; |
|
345 product->yeasts[product->yeasts_row].y_zymocide = query.value(17).toInt(); |
|
346 product->yeasts[product->yeasts_row].y_gr_hl_lo = query.value(18).toInt(); |
|
347 product->yeasts[product->yeasts_row].y_sg_lo = query.value(19).toDouble(); |
|
348 product->yeasts[product->yeasts_row].y_gr_hl_hi = query.value(20).toInt(); |
|
349 product->yeasts[product->yeasts_row].y_sg_hi = query.value(21).toDouble(); |
|
350 product->yeasts[product->yeasts_row].y_cost = query.value(22).toDouble(); |
|
351 |
|
352 /* |
|
353 * Update the visible fields |
|
354 */ |
|
355 ynameEdit->setText(product->yeasts.at(product->yeasts_row).y_name); |
|
356 ylaboratoryEdit->setText(product->yeasts.at(product->yeasts_row).y_laboratory); |
|
357 yproduct_idEdit->setText(product->yeasts.at(product->yeasts_row).y_product_id); |
|
358 if (product->yeasts.at(product->yeasts_row).y_form == 0) { |
|
359 yamountEdit->setDecimals(0); |
|
360 yamountEdit->setSingleStep(1.0); |
|
361 yamountLabel->setText(tr("Total packs:")); |
|
362 } else if (product->yeasts.at(product->yeasts_row).y_form == 1) { |
|
363 yamountEdit->setDecimals(1); |
|
364 yamountEdit->setSingleStep(0.5); |
|
365 yamountLabel->setText(tr("Amount in gr:")); |
|
366 } else { |
|
367 yamountEdit->setDecimals(1); |
|
368 yamountEdit->setSingleStep(0.5); |
|
369 yamountLabel->setText(tr("Amount in ml:")); |
|
370 } |
|
371 |
|
372 ui->yeastsTable->setItem(product->yeasts_row, 0, new QTableWidgetItem(product->yeasts.at(product->yeasts_row).y_name)); |
|
373 ui->yeastsTable->setItem(product->yeasts_row, 1, new QTableWidgetItem(product->yeasts.at(product->yeasts_row).y_laboratory)); |
|
374 ui->yeastsTable->setItem(product->yeasts_row, 2, new QTableWidgetItem(product->yeasts.at(product->yeasts_row).y_product_id)); |
|
375 |
|
376 item = new QTableWidgetItem(yeast_forms[product->yeasts.at(product->yeasts_row).y_form]); |
|
377 item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter); |
|
378 ui->yeastsTable->setItem(product->yeasts_row, 3, item); |
|
379 |
|
380 item = new QTableWidgetItem(QString("%1").arg(product->yeasts.at(product->yeasts_row).y_min_temperature, 2, 'f', 1, '0')); |
|
381 item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); |
|
382 ui->yeastsTable->setItem(product->yeasts_row, 5, item); |
|
383 |
|
384 item = new QTableWidgetItem(QString("%1").arg(product->yeasts.at(product->yeasts_row).y_max_temperature, 2, 'f', 1, '0')); |
|
385 item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); |
|
386 ui->yeastsTable->setItem(product->yeasts_row, 6, item); |
|
387 |
|
388 item = new QTableWidgetItem(QString("%1").arg(product->yeasts.at(product->yeasts_row).y_tolerance, 2, 'f', 1, '0')); |
|
389 item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); |
|
390 ui->yeastsTable->setItem(product->yeasts_row, 7, item); |
|
391 |
|
392 item = new QTableWidgetItem(QString("%1").arg(product->yeasts.at(product->yeasts_row).y_attenuation, 2, 'f', 1, '0')); |
|
393 item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); |
|
394 ui->yeastsTable->setItem(product->yeasts_row, 8, item); |
|
395 |
|
396 calcYeast(); |
|
397 is_changed(); |
|
398 } |
|
399 |
|
400 |
|
401 void EditProduct::yeast_instock_changed(bool val) |
|
402 { |
|
403 QSqlQuery query; |
|
404 |
|
405 qDebug() << "yeast_instock_changed()" << product->yeasts_row << val; |
|
406 |
|
407 this->yselectEdit->setCurrentIndex(-1); |
|
408 this->yselectEdit->clear(); |
|
409 QString sql = "SELECT name,laboratory,product_id,inventory FROM inventory_yeasts "; |
|
410 if (val) |
|
411 sql.append("WHERE inventory > 0 "); |
|
412 sql.append("ORDER BY laboratory,product_id,name"); |
|
413 query.prepare(sql); |
|
414 query.exec(); |
|
415 query.first(); |
|
416 this->yselectEdit->addItem(""); // Start with empty value |
|
417 for (int i = 0; i < query.size(); i++) { |
|
418 this->yselectEdit->addItem(query.value(1).toString()+" - "+query.value(2).toString()+" "+query.value(0).toString() + |
|
419 QString(" (%1 gr)").arg(query.value(3).toDouble() * 1000.0, 2, 'f', 1, '0')); |
|
420 query.next(); |
|
421 } |
|
422 } |
|
423 |
|
424 |
|
425 void EditProduct::yeast_useat_changed(int val) |
|
426 { |
|
427 qDebug() << "yeast_useat_changed()" << product->yeasts_row << val; |
|
428 |
|
429 product->yeasts[product->yeasts_row].y_use = val; |
|
430 QTableWidgetItem *item = new QTableWidgetItem(yeast_use[val]); |
|
431 item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter); |
|
432 ui->yeastsTable->setItem(product->yeasts_row, 5, item); |
|
433 is_changed(); |
|
434 emit refreshAll(); |
|
435 } |
|
436 |
|
437 |
|
438 void EditProduct::editYeastRow_clicked() |
|
439 { |
|
440 QSqlQuery query; |
|
441 |
|
442 if (product->locked) |
|
443 return; |
|
444 |
|
445 QPushButton *pb = qobject_cast<QPushButton *>(QObject::sender()); |
|
446 product->yeasts_row = pb->objectName().toInt(); |
|
447 qDebug() << "Edit yeast row" << product->yeasts_row; |
|
448 Yeasts backup = product->yeasts.at(product->yeasts_row); |
|
449 |
|
450 QDialog* dialog = new QDialog(this); |
|
451 dialog->resize(738, 260); |
|
452 QDialogButtonBox *buttonBox = new QDialogButtonBox(dialog); |
|
453 buttonBox->setObjectName(QString::fromUtf8("buttonBox")); |
|
454 buttonBox->setGeometry(QRect(30, 210, 671, 32)); |
|
455 buttonBox->setLayoutDirection(Qt::LeftToRight); |
|
456 buttonBox->setOrientation(Qt::Horizontal); |
|
457 buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok); |
|
458 buttonBox->setCenterButtons(true); |
|
459 |
|
460 QLabel *nameLabel = new QLabel(dialog); |
|
461 nameLabel->setObjectName(QString::fromUtf8("nameLabel")); |
|
462 nameLabel->setText(tr("Yeast name:")); |
|
463 nameLabel->setGeometry(QRect(10, 10, 141, 20)); |
|
464 nameLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); |
|
465 QLabel *laboratoryLabel = new QLabel(dialog); |
|
466 laboratoryLabel->setObjectName(QString::fromUtf8("laboratoryLabel")); |
|
467 laboratoryLabel->setText(tr("Laboratory:")); |
|
468 laboratoryLabel->setGeometry(QRect(10, 40, 141, 20)); |
|
469 laboratoryLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); |
|
470 QLabel *product_idLabel = new QLabel(dialog); |
|
471 product_idLabel->setObjectName(QString::fromUtf8("product_idLabel")); |
|
472 product_idLabel->setText(tr("Laboratory:")); |
|
473 product_idLabel->setGeometry(QRect(10, 70, 141, 20)); |
|
474 product_idLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); |
|
475 QLabel *selectLabel = new QLabel(dialog); |
|
476 selectLabel->setObjectName(QString::fromUtf8("selectLabel")); |
|
477 selectLabel->setText(tr("Select yeast:")); |
|
478 selectLabel->setGeometry(QRect(10,100, 141, 20)); |
|
479 selectLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); |
|
480 QLabel *instockLabel = new QLabel(dialog); |
|
481 instockLabel->setObjectName(QString::fromUtf8("instockLabel")); |
|
482 instockLabel->setText(tr("In stock:")); |
|
483 instockLabel->setGeometry(QRect(525,100, 121, 20)); |
|
484 instockLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); |
|
485 yamountLabel = new QLabel(dialog); |
|
486 yamountLabel->setObjectName(QString::fromUtf8("amountLabel")); |
|
487 if (product->yeasts.at(product->yeasts_row).y_form == 0) |
|
488 yamountLabel->setText(tr("Total packs:")); |
|
489 else if (product->yeasts.at(product->yeasts_row).y_form == 1) |
|
490 yamountLabel->setText(tr("Amount in gr:")); |
|
491 else |
|
492 yamountLabel->setText(tr("Amount in ml:")); |
|
493 yamountLabel->setGeometry(QRect(10, 130, 141, 20)); |
|
494 yamountLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); |
|
495 QLabel *useatLabel = new QLabel(dialog); |
|
496 useatLabel->setObjectName(QString::fromUtf8("useatLabel")); |
|
497 useatLabel->setText(tr("Use at:")); |
|
498 useatLabel->setGeometry(QRect(10, 160, 141, 20)); |
|
499 useatLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); |
|
500 |
|
501 ynameEdit = new QLineEdit(dialog); |
|
502 ynameEdit->setObjectName(QString::fromUtf8("ynameEdit")); |
|
503 ynameEdit->setText(product->yeasts.at(product->yeasts_row).y_name); |
|
504 ynameEdit->setGeometry(QRect(160, 10, 511, 23)); |
|
505 ynameEdit->setReadOnly(true); |
|
506 ylaboratoryEdit = new QLineEdit(dialog); |
|
507 ylaboratoryEdit->setObjectName(QString::fromUtf8("ylaboratoryEdit")); |
|
508 ylaboratoryEdit->setText(product->yeasts.at(product->yeasts_row).y_laboratory); |
|
509 ylaboratoryEdit->setGeometry(QRect(160, 40, 511, 23)); |
|
510 ylaboratoryEdit->setReadOnly(true); |
|
511 yproduct_idEdit = new QLineEdit(dialog); |
|
512 yproduct_idEdit->setObjectName(QString::fromUtf8("yproduct_idEdit")); |
|
513 yproduct_idEdit->setText(product->yeasts.at(product->yeasts_row).y_product_id); |
|
514 yproduct_idEdit->setGeometry(QRect(160, 70, 511, 23)); |
|
515 yproduct_idEdit->setReadOnly(true); |
|
516 yselectEdit = new QComboBox(dialog); |
|
517 yselectEdit->setObjectName(QString::fromUtf8("selectEdit")); |
|
518 yselectEdit->setGeometry(QRect(160,100, 371, 23)); |
|
519 yinstockEdit = new QCheckBox(dialog); |
|
520 yinstockEdit->setObjectName(QString::fromUtf8("yinstockEdit")); |
|
521 yinstockEdit->setGeometry(QRect(655,100, 85, 21)); |
|
522 yinstockEdit->setChecked(true); |
|
523 yamountEdit = new QDoubleSpinBox(dialog); |
|
524 yamountEdit->setObjectName(QString::fromUtf8("yamountEdit")); |
|
525 yamountEdit->setGeometry(QRect(160, 130, 121, 24)); |
|
526 yamountEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); |
|
527 yamountEdit->setAccelerated(true); |
|
528 if (product->yeasts.at(product->yeasts_row).y_form == 0) { |
|
529 yamountEdit->setDecimals(0); |
|
530 yamountEdit->setSingleStep(1.0); |
|
531 yamountEdit->setValue(product->yeasts.at(product->yeasts_row).y_amount); |
|
532 } else if (product->yeasts.at(product->yeasts_row).y_form == 1) { |
|
533 yamountEdit->setDecimals(1); |
|
534 yamountEdit->setSingleStep(0.5); |
|
535 yamountEdit->setValue(product->yeasts.at(product->yeasts_row).y_amount * 1000.0); |
|
536 } else { |
|
537 yamountEdit->setDecimals(1); |
|
538 yamountEdit->setSingleStep(0.5); |
|
539 yamountEdit->setValue(product->yeasts.at(product->yeasts_row).y_amount * 1000.0); |
|
540 } |
|
541 yamountEdit->setMaximum(1000000000.0); |
|
542 useatEdit = new QComboBox(dialog); |
|
543 useatEdit->setObjectName(QString::fromUtf8("useatEdit")); |
|
544 useatEdit->setGeometry(QRect(160, 160, 161, 23)); |
|
545 useatEdit->addItem(tr("Primary")); |
|
546 useatEdit->addItem(tr("Secondary")); |
|
547 useatEdit->addItem(tr("Tertiary")); |
|
548 useatEdit->addItem(tr("Bottle")); |
|
549 useatEdit->setCurrentIndex(product->yeasts.at(product->yeasts_row).y_use); |
|
550 |
|
551 yeast_instock_changed(true); |
|
552 |
|
553 connect(yselectEdit, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &EditProduct::yeast_select_changed); |
|
554 connect(yamountEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditProduct::yeast_amount_changed); |
|
555 connect(useatEdit, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &EditProduct::yeast_useat_changed); |
|
556 connect(yinstockEdit, &QCheckBox::stateChanged, this, &EditProduct::yeast_instock_changed); |
|
557 connect(buttonBox, SIGNAL(rejected()), dialog, SLOT(reject())); |
|
558 connect(buttonBox, SIGNAL(accepted()), dialog, SLOT(accept())); |
|
559 |
|
560 dialog->setModal(true); |
|
561 dialog->exec(); |
|
562 if (dialog->result() == QDialog::Rejected) { |
|
563 qDebug() << "reject and rollback"; |
|
564 product->yeasts[product->yeasts_row] = backup; |
|
565 } else { |
|
566 |
|
567 } |
|
568 |
|
569 disconnect(yselectEdit, nullptr, nullptr, nullptr); |
|
570 disconnect(yamountEdit, nullptr, nullptr, nullptr); |
|
571 disconnect(useatEdit, nullptr, nullptr, nullptr); |
|
572 disconnect(yinstockEdit, nullptr, nullptr, nullptr); |
|
573 disconnect(buttonBox, nullptr, nullptr, nullptr); |
|
574 |
|
575 emit refreshAll(); |
|
576 } |
|
577 |
|
578 |
|
579 void EditProduct::adjustYeasts(double factor) |
|
580 { |
|
581 double amount; |
|
582 |
|
583 if (product->yeasts.size() == 0) |
|
584 return; |
|
585 |
|
586 for (int i = 0; i < product->yeasts.size(); i++) { |
|
587 if (product->yeasts.at(i).y_form == 1) { // Only adjust dry yeast |
|
588 amount = product->yeasts.at(i).y_amount * factor; |
|
589 product->yeasts[i].y_amount = amount; |
|
590 } |
|
591 } |
|
592 } |
|
593 |