Mon, 11 Apr 2022 17:33:38 +0200
More file splitting
127 | 1 | /** |
2 | * EditRecipe.cpp is part of bmsapp. | |
3 | * | |
4 | * Tab 3, hops | |
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 | ||
22 | bool EditRecipe::hop_sort_test(const Hops &D1, const Hops &D2) | |
23 | { | |
24 | if (D1.h_useat > D2.h_useat) | |
25 | return false; | |
26 | if (D1.h_useat < D2.h_useat) | |
27 | return true; | |
28 | /* Same useat moments, test time. */ | |
29 | if (D1.h_time < D2.h_time) | |
30 | return false; | |
31 | if (D1.h_time > D2.h_time) | |
32 | return true; | |
33 | /* Finally consider the amounts */ | |
34 | return (D1.h_amount > D2.h_amount); | |
35 | } | |
36 | ||
37 | ||
38 | void EditRecipe::refreshHops() | |
39 | { | |
40 | QString w; | |
41 | QWidget* pWidget; | |
42 | QHBoxLayout* pLayout; | |
43 | QTableWidgetItem *item; | |
44 | ||
45 | qDebug() << "refreshHops" << recipe->hops.size(); | |
46 | std::sort(recipe->hops.begin(), recipe->hops.end(), hop_sort_test); | |
47 | ||
48 | /* | |
49 | * During filling the table turn off the cellChanged signal because every cell that is filled | |
50 | * triggers the cellChanged signal. The QTableWidget has no better signal to use. | |
51 | */ | |
52 | this->ignoreChanges = true; | |
53 | ||
54 | const QStringList labels({tr("Origin"), tr("Hop"), tr("Type"), tr("Form"), tr("Alpha"), tr("Use at"), tr("Time"), | |
55 | tr("IBU"), tr("Amount"), tr("Delete"), tr("Edit") }); | |
56 | ||
57 | ui->hopsTable->setColumnCount(11); | |
58 | ui->hopsTable->setColumnWidth(0, 150); /* Origin */ | |
59 | ui->hopsTable->setColumnWidth(1, 225); /* Hop */ | |
60 | ui->hopsTable->setColumnWidth(2, 75); /* Type */ | |
61 | ui->hopsTable->setColumnWidth(3, 75); /* Form */ | |
62 | ui->hopsTable->setColumnWidth(4, 75); /* Alpha% */ | |
63 | ui->hopsTable->setColumnWidth(5, 75); /* Added */ | |
64 | ui->hopsTable->setColumnWidth(6, 75); /* Time */ | |
65 | ui->hopsTable->setColumnWidth(7, 60); /* IBU */ | |
66 | ui->hopsTable->setColumnWidth(8, 75); /* Amount */ | |
67 | ui->hopsTable->setColumnWidth(9, 80); /* Delete */ | |
68 | ui->hopsTable->setColumnWidth(10, 80); /* Edit */ | |
69 | ui->hopsTable->setHorizontalHeaderLabels(labels); | |
70 | ui->hopsTable->verticalHeader()->hide(); | |
71 | ui->hopsTable->setRowCount(recipe->hops.size()); | |
72 | ||
73 | for (int i = 0; i < recipe->hops.size(); i++) { | |
74 | ||
75 | ui->hopsTable->setItem(i, 0, new QTableWidgetItem(recipe->hops.at(i).h_origin)); | |
76 | ui->hopsTable->setItem(i, 1, new QTableWidgetItem(recipe->hops.at(i).h_name)); | |
77 | ||
78 | item = new QTableWidgetItem(h_types[recipe->hops.at(i).h_type]); | |
79 | item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter); | |
80 | ui->hopsTable->setItem(i, 2, item); | |
81 | ||
82 | item = new QTableWidgetItem(h_forms[recipe->hops.at(i).h_form]); | |
83 | item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter); | |
84 | ui->hopsTable->setItem(i, 3, item); | |
85 | ||
86 | item = new QTableWidgetItem(QString("%1%").arg(recipe->hops.at(i).h_alpha, 2, 'f', 1, '0')); | |
87 | item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); | |
88 | ui->hopsTable->setItem(i, 4, item); | |
89 | ||
90 | item = new QTableWidgetItem(h_useat[recipe->hops.at(i).h_useat]); | |
91 | item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter); | |
92 | ui->hopsTable->setItem(i, 5, item); | |
93 | ||
94 | if (recipe->hops.at(i).h_useat == 2 || recipe->hops.at(i).h_useat == 4) { // Boil or whirlpool | |
95 | item = new QTableWidgetItem(QString("%1 min.").arg(recipe->hops.at(i).h_time, 1, 'f', 0, '0')); | |
96 | } else if (recipe->hops.at(i).h_useat == 5) { // Dry-hop | |
97 | item = new QTableWidgetItem(QString("%1 days.").arg(recipe->hops.at(i).h_time / 1440, 1, 'f', 0, '0')); | |
98 | } else { | |
99 | item = new QTableWidgetItem(QString("")); | |
100 | } | |
101 | item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); | |
102 | ui->hopsTable->setItem(i, 6, item); | |
103 | ||
104 | double ibu = Utils::toIBU(recipe->hops.at(i).h_useat, recipe->hops.at(i).h_form, recipe->preboil_sg, recipe->batch_size, recipe->hops.at(i).h_amount, | |
105 | recipe->hops.at(i).h_time, recipe->hops.at(i).h_alpha, recipe->ibu_method, 0, recipe->hops.at(i).h_time, 0); | |
106 | item = new QTableWidgetItem(QString("%1").arg(ibu, 2, 'f', 1, '0')); | |
107 | item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); | |
108 | ui->hopsTable->setItem(i, 7, item); | |
109 | ||
110 | if (recipe->hops.at(i).h_amount < 1.0) { | |
111 | item = new QTableWidgetItem(QString("%1 gr").arg(recipe->hops.at(i).h_amount * 1000.0, 2, 'f', 1, '0')); | |
112 | } else { | |
113 | item = new QTableWidgetItem(QString("%1 kg").arg(recipe->hops.at(i).h_amount, 4, 'f', 3, '0')); | |
114 | } | |
115 | item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); | |
116 | ui->hopsTable->setItem(i, 8, item); | |
117 | ||
118 | /* Add the Delete row button */ | |
119 | pWidget = new QWidget(); | |
120 | QPushButton* btn_dele = new QPushButton(); | |
121 | btn_dele->setObjectName(QString("%1").arg(i)); /* Send row with the button */ | |
122 | btn_dele->setText(tr("Delete")); | |
123 | connect(btn_dele, SIGNAL(clicked()), this, SLOT(on_deleteHopRow_clicked())); | |
124 | pLayout = new QHBoxLayout(pWidget); | |
125 | pLayout->addWidget(btn_dele); | |
126 | pLayout->setContentsMargins(5, 0, 5, 0); | |
127 | pWidget->setLayout(pLayout); | |
128 | ui->hopsTable->setCellWidget(i, 9, pWidget); | |
129 | ||
130 | pWidget = new QWidget(); | |
131 | QPushButton* btn_edit = new QPushButton(); | |
132 | btn_edit->setObjectName(QString("%1").arg(i)); /* Send row with the button */ | |
133 | btn_edit->setText(tr("Edit")); | |
134 | connect(btn_edit, SIGNAL(clicked()), this, SLOT(on_editHopRow_clicked())); | |
135 | pLayout = new QHBoxLayout(pWidget); | |
136 | pLayout->addWidget(btn_edit); | |
137 | pLayout->setContentsMargins(5, 0, 5, 0); | |
138 | pWidget->setLayout(pLayout); | |
139 | ui->hopsTable->setCellWidget(i, 10, pWidget); | |
140 | } | |
141 | this->ignoreChanges = false; | |
142 | } | |
143 | ||
144 | ||
145 | void EditRecipe::on_Flavour_valueChanged(int value) | |
146 | { | |
147 | if (value < 20) { | |
148 | ui->hop_tasteShow->setStyleSheet(bar_20); | |
149 | ui->hop_tasteShow->setFormat(tr("Very low")); | |
150 | } else if (value < 40) { | |
151 | ui->hop_tasteShow->setStyleSheet(bar_40); | |
152 | ui->hop_tasteShow->setFormat(tr("Low")); | |
153 | } else if (value < 60) { | |
154 | ui->hop_tasteShow->setStyleSheet(bar_60); | |
155 | ui->hop_tasteShow->setFormat(tr("Moderate")); | |
156 | } else if (value < 80) { | |
157 | ui->hop_tasteShow->setStyleSheet(bar_80); | |
158 | ui->hop_tasteShow->setFormat(tr("High")); | |
159 | } else { | |
160 | ui->hop_tasteShow->setStyleSheet(bar_100); | |
161 | ui->hop_tasteShow->setFormat(tr("Very high")); | |
162 | } | |
163 | } | |
164 | ||
165 | ||
166 | void EditRecipe::on_Aroma_valueChanged(int value) | |
167 | { | |
168 | if (value < 20) { | |
169 | ui->hop_aromaShow->setStyleSheet(bar_20); | |
170 | ui->hop_aromaShow->setFormat(tr("Very low")); | |
171 | } else if (value < 40) { | |
172 | ui->hop_aromaShow->setStyleSheet(bar_40); | |
173 | ui->hop_aromaShow->setFormat(tr("Low")); | |
174 | } else if (value < 60) { | |
175 | ui->hop_aromaShow->setStyleSheet(bar_60); | |
176 | ui->hop_aromaShow->setFormat(tr("Moderate")); | |
177 | } else if (value < 80) { | |
178 | ui->hop_aromaShow->setStyleSheet(bar_80); | |
179 | ui->hop_aromaShow->setFormat(tr("High")); | |
180 | } else { | |
181 | ui->hop_aromaShow->setStyleSheet(bar_100); | |
182 | ui->hop_aromaShow->setFormat(tr("Very high")); | |
183 | } | |
184 | } | |
185 | ||
186 | ||
187 | void EditRecipe::calcIBUs() | |
188 | { | |
189 | double hop_flavour = 0, hop_aroma = 0, ibus = 0; | |
190 | ||
191 | for (int i = 0; i < recipe->hops.size(); i++) { | |
192 | ||
193 | ibus += Utils::toIBU(recipe->hops.at(i).h_useat, recipe->hops.at(i).h_form, recipe->preboil_sg, recipe->batch_size, recipe->hops.at(i).h_amount, | |
194 | recipe->hops.at(i).h_time, recipe->hops.at(i).h_alpha, recipe->ibu_method, 0, recipe->hops.at(i).h_time, 0); | |
195 | hop_flavour += Utils::hopFlavourContribution(recipe->hops.at(i).h_time, recipe->batch_size, recipe->hops.at(i).h_useat, recipe->hops.at(i).h_amount); | |
196 | hop_aroma += Utils::hopAromaContribution(recipe->hops.at(i).h_time, recipe->batch_size, recipe->hops.at(i).h_useat, recipe->hops.at(i).h_amount); | |
197 | } | |
198 | ||
199 | hop_flavour = round(hop_flavour * 1000.0 / 5.0) / 10; | |
200 | hop_aroma = round(hop_aroma * 1000.0 / 6.0) / 10; | |
201 | if (hop_flavour > 100) | |
202 | hop_flavour = 100; | |
203 | if (hop_aroma > 100) | |
204 | hop_aroma = 100; | |
205 | qDebug() << "ibu" << recipe->est_ibu << ibus << "flavour" << hop_flavour << "aroma" << hop_aroma; | |
206 | ||
207 | recipe->est_ibu = ibus; | |
208 | ui->est_ibuEdit->setValue(recipe->est_ibu); | |
209 | ui->est_ibu2Edit->setValue(recipe->est_ibu); | |
210 | ui->hop_tasteShow->setValue(hop_flavour); | |
211 | ui->hop_aromaShow->setValue(hop_aroma); | |
212 | } | |
213 | ||
214 | ||
215 | void EditRecipe::on_addHopRow_clicked() | |
216 | { | |
217 | Hops newh; | |
218 | ||
219 | qDebug() << "Add hop row"; | |
220 | ||
221 | for (int i = 0; i < recipe->hops.size(); i++) { | |
222 | if (recipe->hops.at(i).h_amount == 0 && recipe->hops.at(i).h_alpha == 0) | |
223 | return; // Add only one at a time. | |
224 | } | |
225 | ||
226 | emit refreshAll(); | |
227 | } | |
228 | ||
229 | ||
230 | void EditRecipe::on_deleteHopRow_clicked() | |
231 | { | |
232 | QPushButton *pb = qobject_cast<QPushButton *>(QObject::sender()); | |
233 | int row = pb->objectName().toInt(); | |
234 | qDebug() << "Delete hop row" << row << recipe->hops.size(); | |
235 | ||
236 | if (recipe->hops.size() < 1) | |
237 | return; | |
238 | ||
239 | int rc = QMessageBox::warning(this, tr("Delete hop"), tr("Delete %1").arg(recipe->hops.at(row).h_name), | |
240 | QMessageBox::Yes | QMessageBox::No, QMessageBox::No); | |
241 | if (rc == QMessageBox::No) | |
242 | return; | |
243 | ||
244 | ||
245 | } | |
246 | ||
247 | ||
248 | void EditRecipe::hop_amount_changed(double val) | |
249 | { | |
250 | QTableWidgetItem *item; | |
251 | ||
252 | qDebug() << "hop_amount_changed()" << recipe->hops_row << val; | |
253 | this->ignoreChanges = true; | |
254 | ||
255 | recipe->hops[recipe->hops_row].h_amount = val / 1000.0; | |
256 | item = new QTableWidgetItem(QString("%1 gr").arg(val, 2, 'f', 1, '0')); | |
257 | item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); | |
258 | ui->hopsTable->setItem(recipe->hops_row, 8, item); | |
259 | ||
260 | double ibu = Utils::toIBU(recipe->hops.at(recipe->hops_row).h_useat, recipe->hops.at(recipe->hops_row).h_form, recipe->preboil_sg, | |
261 | recipe->batch_size, recipe->hops.at(recipe->hops_row).h_amount, recipe->hops.at(recipe->hops_row).h_time, | |
262 | recipe->hops.at(recipe->hops_row).h_alpha, recipe->ibu_method, 0, recipe->hops.at(recipe->hops_row).h_time, 0); | |
263 | ||
264 | ibuEdit->setValue(ibu); | |
265 | item = new QTableWidgetItem(QString("%1").arg(ibu, 2, 'f', 1, '0')); | |
266 | item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); | |
267 | ui->hopsTable->setItem(recipe->hops_row, 7, item); | |
268 | ||
269 | this->ignoreChanges = false; | |
270 | calcIBUs(); | |
271 | is_changed(); | |
272 | } | |
273 | ||
274 | ||
275 | void EditRecipe::hop_time_changed(int val) | |
276 | { | |
277 | QTableWidgetItem *item; | |
278 | ||
279 | qDebug() << "hop_time_changed()" << recipe->hops_row << val; | |
280 | ||
281 | this->ignoreChanges = true; | |
282 | recipe->hops[recipe->hops_row].h_time = val; | |
283 | ||
284 | if (recipe->hops.at(recipe->hops_row).h_useat == 2 || recipe->hops.at(recipe->hops_row).h_useat == 4) { // Boil or whirlpool | |
285 | item = new QTableWidgetItem(QString("%1 min.").arg(val, 1, 'f', 0, '0')); | |
286 | } else if (recipe->hops.at(recipe->hops_row).h_useat == 5) { // Dry-hop | |
287 | item = new QTableWidgetItem(QString("%1 days.").arg(val / 1440, 1, 'f', 0, '0')); | |
288 | } else { | |
289 | item = new QTableWidgetItem(QString("")); | |
290 | } | |
291 | item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); | |
292 | ui->hopsTable->setItem(recipe->hops_row, 6, item); | |
293 | ||
294 | double ibu = Utils::toIBU(recipe->hops.at(recipe->hops_row).h_useat, recipe->hops.at(recipe->hops_row).h_form, recipe->preboil_sg, | |
295 | recipe->batch_size, recipe->hops.at(recipe->hops_row).h_amount, recipe->hops.at(recipe->hops_row).h_time, | |
296 | recipe->hops.at(recipe->hops_row).h_alpha, recipe->ibu_method, 0, recipe->hops.at(recipe->hops_row).h_time, 0); | |
297 | ||
298 | ibuEdit->setValue(ibu); | |
299 | item = new QTableWidgetItem(QString("%1").arg(ibu, 2, 'f', 1, '0')); | |
300 | item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); | |
301 | ui->hopsTable->setItem(recipe->hops_row, 7, item); | |
302 | ||
303 | this->ignoreChanges = false; | |
304 | calcIBUs(); | |
305 | is_changed(); | |
306 | } | |
307 | ||
308 | ||
309 | void EditRecipe::hop_select_changed(int val) | |
310 | { | |
311 | QSqlQuery query; | |
312 | bool instock = hinstockEdit->isChecked(); | |
313 | QString w; | |
314 | QTableWidgetItem *item; | |
315 | ||
316 | if (val < 1) | |
317 | return; | |
318 | ||
319 | qDebug() << "hop_select_changed()" << recipe->fermentables_row << val << instock; | |
320 | ||
321 | /* | |
322 | * Search the hop pointed by the index and instock flag. | |
323 | */ | |
324 | QString sql = "SELECT name,origin,alpha,beta,humulene,caryophyllene,cohumulone,myrcene,hsi,total_oil,type,form,cost FROM inventory_hops "; | |
325 | if (instock) | |
326 | sql.append("WHERE inventory > 0 "); | |
327 | sql.append("ORDER BY origin,name"); | |
328 | query.prepare(sql); | |
329 | query.exec(); | |
330 | query.first(); | |
331 | for (int i = 0; i < (val - 1); i++) { | |
332 | query.next(); | |
333 | } | |
334 | qDebug() << "found" << query.value(1).toString() << query.value(0).toString(); | |
335 | ||
336 | /* | |
337 | * Replace the hop record contents | |
338 | */ | |
339 | this->ignoreChanges = true; | |
340 | recipe->hops[recipe->hops_row].h_name = query.value(0).toString(); | |
341 | recipe->hops[recipe->hops_row].h_origin = query.value(1).toString(); | |
342 | recipe->hops[recipe->hops_row].h_alpha = query.value(2).toDouble(); | |
343 | recipe->hops[recipe->hops_row].h_beta = query.value(3).toDouble(); | |
344 | recipe->hops[recipe->hops_row].h_humulene = query.value(4).toDouble(); | |
345 | recipe->hops[recipe->hops_row].h_caryophyllene = query.value(5).toDouble(); | |
346 | recipe->hops[recipe->hops_row].h_cohumulone = query.value(6).toDouble(); | |
347 | recipe->hops[recipe->hops_row].h_myrcene = query.value(7).toDouble(); | |
348 | recipe->hops[recipe->hops_row].h_hsi = query.value(8).toDouble(); | |
349 | recipe->hops[recipe->hops_row].h_total_oil = query.value(9).toDouble(); | |
350 | recipe->hops[recipe->hops_row].h_type = query.value(10).toInt(); | |
351 | recipe->hops[recipe->hops_row].h_form = query.value(11).toInt(); | |
352 | recipe->hops[recipe->hops_row].h_cost = query.value(12).toDouble(); | |
353 | ||
354 | /* | |
355 | * Update the visible fields | |
356 | */ | |
357 | hnameEdit->setText(recipe->hops.at(recipe->hops_row).h_name); | |
358 | horiginEdit->setText(recipe->hops.at(recipe->hops_row).h_origin); | |
359 | ||
360 | double ibu = Utils::toIBU(recipe->hops.at(recipe->hops_row).h_useat, recipe->hops.at(recipe->hops_row).h_form, recipe->preboil_sg, | |
361 | recipe->batch_size, recipe->hops.at(recipe->hops_row).h_amount, recipe->hops.at(recipe->hops_row).h_time, | |
362 | recipe->hops.at(recipe->hops_row).h_alpha, recipe->ibu_method, 0, recipe->hops.at(recipe->hops_row).h_time, 0); | |
363 | ibuEdit->setValue(ibu); | |
364 | ||
365 | ui->hopsTable->setItem(recipe->hops_row, 0, new QTableWidgetItem(recipe->hops.at(recipe->hops_row).h_origin)); | |
366 | ui->hopsTable->setItem(recipe->hops_row, 1, new QTableWidgetItem(recipe->hops.at(recipe->hops_row).h_name)); | |
367 | ||
368 | item = new QTableWidgetItem(h_types[recipe->hops.at(recipe->hops_row).h_type]); | |
369 | item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter); | |
370 | ui->hopsTable->setItem(recipe->hops_row, 2, item); | |
371 | ||
372 | item = new QTableWidgetItem(h_forms[recipe->hops.at(recipe->hops_row).h_form]); | |
373 | item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter); | |
374 | ui->hopsTable->setItem(recipe->hops_row, 3, item); | |
375 | ||
376 | item = new QTableWidgetItem(QString("%1%").arg(recipe->hops.at(recipe->hops_row).h_alpha, 2, 'f', 1, '0')); | |
377 | item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); | |
378 | ui->hopsTable->setItem(recipe->hops_row, 4, item); | |
379 | ||
380 | item = new QTableWidgetItem(QString("%1").arg(ibu, 2, 'f', 1, '0')); | |
381 | item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); | |
382 | ui->hopsTable->setItem(recipe->hops_row, 7, item); | |
383 | ||
384 | this->ignoreChanges = false; | |
385 | calcIBUs(); | |
386 | is_changed(); | |
387 | } | |
388 | ||
389 | ||
390 | void EditRecipe::hop_instock_changed(bool val) | |
391 | { | |
392 | QSqlQuery query; | |
393 | ||
394 | qDebug() << "hop_instock_changed()" << recipe->hops_row << val; | |
395 | ||
396 | this->hselectEdit->setCurrentIndex(-1); | |
397 | this->hselectEdit->clear(); | |
398 | QString sql = "SELECT origin,name,alpha,inventory FROM inventory_hops "; | |
399 | if (val) | |
400 | sql.append("WHERE inventory > 0 "); | |
401 | sql.append("ORDER BY origin,name"); | |
402 | query.prepare(sql); | |
403 | query.exec(); | |
404 | query.first(); | |
405 | this->hselectEdit->addItem(""); // Start with empty value | |
406 | for (int i = 0; i < query.size(); i++) { | |
407 | this->hselectEdit->addItem(query.value(0).toString()+" - "+query.value(1).toString()+" ("+query.value(2).toString()+"%) "+ | |
408 | QString("%1 gr").arg(query.value(3).toDouble() * 1000.0, 2, 'f', 1, '0')); | |
409 | query.next(); | |
410 | } | |
411 | } | |
412 | ||
413 | ||
414 | void EditRecipe::hop_useat_changed(int val) | |
415 | { | |
416 | qDebug() << "hop_useat_changed()" << recipe->hops_row << val; | |
417 | ||
418 | this->ignoreChanges = true; | |
419 | recipe->hops[recipe->hops_row].h_useat = val; | |
420 | QTableWidgetItem *item = new QTableWidgetItem(h_useat[val]); | |
421 | item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter); | |
422 | ui->hopsTable->setItem(recipe->hops_row, 5, item); | |
423 | ||
424 | if (val == 2 || val == 4) { // Boil or whirlpool | |
425 | htimeLabel->setText(tr("Time in minutes:")); | |
426 | htimeEdit->setValue(recipe->hops.at(recipe->hops_row).h_time); | |
427 | htimeEdit->setReadOnly(false); | |
428 | } else if (val == 5) { // Dry-hop | |
429 | htimeLabel->setText(tr("Time in days:")); | |
430 | htimeEdit->setValue(recipe->hops.at(recipe->hops_row).h_time / 1440); | |
431 | htimeEdit->setReadOnly(false); | |
432 | } else { | |
433 | htimeLabel->setText(""); | |
434 | htimeEdit->setValue(0); | |
435 | htimeEdit->setReadOnly(true); | |
436 | } | |
437 | ||
438 | this->ignoreChanges = false; | |
439 | is_changed(); | |
440 | emit refreshAll(); | |
441 | } | |
442 | ||
443 | ||
444 | void EditRecipe::on_editHopRow_clicked() | |
445 | { | |
446 | QSqlQuery query; | |
447 | ||
448 | QPushButton *pb = qobject_cast<QPushButton *>(QObject::sender()); | |
449 | recipe->hops_row = pb->objectName().toInt(); | |
450 | qDebug() << "Edit hop row" << recipe->hops_row; | |
451 | Hops backup = recipe->hops.at(recipe->hops_row); | |
452 | ||
453 | QDialog* dialog = new QDialog(this); | |
454 | dialog->resize(738, 260); | |
455 | QDialogButtonBox *buttonBox = new QDialogButtonBox(dialog); | |
456 | buttonBox->setObjectName(QString::fromUtf8("buttonBox")); | |
457 | buttonBox->setGeometry(QRect(30, 210, 671, 32)); | |
458 | buttonBox->setLayoutDirection(Qt::LeftToRight); | |
459 | buttonBox->setOrientation(Qt::Horizontal); | |
460 | buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok); | |
461 | buttonBox->setCenterButtons(true); | |
462 | QLabel *nameLabel = new QLabel(dialog); | |
463 | nameLabel->setObjectName(QString::fromUtf8("nameLabel")); | |
464 | nameLabel->setText(tr("Current hop:")); | |
465 | nameLabel->setGeometry(QRect(10, 10, 141, 20)); | |
466 | nameLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); | |
467 | QLabel *originLabel = new QLabel(dialog); | |
468 | originLabel->setObjectName(QString::fromUtf8("originLabel")); | |
469 | originLabel->setText(tr("Origin:")); | |
470 | originLabel->setGeometry(QRect(10, 40, 141, 20)); | |
471 | originLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); | |
472 | QLabel *amountLabel = new QLabel(dialog); | |
473 | amountLabel->setObjectName(QString::fromUtf8("amountLabel")); | |
474 | amountLabel->setText(tr("Amount in gr:")); | |
475 | amountLabel->setGeometry(QRect(10, 100, 141, 20)); | |
476 | amountLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); | |
477 | htimeLabel = new QLabel(dialog); | |
478 | htimeLabel->setObjectName(QString::fromUtf8("htimeLabel")); | |
479 | if (recipe->hops.at(recipe->hops_row).h_useat == 5) // Dry-hop | |
480 | htimeLabel->setText(tr("Time in days:")); | |
481 | else if (recipe->hops.at(recipe->hops_row).h_useat == 2 || recipe->hops.at(recipe->hops_row).h_useat == 4) // Boil or whirlpool | |
482 | htimeLabel->setText(tr("Time in minutes:")); | |
483 | else | |
484 | htimeLabel->setText(""); | |
485 | ||
486 | htimeLabel->setGeometry(QRect(10, 130, 141, 20)); | |
487 | htimeLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); | |
488 | QLabel *useatLabel = new QLabel(dialog); | |
489 | useatLabel->setObjectName(QString::fromUtf8("useatLabel")); | |
490 | useatLabel->setText(tr("Use at:")); | |
491 | useatLabel->setGeometry(QRect(10, 160, 141, 20)); | |
492 | useatLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); | |
493 | QLabel *selectLabel = new QLabel(dialog); | |
494 | selectLabel->setObjectName(QString::fromUtf8("selectLabel")); | |
495 | selectLabel->setText(tr("Select hop:")); | |
496 | selectLabel->setGeometry(QRect(10, 70, 141, 20)); | |
497 | selectLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); | |
498 | QLabel *instockLabel = new QLabel(dialog); | |
499 | instockLabel->setObjectName(QString::fromUtf8("instockLabel")); | |
500 | instockLabel->setText(tr("In stock:")); | |
501 | instockLabel->setGeometry(QRect(525, 70, 121, 20)); | |
502 | instockLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); | |
503 | QLabel *ibuLabel = new QLabel(dialog); | |
504 | ibuLabel->setObjectName(QString::fromUtf8("maxLabel")); | |
505 | ibuLabel->setText(tr("Bitterness IBU:")); | |
506 | ibuLabel->setGeometry(QRect(420, 130, 121, 20)); | |
507 | ibuLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); | |
508 | ||
509 | hselectEdit = new QComboBox(dialog); | |
510 | hselectEdit->setObjectName(QString::fromUtf8("selectEdit")); | |
511 | hselectEdit->setGeometry(QRect(160, 70, 371, 23)); | |
512 | ||
513 | hnameEdit = new QLineEdit(dialog); | |
514 | hnameEdit->setObjectName(QString::fromUtf8("hnameEdit")); | |
515 | hnameEdit->setText(recipe->hops.at(recipe->hops_row).h_name); | |
516 | hnameEdit->setGeometry(QRect(160, 10, 511, 23)); | |
517 | hnameEdit->setReadOnly(true); | |
518 | horiginEdit = new QLineEdit(dialog); | |
519 | horiginEdit->setObjectName(QString::fromUtf8("horiginEdit")); | |
520 | horiginEdit->setText(recipe->hops.at(recipe->hops_row).h_origin); | |
521 | horiginEdit->setGeometry(QRect(160, 40, 511, 23)); | |
522 | horiginEdit->setReadOnly(true); | |
523 | hamountEdit = new QDoubleSpinBox(dialog); | |
524 | hamountEdit->setObjectName(QString::fromUtf8("hamountEdit")); | |
525 | hamountEdit->setGeometry(QRect(160, 100, 121, 24)); | |
526 | hamountEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); | |
527 | hamountEdit->setAccelerated(true); | |
528 | hamountEdit->setDecimals(1); | |
529 | hamountEdit->setMaximum(1000000.0); | |
530 | hamountEdit->setSingleStep(0.5); | |
531 | hamountEdit->setValue(recipe->hops.at(recipe->hops_row).h_amount * 1000.0); | |
532 | htimeEdit = new QSpinBox(dialog); | |
533 | htimeEdit->setObjectName(QString::fromUtf8("htimeEdit")); | |
534 | htimeEdit->setGeometry(QRect(160, 130, 121, 24)); | |
535 | htimeEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); | |
536 | htimeEdit->setAccelerated(true); | |
537 | htimeEdit->setMaximum(10000.0); | |
538 | if (recipe->hops.at(recipe->hops_row).h_useat == 2 || recipe->hops.at(recipe->hops_row).h_useat == 4) { // Boil or whirlpool | |
539 | htimeEdit->setValue(recipe->hops.at(recipe->hops_row).h_time); | |
540 | htimeEdit->setReadOnly(false); | |
541 | } else if (recipe->hops.at(recipe->hops_row).h_useat == 5){ // Dry-hop | |
542 | htimeEdit->setValue(recipe->hops.at(recipe->hops_row).h_time / 1440); | |
543 | htimeEdit->setReadOnly(false); | |
544 | } else { | |
545 | htimeEdit->setReadOnly(true); | |
546 | } | |
547 | useatEdit = new QComboBox(dialog); | |
548 | useatEdit->setObjectName(QString::fromUtf8("useatEdit")); | |
549 | useatEdit->setGeometry(QRect(160, 160, 161, 23)); | |
550 | useatEdit->addItem(tr("Mash")); | |
551 | useatEdit->addItem(tr("First wort")); | |
552 | useatEdit->addItem(tr("Boil")); | |
553 | useatEdit->addItem(tr("Aroma")); | |
554 | useatEdit->addItem(tr("Whirlpool")); | |
555 | useatEdit->addItem(tr("Dry hop")); | |
556 | useatEdit->setCurrentIndex(recipe->hops.at(recipe->hops_row).h_useat); | |
557 | ||
558 | hinstockEdit = new QCheckBox(dialog); | |
559 | hinstockEdit->setObjectName(QString::fromUtf8("hinstockEdit")); | |
560 | hinstockEdit->setGeometry(QRect(655, 70, 85, 21)); | |
561 | hinstockEdit->setChecked(true); | |
562 | ||
563 | ibuEdit = new QDoubleSpinBox(dialog); | |
564 | ibuEdit->setObjectName(QString::fromUtf8("ibuEdit")); | |
565 | ibuEdit->setGeometry(QRect(550, 130, 121, 24)); | |
566 | ibuEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); | |
567 | ibuEdit->setReadOnly(true); | |
568 | ibuEdit->setButtonSymbols(QAbstractSpinBox::NoButtons); | |
569 | ibuEdit->setDecimals(1); | |
570 | double ibu = Utils::toIBU(recipe->hops.at(recipe->hops_row).h_useat, recipe->hops.at(recipe->hops_row).h_form, recipe->preboil_sg, | |
571 | recipe->batch_size, recipe->hops.at(recipe->hops_row).h_amount, recipe->hops.at(recipe->hops_row).h_time, | |
572 | recipe->hops.at(recipe->hops_row).h_alpha, recipe->ibu_method, 0, recipe->hops.at(recipe->hops_row).h_time, 0); | |
573 | ibuEdit->setValue(ibu); | |
574 | ||
575 | hop_instock_changed(true); | |
576 | ||
577 | connect(hselectEdit, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &EditRecipe::hop_select_changed); | |
578 | connect(hamountEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditRecipe::hop_amount_changed); | |
579 | connect(htimeEdit, QOverload<int>::of(&QSpinBox::valueChanged), this, &EditRecipe::hop_time_changed); | |
580 | connect(useatEdit, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &EditRecipe::hop_useat_changed); | |
581 | connect(hinstockEdit, &QCheckBox::stateChanged, this, &EditRecipe::hop_instock_changed); | |
582 | connect(buttonBox, SIGNAL(rejected()), dialog, SLOT(reject())); | |
583 | connect(buttonBox, SIGNAL(accepted()), dialog, SLOT(accept())); | |
584 | ||
585 | dialog->setModal(true); | |
586 | dialog->exec(); | |
587 | if (dialog->result() == QDialog::Rejected) { | |
588 | qDebug() << "reject and rollback"; | |
589 | recipe->hops[recipe->hops_row] = backup; | |
590 | } else { | |
591 | /* Clear time if hop is not used for boil, whirlpool or dry-hop. */ | |
592 | if (! (recipe->hops.at(recipe->hops_row).h_useat == 2 || | |
593 | recipe->hops.at(recipe->hops_row).h_useat == 4 || | |
594 | recipe->hops.at(recipe->hops_row).h_useat == 5)) { | |
595 | if (recipe->hops.at(recipe->hops_row).h_time) { | |
596 | recipe->hops[recipe->hops_row].h_time = 0; | |
597 | is_changed(); | |
598 | } | |
599 | } | |
600 | } | |
601 | ||
602 | disconnect(hselectEdit, nullptr, nullptr, nullptr); | |
603 | disconnect(hamountEdit, nullptr, nullptr, nullptr); | |
604 | disconnect(htimeEdit, nullptr, nullptr, nullptr); | |
605 | disconnect(useatEdit, nullptr, nullptr, nullptr); | |
606 | disconnect(hinstockEdit, nullptr, nullptr, nullptr); | |
607 | disconnect(buttonBox, nullptr, nullptr, nullptr); | |
608 | ||
609 | emit refreshAll(); | |
610 | } | |
611 | ||
612 |