src/EditProductTab7.cpp

changeset 175
f1ed3a2a94e9
child 177
62b8d701cd88
equal deleted inserted replaced
174:ceb8aa4ebd25 175:f1ed3a2a94e9
1 /**
2 * EditProduct.cpp is part of bmsapp.
3 *
4 * tab 7, mash.
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 hope 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 void EditProduct::refreshMashs()
22 {
23 QString w;
24 QWidget* pWidget;
25 QHBoxLayout* pLayout;
26 QTableWidgetItem *item;
27 QIcon down_icon, up_icon;
28
29 qDebug() << "refreshMashs" << product->mashs.size();
30
31 down_icon.addFile(QString::fromUtf8(":/icons/silk/bullet_arrow_down.png"), QSize(), QIcon::Normal, QIcon::Off);
32 up_icon.addFile(QString::fromUtf8(":/icons/silk/bullet_arrow_up.png"), QSize(), QIcon::Normal, QIcon::Off);
33
34 const QStringList labels({tr("Step name"), tr("Type"), tr("Start"), tr("End"), tr("Rest"), tr("Ramp"),
35 tr("Inf/dec"), tr("Inf/dec"), tr("Volume"), tr("W/G ratio"), "", "", tr("Delete"), tr("Edit") });
36
37 ui->mashsTable->setColumnCount(14);
38 ui->mashsTable->setColumnWidth(0, 189); /* Step name */
39 ui->mashsTable->setColumnWidth(1, 100); /* Type */
40 ui->mashsTable->setColumnWidth(2, 70); /* Start temp */
41 ui->mashsTable->setColumnWidth(3, 70); /* End temp */
42 ui->mashsTable->setColumnWidth(4, 70); /* Rest time */
43 ui->mashsTable->setColumnWidth(5, 70); /* Ramp time */
44 ui->mashsTable->setColumnWidth(6, 70); /* Infusion vol */
45 ui->mashsTable->setColumnWidth(7, 70); /* Infusion tmp */
46 ui->mashsTable->setColumnWidth(8, 70); /* Volume */
47 ui->mashsTable->setColumnWidth(9, 80); /* W/G ratio */
48 ui->mashsTable->setColumnWidth(10, 30); /* Up button */
49 ui->mashsTable->setColumnWidth(11, 30); /* Down button */
50 ui->mashsTable->setColumnWidth(12, 80); /* Delete */
51 ui->mashsTable->setColumnWidth(13, 80); /* Edit */
52 ui->mashsTable->setHorizontalHeaderLabels(labels);
53 ui->mashsTable->verticalHeader()->hide();
54 ui->mashsTable->setRowCount(product->mashs.size());
55
56 for (int i = 0; i < product->mashs.size(); i++) {
57
58 ui->mashsTable->setItem(i, 0, new QTableWidgetItem(product->mashs.at(i).step_name));
59
60 item = new QTableWidgetItem(step_types[product->mashs.at(i).step_type]);
61 item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter);
62 ui->mashsTable->setItem(i, 1, item);
63
64 item = new QTableWidgetItem(QString("%1 °C").arg(product->mashs.at(i).step_temp, 2, 'f', 1, '0'));
65 item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
66 ui->mashsTable->setItem(i, 2, item);
67
68 item = new QTableWidgetItem(QString("%1 °C").arg(product->mashs.at(i).end_temp, 2, 'f', 1, '0'));
69 item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
70 ui->mashsTable->setItem(i, 3, item);
71
72 item = new QTableWidgetItem(QString("%1 min").arg(product->mashs.at(i).step_time, 1, 'f', 0, '0'));
73 item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
74 ui->mashsTable->setItem(i, 4, item);
75
76 item = new QTableWidgetItem(QString("%1 min").arg(product->mashs.at(i).ramp_time, 1, 'f', 0, '0'));
77 item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
78 ui->mashsTable->setItem(i, 5, item);
79
80 if (product->mashs.at(i).step_infuse_amount > 0) {
81 item = new QTableWidgetItem(QString("%1 L").arg(product->mashs.at(i).step_infuse_amount, 2, 'f', 1, '0'));
82 item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
83 ui->mashsTable->setItem(i, 6, item);
84 item = new QTableWidgetItem(QString("%1 °C").arg(product->mashs.at(i).step_infuse_temp, 3, 'f', 2, '0'));
85 item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
86 ui->mashsTable->setItem(i, 7, item);
87 } else {
88 ui->mashsTable->removeCellWidget(i, 6);
89 ui->mashsTable->removeCellWidget(i, 7);
90 }
91
92 item = new QTableWidgetItem(QString("%1 L").arg(product->mashs.at(i).step_volume, 2, 'f', 1, '0'));
93 item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
94 ui->mashsTable->setItem(i, 8, item);
95
96 item = new QTableWidgetItem(QString("%1 L/kg").arg(product->mashs.at(i).step_wg_ratio, 3, 'f', 2, '0'));
97 item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
98 ui->mashsTable->setItem(i, 9, item);
99
100 if (i > 0) {
101 pWidget = new QWidget();
102 QPushButton* btn_up = new QPushButton();
103 btn_up->setObjectName(QString("%1").arg(i)); /* Send row with the button */
104 btn_up->setIcon(up_icon);
105 connect(btn_up, SIGNAL(clicked()), this, SLOT(upMashRow_clicked()));
106 pLayout = new QHBoxLayout(pWidget);
107 pLayout->addWidget(btn_up);
108 pLayout->setContentsMargins(5, 0, 5, 0);
109 pWidget->setLayout(pLayout);
110 ui->mashsTable->setCellWidget(i, 10, pWidget);
111 } else {
112 ui->mashsTable->removeCellWidget(i, 10);
113 }
114
115 if (i < (product->mashs.size() - 1)) {
116 pWidget = new QWidget();
117 QPushButton* btn_down = new QPushButton();
118 btn_down->setObjectName(QString("%1").arg(i)); /* Send row with the button */
119 btn_down->setIcon(down_icon);
120 connect(btn_down, SIGNAL(clicked()), this, SLOT(downMashRow_clicked()));
121 pLayout = new QHBoxLayout(pWidget);
122 pLayout->addWidget(btn_down);
123 pLayout->setContentsMargins(5, 0, 5, 0);
124 pWidget->setLayout(pLayout);
125 ui->mashsTable->setCellWidget(i, 11, pWidget);
126 } else {
127 ui->mashsTable->removeCellWidget(i, 11);
128 }
129
130 pWidget = new QWidget();
131 QPushButton* btn_dele = new QPushButton();
132 btn_dele->setObjectName(QString("%1").arg(i)); /* Send row with the button */
133 btn_dele->setText(tr("Delete"));
134 connect(btn_dele, SIGNAL(clicked()), this, SLOT(deleteMashRow_clicked()));
135 pLayout = new QHBoxLayout(pWidget);
136 pLayout->addWidget(btn_dele);
137 pLayout->setContentsMargins(5, 0, 5, 0);
138 pWidget->setLayout(pLayout);
139 ui->mashsTable->setCellWidget(i, 12, pWidget);
140
141 pWidget = new QWidget();
142 QPushButton* btn_edit = new QPushButton();
143 btn_edit->setObjectName(QString("%1").arg(i)); /* Send row with the button */
144 btn_edit->setText(tr("Edit"));
145 connect(btn_edit, SIGNAL(clicked()), this, SLOT(editMashRow_clicked()));
146 pLayout = new QHBoxLayout(pWidget);
147 pLayout->addWidget(btn_edit);
148 pLayout->setContentsMargins(5, 0, 5, 0);
149 pWidget->setLayout(pLayout);
150 ui->mashsTable->setCellWidget(i, 13, pWidget);
151 }
152 }
153
154
155 double EditProduct::infusionVol(double step_infused, double step_mashkg, double infuse_temp, double step_temp, double last_temp)
156 {
157 double a = last_temp * (equip_tun_weight * equip_tun_specific_heat + step_infused * SpecificHeatWater + step_mashkg * SpecificHeatMalt);
158 double b = step_temp * (equip_tun_weight * equip_tun_specific_heat + step_infused * SpecificHeatWater + step_mashkg * SpecificHeatMalt);
159 double vol = round(((b - a) / ((infuse_temp - step_temp) * SpecificHeatWater)) * 100.0) / 100.0;
160
161 if (vol < 0)
162 vol = 0;
163 qDebug() << " infusionVol(" << step_infused << "," << step_mashkg << "," << infuse_temp <<"," << step_temp << "," << last_temp << "):" << vol;
164 return vol;
165 }
166
167
168 double EditProduct::decoctionVol(double step_volume, double step_temp, double prev_temp)
169 {
170 double a = (equip_tun_weight * equip_tun_specific_heat + step_volume * SpecificHeatWater) * (step_temp - prev_temp);
171 double b = SpecificHeatWater * (99 - step_temp);
172 double vol = 0;
173
174 if (b > 0)
175 vol = round((a / b) * 1000000.0) / 1000000.0;
176 qDebug() << " decoctionVol(" << step_volume << "," << step_temp << "," << prev_temp << "):" << vol;
177 return vol;
178 }
179
180
181 void EditProduct::calcMash()
182 {
183 double infused = 0, vol, a, b, temp;
184 int i, j, n;
185 double lasttemp = 18.0;
186 double graintemp = 18.0;
187 double tuntemp = 18.0;
188
189 product->mashs_time = 0;
190
191 if (product->mashs.size() && product->mashs_kg > 0) {
192 qDebug() << "calcMash()";
193
194 for (i = 0; i < product->mashs.size(); i++) {
195 if (product->mashs.at(i).step_type == 0) { // Infusion
196 if (i == 0) {
197 // First mash step, temperature from the mashtun and malt.
198 n = 20; // tun is preheated.
199 tuntemp = product->mashs.at(i).step_temp;
200 for (j = 0; j < n; j++) {
201 a = product->mashs_kg * graintemp * SpecificHeatMalt + equip_tun_weight * tuntemp * equip_tun_specific_heat;
202 b = product->mashs[i].step_temp *
203 (equip_tun_weight * equip_tun_specific_heat +
204 product->mashs.at(i).step_infuse_amount * SpecificHeatWater +
205 product->mashs_kg * SpecificHeatMalt) -
206 SlakingHeat * product->mashs_kg;
207 if (product->mashs.at(i).step_infuse_amount > 0) {
208 temp = (b - a) / (product->mashs.at(i).step_infuse_amount * SpecificHeatWater);
209 } else {
210 temp = 99;
211 }
212 tuntemp += (temp - tuntemp) / 2;
213 product->mashs[i].step_infuse_temp = round(temp * 1000000.0) / 1000000.0;
214 }
215 qDebug() << " init infuse temp:" << product->mashs.at(i).step_infuse_temp;
216 } else {
217 // Calculate amount of infusion water.
218 product->mashs[i].step_infuse_amount =
219 infusionVol(infused, product->mashs_kg, product->mashs.at(i).step_infuse_temp, product->mashs.at(i).step_temp, lasttemp);
220 qDebug() << i << " vol:" << product->mashs.at(i).step_infuse_amount << "temp:" << product->mashs.at(i).step_infuse_temp;
221 }
222 infused += product->mashs.at(i).step_infuse_amount;
223 } else if (product->mashs.at(i).step_type == 1) { // Temperature
224 if (i > 0)
225 product->mashs[i].step_infuse_amount = 0;
226 product->mashs[i].step_infuse_temp = 0;
227 } else if (product->mashs.at(i).step_type == 2) { // Decoction
228 product->mashs[i].step_infuse_amount = decoctionVol(infused, product->mashs.at(i).step_temp, lasttemp);
229 product->mashs[i].step_infuse_temp = 99;
230 }
231 product->mashs[i].step_volume = infused;
232 //qDebug() << i << " type:" << product->mashs.at(i).step_type << "volume:" << product->mashs.at(i).step_infuse_amount << "temp:" << product->mashs.at(i).step_infuse_temp;
233 lasttemp = product->mashs.at(i).step_temp;
234 product->mashs_time += product->mashs.at(i).step_time;
235 if (i > 0)
236 product->mashs_time += product->mashs.at(i).ramp_time;
237 product->mashs[i].step_wg_ratio = round((infused / product->mashs_kg) * 1000000.0) / 1000000.0;
238 }
239 }
240
241 /* Show the calculated total mash time. */
242 ui->mash_timeEdit->setText(QString("%1:%2").arg(product->mashs_time / 60).arg(product->mashs_time % 60, 2, 'f', 0, '0'));
243 }
244
245
246 void EditProduct::addMashRow_clicked()
247 {
248 Mashs newm;
249
250 for (int i = 0; i < product->mashs.size(); i++) {
251 if (product->mashs.at(i).step_time == 0)
252 return; // Add only one at a time.
253 }
254
255 newm.step_name = "Name me";
256 newm.step_temp = newm.end_temp = 67.0;
257 newm.step_time = 20;
258 newm.ramp_time = 10;
259 if (product->mashs.size()) {
260 newm.step_volume = product->mashs.at(product->mashs.size() - 1).step_volume;
261 newm.step_wg_ratio = product->mashs.at(product->mashs.size() - 1).step_wg_ratio;
262 newm.step_type = product->mashs.at(product->mashs.size() - 1).step_type;
263 } else {
264 newm.step_volume = 0;
265 newm.step_wg_ratio = 0;
266 newm.step_type = 1;
267 }
268 newm.step_infuse_amount = newm.step_infuse_temp = 0;
269
270 product->mashs.append(newm);
271 is_changed();
272 emit refreshAll();
273 }
274
275
276 void EditProduct::deleteMashRow_clicked()
277 {
278 if (product->locked || product->mashs.size() < 1)
279 return;
280
281 QPushButton *pb = qobject_cast<QPushButton *>(QObject::sender());
282 int row = pb->objectName().toInt();
283 qDebug() << "Delete mash row" << row << product->mashs.size();
284
285 int rc = QMessageBox::warning(this, tr("Delete mash step"), tr("Delete %1").arg(product->mashs.at(row).step_name),
286 QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
287 if (rc == QMessageBox::No)
288 return;
289
290 product->mashs.removeAt(row);
291 is_changed();
292 emit refreshAll();
293 }
294
295
296 void EditProduct::upMashRow_clicked()
297 {
298 if (product->locked || product->mashs.size() < 1)
299 return;
300
301 QPushButton *pb = qobject_cast<QPushButton *>(QObject::sender());
302 int row = pb->objectName().toInt();
303 qDebug() << "Move up mash row" << row << product->mashs.size();
304
305 Mashs temp;
306 temp = product->mashs[row - 1];
307 product->mashs[row - 1] = product->mashs[row];
308 product->mashs[row] = temp;
309 is_changed();
310 emit refreshAll();
311 }
312
313
314 void EditProduct::downMashRow_clicked()
315 {
316 if (product->locked || product->mashs.size() < 1)
317 return;
318
319 QPushButton *pb = qobject_cast<QPushButton *>(QObject::sender());
320 int row = pb->objectName().toInt();
321 qDebug() << "Move down mash row" << row << product->mashs.size();
322
323 Mashs temp;
324 temp = product->mashs[row + 1];
325 product->mashs[row + 1] = product->mashs[row];
326 product->mashs[row] = temp;
327 is_changed();
328 emit refreshAll();
329 }
330
331
332 void EditProduct::step_name_changed(QString val)
333 {
334 product->mashs[product->mashs_row].step_name = val;
335 ui->mashsTable->setItem(product->mashs_row, 0, new QTableWidgetItem(val));
336 is_changed();
337 }
338
339
340 void EditProduct::step_type_changed(int val)
341 {
342 qDebug() << "step_type_changed" << product->mashs_row << val;
343
344 product->mashs[product->mashs_row].step_type = val;
345 ivolLabel->setVisible(product->mashs.at(product->mashs_row).step_type == 0);
346 stepivolEdit->setVisible(product->mashs.at(product->mashs_row).step_type == 0);
347 itmpLabel->setVisible(product->mashs.at(product->mashs_row).step_type == 0);
348 stepitmpEdit->setVisible(product->mashs.at(product->mashs_row).step_type == 0);
349 is_changed();
350 emit refreshAll();
351 }
352
353
354 void EditProduct::step_temp_changed(double val)
355 {
356 qDebug() << "step_temp_changed" << product->mashs_row << val;
357 product->mashs[product->mashs_row].step_temp = val;
358 QTableWidgetItem *item = new QTableWidgetItem(QString("%1 °C").arg(val, 2, 'f', 1, '0'));
359 item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
360 ui->mashsTable->setItem(product->mashs_row, 2, item);
361 is_changed();
362 emit refreshAll();
363 }
364
365
366 void EditProduct::end_temp_changed(double val)
367 {
368 qDebug() << "end_temp_changed" << product->mashs_row << val;
369 product->mashs[product->mashs_row].end_temp = val;
370 QTableWidgetItem *item = new QTableWidgetItem(QString("%1 °C").arg(val, 2, 'f', 1, '0'));
371 item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
372 ui->mashsTable->setItem(product->mashs_row, 3, item);
373 is_changed();
374 emit refreshAll();
375 }
376
377
378 void EditProduct::step_time_changed(double val)
379 {
380 qDebug() << "step_time_changed" << product->mashs_row << val;
381 product->mashs[product->mashs_row].step_time = val;
382 QTableWidgetItem *item = new QTableWidgetItem(QString("%1 min").arg(val, 1, 'f', 0, '0'));
383 item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
384 ui->mashsTable->setItem(product->mashs_row, 4, item);
385 is_changed();
386 emit refreshAll();
387 }
388
389
390 void EditProduct::ramp_time_changed(double val)
391 {
392 qDebug() << "ramp_time_changed" << product->mashs_row << val;
393 product->mashs[product->mashs_row].ramp_time = val;
394 QTableWidgetItem *item = new QTableWidgetItem(QString("%1 min").arg(val, 1, 'f', 0, '0'));
395 item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
396 ui->mashsTable->setItem(product->mashs_row, 5, item);
397 is_changed();
398 emit refreshAll();
399 }
400
401
402 void EditProduct::infuse_changed(double val)
403 {
404 qDebug() << "infuse_changed" << product->mashs_row << val;
405 product->mashs[product->mashs_row].step_infuse_amount = val;
406 QTableWidgetItem *item = new QTableWidgetItem(QString("%1 L").arg(val, 1, 'f', 0, '0'));
407 item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
408 ui->mashsTable->setItem(product->mashs_row, 6, item);
409
410 /*
411 * Recalculate water volumes
412 */
413 double volume = 0;
414 for (int i = 0; i < product->mashs.size(); i++) {
415 if (product->mashs.at(i).step_type == 0) {
416 volume += product->mashs.at(i).step_infuse_amount;
417 }
418 product->mashs[i].step_volume = volume;
419 }
420 product->w1_amount = volume - product->w2_amount;
421 product->wg_amount = volume;
422 ui->w1_volEdit->setValue(product->w1_amount);
423
424 is_changed();
425 emit refreshAll();
426 }
427
428
429 void EditProduct::editMashRow_clicked()
430 {
431 QSqlQuery query;
432
433 if (product->locked)
434 return;
435
436 QPushButton *pb = qobject_cast<QPushButton *>(QObject::sender());
437 product->mashs_row = pb->objectName().toInt();
438 qDebug() << "Edit mash row" << product->mashs_row;
439 Mashs backup = product->mashs.at(product->mashs_row);
440
441 QDialog* dialog = new QDialog(this);
442 dialog->resize(738, 230);
443 QDialogButtonBox *buttonBox = new QDialogButtonBox(dialog);
444 buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
445 buttonBox->setGeometry(QRect(30, 180, 671, 32));
446 buttonBox->setLayoutDirection(Qt::LeftToRight);
447 buttonBox->setOrientation(Qt::Horizontal);
448 buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
449 buttonBox->setCenterButtons(true);
450
451 QLabel *nameLabel = new QLabel(dialog);
452 nameLabel->setObjectName(QString::fromUtf8("nameLabel"));
453 nameLabel->setText(tr("Step name:"));
454 nameLabel->setGeometry(QRect(10, 10, 141, 20));
455 nameLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
456 stepnameEdit = new QLineEdit(dialog);
457 stepnameEdit->setObjectName(QString::fromUtf8("stepnameEdit"));
458 stepnameEdit->setText(product->mashs.at(product->mashs_row).step_name);
459 stepnameEdit->setGeometry(QRect(160, 10, 511, 23));
460
461 QLabel *typeLabel = new QLabel(dialog);
462 typeLabel->setObjectName(QString::fromUtf8("typeLabel"));
463 typeLabel->setText(tr("Step type:"));
464 typeLabel->setGeometry(QRect(10, 40, 141, 20));
465 typeLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
466 QComboBox *typeEdit = new QComboBox(dialog);
467 typeEdit->setObjectName(QString::fromUtf8("typeEdit"));
468 typeEdit->setGeometry(QRect(160, 40, 161, 23));
469 typeEdit->addItem(tr("Infusion"));
470 typeEdit->addItem(tr("Temperature"));
471 typeEdit->addItem(tr("Decoction"));
472 typeEdit->setCurrentIndex(product->mashs.at(product->mashs_row).step_type);
473
474 QLabel *tempLabel = new QLabel(dialog);
475 tempLabel->setObjectName(QString::fromUtf8("tempLabel"));
476 tempLabel->setText(tr("Step start temp:"));
477 tempLabel->setGeometry(QRect(10, 70, 141, 20));
478 tempLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
479 steptempEdit = new QDoubleSpinBox(dialog);
480 steptempEdit->setObjectName(QString::fromUtf8("steptempEdit"));
481 steptempEdit->setGeometry(QRect(160, 70, 121, 24));
482 steptempEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
483 steptempEdit->setDecimals(1);
484 steptempEdit->setValue(product->mashs.at(product->mashs_row).step_temp);
485
486 QLabel *endLabel = new QLabel(dialog);
487 endLabel->setObjectName(QString::fromUtf8("endLabel"));
488 endLabel->setText(tr("Step end temp:"));
489 endLabel->setGeometry(QRect(360, 70, 141, 20));
490 endLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
491 endtempEdit = new QDoubleSpinBox(dialog);
492 endtempEdit->setObjectName(QString::fromUtf8("endtempEdit"));
493 endtempEdit->setGeometry(QRect(510, 70, 121, 24));
494 endtempEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
495 endtempEdit->setDecimals(1);
496 endtempEdit->setValue(product->mashs.at(product->mashs_row).end_temp);
497
498 QLabel *timeLabel = new QLabel(dialog);
499 timeLabel->setObjectName(QString::fromUtf8("timeLabel"));
500 timeLabel->setText(tr("Step rest time:"));
501 timeLabel->setGeometry(QRect(10, 100, 141, 20));
502 timeLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
503 steptimeEdit = new QDoubleSpinBox(dialog);
504 steptimeEdit->setObjectName(QString::fromUtf8("steptimeEdit"));
505 steptimeEdit->setGeometry(QRect(160, 100, 121, 24));
506 steptimeEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
507 steptimeEdit->setDecimals(0);
508 steptimeEdit->setValue(product->mashs.at(product->mashs_row).step_time);
509
510 QLabel *rampLabel = new QLabel(dialog);
511 rampLabel->setObjectName(QString::fromUtf8("rampLabel"));
512 rampLabel->setText(tr("Step ramp time:"));
513 rampLabel->setGeometry(QRect(360, 100, 141, 20));
514 rampLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
515 ramptimeEdit = new QDoubleSpinBox(dialog);
516 ramptimeEdit->setObjectName(QString::fromUtf8("ramptimeEdit"));
517 ramptimeEdit->setGeometry(QRect(510, 100, 121, 24));
518 ramptimeEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
519 ramptimeEdit->setDecimals(0);
520 ramptimeEdit->setValue(product->mashs.at(product->mashs_row).ramp_time);
521
522 /*
523 * Only used for Infusion steps.
524 */
525 ivolLabel = new QLabel(dialog);
526 ivolLabel->setObjectName(QString::fromUtf8("ivolLabel"));
527 ivolLabel->setText(tr("Infusion volume:"));
528 ivolLabel->setGeometry(QRect(10, 130, 141, 20));
529 ivolLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
530 ivolLabel->setVisible(product->mashs.at(product->mashs_row).step_type == 0);
531 stepivolEdit = new QDoubleSpinBox(dialog);
532 stepivolEdit->setObjectName(QString::fromUtf8("stepivolEdit"));
533 stepivolEdit->setGeometry(QRect(160, 130, 121, 24));
534 stepivolEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
535 stepivolEdit->setVisible(product->mashs.at(product->mashs_row).step_type == 0);
536 stepivolEdit->setDecimals(1);
537 stepivolEdit->setAccelerated(true);
538 stepivolEdit->setMaximum(100000.0);
539 stepivolEdit->setSingleStep(0.5);
540 stepivolEdit->setValue(product->mashs.at(product->mashs_row).step_infuse_amount);
541
542 itmpLabel = new QLabel(dialog);
543 itmpLabel->setObjectName(QString::fromUtf8("itmpLabel"));
544 itmpLabel->setText(tr("Infusion Temperature:"));
545 itmpLabel->setGeometry(QRect(360, 130, 141, 20));
546 itmpLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
547 itmpLabel->setVisible(product->mashs.at(product->mashs_row).step_type == 0);
548 stepitmpEdit = new QDoubleSpinBox(dialog);
549 stepitmpEdit->setObjectName(QString::fromUtf8("stepitmpEdit"));
550 stepitmpEdit->setGeometry(QRect(510, 130, 121, 24));
551 stepitmpEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
552 stepitmpEdit->setVisible(product->mashs.at(product->mashs_row).step_type == 0);
553 stepitmpEdit->setDecimals(1);
554 stepitmpEdit->setReadOnly(true);
555 stepitmpEdit->setButtonSymbols(QAbstractSpinBox::NoButtons);
556 stepitmpEdit->setValue(product->mashs.at(product->mashs_row).step_infuse_temp);
557
558 connect(stepnameEdit, &QLineEdit::textEdited, this, &EditProduct::step_name_changed);
559 connect(typeEdit, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &EditProduct::step_type_changed);
560 connect(steptempEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditProduct::step_temp_changed);
561 connect(endtempEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditProduct::end_temp_changed);
562 connect(steptimeEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditProduct::step_time_changed);
563 connect(ramptimeEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditProduct::ramp_time_changed);
564 connect(stepivolEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditProduct::infuse_changed);
565 connect(buttonBox, SIGNAL(rejected()), dialog, SLOT(reject()));
566 connect(buttonBox, SIGNAL(accepted()), dialog, SLOT(accept()));
567
568 dialog->setModal(true);
569 dialog->exec();
570 if (dialog->result() == QDialog::Rejected) {
571 qDebug() << "reject and rollback";
572 product->mashs[product->mashs_row] = backup;
573 /* Rollback water volumes too */
574 double volume = 0;
575 for (int i = 0; i < product->mashs.size(); i++) {
576 if (product->mashs.at(i).step_type == 0) {
577 volume += product->mashs.at(i).step_infuse_amount;
578 }
579 product->mashs[i].step_volume = volume;
580 }
581 product->w1_amount = volume - product->w2_amount;
582 product->wg_amount = volume;
583 ui->w1_volEdit->setValue(product->w1_amount);
584 }
585
586 disconnect(stepnameEdit, nullptr, nullptr, nullptr);
587 disconnect(steptempEdit, nullptr, nullptr, nullptr);
588 disconnect(endtempEdit, nullptr, nullptr, nullptr);
589 disconnect(steptimeEdit, nullptr, nullptr, nullptr);
590 disconnect(ramptimeEdit, nullptr, nullptr, nullptr);
591 disconnect(stepivolEdit, nullptr, nullptr, nullptr);
592 disconnect(buttonBox, nullptr, nullptr, nullptr);
593
594 emit refreshAll();
595 }
596
597
598 void EditProduct::mash_name_changed(QString name)
599 {
600 qDebug() << "mash_name_changed" << name;
601 product->mash_name = name;
602 is_changed();
603 }
604
605
606 void EditProduct::mash_select_changed(int val)
607 {
608 QSqlQuery query;
609 int i;
610
611 qDebug() << "mash_select_changed" << val;
612
613 const QSignalBlocker blocker1(ui->mash_nameEdit);
614 query.prepare("SELECT name,steps FROM profile_mash ORDER BY name");
615 query.exec();
616 query.first();
617 for (i = 0; i < (val -1); i++) {
618 query.next();
619 }
620
621 product->mash_name = query.value(0).toString();
622 ui->mash_nameEdit->setText(product->mash_name);
623
624 QJsonParseError parseError;
625 const auto& json = query.value(1).toString();
626 if (!json.trimmed().isEmpty()) {
627 const auto& formattedJson = QString("%1").arg(json);
628 QJsonDocument newsteps = QJsonDocument::fromJson(formattedJson.toUtf8(), &parseError);
629
630 if (parseError.error != QJsonParseError::NoError) {
631 qDebug() << "Parse error: " << parseError.errorString() << "at" << parseError.offset;
632 } else {
633 /*
634 * Got the json data in the steps array, replace the product steps.
635 */
636 double infuse = 0;
637 if (product->mashs.size()) {
638 infuse = product->mashs.at(0).step_infuse_amount;
639 product->mashs.clear();
640 ui->mashsTable->clear();
641 }
642 if (newsteps.isArray()) {
643 for (i = 0; i < newsteps.array().size(); i++) {
644 QJsonObject obj = newsteps.array().at(i).toObject();
645 Mashs m;
646 m.step_name = obj["step_name"].toString();
647 if (obj["step_type"].isString())
648 m.step_type = QString(obj["step_type"].toString()).toInt();
649 else
650 m.step_type = obj["step_type"].toInt();
651 m.step_volume = 0;
652 m.step_infuse_amount = 0;
653 m.step_infuse_temp = 0;
654 if (obj["step_temp"].isString())
655 m.step_temp = QString(obj["step_temp"].toString()).toDouble();
656 else
657 m.step_temp = obj["step_temp"].toDouble();
658 if (obj["step_time"].isString())
659 m.step_time = QString(obj["step_time"].toString()).toDouble();
660 else
661 m.step_time = obj["step_time"].toDouble();
662 if (obj["ramp_time"].isString())
663 m.ramp_time = QString(obj["ramp_time"].toString()).toDouble();
664 else
665 m.ramp_time = obj["ramp_time"].toDouble();
666 if (obj["end_temp"].isString())
667 m.end_temp = QString(obj["end_temp"].toString()).toDouble();
668 else
669 m.end_temp = obj["end_temp"].toDouble();
670 m.step_wg_ratio = 0;
671 product->mashs.append(m);
672 }
673 }
674 if (product->mashs.at(0).step_type == 0)
675 product->mashs[0].step_infuse_amount = infuse; // Restore saved initial infusion
676 }
677 }
678 is_changed();
679 emit refreshAll();
680 }
681
682

mercurial