src/EditProduct.cpp

changeset 175
f1ed3a2a94e9
child 176
69a033e099a2
equal deleted inserted replaced
174:ceb8aa4ebd25 175:f1ed3a2a94e9
1 /**
2 * EditProduct.cpp is part of bmsapp.
3 *
4 * bmsapp is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * bmsapp is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17 #include "MainWindow.h"
18 #include "EditProduct.h"
19 #include "PrinterDialog.h"
20 #include "../ui/ui_EditProduct.h"
21 #include "Utils.h"
22 #include "global.h"
23
24
25
26 EditProduct::EditProduct(int id, QWidget *parent) : QDialog(parent), ui(new Ui::EditProduct)
27 {
28 QSqlQuery query, wquery, yquery;
29
30 qDebug() << "EditProduct record:" << id;
31 product = new Product;
32 ui->setupUi(this);
33 product->fermentables_row = product->hops_row = product->miscs_row = product->yeasts_row = product->mashs_row = -1;
34 product->fermentables_use100 = false;
35 this->recno = id;
36
37 WindowTitle();
38
39 ui->typeEdit->addItem(tr("Extract"));
40 ui->typeEdit->addItem(tr("Partial Mash"));
41 ui->typeEdit->addItem(tr("All Grain"));
42
43 ui->color_methodEdit->addItem("Morey");
44 ui->color_methodEdit->addItem("Mosher");
45 ui->color_methodEdit->addItem("Daniels");
46 ui->color_methodEdit->addItem("Halberstadt");
47 ui->color_methodEdit->addItem("Naudts");
48
49 ui->ibu_methodEdit->addItem("Tinseth");
50 ui->ibu_methodEdit->addItem("Rager");
51 ui->ibu_methodEdit->addItem("Daniels");
52
53 for (int i = 0; i < my_acids.size(); i++) {
54 ui->mw_acidPick->addItem(my_acids.at(i).name_en);
55 ui->sp_acidtypeEdit->addItem(my_acids.at(i).name_en);
56 }
57
58 ui->sp_sourceEdit->addItem(tr("Source 1"));
59 ui->sp_sourceEdit->addItem(tr("Source 2"));
60 ui->sp_sourceEdit->addItem(tr("Mixed"));
61
62 query.prepare("SELECT name FROM inventory_waters ORDER BY record");
63 query.exec();
64 query.first();
65 ui->w1_nameEdit->addItem("");
66 ui->w2_nameEdit->addItem("");
67 for (int i = 0; i < query.size(); i++) {
68 ui->w1_nameEdit->addItem(query.value(0).toString());
69 ui->w2_nameEdit->addItem(query.value(0).toString());
70 query.next();
71 }
72
73 query.prepare("SELECT name FROM profile_water ORDER BY name");
74 query.exec();
75 ui->wt_sourceEdit->addItem("");
76 while (query.next()) {
77 ui->wt_sourceEdit->addItem(query.value(0).toString());
78 }
79
80 query.prepare("SELECT name FROM profile_mash ORDER BY name");
81 query.exec();
82 ui->mash_pickEdit->addItem("");
83 while (query.next()) {
84 ui->mash_pickEdit->addItem(query.value(0).toString());
85 }
86
87 ui->beerstyleEdit->addItem(""); // First add a dummy
88 query.prepare("SELECT style_guide,style_letter,name FROM profile_styles ORDER BY style_guide,style_letter,name");
89 query.exec();
90 query.first();
91 for (int i = 0; i < query.size(); i++) {
92 ui->beerstyleEdit->addItem(query.value(0).toString()+" "+query.value(1).toString()+" "+query.value(2).toString());
93 query.next();
94 }
95
96 if (id >= 0) {
97 query.prepare("SELECT * FROM products WHERE record = :recno");
98 query.bindValue(":recno", id);
99 query.exec();
100 if (! query.first()) {
101 qDebug() << "EditProduct seek error record" << id;
102 QMessageBox::warning(this, tr("Database error"), tr("MySQL error: record %1 not found").arg(id));
103 this->done(QDialog::Rejected); // At this stage, this doesn't work because the dialog is not yet visible.
104 return;
105 }
106
107 QSqlRecord rec = query.record();
108 for (int i = 0; i < rec.count(); i++)
109 qDebug() << i << rec.fieldName(i) << query.value(i);
110
111 product->record = query.value("record").toInt();
112 product->uuid = query.value("uuid").toString();
113 product->name = query.value("name").toString();
114 product->code = query.value("code").toString();
115 product->birth = query.value("birth").toDate();
116 product->stage = query.value("stage").toInt();
117 product->notes = query.value("notes").toString();
118 product->log_brew = query.value("log_brew").toInt() ? true:false;
119 product->log_fermentation = query.value("log_fermentation").toInt() ? true:false;
120 product->log_ispindel = query.value("log_ispindel").toInt() ? true:false;
121 product->log_co2pressure = query.value("log_co2pressure").toInt() ? true:false;
122 product->inventory_reduced = query.value("inventory_reduced").toInt();
123 product->locked = query.value("locked").toInt() ? true:false;
124
125 product->eq_name = query.value("eq_name").toString();
126 product->eq_notes = query.value("eq_notes").toString();
127 product->eq_boil_size = query.value("eq_boil_size").toDouble();
128 product->eq_batch_size = query.value("eq_batch_size").toDouble();
129 product->eq_tun_volume = query.value("eq_tun_volume").toDouble();
130 product->eq_tun_weight = query.value("eq_tun_weight").toDouble();
131 product->eq_tun_specific_heat = query.value("eq_tun_specific_heat").toDouble();
132 product->eq_tun_material = query.value("eq_tun_material").toInt();
133 product->eq_tun_height = query.value("eq_tun_height").toDouble();
134 product->eq_top_up_water = query.value("eq_top_up_water").toDouble();
135 product->eq_trub_chiller_loss = query.value("eq_trub_chiller_loss").toDouble();
136 product->eq_evap_rate = query.value("eq_evap_rate").toDouble();
137 product->eq_boil_time = query.value("eq_boil_time").toDouble();
138 product->eq_calc_boil_volume = query.value("eq_calc_boil_volume").toInt() ? true:false;
139 product->eq_top_up_kettle = query.value("eq_top_up_kettle").toDouble();
140 product->eq_hop_utilization = query.value("eq_hop_utilization").toDouble();
141 product->eq_lauter_volume = query.value("eq_lauter_volume").toDouble();
142 product->eq_lauter_height = query.value("eq_lauter_height").toDouble();
143 product->eq_lauter_deadspace = query.value("eq_lauter_deadspace").toDouble();
144 product->eq_kettle_volume = query.value("eq_kettle_volume").toDouble();
145 product->eq_kettle_height = query.value("eq_kettle_height").toDouble();
146 product->eq_mash_volume = query.value("eq_mash_volume").toDouble();
147 product->eq_mash_max = query.value("eq_mash_max").toDouble();
148 product->eq_efficiency = query.value("eq_efficiency").toDouble();
149
150 product->brew_date_start = query.value("brew_date_start").toDateTime();
151 product->brew_mash_ph = query.value("brew_mash_ph").toDouble();
152 product->brew_mash_sg = query.value("brew_mash_sg").toDouble();
153 product->brew_mash_efficiency = query.value("brew_mash_efficiency").toDouble();
154 product->brew_sparge_temperature = query.value("brew_sparge_temperature").toDouble();
155 product->brew_sparge_volume = query.value("brew_sparge_volume").toDouble();
156 product->brew_sparge_est = query.value("brew_sparge_est").toDouble();
157 product->brew_sparge_ph = query.value("brew_sparge_ph").toDouble();
158 product->brew_preboil_volume = query.value("brew_preboil_volume").toDouble();
159 product->brew_preboil_sg = query.value("brew_preboil_sg").toDouble();
160 product->brew_preboil_ph = query.value("brew_preboil_ph").toDouble();
161 product->brew_preboil_efficiency = query.value("brew_preboil_efficiency").toDouble();
162 product->brew_aboil_volume = query.value("brew_aboil_volume").toDouble();
163 product->brew_aboil_sg = query.value("brew_aboil_sg").toDouble();
164 product->brew_aboil_ph = query.value("brew_aboil_ph").toDouble();
165 product->brew_aboil_efficiency = query.value("brew_aboil_efficiency").toDouble();
166 product->brew_cooling_method = query.value("brew_cooling_method").toInt();
167 product->brew_cooling_time = query.value("brew_cooling_time").toDouble();
168 product->brew_cooling_to = query.value("brew_cooling_to").toDouble();
169 product->brew_whirlpool9 = query.value("brew_whirlpool9").toDouble();
170 product->brew_whirlpool7 = query.value("brew_whirlpool7").toDouble();
171 product->brew_whirlpool6 = query.value("brew_whirlpool6").toDouble();
172 product->brew_whirlpool2 = query.value("brew_whirlpool2").toDouble();
173 product->brew_fermenter_volume = query.value("brew_fermenter_volume").toDouble();
174 product->brew_fermenter_extrawater = query.value("brew_fermenter_extrawater").toDouble();
175 product->brew_fermenter_tcloss = query.value("brew_fermenter_tcloss").toDouble();
176 product->brew_aeration_time = query.value("brew_aeration_time").toDouble();
177 product->brew_aeration_speed = query.value("brew_aeration_speed").toDouble();
178 product->brew_aeration_type = query.value("brew_aeration_type").toInt();
179 product->brew_fermenter_sg = query.value("brew_fermenter_sg").toDouble();
180 product->brew_fermenter_ibu = query.value("brew_fermenter_ibu").toDouble();
181 product->brew_fermenter_color = query.value("brew_fermenter_color").toDouble();
182 product->brew_date_end = query.value("brew_date_end").toDateTime();
183
184 product->og = query.value("og").toDouble();
185 product->fg = query.value("fg").toDouble();
186 product->primary_start_temp = query.value("primary_start_temp").toDouble();
187 product->primary_max_temp = query.value("primary_max_temp").toDouble();
188 product->primary_end_temp = query.value("primary_end_temp").toDouble();
189 product->primary_end_sg = query.value("primary_end_sg").toDouble();
190 product->primary_end_date = query.value("primary_end_date").toDate();
191 product->secondary_temp = query.value("secondary_temp").toDouble();
192 product->secondary_end_sg = query.value("secondary_end_sg").toDouble();
193 product->secondary_end_date = query.value("secondary_end_date").toDate();
194 product->tertiary_temp = query.value("tertiary_temp").toDouble();
195
196 product->package_date = query.value("package_date").toDate();
197 product->package_volume = query.value("package_volume").toDouble();
198 product->package_infuse_amount = query.value("package_infuse_amount").toDouble();
199 product->package_infuse_abv = query.value("package_infuse_abv").toDouble();
200 product->package_infuse_notes = query.value("package_infuse_notes").toString();
201 product->package_abv = query.value("package_abv").toDouble();
202 product->package_ph = query.value("package_ph").toDouble();
203
204 product->bottle_amount = query.value("bottle_amount").toDouble();
205 product->bottle_carbonation = query.value("bottle_carbonation").toDouble();
206 product->bottle_priming_sugar = query.value("bottle_priming_sugar").toInt();
207 product->bottle_priming_amount = query.value("bottle_priming_amount").toDouble();
208 product->bottle_priming_water = query.value("bottle_priming_water").toDouble();
209 product->bottle_carbonation_temp = query.value("bottle_carbonation_temp").toDouble();
210
211 product->keg_amount = query.value("keg_amount").toDouble();
212 product->keg_carbonation = query.value("keg_carbonation").toDouble();
213 product->keg_priming_sugar = query.value("keg_priming_sugar").toInt();
214 product->keg_priming_amount = query.value("keg_priming_amount").toDouble();
215 product->keg_priming_water = query.value("keg_priming_water").toDouble();
216 product->keg_carbonation_temp = query.value("keg_carbonation_temp").toDouble();
217 product->keg_forced_carb = query.value("keg_forced_carb").toInt() ? true:false;
218 product->keg_pressure = query.value("keg_pressure").toDouble();
219
220 product->taste_notes = query.value("taste_notes").toString();
221 product->taste_rate = query.value("taste_rate").toDouble();
222 product->taste_date = query.value("taste_date").toDate();
223 product->taste_color = query.value("taste_color").toString();
224 product->taste_transparency = query.value("taste_transparency").toString();
225 product->taste_head = query.value("taste_head").toString();
226 product->taste_aroma = query.value("taste_aroma").toString();
227 product->taste_taste = query.value("taste_taste").toString();
228 product->taste_mouthfeel = query.value("taste_mouthfeel").toString();
229 product->taste_aftertaste = query.value("taste_aftertaste").toString();
230
231 product->st_name = query.value("st_name").toString();
232 product->st_letter = query.value("st_letter").toString();
233 product->st_guide = query.value("st_guide").toString();
234 product->st_category = query.value("st_category").toString();
235 product->st_category_number = query.value("st_category_number").toInt();
236 product->st_type = query.value("st_type").toInt();
237 product->st_og_min = query.value("st_og_min").toDouble();
238 product->st_og_max = query.value("st_og_max").toDouble();
239 product->st_fg_min = query.value("st_fg_min").toDouble();
240 product->st_fg_max = query.value("st_fg_max").toDouble();
241 product->st_ibu_min = query.value("st_ibu_min").toDouble();
242 product->st_ibu_max = query.value("st_ibu_max").toDouble();
243 product->st_color_min = query.value("st_color_min").toDouble();
244 product->st_color_max = query.value("st_color_max").toDouble();
245 product->st_carb_min = query.value("st_carb_min").toDouble();
246 product->st_carb_max = query.value("st_carb_max").toDouble();
247 product->st_abv_min = query.value("st_abv_min").toDouble();
248 product->st_abv_max = query.value("st_abv_max").toDouble();
249
250 product->type = query.value("type").toInt();
251 product->batch_size = query.value("batch_size").toDouble();
252 product->boil_size = query.value("boil_size").toDouble();
253 product->boil_time = query.value("boil_time").toDouble();
254 product->efficiency = query.value("efficiency").toDouble();
255 product->est_og = query.value("est_og").toDouble();
256 product->est_fg = query.value("est_fg").toDouble();
257 product->est_abv = query.value("est_abv").toDouble();
258 product->est_color = query.value("est_color").toDouble();
259 product->color_method = query.value("color_method").toInt();
260 product->est_ibu = query.value("est_ibu").toDouble();
261 product->ibu_method = query.value("ibu_method").toInt();
262 product->est_carb = query.value("est_carb").toDouble();
263
264 product->sparge_temp = query.value("sparge_temp").toDouble();
265 product->sparge_ph = query.value("sparge_ph").toDouble();
266 product->sparge_volume = query.value("sparge_volume").toDouble();
267 product->sparge_source = query.value("sparge_source").toInt();
268 product->sparge_acid_type = query.value("sparge_acid_type").toInt();
269 product->sparge_acid_perc = query.value("sparge_acid_perc").toDouble();
270 product->sparge_acid_amount = query.value("sparge_acid_amount").toDouble();
271 product->mash_ph = query.value("mash_ph").toDouble();
272 product->mash_name = query.value("mash_name").toString();
273 product->calc_acid = query.value("calc_acid").toInt() ? true:false;
274
275 product->w1_name = query.value("w1_name").toString();
276 product->w1_amount = query.value("w1_amount").toDouble();
277 product->w1_calcium = query.value("w1_calcium").toDouble();
278 product->w1_sulfate = query.value("w1_sulfate").toDouble();
279 product->w1_chloride = query.value("w1_chloride").toDouble();
280 product->w1_sodium = query.value("w1_sodium").toDouble();
281 product->w1_magnesium = query.value("w1_magnesium").toDouble();
282 product->w1_total_alkalinity = query.value("w1_total_alkalinity").toDouble();
283 product->w1_ph = query.value("w1_ph").toDouble();
284 product->w1_cost = query.value("w1_cost").toDouble();
285 product->w2_name = query.value("w2_name").toString();
286 product->w2_amount = query.value("w2_amount").toDouble();
287 product->w2_calcium = query.value("w2_calcium").toDouble();
288 product->w2_sulfate = query.value("w2_sulfate").toDouble();
289 product->w2_chloride = query.value("w2_chloride").toDouble();
290 product->w2_sodium = query.value("w2_sodium").toDouble();
291 product->w2_magnesium = query.value("w2_magnesium").toDouble();
292 product->w2_total_alkalinity = query.value("w2_total_alkalinity").toDouble();
293 product->w2_ph = query.value("w2_ph").toDouble();
294 product->w2_cost = query.value("w2_cost").toDouble();
295 product->wg_amount = query.value("wg_amount").toDouble();
296 product->wg_calcium = query.value("wg_calcium").toDouble();
297 product->wg_sulfate = query.value("wg_sulfate").toDouble();
298 product->wg_chloride = query.value("wg_chloride").toDouble();
299 product->wg_sodium = query.value("wg_sodium").toDouble();
300 product->wg_magnesium = query.value("wg_magnesium").toDouble();
301 product->wg_total_alkalinity = query.value("wg_total_alkalinity").toDouble();
302 product->wg_ph = query.value("wg_ph").toDouble();
303 product->wb_calcium = query.value("wb_calcium").toDouble();
304 product->wb_sulfate = query.value("wb_sulfate").toDouble();
305 product->wb_chloride = query.value("wb_chloride").toDouble();
306 product->wb_sodium = query.value("wb_sodium").toDouble();
307 product->wb_magnesium = query.value("wb_magnesium").toDouble();
308 product->wb_total_alkalinity = query.value("wb_total_alkalinity").toDouble();
309 product->wb_ph = query.value("wb_ph").toDouble();
310 product->wa_acid_name = query.value("wa_acid_name").toInt();
311 product->wa_acid_perc = query.value("wa_acid_perc").toDouble();
312 product->wa_base_name = query.value("wa_base_name").toInt();
313
314 product->starter_enable = query.value("starter_enable").toInt() ? true:false;
315 product->starter_type = query.value("starter_type").toInt();
316 product->starter_sg = query.value("starter_sg").toDouble();
317 product->starter_viability = query.value("starter_viability").toInt();
318 product->yeast_prod_date = query.value("yeast_prod_date").toDate();
319 product->yeast_pitchrate = query.value("yeast_pitchrate").toDouble();
320 product->prop1_type = query.value("prop1_type").toInt();
321 product->prop1_volume = query.value("prop1_volume").toDouble();
322 product->prop2_type = query.value("prop2_type").toInt();
323 product->prop2_volume = query.value("prop2_volume").toDouble();
324 product->prop3_type = query.value("prop3_type").toInt();
325 product->prop3_volume = query.value("prop3_volume").toDouble();
326 product->prop4_type = query.value("prop4_type").toInt();
327 product->prop4_volume = query.value("prop4_volume").toDouble();
328
329 product->divide_type = query.value("divide_type").toInt();
330 product->divide_size = query.value("divide_size").toDouble();
331 product->divide_factor = query.value("divide_factor").toDouble();
332 product->divide_parts = query.value("divide_parts").toInt();
333 product->divide_part = query.value("divide_part").toInt();
334
335 QJsonParseError parseError;
336 const auto& f_json = query.value("json_fermentables").toString();
337 if (!f_json.trimmed().isEmpty()) {
338 const auto& formattedJson = QString("%1").arg(f_json);
339 QJsonDocument fermentables = QJsonDocument::fromJson(formattedJson.toUtf8(), &parseError);
340 if (parseError.error != QJsonParseError::NoError) {
341 qDebug() << "Parse error: " << parseError.errorString() << "at" << parseError.offset ;
342 } else if (fermentables.isArray()) {
343 double percentcheck = 0;
344 for (int i = 0; i < fermentables.array().size(); i++) {
345 QJsonObject obj = fermentables.array().at(i).toObject();
346 //qDebug() << i << obj;
347 Fermentables f;
348 f.f_name = obj["f_name"].toString();
349 f.f_origin = obj["f_origin"].toString();
350 f.f_supplier = obj["f_supplier"].toString();
351 f.f_amount = obj["f_amount"].toDouble();
352 f.f_cost = obj["f_cost"].toDouble();
353 f.f_type = obj["f_type"].toInt();
354 f.f_yield = obj["f_yield"].toDouble();
355 f.f_color = obj["f_color"].toDouble();
356 f.f_coarse_fine_diff = obj["f_coarse_fine_diff"].toDouble();
357 f.f_moisture = obj["f_moisture"].toDouble();
358 f.f_diastatic_power = obj["f_diastatic_power"].toDouble();
359 f.f_protein = obj["f_protein"].toDouble();
360 f.f_dissolved_protein = obj["f_dissolved_protein"].toDouble();
361 f.f_max_in_batch = obj["f_max_in_batch"].toDouble();
362 f.f_graintype = obj["f_graintype"].toInt();
363 f.f_added = obj["f_added"].toInt();
364 f.f_recommend_mash = obj["f_recommend_mash"].toInt() ? true:false;
365 f.f_add_after_boil = obj["f_add_after_boil"].toInt() ? true:false;
366 f.f_adjust_to_total_100 = obj["f_adjust_to_total_100"].toInt() ? true:false;
367 f.f_percentage = obj["f_percentage"].toDouble();
368 f.f_di_ph = obj["f_di_ph"].toDouble();
369 f.f_acid_to_ph_57 = obj["f_acid_to_ph_57"].toDouble();
370 if (f.f_adjust_to_total_100)
371 product->fermentables_use100 = true;
372 percentcheck += f.f_percentage;
373 product->fermentables.append(f);
374 }
375 qDebug() << "fermentables" << product->fermentables.size() << percentcheck;
376 if (percentcheck == 0) {
377 /* Missing percentages, fix it. */
378 double total = 0;
379 for (int i = 0; i < product->fermentables.size(); i++) {
380 if (product->fermentables.at(i).f_added < 4)
381 total += product->fermentables.at(i).f_amount;
382 }
383 for (int i = 0; i < product->fermentables.size(); i++) {
384 if (product->fermentables.at(i).f_added < 4)
385 product->fermentables[i].f_percentage = round((product->fermentables.at(i).f_amount / total) * 10000.0) / 100.0;
386 }
387 qDebug() << " fixed missing percentages";
388 is_changed();
389 }
390 }
391 } else {
392 qDebug() << "empty fermentables";
393 }
394
395 const auto& h_json = query.value("json_hops").toString();
396 if (!h_json.trimmed().isEmpty()) {
397 const auto& formattedJson = QString("%1").arg(h_json);
398 QJsonDocument hops = QJsonDocument::fromJson(formattedJson.toUtf8(), &parseError);
399 if (parseError.error != QJsonParseError::NoError) {
400 qDebug() << "Parse error: " << parseError.errorString() << "at" << parseError.offset;
401 } else if (hops.isArray()) {
402 for (int i = 0; i < hops.array().size(); i++) {
403 QJsonObject obj = hops.array().at(i).toObject();
404 //qDebug() << i << obj;
405 Hops h;
406 h.h_name = obj["h_name"].toString();
407 h.h_origin = obj["h_origin"].toString();
408 h.h_amount = obj["h_amount"].toDouble();
409 h.h_cost = obj["h_cost"].toDouble();
410 h.h_type = obj["h_type"].toInt();
411 h.h_form = obj["h_form"].toInt();
412 h.h_useat = obj["h_useat"].toInt();
413 h.h_time = obj["h_time"].toInt();
414 h.h_alpha = obj["h_alpha"].toDouble();
415 h.h_beta = obj["h_beta"].toDouble();
416 h.h_hsi = obj["h_hsi"].toDouble();
417 h.h_humulene = obj["h_humulene"].toDouble();
418 h.h_caryophyllene = obj["h_caryophyllene"].toDouble();
419 h.h_cohumulone = obj["h_cohumulone"].toDouble();
420 h.h_myrcene = obj["h_myrcene"].toDouble();
421 h.h_total_oil = obj["h_total_oil"].toDouble();
422 product->hops.append(h);
423 }
424 qDebug() << "hops" << product->hops.size();
425 }
426 } else {
427 qDebug() << "empty hops";
428 }
429
430 const auto& m_json = query.value("json_miscs").toString();
431 if (!m_json.trimmed().isEmpty()) {
432 const auto& formattedJson = QString("%1").arg(m_json);
433 QJsonDocument miscs = QJsonDocument::fromJson(formattedJson.toUtf8(), &parseError);
434 if (parseError.error != QJsonParseError::NoError) {
435 qDebug() << "Parse error: " << parseError.errorString() << "at" << parseError.offset;
436 } else if (miscs.isArray()) {
437 for (int i = 0; i < miscs.array().size(); i++) {
438 QJsonObject obj = miscs.array().at(i).toObject();
439 //qDebug() << i << obj;
440 Miscs m;
441 m.m_name = obj["m_name"].toString();
442 m.m_amount = obj["m_amount"].toDouble();
443 m.m_type = obj["m_type"].toInt();
444 m.m_use_use = obj["m_use_use"].toInt();
445 m.m_time = obj["m_time"].toDouble();
446 m.m_amount_is_weight = obj["m_amount_is_weight"].toInt() ? true:false;
447 m.m_cost = obj["m_cost"].toDouble();
448 product->miscs.append(m);
449 }
450 qDebug() << "miscs" << product->miscs.size();
451 }
452 } else {
453 qDebug() << "empty miscs";
454 }
455
456 const auto& y_json = query.value("json_yeasts").toString();
457 if (!y_json.trimmed().isEmpty()) {
458 const auto& formattedJson = QString("%1").arg(y_json);
459 QJsonDocument yeasts = QJsonDocument::fromJson(formattedJson.toUtf8(), &parseError);
460 if (parseError.error != QJsonParseError::NoError) {
461 qDebug() << "Parse error: " << parseError.errorString() << "at" << parseError.offset ;
462 } else if (yeasts.isArray()) {
463 for (int i = 0; i < yeasts.array().size(); i++) {
464 QJsonObject obj = yeasts.array().at(i).toObject();
465 //qDebug() << i << obj;
466 Yeasts y;
467 /* First some defaults for newer fields. */
468 y.y_tolerance = y.y_harvest_time = y.y_pitch_temperature = y.y_zymocide = 0;
469 y.y_sta1 = y.y_bacteria = y.y_harvest_top = y.y_pofpos = false;
470 y.y_gr_hl_lo = 50;
471 y.y_sg_lo = 1.04;
472 y.y_gr_hl_hi = 80;
473 y.y_sg_hi = 1.08;
474 /* Now get what we have got */
475 y.y_name = obj["y_name"].toString();
476 y.y_laboratory = obj["y_laboratory"].toString();
477 y.y_product_id = obj["y_product_id"].toString();
478 y.y_amount = obj["y_amount"].toDouble();
479 y.y_type = obj["y_type"].toInt();
480 y.y_form = obj["y_form"].toInt();
481 y.y_min_temperature = obj["y_min_temperature"].toDouble();
482 y.y_max_temperature = obj["y_max_temperature"].toDouble();
483 y.y_flocculation = obj["y_flocculation"].toInt();
484 y.y_attenuation = obj["y_attenuation"].toDouble();
485 y.y_cells = obj["y_cells"].toDouble();
486 y.y_tolerance = obj["y_tolerance"].toDouble();
487 y.y_inventory = obj["y_inventory"].toDouble();
488 y.y_use = obj["y_use"].toInt();
489 y.y_sta1 = obj["y_sta1"].toInt() ? true:false;
490 y.y_bacteria = obj["y_bacteria"].toInt() ? true:false;
491 y.y_harvest_top = obj["y_harvest_top"].toInt() ? true:false;
492 y.y_harvest_time = obj["y_harvest_time"].toInt();
493 y.y_pitch_temperature = obj["y_pitch_temperature"].toDouble();
494 y.y_pofpos = obj["y_pofpos"].toInt() ? true:false;
495 y.y_zymocide = obj["y_zymocide"].toInt();
496 y.y_gr_hl_lo = obj["y_gr_hl_lo"].toInt();
497 y.y_sg_lo = obj["y_sg_lo"].toDouble();
498 y.y_gr_hl_hi = obj["y_gr_hl_hi"].toInt();
499 y.y_sg_hi = obj["y_sg_hi"].toDouble();
500 y.y_cost = obj["y_cost"].toDouble();
501
502 if (y.y_tolerance == 0 || y.y_cells == 0) { // More and better tests?
503 /*
504 * Possible data upgrade needed.
505 */
506 yquery.prepare("SELECT tolerance,cells,sta1,bacteria,harvest_top,harvest_time,pitch_temperature,"
507 "pofpos,zymocide,gr_hl_lo,sg_lo,gr_hl_hi,sg_hi "
508 "FROM inventory_yeasts WHERE name=:name AND laboratory=:laboratory AND product_id=:product_id");
509 yquery.bindValue(":name", y.y_name);
510 yquery.bindValue(":laboratory", y.y_laboratory);
511 yquery.bindValue(":product_id", y.y_product_id);
512 yquery.exec();
513 if (yquery.first()) {
514 y.y_tolerance = yquery.value(0).toDouble();
515 y.y_cells = yquery.value(1).toDouble();
516 y.y_sta1 = yquery.value(2).toInt() ? true:false;
517 y.y_bacteria = yquery.value(3).toInt() ? true:false;
518 y.y_harvest_top = yquery.value(4).toInt() ? true:false;
519 y.y_harvest_time = yquery.value(5).toInt();
520 y.y_pitch_temperature = yquery.value(6).toDouble();
521 y.y_pofpos = yquery.value(7).toInt() ? true:false;
522 y.y_zymocide = yquery.value(8).toInt();
523 y.y_gr_hl_lo = yquery.value(9).toInt();
524 y.y_sg_lo = yquery.value(10).toDouble();
525 y.y_gr_hl_hi = yquery.value(11).toInt();
526 y.y_sg_hi = yquery.value(12).toDouble();
527 } else {
528 qDebug() << y.y_name << y.y_product_id << "not found for upgrade";
529 }
530 }
531 product->yeasts.append(y);
532 }
533 qDebug() << "yeasts" << product->yeasts.size();
534 }
535 } else {
536 qDebug() << "empty yeasts";
537 }
538
539 const auto& ma_json = query.value("json_mashs").toString().trimmed();
540 if (!ma_json.trimmed().isEmpty()) {
541 const auto& formattedJson = QString("%1").arg(ma_json);
542 QJsonDocument mashs = QJsonDocument::fromJson(formattedJson.toUtf8(), &parseError);
543 if (parseError.error != QJsonParseError::NoError) {
544 qDebug() << "Parse error: " << parseError.errorString() << "at" << parseError.offset ;
545 } else if (mashs.isArray()) {
546 for (int i = 0; i < mashs.array().size(); i++) {
547 QJsonObject obj = mashs.array().at(i).toObject();
548 qDebug() << i << obj;
549 Mashs m;
550 m.step_name = obj["step_name"].toString();
551 m.step_type = obj["step_type"].toInt();
552 m.step_volume = obj["step_volume"].toDouble();
553 m.step_infuse_amount = obj["step_infuse_amount"].toDouble();
554 m.step_infuse_temp = obj["step_infuse_temp"].toDouble();
555 m.step_temp = obj["step_temp"].toDouble();
556 m.step_time = obj["step_time"].toDouble();
557 m.ramp_time = obj["ramp_time"].toDouble();
558 m.end_temp = obj["end_temp"].toDouble();
559 m.step_wg_ratio = obj["step_wg_ratio"].toDouble();
560 product->mashs.append(m);
561 }
562 }
563 } else {
564 qDebug() << "empty mashs";
565 }
566 qDebug() << "mashs" << product->mashs.size();
567
568 } else {
569 /* Set some defaults */
570 product->locked = false;
571 product->st_name = "";
572 product->st_letter = "";
573 product->st_guide = "";
574 product->st_category = "";
575 product->st_category_number = 0;
576 product->st_type = 0;
577 product->st_og_min = 1.025; product->st_og_max = 1.100;
578 product->st_fg_min = 1.000; product->st_fg_max = 1.020;
579 product->st_ibu_min = 5; product->st_ibu_max = 200;
580 product->st_color_min = 3; product->st_color_max = 100;
581 product->st_carb_min = 1.0; product->st_carb_max = 4.5;
582 product->st_abv_min = 1; product->st_abv_max = 15;
583 product->name = "";
584 product->notes = "";
585 product->efficiency = 75;
586 product->batch_size = 20;
587 product->boil_time = 60;
588 product->boil_size = product->batch_size + (round(product->batch_size * product->boil_time / 60.0) / 10.0);
589 product->type = 2;
590 product->est_og = product->est_fg = product->est_color = product->est_ibu = product->est_abv = 0;
591 product->sparge_temp = 80;
592 product->sparge_ph = 5.4;
593 product->sparge_volume = 8;
594 product->sparge_source = 0;
595 product->sparge_acid_type = 0;
596 product->sparge_acid_perc = 80;
597 product->sparge_acid_amount = 0;
598 product->mash_ph = 5.4;
599 product->mash_name = "";
600 product->calc_acid = true;
601 product->w1_name = "";
602 product->w1_amount = 0;
603 product->w1_calcium = 0;
604 product->w1_sulfate = 0;
605 product->w1_chloride = 0;
606 product->w1_sodium = 0;
607 product->w1_magnesium = 0;
608 product->w1_total_alkalinity = 0;
609 product->w1_ph = 7;
610 product->w1_cost = 0;
611 product->w2_name = "";
612 product->w2_amount = 0;
613 product->w2_calcium = 0;
614 product->w2_sulfate = 0;
615 product->w2_chloride = 0;
616 product->w2_sodium = 0;
617 product->w2_magnesium = 0;
618 product->w2_total_alkalinity = 0;
619 product->w2_ph = 7;
620 product->w2_cost = 0;
621 product->wg_amount = 0;
622 product->wg_calcium = 0;
623 product->wg_sulfate = 0;
624 product->wg_chloride = 0;
625 product->wg_sodium = 0;
626 product->wg_magnesium = 0;
627 product->wg_total_alkalinity = 0;
628 product->wg_ph = 7;
629 product->wb_calcium = 0;
630 product->wb_sulfate = 0;
631 product->wb_chloride = 0;
632 product->wb_sodium = 0;
633 product->wb_magnesium = 0;
634 product->wb_total_alkalinity = 0;
635 product->wb_ph = 7;
636 product->wa_acid_name = 0;
637 product->wa_acid_perc = 80;
638 product->wa_base_name = 0;
639 }
640
641 // Tab generic.
642 ui->lockedEdit->setChecked(product->locked);
643 ui->st_nameEdit->setText(product->st_name);
644 ui->st_groupEdit->setText(product->st_letter);
645 ui->st_guideEdit->setText(product->st_guide);
646 ui->st_catEdit->setText(product->st_category);
647 ui->st_catnrEdit->setText(QString("%1").arg(product->st_category_number));
648 ui->st_typeEdit->setText(style_types[product->st_type]);
649 ui->nameEdit->setText(product->name);
650 ui->notesEdit->setPlainText(product->notes);
651 ui->typeEdit->setCurrentIndex(product->type);
652 ui->batch_sizeEdit->setValue(product->batch_size);
653 ui->boil_sizeEdit->setValue(product->boil_size);
654 ui->boil_timeEdit->setValue(product->boil_time);
655 ui->efficiencyEdit->setValue(product->efficiency);
656 ui->est_ogEdit->setValue(product->est_og);
657 ui->est_ogShow->setRange(product->st_og_min, product->st_og_max);
658 ui->est_ogShow->setPrecision(3);
659 ui->est_ogShow->setMarkerTextIsValue(true);
660 ui->est_ogShow->setValue(product->est_og);
661 ui->est_fgEdit->setValue(product->est_fg);
662 ui->est_fgShow->setRange(product->st_fg_min, product->st_fg_max);
663 ui->est_fgShow->setPrecision(3);
664 ui->est_fgShow->setMarkerTextIsValue(true);
665 ui->est_fgShow->setValue(product->est_fg);
666 ui->est_abvEdit->setValue(product->est_abv);
667 ui->est_abvShow->setRange(product->st_abv_min, product->st_abv_max);
668 ui->est_abvShow->setPrecision(1);
669 ui->est_abvShow->setMarkerTextIsValue(true);
670 ui->est_abvShow->setValue(product->est_abv);
671 ui->est_colorEdit->setValue(product->est_color);
672 ui->est_colorEdit->setStyleSheet(Utils::ebc_to_style(product->est_color));
673 ui->est_colorShow->setPrecision(0);
674 ui->est_colorShow->setMarkerTextIsValue(true);
675 ui->est_colorShow->setRange(product->st_color_min, product->st_color_max);
676 ui->est_colorShow->setValue(product->est_color);
677 ui->color_methodEdit->setCurrentIndex(product->color_method);
678 ui->est_ibuEdit->setValue(product->est_ibu);
679 ui->est_ibuShow->setPrecision(0);
680 ui->est_ibuShow->setMarkerTextIsValue(true);
681 ui->est_ibuShow->setRange(product->st_ibu_min, product->st_ibu_max);
682 ui->est_ibuShow->setValue(product->est_ibu);
683 ui->ibu_methodEdit->setCurrentIndex(product->ibu_method);
684 ui->est_carbEdit->setValue(product->est_carb);
685 ui->est_carbShow->setPrecision(1);
686 ui->est_carbShow->setMarkerTextIsValue(true);
687 ui->est_carbShow->setRange(product->st_carb_min, product->st_carb_max);
688 ui->est_carbShow->setValue(product->est_carb);
689
690 // Tab fermentables.
691 ui->est_og2Edit->setValue(product->est_og);
692 ui->est_color2Edit->setValue(product->est_color);
693 ui->est_color2Edit->setStyleSheet(Utils::ebc_to_style(product->est_color));
694
695 // Tab hops.
696 ui->est_ibu2Edit->setValue(product->est_ibu);
697
698 // Tab yeasts.
699 ui->est_og3Edit->setValue(product->est_og);
700 ui->est_fg3Edit->setValue(product->est_fg);
701 ui->est_abv2Edit->setValue(product->est_abv);
702
703 // Tab mashs.
704 ui->mash_nameEdit->setText(product->mash_name);
705
706 // Tab waters.
707 qDebug() << "water 1" << product->w1_name << "default" << my_default_water;
708 if (product->w1_ph > 4.0) {
709 /*
710 * Water data seems present, use that and set the name between []
711 */
712 ui->w1_nameEdit->setPlaceholderText(QString("["+product->w1_name+"]"));
713 } else {
714 bool found = false;
715 if (product->w1_name != "") {
716 /*
717 * We have a name, but do we know it?
718 */
719 query.prepare("SELECT * FROM inventory_waters WHERE name=:water");
720 query.bindValue(":water", product->w1_name);
721 query.exec();
722 found = query.first();
723 }
724 if (!found) {
725 /*
726 * Try to load default water
727 */
728 query.prepare("SELECT * FROM inventory_waters WHERE record=:record");
729 query.bindValue(":record", my_default_water);
730 query.exec();
731 found = query.first();
732 }
733 if (found) {
734 product->w1_calcium = query.value(3).toDouble();
735 product->w1_magnesium = query.value(8).toDouble();
736 product->w1_total_alkalinity = query.value(11).toDouble();
737 product->w1_sodium = query.value(7).toDouble();
738 product->w1_chloride = query.value(6).toDouble();
739 product->w1_sulfate = query.value(5).toDouble();
740 product->w1_ph = query.value(9).toDouble();
741 ui->w1_nameEdit->setCurrentIndex(query.value(0).toInt());
742 } else {
743 product->w1_calcium = 0;
744 product->w1_magnesium = 0;
745 product->w1_total_alkalinity = 0;
746 product->w1_sodium = 0;
747 product->w1_chloride = 0;
748 product->w1_sulfate = 0;
749 product->w1_ph = 0;
750 }
751 }
752 ui->w1_volEdit->setValue(product->w1_amount);
753 ui->w1_caEdit->setValue(product->w1_calcium);
754 ui->w1_mgEdit->setValue(product->w1_magnesium);
755 ui->w1_hco3Edit->setValue(product->w1_total_alkalinity * 1.22);
756 ui->w1_caco3Edit->setValue(product->w1_total_alkalinity);
757 ui->w1_naEdit->setValue(product->w1_sodium);
758 ui->w1_clEdit->setValue(product->w1_chloride);
759 ui->w1_so4Edit->setValue(product->w1_sulfate);
760 ui->w1_phEdit->setValue(product->w1_ph);
761
762 qDebug() << "water 2" << product->w2_name;
763 if (product->w2_ph > 4.0) {
764 ui->w2_nameEdit->setPlaceholderText(QString("["+product->w2_name+"]"));
765 } else if (product->w2_name != "") {
766 query.prepare("SELECT * FROM inventory_waters WHERE name=:water");
767 query.bindValue(":water", product->w2_name);
768 query.exec();
769 if (query.first()) {
770 product->w2_calcium = query.value(3).toDouble();
771 product->w2_magnesium = query.value(8).toDouble();
772 product->w2_total_alkalinity = query.value(11).toDouble();
773 product->w2_sodium = query.value(7).toDouble();
774 product->w2_chloride = query.value(6).toDouble();
775 product->w2_sulfate = query.value(5).toDouble();
776 product->w2_ph = query.value(9).toDouble();
777 ui->w2_nameEdit->setCurrentIndex(query.value(0).toInt());
778 } else {
779 product->w2_calcium = 0;
780 product->w2_magnesium = 0;
781 product->w2_total_alkalinity = 0;
782 product->w2_sodium = 0;
783 product->w2_chloride = 0;
784 product->w2_sulfate = 0;
785 product->w2_ph = 0;
786 }
787 }
788 ui->w2_volEdit->setValue(product->w2_amount);
789 ui->w2_caEdit->setValue(product->w2_calcium);
790 ui->w2_mgEdit->setValue(product->w2_magnesium);
791 ui->w2_hco3Edit->setValue(product->w2_total_alkalinity * 1.22);
792 ui->w2_caco3Edit->setValue(product->w2_total_alkalinity);
793 ui->w2_naEdit->setValue(product->w2_sodium);
794 ui->w2_clEdit->setValue(product->w2_chloride);
795 ui->w2_so4Edit->setValue(product->w2_sulfate);
796 ui->w2_phEdit->setValue(product->w2_ph);
797 ui->mw_autoEdit->setChecked(product->calc_acid);
798 ui->mw_phEdit->setReadOnly(! product->calc_acid);
799 ui->mw_phEdit->setButtonSymbols(product->calc_acid ? QAbstractSpinBox::UpDownArrows : QAbstractSpinBox::NoButtons);
800 ui->mw_acidvolEdit->setReadOnly(product->calc_acid);
801 ui->mw_acidvolEdit->setButtonSymbols(product->calc_acid ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
802
803 ui->sp_volEdit->setValue(product->sparge_volume);
804 ui->sp_tempEdit->setValue(product->sparge_temp);
805 ui->sp_phEdit->setValue(product->sparge_ph);
806 ui->sp_sourceEdit->setCurrentIndex(product->sparge_source);
807 ui->sp_acidtypeEdit->setCurrentIndex(product->sparge_acid_type);
808 ui->sp_acidpercEdit->setValue(product->sparge_acid_perc);
809 ui->sp_acidvolEdit->setValue(product->sparge_acid_amount);
810
811 // All signals from tab "Generic"
812 connect(ui->lockedEdit, &QCheckBox::stateChanged, this, &EditProduct::is_changed);
813 connect(ui->nameEdit, &QLineEdit::textChanged, this, &EditProduct::name_changed);
814 connect(ui->notesEdit, SIGNAL(textChanged()), this, SLOT(notes_changed()));
815 connect(ui->typeEdit, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &EditProduct::brew_type_changed);
816 connect(ui->batch_sizeEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditProduct::batch_size_changed);
817 connect(ui->boil_timeEdit, QOverload<int>::of(&QSpinBox::valueChanged), this, &EditProduct::boil_time_changed);
818 connect(ui->efficiencyEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditProduct::efficiency_changed);
819 connect(ui->beerstyleEdit, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &EditProduct::style_changed);
820 connect(ui->est_ogEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditProduct::est_og_changed);
821 connect(ui->color_methodEdit, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &EditProduct::colormethod_changed);
822 connect(ui->ibu_methodEdit, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &EditProduct::ibumethod_changed);
823 connect(ui->lockedEdit, &QCheckBox::stateChanged, this, &EditProduct::locked_changed);
824
825 // All signals from tab "Fermentables"
826 ui->fermentablesTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
827 connect(ui->est_og2Edit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditProduct::est_og_changed);
828 connect(ui->perc_mashShow, &QProgressBar::valueChanged, this, &EditProduct::ferment_perc_mash_valueChanged);
829 connect(ui->perc_sugarsShow, &QProgressBar::valueChanged, this, &EditProduct::ferment_perc_sugars_valueChanged);
830 connect(ui->perc_caraShow, &QProgressBar::valueChanged, this, &EditProduct::ferment_perc_cara_valueChanged);
831 connect(ui->lintnerShow, &QProgressBar::valueChanged, this, &EditProduct::ferment_lintner_valueChanged);
832 connect(ui->addFermentable, SIGNAL(clicked()), this, SLOT(addFermentRow_clicked()));
833
834 // All signals from tab "Hops"
835 ui->hopsTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
836 connect(ui->hop_tasteShow, &QProgressBar::valueChanged, this, &EditProduct::hop_Flavour_valueChanged);
837 connect(ui->hop_aromaShow, &QProgressBar::valueChanged, this, &EditProduct::hop_Aroma_valueChanged);
838 connect(ui->addHop, SIGNAL(clicked()), this, SLOT(addHopRow_clicked()));
839
840 // All signals from tab "Miscs"
841 ui->miscsTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
842 connect(ui->addMisc, SIGNAL(clicked()), this, SLOT(addMiscRow_clicked()));
843
844 // All signals from tab "Yeasts"
845 ui->yeastsTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
846 connect(ui->addYeast, SIGNAL(clicked()), this, SLOT(addYeastRow_clicked()));
847
848 // All signals from tab "Mash"
849 ui->mashsTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
850 connect(ui->addMash, SIGNAL(clicked()), this, SLOT(addMashRow_clicked()));
851 connect(ui->mash_pickEdit, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &EditProduct::mash_select_changed);
852 connect(ui->mash_nameEdit, &QLineEdit::textChanged, this, &EditProduct::mash_name_changed);
853
854 // All signals from tab "Water"
855 connect(ui->bs_cacl2Edit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditProduct::wb_cacl2_changed);
856 connect(ui->bs_caso4Edit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditProduct::wb_caso4_changed);
857 connect(ui->bs_mgso4Edit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditProduct::wb_mgso4_changed);
858 connect(ui->bs_naclEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditProduct::wb_nacl_changed);
859 connect(ui->bs_mgcl2Edit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditProduct::wb_mgcl2_changed);
860 connect(ui->bs_nahco3Edit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditProduct::wb_nahco3_changed);
861 connect(ui->bs_caco3Edit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditProduct::wb_caco3_changed);
862 connect(ui->mw_autoEdit, &QCheckBox::stateChanged, this, &EditProduct::mw_calc_acid_clicked);
863 connect(ui->mw_phEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditProduct::mw_ph_changed);
864 connect(ui->mw_acidvolEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditProduct::mw_acid_changed);
865 connect(ui->mw_acidPick, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &EditProduct::mw_type_changed);
866 connect(ui->wt_sourceEdit, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &EditProduct::wt_target_changed);
867 connect(ui->w1_nameEdit, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &EditProduct::w1_name_changed);
868 connect(ui->w2_nameEdit, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &EditProduct::w2_name_changed);
869 connect(ui->w2_volEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditProduct::w2_volume_changed);
870 connect(ui->sp_sourceEdit, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &EditProduct::sp_source_changed);
871 connect(ui->sp_acidtypeEdit, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &EditProduct::sp_type_changed);
872 connect(ui->sp_phEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditProduct::sp_ph_changed);
873
874 setLocked(product->locked);
875
876 ui->saveButton->setEnabled(false);
877 ui->deleteButton->setEnabled((id >= 0 && ! product->locked) ? true:false);
878
879 emit refreshAll();
880 }
881
882
883 EditProduct::~EditProduct()
884 {
885 qDebug() << "EditProduct done start";
886 delete ui;
887 emit entry_changed();
888 qDebug() << "EditProduct done final";
889 }
890
891
892 void EditProduct::refreshAll()
893 {
894 refreshFermentables();
895 calcFermentables(); /* Must be before Hops */
896 refreshHops();
897 calcIBUs();
898 refreshMiscs();
899 refreshYeasts();
900 calcYeast();
901 calcMash();
902 refreshMashs();
903 refreshWaters();
904 calcWater();
905 }
906
907
908 /*
909 * Window header, mark any change with '**'
910 */
911 void EditProduct::WindowTitle()
912 {
913 QString txt;
914
915 if (this->recno < 0) {
916 txt = QString(tr("BMSapp - Add new product"));
917 } else {
918 txt = QString(tr("BMSapp - Edit product %1").arg(this->recno));
919 }
920
921 if (this->textIsChanged) {
922 txt.append((QString(" **")));
923 }
924 setWindowTitle(txt);
925 }
926
927
928 void EditProduct::on_saveButton_clicked()
929 {
930 QSqlQuery query;
931
932 /* If there are errors in the form, show a message and do "return;" */
933 if (ui->nameEdit->text().length() < 2) {
934 QMessageBox::warning(this, tr("Edit Product"), tr("Name empty or too short."));
935 return;
936 }
937 if (ui->st_nameEdit->text().length() < 2) {
938 QMessageBox::warning(this, tr("Edit Product"), tr("No beerstyle selected."));
939 return;
940 }
941
942 if (this->textIsChanged) {
943 if (this->recno == -1) {
944 query.prepare("INSERT INTO products SET locked=:locked, st_name=:st_name, st_letter=:st_letter, "
945 "st_guide=:st_guide, st_category=:st_category, st_category_number=:st_catnr, st_type=:st_type, "
946 "st_og_min=:st_og_min, st_og_max=:st_og_max, st_fg_min=:st_fg_min, st_fg_max=:st_fg_max, "
947 "st_ibu_min=:st_ibu_min, st_ibu_max=:st_ibu_max, st_color_min=:st_color_min, st_color_max=:st_color_max, "
948 "st_carb_min=:st_carb_min, st_carb_max=:st_carb_max, st_abv_min=:st_abv_min, st_abv_max=:st_abv_max, "
949 "name=:name, notes=:notes, type=:type, batch_size=:batch_size, boil_size=:boil_size, "
950 "boil_time=:boil_time, efficiency=:efficiency, est_og=:est_og, est_fg=:est_fg, est_abv=:est_abv, "
951 "est_color=:est_color, color_method=:color_method, est_ibu=:est_ibu, ibu_method=:ibu_method, "
952 "est_carb=:est_carb, sparge_temp=:sparge_temp, sparge_ph=:sparge_ph, "
953 "sparge_volume=:sparge_volume, sparge_source=:sparge_source, sparge_acid_type=:sparge_acid_type, "
954 "sparge_acid_perc=:sparge_acid_perc, sparge_acid_amount=:sparge_acid_amount, mash_ph=:mash_ph, "
955 "mash_name=:mash_name, calc_acid=:calc_acid, "
956 "w1_name=:w1_name, w1_amount=:w1_amount, w1_calcium=:w1_calcium, w1_sulfate=:w1_sulfate, "
957 "w1_chloride=:w1_chloride, w1_sodium=:w1_sodium, w1_magnesium=:w1_magnesium, "
958 "w1_total_alkalinity=:w1_total_alkalinity, w1_ph=:w1_ph, w1_cost=:w1_cost, "
959 "w2_name=:w2_name, w2_amount=:w2_amount, w2_calcium=:w2_calcium, w2_sulfate=:w2_sulfate, "
960 "w2_chloride=:w2_chloride, w2_sodium=:w2_sodium, w2_magnesium=:w2_magnesium, "
961 "w2_total_alkalinity=:w2_total_alkalinity, w2_ph=:w2_ph, w2_cost=:w2_cost, "
962 "wg_amount=:wg_amount, wg_calcium=:wg_calcium, wg_sulfate=:wg_sulfate, "
963 "wg_chloride=:wg_chloride, wg_sodium=:wg_sodium, wg_magnesium=:wg_magnesium, "
964 "wg_total_alkalinity=:wg_total_alkalinity, wg_ph=:wg_ph, "
965 "wb_calcium=:wb_calcium, wb_sulfate=:wb_sulfate, wb_chloride=:wb_chloride, wb_sodium=:wb_sodium, "
966 "wb_magnesium=:wb_magnesium, wb_total_alkalinity=:wb_total_alkalinity, wb_ph=:wb_ph, "
967 "wa_acid_name=:wa_acid_name, wa_acid_perc=:wa_acid_perc, wa_base_name=:wa_base_name, "
968 "json_fermentables=:json_fermentables, json_hops=:json_hops, json_miscs=:json_miscs, "
969 "json_yeasts=:json_yeasts, json_mashs=:json_mashs, uuid=:uuid");
970 } else {
971 query.prepare("UPDATE products SET locked=:locked, st_name=:st_name, st_letter=:st_letter, "
972 "st_guide=:st_guide, st_category=:st_category, st_category_number=:st_catnr, st_type=:st_type, "
973 "st_og_min=:st_og_min, st_og_max=:st_og_max, st_fg_min=:st_fg_min, st_fg_max=:st_fg_max, "
974 "st_ibu_min=:st_ibu_min, st_ibu_max=:st_ibu_max, st_color_min=:st_color_min, st_color_max=:st_color_max, "
975 "st_carb_min=:st_carb_min, st_carb_max=:st_carb_max, st_abv_min=:st_abv_min, st_abv_max=:st_abv_max, "
976 "name=:name, notes=:notes, type=:type, batch_size=:batch_size, boil_size=:boil_size, "
977 "boil_time=:boil_time, efficiency=:efficiency, est_og=:est_og, est_fg=:est_fg, est_abv=:est_abv, "
978 "est_color=:est_color, color_method=:color_method, est_ibu=:est_ibu, ibu_method=:ibu_method, "
979 "est_carb=:est_carb, sparge_temp=:sparge_temp, sparge_ph=:sparge_ph, "
980 "sparge_volume=:sparge_volume, sparge_source=:sparge_source, sparge_acid_type=:sparge_acid_type, "
981 "sparge_acid_perc=:sparge_acid_perc, sparge_acid_amount=:sparge_acid_amount, mash_ph=:mash_ph, "
982 "mash_name=:mash_name, calc_acid=:calc_acid, "
983 "w1_name=:w1_name, w1_amount=:w1_amount, w1_calcium=:w1_calcium, w1_sulfate=:w1_sulfate, "
984 "w1_chloride=:w1_chloride, w1_sodium=:w1_sodium, w1_magnesium=:w1_magnesium, "
985 "w1_total_alkalinity=:w1_total_alkalinity, w1_ph=:w1_ph, w1_cost=:w1_cost, "
986 "w2_name=:w2_name, w2_amount=:w2_amount, w2_calcium=:w2_calcium, w2_sulfate=:w2_sulfate, "
987 "w2_chloride=:w2_chloride, w2_sodium=:w2_sodium, w2_magnesium=:w2_magnesium, "
988 "w2_total_alkalinity=:w2_total_alkalinity, w2_ph=:w2_ph, w2_cost=:w2_cost, "
989 "wg_amount=:wg_amount, wg_calcium=:wg_calcium, wg_sulfate=:wg_sulfate, "
990 "wg_chloride=:wg_chloride, wg_sodium=:wg_sodium, wg_magnesium=:wg_magnesium, "
991 "wg_total_alkalinity=:wg_total_alkalinity, wg_ph=:wg_ph, "
992 "wb_calcium=:wb_calcium, wb_sulfate=:wb_sulfate, wb_chloride=:wb_chloride, wb_sodium=:wb_sodium, "
993 "wb_magnesium=:wb_magnesium, wb_total_alkalinity=:wb_total_alkalinity, wb_ph=:wb_ph, "
994 "wa_acid_name=:wa_acid_name, wa_acid_perc=:wa_acid_perc, wa_base_name=:wa_base_name, "
995 "json_fermentables=:json_fermentables, json_hops=:json_hops, json_miscs=:json_miscs, "
996 "json_yeasts=:json_yeasts, json_mashs=:json_mashs WHERE record = :recno");
997 }
998 query.bindValue(":locked", product->locked ? 1:0);
999 query.bindValue(":st_name", product->st_name);
1000 query.bindValue(":st_letter", product->st_letter);
1001 query.bindValue(":st_guide", product->st_guide);
1002 query.bindValue(":st_category", product->st_category);
1003 query.bindValue(":st_catnr", product->st_category_number);
1004 query.bindValue(":st_type", product->st_type);
1005 query.bindValue(":st_og_min", round(product->st_og_min * 1000) / 1000);
1006 query.bindValue(":st_og_max", round(product->st_og_max * 1000) / 1000);
1007 query.bindValue(":st_fg_min", round(product->st_fg_min * 1000) / 1000);
1008 query.bindValue(":st_fg_max", round(product->st_fg_max * 1000) / 1000);
1009 query.bindValue(":st_ibu_min", round(product->st_ibu_min * 10) / 10);
1010 query.bindValue(":st_ibu_max", round(product->st_ibu_max * 10) / 10);
1011 query.bindValue(":st_color_min", round(product->st_color_min * 10) / 10);
1012 query.bindValue(":st_color_max", round(product->st_color_max * 10) / 10);
1013 query.bindValue(":st_carb_min", round(product->st_carb_min * 10) / 10);
1014 query.bindValue(":st_carb_max", round(product->st_carb_max * 10) / 10);
1015 query.bindValue(":st_abv_min", round(product->st_abv_min * 10) / 10);
1016 query.bindValue(":st_abv_max", round(product->st_abv_max * 10) / 10);
1017 query.bindValue(":name", product->name);
1018 query.bindValue(":notes", product->notes);
1019 query.bindValue(":type", product->type);
1020 query.bindValue(":batch_size", round(product->batch_size * 10) / 10);
1021 query.bindValue(":boil_size", round(product->boil_size * 10) / 10);
1022 query.bindValue(":boil_time", round(product->boil_time * 10) / 10);
1023 query.bindValue(":efficiency", round(product->efficiency * 10) / 10);
1024 query.bindValue(":est_og", round(product->est_og * 1000) / 1000);
1025 query.bindValue(":est_fg", round(product->est_fg * 1000) / 1000);
1026 query.bindValue(":est_abv", round(product->est_abv * 10) / 10);
1027 query.bindValue(":est_color", round(product->est_color * 10) / 10);
1028 query.bindValue(":color_method", product->color_method);
1029 query.bindValue(":est_ibu", round(product->est_ibu * 10) / 10);
1030 query.bindValue(":ibu_method", product->ibu_method);
1031 query.bindValue(":est_carb", round(product->est_carb * 10) / 10);
1032 query.bindValue(":sparge_temp", round(product->sparge_temp * 10) / 10);
1033 query.bindValue(":sparge_ph", round(product->sparge_ph * 100) / 100);
1034 query.bindValue(":sparge_volume", round(product->sparge_volume * 10) / 10);
1035 query.bindValue(":sparge_source", product->sparge_source);
1036 query.bindValue(":sparge_acid_type", product->sparge_acid_type);
1037 query.bindValue(":sparge_acid_perc", round(product->sparge_acid_perc * 10) / 10);
1038 query.bindValue(":sparge_acid_amount", round(product->sparge_acid_amount * 100000) / 100000);
1039 query.bindValue(":mash_ph", round(product->mash_ph * 100) / 100);
1040 query.bindValue(":mash_name", product->mash_name);
1041 query.bindValue(":calc_acid", product->calc_acid ?1:0);
1042 query.bindValue(":w1_name", product->w1_name);
1043 query.bindValue(":w1_amount", round(product->w1_amount * 10) / 10);
1044 query.bindValue(":w1_calcium", round(product->w1_calcium * 100000) / 100000);
1045 query.bindValue(":w1_sulfate", round(product->w1_sulfate * 100000) / 100000);
1046 query.bindValue(":w1_chloride", round(product->w1_chloride * 100000) / 100000);
1047 query.bindValue(":w1_sodium", round(product->w1_sodium * 100000) / 100000);
1048 query.bindValue(":w1_magnesium", round(product->w1_magnesium * 100000) / 100000);
1049 query.bindValue(":w1_total_alkalinity", round(product->w1_total_alkalinity * 100000) / 100000);
1050 query.bindValue(":w1_ph", round(product->w1_ph * 100) / 100);
1051 query.bindValue(":w1_cost", round(product->w1_cost * 100) / 100);
1052 query.bindValue(":w2_name", product->w2_name);
1053 query.bindValue(":w2_amount", round(product->w2_amount * 10) / 10);
1054 query.bindValue(":w2_calcium", round(product->w2_calcium * 100000) / 100000);
1055 query.bindValue(":w2_sulfate", round(product->w2_sulfate * 100000) / 100000);
1056 query.bindValue(":w2_chloride", round(product->w2_chloride * 100000) / 100000);
1057 query.bindValue(":w2_sodium", round(product->w2_sodium * 100000) / 100000);
1058 query.bindValue(":w2_magnesium", round(product->w2_magnesium * 100000) / 100000);
1059 query.bindValue(":w2_total_alkalinity", round(product->w2_total_alkalinity * 100000) / 100000);
1060 query.bindValue(":w2_ph", round(product->w2_ph * 100) / 100);
1061 query.bindValue(":w2_cost", round(product->w2_cost * 100) / 100);
1062 query.bindValue(":wg_amount", round(product->wg_amount * 10) / 10);
1063 query.bindValue(":wg_calcium", round(product->wg_calcium * 100000) / 100000);
1064 query.bindValue(":wg_sulfate", round(product->wg_sulfate * 100000) / 100000);
1065 query.bindValue(":wg_chloride", round(product->wg_chloride * 100000) / 100000);
1066 query.bindValue(":wg_sodium", round(product->wg_sodium * 100000) / 100000);
1067 query.bindValue(":wg_magnesium", round(product->wg_magnesium * 100000) / 100000);
1068 query.bindValue(":wg_total_alkalinity", round(product->wg_total_alkalinity * 100000) / 100000);
1069 query.bindValue(":wg_ph", round(product->wg_ph * 100) / 100);
1070 query.bindValue(":wb_calcium", round(product->wb_calcium * 100000) / 100000);
1071 query.bindValue(":wb_sulfate", round(product->wb_sulfate * 100000) / 100000);
1072 query.bindValue(":wb_chloride", round(product->wb_chloride * 100000) / 100000);
1073 query.bindValue(":wb_sodium", round(product->wb_sodium * 100000) / 100000);
1074 query.bindValue(":wb_magnesium", round(product->wb_magnesium * 100000) / 100000);
1075 query.bindValue(":wb_total_alkalinity", round(product->wb_total_alkalinity * 100000) / 100000);
1076 query.bindValue(":wb_ph", round(product->wb_ph * 100) / 100);
1077 query.bindValue(":wa_acid_name", product->wa_acid_name);
1078 query.bindValue(":wa_acid_perc", round(product->wa_acid_perc * 10) / 10);
1079 query.bindValue(":wa_base_name", product->wa_base_name);
1080
1081 if (product->fermentables.size() == 0) {
1082 query.bindValue(":json_fermentables", "[]");
1083 } else {
1084 QJsonArray array;
1085 for (int i = 0; i < product->fermentables.size(); i++) {
1086 QJsonObject obj;
1087 obj.insert("f_name", product->fermentables.at(i).f_name);
1088 obj.insert("f_origin", product->fermentables.at(i).f_origin);
1089 obj.insert("f_supplier", product->fermentables.at(i).f_supplier);
1090 obj.insert("f_amount", round(product->fermentables.at(i).f_amount * 10000) / 10000);
1091 obj.insert("f_cost", round(product->fermentables.at(i).f_cost * 1000) / 1000);
1092 obj.insert("f_type", product->fermentables.at(i).f_type);
1093 obj.insert("f_yield", round(product->fermentables.at(i).f_yield * 10) / 10);
1094 obj.insert("f_color", round(product->fermentables.at(i).f_color * 10) / 10);
1095 obj.insert("f_coarse_fine_diff", round(product->fermentables.at(i).f_coarse_fine_diff * 10) / 10);
1096 obj.insert("f_moisture", round(product->fermentables.at(i).f_moisture * 10) / 10);
1097 obj.insert("f_diastatic_power", round(product->fermentables.at(i).f_diastatic_power * 100000) / 100000);
1098 obj.insert("f_protein", round(product->fermentables.at(i).f_protein * 10) / 10);
1099 obj.insert("f_dissolved_protein", round(product->fermentables.at(i).f_dissolved_protein * 10) / 10);
1100 obj.insert("f_max_in_batch", product->fermentables.at(i).f_max_in_batch);
1101 obj.insert("f_graintype", product->fermentables.at(i).f_graintype);
1102 obj.insert("f_added", product->fermentables.at(i).f_added);
1103 obj.insert("f_recommend_mash", product->fermentables.at(i).f_recommend_mash ? 1:0);
1104 obj.insert("f_add_after_boil", product->fermentables.at(i).f_add_after_boil ? 1:0);
1105 obj.insert("f_adjust_to_total_100", product->fermentables.at(i).f_adjust_to_total_100 ? 1:0);
1106 obj.insert("f_percentage", round(product->fermentables.at(i).f_percentage * 10) / 10);
1107 obj.insert("f_di_ph", round(product->fermentables.at(i).f_di_ph * 100000) / 100000);
1108 obj.insert("f_acid_to_ph_57", round(product->fermentables.at(i).f_acid_to_ph_57 * 100000) / 100000);
1109 qDebug() << "fermentables_Json" << i << obj;
1110 array.append(obj); /* Append this object */
1111 }
1112 QJsonDocument doc;
1113 doc.setArray(array);
1114 // qDebug() << doc.toJson(QJsonDocument::Compact);
1115 query.bindValue(":json_fermentables", doc.toJson(QJsonDocument::Compact));
1116 }
1117
1118 if (product->hops.size() == 0) {
1119 query.bindValue(":json_hops", "[]");
1120 } else {
1121 QJsonArray array;
1122 for (int i = 0; i < product->hops.size(); i++) {
1123 QJsonObject obj;
1124 obj.insert("h_name", product->hops.at(i).h_name);
1125 obj.insert("h_origin", product->hops.at(i).h_origin);
1126 obj.insert("h_amount", round(product->hops.at(i).h_amount * 10000) / 10000);
1127 obj.insert("h_cost", round(product->hops.at(i).h_cost * 100) / 100);
1128 obj.insert("h_type", product->hops.at(i).h_type);
1129 obj.insert("h_form", product->hops.at(i).h_form);
1130 obj.insert("h_useat", product->hops.at(i).h_useat);
1131 obj.insert("h_time", round(product->hops.at(i).h_time));
1132 obj.insert("h_alpha", round(product->hops.at(i).h_alpha * 100) / 100);
1133 obj.insert("h_beta", round(product->hops.at(i).h_beta * 100) / 100);
1134 obj.insert("h_hsi", round(product->hops.at(i).h_hsi * 100) / 100);
1135 obj.insert("h_humulene", round(product->hops.at(i).h_humulene * 100) / 100);
1136 obj.insert("h_caryophyllene", round(product->hops.at(i).h_caryophyllene * 100) / 100);
1137 obj.insert("h_cohumulone", round(product->hops.at(i).h_cohumulone * 100) / 100);
1138 obj.insert("h_myrcene", round(product->hops.at(i).h_myrcene * 100) / 100);
1139 obj.insert("h_total_oil", round(product->hops.at(i).h_total_oil * 100) / 100);
1140 qDebug() << "hops_Json" << i << obj;
1141 array.append(obj); /* Append this object */
1142 }
1143 QJsonDocument doc;
1144 doc.setArray(array);
1145 query.bindValue(":json_hops", doc.toJson(QJsonDocument::Compact));
1146 }
1147
1148 if (product->miscs.size() == 0) {
1149 query.bindValue(":json_miscs", "[]");
1150 } else {
1151 QJsonArray array;
1152 for (int i = 0; i < product->miscs.size(); i++) {
1153 QJsonObject obj;
1154 obj.insert("m_name", product->miscs.at(i).m_name);
1155 obj.insert("m_amount", round(product->miscs.at(i).m_amount * 10000) / 10000);
1156 obj.insert("m_type", product->miscs.at(i).m_type);
1157 obj.insert("m_use_use", product->miscs.at(i).m_use_use);
1158 obj.insert("m_time", round(product->miscs.at(i).m_time));
1159 obj.insert("m_amount_is_weight", product->miscs.at(i).m_amount_is_weight ? 1:0);
1160 obj.insert("m_cost", round(product->miscs.at(i).m_cost * 10000) / 10000);
1161 qDebug() << "miscs_Json" << i << obj;
1162 array.append(obj); /* Append this object */
1163 }
1164 QJsonDocument doc;
1165 doc.setArray(array);
1166 // qDebug() << doc.toJson(QJsonDocument::Compact);
1167 query.bindValue(":json_miscs", doc.toJson(QJsonDocument::Compact));
1168 }
1169
1170 if (product->yeasts.size() == 0) {
1171 query.bindValue(":json_yeasts", "[]");
1172 } else {
1173 QJsonArray array;
1174 for (int i = 0; i < product->yeasts.size(); i++) {
1175 QJsonObject obj;
1176 obj.insert("y_name", product->yeasts.at(i).y_name);
1177 obj.insert("y_laboratory", product->yeasts.at(i).y_laboratory);
1178 obj.insert("y_product_id", product->yeasts.at(i).y_product_id);
1179 obj.insert("y_amount", round(product->yeasts.at(i).y_amount * 10000) / 10000);
1180 obj.insert("y_type", product->yeasts.at(i).y_type);
1181 obj.insert("y_form", product->yeasts.at(i).y_form);
1182 obj.insert("y_min_temperature", round(product->yeasts.at(i).y_min_temperature * 10) / 10);
1183 obj.insert("y_max_temperature", round(product->yeasts.at(i).y_max_temperature * 10) / 10);
1184 obj.insert("y_flocculation", product->yeasts.at(i).y_flocculation);
1185 obj.insert("y_attenuation", round(product->yeasts.at(i).y_attenuation * 10) / 10);
1186 obj.insert("y_cells", product->yeasts.at(i).y_cells);
1187 obj.insert("y_tolerance", round(product->yeasts.at(i).y_tolerance * 10) / 10);
1188 obj.insert("y_inventory", round(product->yeasts.at(i).y_inventory * 10000) / 10000);
1189 obj.insert("y_use", product->yeasts.at(i).y_use);
1190 obj.insert("y_sta1", product->yeasts.at(i).y_sta1 ? 1:0);
1191 obj.insert("y_bacteria", product->yeasts.at(i).y_bacteria ? 1:0);
1192 obj.insert("y_harvest_top", product->yeasts.at(i).y_harvest_top ? 1:0);
1193 obj.insert("y_harvest_time", product->yeasts.at(i).y_harvest_time);
1194 obj.insert("y_pitch_temperature", round(product->yeasts.at(i).y_pitch_temperature * 10) / 10);
1195 obj.insert("y_pofpos", product->yeasts.at(i).y_pofpos ? 1:0);
1196 obj.insert("y_zymocide", product->yeasts.at(i).y_zymocide);
1197 obj.insert("y_gr_hl_lo", product->yeasts.at(i).y_gr_hl_lo);
1198 obj.insert("y_sg_lo", round(product->yeasts.at(i).y_sg_lo * 1000) / 1000);
1199 obj.insert("y_gr_hl_hi", product->yeasts.at(i).y_gr_hl_hi);
1200 obj.insert("y_sg_hi", round(product->yeasts.at(i).y_sg_hi * 1000) / 1000);
1201 obj.insert("y_cost", round(product->yeasts.at(i).y_cost * 1000) / 1000);
1202 qDebug() << "yeasts_Json" << i << obj;
1203 array.append(obj); /* Append this object */
1204 }
1205 QJsonDocument doc;
1206 doc.setArray(array);
1207 // qDebug() << doc.toJson(QJsonDocument::Compact);
1208 query.bindValue(":json_yeasts", doc.toJson(QJsonDocument::Compact));
1209 }
1210
1211 if (product->mashs.size() == 0) {
1212 query.bindValue(":json_mashs", "[]");
1213 qDebug() << "Saved empty mashs";
1214 } else {
1215 QJsonArray array;
1216 for (int i = 0; i < product->mashs.size(); i++) {
1217 QJsonObject obj;
1218 obj.insert("step_name", product->mashs.at(i).step_name);
1219 obj.insert("step_type", product->mashs.at(i).step_type);
1220 obj.insert("step_volume", round(product->mashs.at(i).step_volume * 100) / 100);
1221 obj.insert("step_infuse_amount", round(product->mashs.at(i).step_infuse_amount * 100) / 100);
1222 obj.insert("step_infuse_temp", round(product->mashs.at(i).step_infuse_temp * 100) / 100);
1223 obj.insert("step_temp", round(product->mashs.at(i).step_temp * 100) / 100);
1224 obj.insert("step_time", round(product->mashs.at(i).step_time * 100) / 100);
1225 obj.insert("ramp_time", round(product->mashs.at(i).ramp_time * 100) / 100);
1226 obj.insert("end_temp", round(product->mashs.at(i).end_temp * 100) / 100);
1227 obj.insert("step_wg_ratio", round(product->mashs.at(i).step_wg_ratio * 100) / 100);
1228 qDebug() << "mashs_Json" << i << obj;
1229 array.append(obj); /* Append this object */
1230 }
1231 QJsonDocument doc;
1232 doc.setArray(array);
1233 qDebug() << doc.toJson(QJsonDocument::Compact);
1234 query.bindValue(":json_mashs", doc.toJson(QJsonDocument::Compact));
1235 }
1236
1237 if (this->recno == -1) {
1238 query.bindValue(":uuid", QUuid::createUuid().toString().mid(1, 36));
1239 } else {
1240 query.bindValue(":recno", this->recno);
1241 }
1242 query.exec();
1243 qDebug() << query.lastQuery();
1244 if (query.lastError().isValid()) {
1245 qDebug() << "EditProduct" << query.lastError();
1246 QMessageBox::warning(this, tr("Database error"),
1247 tr("MySQL error: %1\n%2\n%3")
1248 .arg(query.lastError().nativeErrorCode())
1249 .arg(query.lastError().driverText())
1250 .arg(query.lastError().databaseText()));
1251 } else {
1252 /*
1253 * If this was a new product, find out what record number we
1254 * have got and set it. So when the user saves this record
1255 * again, it will be updated instead of inserting a new copy.
1256 */
1257 if (this->recno < 0) {
1258 QVariant id = query.lastInsertId();
1259 this->recno = product->record = id.toInt();
1260 qDebug() << "EditProduct Inserted record" << this->recno;
1261 } else {
1262 qDebug() << "EditProduct Updated record" << this->recno;
1263 }
1264 }
1265 }
1266
1267 ui->saveButton->setEnabled(false);
1268 this->textIsChanged = false;
1269 WindowTitle();
1270 }
1271
1272
1273 #include "EditProductTab1.cpp"
1274 #include "EditProductTab2.cpp"
1275 #include "EditProductTab3.cpp"
1276 #include "EditProductTab4.cpp"
1277 #include "EditProductTab5.cpp"
1278 #include "EditProductTab6.cpp"
1279 #include "EditProductTab7.cpp"
1280 #include "EditProductTab8.cpp"
1281 #include "EditProductTab9.cpp"
1282 #include "EditProductTab10.cpp"
1283 #include "EditProductTab11.cpp"
1284 #include "EditProductExport.cpp"
1285
1286
1287 void EditProduct::on_deleteButton_clicked()
1288 {
1289 QSqlQuery query;
1290
1291 int rc = QMessageBox::warning(this, tr("Delete product"), tr("Delete %1").arg(product->name),
1292 QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
1293 if (rc == QMessageBox::No)
1294 return;
1295
1296 query.prepare("DELETE FROM products WHERE record = :recno");
1297 query.bindValue(":recno", this->recno);
1298 query.exec();
1299 if (query.lastError().isValid()) {
1300 qDebug() << "EditProduct" << query.lastError();
1301 QMessageBox::warning(this, tr("Database error"),
1302 tr("MySQL error: %1\n%2\n%3")
1303 .arg(query.lastError().nativeErrorCode())
1304 .arg(query.lastError().driverText())
1305 .arg(query.lastError().databaseText()));
1306 } else {
1307 qDebug() << "EditProduct Deleted" << this->recno;
1308 }
1309
1310 this->close();
1311 this->setResult(1);
1312 }
1313
1314
1315 void EditProduct::is_changed()
1316 {
1317 ui->saveButton->setEnabled(true);
1318 ui->deleteButton->setEnabled(((this->recno >= 0) ? true:false) && ! product->locked);
1319 this->textIsChanged = true;
1320 WindowTitle();
1321 }
1322
1323
1324 void EditProduct::on_quitButton_clicked()
1325 {
1326 if (this->textIsChanged) {
1327 int rc = QMessageBox::warning(this, tr("Product changed"), tr("The product has been modified. Save changes?"),
1328 QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Save);
1329 switch (rc) {
1330 case QMessageBox::Save:
1331 on_saveButton_clicked();
1332 break; /* Saved and then Quit */
1333 case QMessageBox::Discard:
1334 break; /* Quit without Save */
1335 case QMessageBox::Cancel:
1336 return; /* Return to the editor page */
1337 }
1338 }
1339
1340 this->close();
1341 this->setResult(1);
1342 }

mercurial