Tue, 05 Mar 2024 10:25:15 +0100
Clear mash measurments when duplicating a product.
/** * EditRecipe.cpp is part of bmsapp. * * Tab 3, hops * * bmsapp is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * bmsapp is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ bool EditRecipe::hop_sort_test(const Hops &D1, const Hops &D2) { if (D1.useat > D2.useat) return false; if (D1.useat < D2.useat) return true; /* Same useat moments, test time. */ if (D1.time < D2.time) return false; if (D1.time > D2.time) return true; /* Finally consider the amounts */ return (D1.amount > D2.amount); } void EditRecipe::refreshHops() { QString w; QWidget* pWidget; QHBoxLayout* pLayout; QTableWidgetItem *item; std::sort(recipe->hops.begin(), recipe->hops.end(), hop_sort_test); const QStringList labels({tr("Origin"), tr("Hop"), tr("Type"), tr("Form"), tr("Alpha"), tr("Use at"), tr("Time"), tr("IBU"), tr("Amount"), tr("Delete"), tr("Edit") }); ui->hopsTable->setColumnCount(11); ui->hopsTable->setColumnWidth(0, 150); /* Origin */ ui->hopsTable->setColumnWidth(1, 225); /* Hop */ ui->hopsTable->setColumnWidth(2, 84); /* Type */ ui->hopsTable->setColumnWidth(3, 84); /* Form */ ui->hopsTable->setColumnWidth(4, 75); /* Alpha% */ ui->hopsTable->setColumnWidth(5, 75); /* Added */ ui->hopsTable->setColumnWidth(6, 75); /* Time */ ui->hopsTable->setColumnWidth(7, 60); /* IBU */ ui->hopsTable->setColumnWidth(8, 90); /* Amount */ ui->hopsTable->setColumnWidth(9, 80); /* Delete */ ui->hopsTable->setColumnWidth(10, 80); /* Edit */ ui->hopsTable->setHorizontalHeaderLabels(labels); ui->hopsTable->verticalHeader()->hide(); ui->hopsTable->setRowCount(recipe->hops.size()); for (int i = 0; i < recipe->hops.size(); i++) { ui->hopsTable->setItem(i, 0, new QTableWidgetItem(recipe->hops.at(i).origin)); ui->hopsTable->setItem(i, 1, new QTableWidgetItem(recipe->hops.at(i).name)); item = new QTableWidgetItem(QCoreApplication::translate("HopTypes", g_hop_types[recipe->hops.at(i).type])); item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter); ui->hopsTable->setItem(i, 2, item); item = new QTableWidgetItem(QCoreApplication::translate("HopForm", g_hop_forms[recipe->hops.at(i).form])); item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter); ui->hopsTable->setItem(i, 3, item); item = new QTableWidgetItem(QString("%1%").arg(recipe->hops.at(i).alpha, 2, 'f', 1, '0')); item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); ui->hopsTable->setItem(i, 4, item); item = new QTableWidgetItem(QCoreApplication::translate("HopUse", g_hop_useat[recipe->hops.at(i).useat])); item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter); ui->hopsTable->setItem(i, 5, item); if (recipe->hops.at(i).useat == 2 || recipe->hops.at(i).useat == 4) { // Boil or whirlpool item = new QTableWidgetItem(QString("%1 min.").arg(recipe->hops.at(i).time, 1, 'f', 0, '0')); } else if (recipe->hops.at(i).useat == 5) { // Dry-hop item = new QTableWidgetItem(QString("%1 days.").arg(recipe->hops.at(i).time / 1440, 1, 'f', 0, '0')); } else { item = new QTableWidgetItem(QString("")); } item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); ui->hopsTable->setItem(i, 6, item); double ibu = Utils::toIBU(recipe->hops.at(i).useat, recipe->hops.at(i).form, recipe->preboil_sg, recipe->est_og, recipe->batch_size, recipe->hops.at(i).amount, recipe->hops.at(i).time, recipe->hops.at(i).alpha, recipe->ibu_method, 0, recipe->hops.at(i).time, 0, recipe->boil_time, 0, 0, 0, recipe->hops.at(i).utilisation, recipe->hops.at(i).bu_factor); item = new QTableWidgetItem(QString("%1").arg(ibu, 2, 'f', 1, '0')); item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); ui->hopsTable->setItem(i, 7, item); if (recipe->hops.at(i).amount < 1.0) { item = new QTableWidgetItem(QString("%1 gr").arg(recipe->hops.at(i).amount * 1000.0, 2, 'f', 1, '0')); } else { item = new QTableWidgetItem(QString("%1 kg").arg(recipe->hops.at(i).amount, 4, 'f', 3, '0')); } item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); ui->hopsTable->setItem(i, 8, item); /* Add the Delete row button */ pWidget = new QWidget(); QPushButton* btn_dele = new QPushButton(); btn_dele->setObjectName(QString("%1").arg(i)); /* Send row with the button */ btn_dele->setText(tr("Delete")); connect(btn_dele, SIGNAL(clicked()), this, SLOT(deleteHopRow_clicked())); pLayout = new QHBoxLayout(pWidget); pLayout->addWidget(btn_dele); pLayout->setContentsMargins(5, 0, 5, 0); pWidget->setLayout(pLayout); ui->hopsTable->setCellWidget(i, 9, pWidget); pWidget = new QWidget(); QPushButton* btn_edit = new QPushButton(); btn_edit->setObjectName(QString("%1").arg(i)); /* Send row with the button */ btn_edit->setText(tr("Edit")); connect(btn_edit, SIGNAL(clicked()), this, SLOT(editHopRow_clicked())); pLayout = new QHBoxLayout(pWidget); pLayout->addWidget(btn_edit); pLayout->setContentsMargins(5, 0, 5, 0); pWidget->setLayout(pLayout); ui->hopsTable->setCellWidget(i, 10, pWidget); } } void EditRecipe::hop_Flavour_valueChanged(int value) { if (value < 20) { ui->hop_tasteShow->setStyleSheet(bar_20); ui->hop_tasteShow->setFormat(tr("Very low")); } else { double s1 = 20.0 / value; if (value < 40) { ui->hop_tasteShow->setStyleSheet(QString("QProgressBar::chunk {background-color: qlineargradient(x0: 0, x2: 1, " "stop: 0 #004D00, stop: %1 #004D00, stop: %2 #008C00, stop: 1 #008C00);}").arg(s1).arg(s1)); ui->hop_tasteShow->setFormat(tr("Low")); } else { double s2 = 40.0 / value; if (value < 60) { ui->hop_tasteShow->setStyleSheet(QString("QProgressBar::chunk {background-color: qlineargradient(x0: 0, x2: 1, " "stop: 0 #004D00, stop: %1 #004D00, stop: %2 #006C00, stop: %3 #006C00, stop: %4 #008C00, stop: 1 #008C00" ");}").arg(s1).arg(s1).arg(s2).arg(s2)); ui->hop_tasteShow->setFormat(tr("Moderate")); } else { double s3 = 60.0 / value; if (value < 80) { ui->hop_tasteShow->setStyleSheet(QString("QProgressBar::chunk {background-color: qlineargradient(x0: 0, x2: 1, " "stop: 0 #004D00, stop: %1 #004D00, stop: %2 #006C00, stop: %3 #006C00, stop: %4 #008C00, stop: %5 #008C00, " "stop: %6 #00AC00, stop: 1 #00AC00" ");}").arg(s1).arg(s1).arg(s2).arg(s2).arg(s3).arg(s3)); ui->hop_tasteShow->setFormat(tr("High")); } else { double s4 = 80.0 / value; ui->hop_tasteShow->setStyleSheet(QString("QProgressBar::chunk {background-color: qlineargradient(x0: 0, x2: 1, " "stop: 0 #004D00, stop: %1 #004D00, stop: %2 #006C00, stop: %3 #006C00, stop: %4 #008C00, stop: %5 #008C00, " "stop: %6 #00AC00, stop: %7 #00AC00, stop: %8 #00CC00, stop: 1 #00CC00" ");}").arg(s1).arg(s1).arg(s2).arg(s2).arg(s3).arg(s3).arg(s4).arg(s4)); ui->hop_tasteShow->setFormat(tr("Very high")); } } } } } void EditRecipe::hop_Aroma_valueChanged(int value) { if (value < 20) { ui->hop_aromaShow->setStyleSheet(bar_20); ui->hop_aromaShow->setFormat(tr("Very low")); } else { double s1 = 20.0 / value; if (value < 40) { ui->hop_aromaShow->setStyleSheet(QString("QProgressBar::chunk {background-color: qlineargradient(x0: 0, x2: 1, " "stop: 0 #004D00, stop: %1 #004D00, stop: %2 #008C00, stop: 1 #008C00);}").arg(s1).arg(s1)); ui->hop_aromaShow->setFormat(tr("Low")); } else { double s2 = 40.0 / value; if (value < 60) { ui->hop_aromaShow->setStyleSheet(QString("QProgressBar::chunk {background-color: qlineargradient(x0: 0, x2: 1, " "stop: 0 #004D00, stop: %1 #004D00, stop: %2 #006C00, stop: %3 #006C00, stop: %4 #008C00, stop: 1 #008C00" ");}").arg(s1).arg(s1).arg(s2).arg(s2)); ui->hop_aromaShow->setFormat(tr("Moderate")); } else { double s3 = 60.0 / value; if (value < 80) { ui->hop_aromaShow->setStyleSheet(QString("QProgressBar::chunk {background-color: qlineargradient(x0: 0, x2: 1, " "stop: 0 #004D00, stop: %1 #004D00, stop: %2 #006C00, stop: %3 #006C00, stop: %4 #008C00, stop: %5 #008C00, " "stop: %6 #00AC00, stop: 1 #00AC00" ");}").arg(s1).arg(s1).arg(s2).arg(s2).arg(s3).arg(s3)); ui->hop_aromaShow->setFormat(tr("High")); } else { double s4 = 80.0 / value; ui->hop_aromaShow->setStyleSheet(QString("QProgressBar::chunk {background-color: qlineargradient(x0: 0, x2: 1, " "stop: 0 #004D00, stop: %1 #004D00, stop: %2 #006C00, stop: %3 #006C00, stop: %4 #008C00, stop: %5 #008C00, " "stop: %6 #00AC00, stop: %7 #00AC00, stop: %8 #00CC00, stop: 1 #00CC00" ");}").arg(s1).arg(s1).arg(s2).arg(s2).arg(s3).arg(s3).arg(s4).arg(s4)); ui->hop_aromaShow->setFormat(tr("Very high")); } } } } } void EditRecipe::calcIBUs() { double hop_flavour = 0, hop_aroma = 0, ibus = 0; for (int i = 0; i < recipe->hops.size(); i++) { ibus += Utils::toIBU(recipe->hops.at(i).useat, recipe->hops.at(i).form, recipe->preboil_sg, recipe->est_og, recipe->batch_size, recipe->hops.at(i).amount, recipe->hops.at(i).time, recipe->hops.at(i).alpha, recipe->ibu_method, 0, recipe->hops.at(i).time, 0, recipe->boil_time, 0, 0, 0, recipe->hops.at(i).utilisation, recipe->hops.at(i).bu_factor); hop_flavour += Utils::hopFlavourContribution(recipe->hops.at(i).time, recipe->batch_size, recipe->hops.at(i).useat, recipe->hops.at(i).amount, recipe->hops.at(i).form); hop_aroma += Utils::hopAromaContribution(recipe->hops.at(i).time, recipe->batch_size, recipe->hops.at(i).useat, recipe->hops.at(i).amount, recipe->hops.at(i).form); } hop_flavour = round(hop_flavour * 1000.0 / 5.0) / 10; hop_aroma = round(hop_aroma * 1000.0 / 6.0) / 10; if (hop_flavour > 100) hop_flavour = 100; if (hop_aroma > 100) hop_aroma = 100; qDebug() << "ibu" << recipe->est_ibu << ibus << "flavour" << hop_flavour << "aroma" << hop_aroma << "method" << recipe->ibu_method; recipe->est_ibu = ibus; ui->est_ibuEdit->setValue(recipe->est_ibu); ui->est_ibu2Edit->setValue(recipe->est_ibu); ui->est_ibuShow->setValue(recipe->est_ibu); ui->hop_tasteShow->setValue(hop_flavour); ui->hop_aromaShow->setValue(hop_aroma); } void EditRecipe::addHopRow_clicked() { Hops newh; qDebug() << "Add hop row"; for (int i = 0; i < recipe->hops.size(); i++) { if (recipe->hops.at(i).amount == 0 && recipe->hops.at(i).alpha == 0) return; // Add only one at a time. } newh.name = "Select one"; newh.origin = ""; newh.amount = 0; newh.cost = 0; newh.type = 0; newh.form = 0; newh.useat = 2; newh.time = 0; newh.alpha = 0; newh.beta = 0; newh.hsi = 0; newh.humulene = 0; newh.caryophyllene = 0; newh.cohumulone = 0; newh.myrcene = 0; newh.total_oil = 0; newh.utilisation = 20; newh.bu_factor = 1; recipe->hops.append(newh); emit refreshAll(); } void EditRecipe::deleteHopRow_clicked() { if (recipe->locked || recipe->hops.size() < 1) return; QPushButton *pb = qobject_cast<QPushButton *>(QObject::sender()); int row = pb->objectName().toInt(); qDebug() << "Delete hop row" << row << recipe->hops.size(); int rc = QMessageBox::warning(this, tr("Delete hop"), tr("Delete %1").arg(recipe->hops.at(row).name), QMessageBox::Yes | QMessageBox::No, QMessageBox::No); if (rc == QMessageBox::No) return; recipe->hops.removeAt(row); is_changed(); emit refreshAll(); } void EditRecipe::hop_amount_changed(double val) { QTableWidgetItem *item; recipe->hops[recipe->hops_row].amount = val / 1000.0; item = new QTableWidgetItem(QString("%1 gr").arg(val, 2, 'f', 1, '0')); item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); ui->hopsTable->setItem(recipe->hops_row, 8, item); double ibu = Utils::toIBU(recipe->hops.at(recipe->hops_row).useat, recipe->hops.at(recipe->hops_row).form, recipe->preboil_sg, recipe->est_og, recipe->batch_size, recipe->hops.at(recipe->hops_row).amount, recipe->hops.at(recipe->hops_row).time, recipe->hops.at(recipe->hops_row).alpha, recipe->ibu_method, 0, recipe->hops.at(recipe->hops_row).time, 0, recipe->boil_time, 0, 0, 0, recipe->hops.at(recipe->hops_row).utilisation, recipe->hops.at(recipe->hops_row).bu_factor); ibuEdit->setValue(ibu); item = new QTableWidgetItem(QString("%1").arg(ibu, 2, 'f', 1, '0')); item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); ui->hopsTable->setItem(recipe->hops_row, 7, item); calcIBUs(); is_changed(); } void EditRecipe::hop_alpha_changed(double val) { QTableWidgetItem *item; recipe->hops[recipe->hops_row].alpha = val; item = new QTableWidgetItem(QString("%1%").arg(val, 2, 'f', 1, '0')); item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); ui->hopsTable->setItem(recipe->hops_row, 4, item); double ibu = Utils::toIBU(recipe->hops.at(recipe->hops_row).useat, recipe->hops.at(recipe->hops_row).form, recipe->preboil_sg, recipe->est_og, recipe->batch_size, recipe->hops.at(recipe->hops_row).amount, recipe->hops.at(recipe->hops_row).time, recipe->hops.at(recipe->hops_row).alpha, recipe->ibu_method, 0, recipe->hops.at(recipe->hops_row).time, 0, recipe->boil_time, 0, 0, 0, recipe->hops.at(recipe->hops_row).utilisation, recipe->hops.at(recipe->hops_row).bu_factor); ibuEdit->setValue(ibu); item = new QTableWidgetItem(QString("%1").arg(ibu, 2, 'f', 1, '0')); item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); ui->hopsTable->setItem(recipe->hops_row, 7, item); calcIBUs(); is_changed(); } void EditRecipe::hop_time_changed(int val) { QTableWidgetItem *item; if (recipe->hops.at(recipe->hops_row).useat == 2 || recipe->hops.at(recipe->hops_row).useat == 4) { // Boil or whirlpool item = new QTableWidgetItem(QString("%1 min.").arg(val, 1, 'f', 0, '0')); recipe->hops[recipe->hops_row].time = val; } else if (recipe->hops.at(recipe->hops_row).useat == 5) { // Dry-hop item = new QTableWidgetItem(QString("%1 days.").arg(val, 1, 'f', 0, '0')); recipe->hops[recipe->hops_row].time = val * 1440; } else { item = new QTableWidgetItem(QString("")); recipe->hops[recipe->hops_row].time = val; } item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); ui->hopsTable->setItem(recipe->hops_row, 6, item); double ibu = Utils::toIBU(recipe->hops.at(recipe->hops_row).useat, recipe->hops.at(recipe->hops_row).form, recipe->preboil_sg, recipe->est_og, recipe->batch_size, recipe->hops.at(recipe->hops_row).amount, recipe->hops.at(recipe->hops_row).time, recipe->hops.at(recipe->hops_row).alpha, recipe->ibu_method, 0, recipe->hops.at(recipe->hops_row).time, 0, recipe->boil_time, 0, 0, 0, recipe->hops.at(recipe->hops_row).utilisation, recipe->hops.at(recipe->hops_row).bu_factor); ibuEdit->setValue(ibu); item = new QTableWidgetItem(QString("%1").arg(ibu, 2, 'f', 1, '0')); item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); ui->hopsTable->setItem(recipe->hops_row, 7, item); calcIBUs(); is_changed(); } void EditRecipe::hop_select_changed(int val) { QSqlQuery query; bool instock = hinstockEdit->isChecked(); QString w; QTableWidgetItem *item; if (val < 1) return; /* * Search the hop pointed by the index and instock flag. */ QString sql = "SELECT * FROM inventory_hops "; if (instock) sql.append("WHERE inventory > 0 "); sql.append("ORDER BY origin,name"); query.prepare(sql); query.exec(); query.first(); for (int i = 0; i < (val - 1); i++) { query.next(); } /* * Replace the hop record contents */ recipe->hops[recipe->hops_row].name = query.value("name").toString(); recipe->hops[recipe->hops_row].origin = query.value("origin").toString(); recipe->hops[recipe->hops_row].alpha = query.value("alpha").toDouble(); recipe->hops[recipe->hops_row].beta = query.value("beta").toDouble(); recipe->hops[recipe->hops_row].humulene = query.value("humulene").toDouble(); recipe->hops[recipe->hops_row].caryophyllene = query.value("caryophyllene").toDouble(); recipe->hops[recipe->hops_row].cohumulone = query.value("cohumulone").toDouble(); recipe->hops[recipe->hops_row].myrcene = query.value("myrcene").toDouble(); recipe->hops[recipe->hops_row].hsi = query.value("hsi").toDouble(); recipe->hops[recipe->hops_row].total_oil = query.value("total_oil").toDouble(); recipe->hops[recipe->hops_row].type = query.value("type").toInt(); recipe->hops[recipe->hops_row].form = query.value("form").toInt(); recipe->hops[recipe->hops_row].cost = query.value("cost").toDouble(); recipe->hops[recipe->hops_row].utilisation = query.value("utilisation").toDouble(); recipe->hops[recipe->hops_row].bu_factor = query.value("bu_factor").toDouble(); /* * Update the visible fields */ hnameEdit->setText(recipe->hops.at(recipe->hops_row).name); horiginEdit->setText(recipe->hops.at(recipe->hops_row).origin); double ibu = Utils::toIBU(recipe->hops.at(recipe->hops_row).useat, recipe->hops.at(recipe->hops_row).form, recipe->preboil_sg, recipe->est_og, recipe->batch_size, recipe->hops.at(recipe->hops_row).amount, recipe->hops.at(recipe->hops_row).time, recipe->hops.at(recipe->hops_row).alpha, recipe->ibu_method, 0, recipe->hops.at(recipe->hops_row).time, 0, recipe->boil_time, 0, 0, 0, recipe->hops.at(recipe->hops_row).utilisation, recipe->hops.at(recipe->hops_row).bu_factor); ibuEdit->setValue(ibu); ui->hopsTable->setItem(recipe->hops_row, 0, new QTableWidgetItem(recipe->hops.at(recipe->hops_row).origin)); ui->hopsTable->setItem(recipe->hops_row, 1, new QTableWidgetItem(recipe->hops.at(recipe->hops_row).name)); QString hoptype = QCoreApplication::translate("HopTypes", g_hop_types[recipe->hops.at(recipe->hops_row).type]); item = new QTableWidgetItem(hoptype); item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter); ui->hopsTable->setItem(recipe->hops_row, 2, item); item = new QTableWidgetItem(QCoreApplication::translate("HopForm", g_hop_forms[recipe->hops.at(recipe->hops_row).form])); //item = new QTableWidgetItem(hop_forms[recipe->hops.at(recipe->hops_row).form]); item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter); ui->hopsTable->setItem(recipe->hops_row, 3, item); item = new QTableWidgetItem(QString("%1%").arg(recipe->hops.at(recipe->hops_row).alpha, 2, 'f', 1, '0')); item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); ui->hopsTable->setItem(recipe->hops_row, 4, item); item = new QTableWidgetItem(QString("%1").arg(ibu, 2, 'f', 1, '0')); item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); ui->hopsTable->setItem(recipe->hops_row, 7, item); calcIBUs(); is_changed(); } void EditRecipe::hop_instock_changed(bool val) { QSqlQuery query; this->hselectEdit->setCurrentIndex(-1); this->hselectEdit->clear(); QString sql = "SELECT origin,name,alpha,inventory FROM inventory_hops "; if (val) sql.append("WHERE inventory > 0 "); sql.append("ORDER BY origin,name"); query.prepare(sql); query.exec(); query.first(); this->hselectEdit->addItem(""); // Start with empty value for (int i = 0; i < query.size(); i++) { this->hselectEdit->addItem(query.value(0).toString()+" - "+query.value(1).toString()+" ("+query.value(2).toString()+"%) "+ QString("%1 gr").arg(query.value(3).toDouble() * 1000.0, 2, 'f', 1, '0')); query.next(); } } void EditRecipe::hop_useat_changed(int val) { recipe->hops[recipe->hops_row].useat = val; QTableWidgetItem *item = new QTableWidgetItem(QCoreApplication::translate("HopUse", g_hop_useat[val])); item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter); ui->hopsTable->setItem(recipe->hops_row, 5, item); if (val == 2 || val == 4) { // Boil or whirlpool htimeLabel->setText(tr("Time in minutes:")); htimeEdit->setValue(recipe->hops.at(recipe->hops_row).time); htimeEdit->setReadOnly(false); } else if (val == 5) { // Dry-hop htimeLabel->setText(tr("Time in days:")); htimeEdit->setValue(recipe->hops.at(recipe->hops_row).time / 1440); htimeEdit->setReadOnly(false); } else { htimeLabel->setText(""); htimeEdit->setValue(0); htimeEdit->setReadOnly(true); } is_changed(); emit refreshAll(); } void EditRecipe::hop_form_changed(int val) { recipe->hops[recipe->hops_row].form = val; QTableWidgetItem *item = new QTableWidgetItem(QCoreApplication::translate("HopForm", g_hop_forms[val])); item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter); ui->hopsTable->setItem(recipe->hops_row, 3, item); double ibu = Utils::toIBU(recipe->hops.at(recipe->hops_row).useat, recipe->hops.at(recipe->hops_row).form, recipe->preboil_sg, recipe->est_og, recipe->batch_size, recipe->hops.at(recipe->hops_row).amount, recipe->hops.at(recipe->hops_row).time, recipe->hops.at(recipe->hops_row).alpha, recipe->ibu_method, 0, recipe->hops.at(recipe->hops_row).time, 0, recipe->boil_time, 0, 0, 0, recipe->hops.at(recipe->hops_row).utilisation, recipe->hops.at(recipe->hops_row).bu_factor); ibuEdit->setValue(ibu); item = new QTableWidgetItem(QString("%1").arg(ibu, 2, 'f', 1, '0')); item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); ui->hopsTable->setItem(recipe->hops_row, 7, item); is_changed(); emit refreshAll(); } void EditRecipe::editHopRow_clicked() { QSqlQuery query; if (recipe->locked) return; QPushButton *pb = qobject_cast<QPushButton *>(QObject::sender()); recipe->hops_row = pb->objectName().toInt(); qDebug() << "Edit hop row" << recipe->hops_row; Hops backup = recipe->hops.at(recipe->hops_row); QDialog* dialog = new QDialog(this); dialog->resize(738, 260); QDialogButtonBox *buttonBox = new QDialogButtonBox(dialog); buttonBox->setObjectName(QString::fromUtf8("buttonBox")); buttonBox->setGeometry(QRect(30, 210, 671, 32)); buttonBox->setLayoutDirection(Qt::LeftToRight); buttonBox->setOrientation(Qt::Horizontal); buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok); buttonBox->setCenterButtons(true); QLabel *nameLabel = new QLabel(dialog); nameLabel->setObjectName(QString::fromUtf8("nameLabel")); nameLabel->setText(tr("Current hop:")); nameLabel->setGeometry(QRect(10, 10, 141, 20)); nameLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); QLabel *originLabel = new QLabel(dialog); originLabel->setObjectName(QString::fromUtf8("originLabel")); originLabel->setText(tr("Origin:")); originLabel->setGeometry(QRect(10, 40, 141, 20)); originLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); QLabel *amountLabel = new QLabel(dialog); amountLabel->setObjectName(QString::fromUtf8("amountLabel")); amountLabel->setText(tr("Amount in gr:")); amountLabel->setGeometry(QRect(10, 100, 141, 20)); amountLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); QLabel *alphaLabel = new QLabel(dialog); alphaLabel->setObjectName(QString::fromUtf8("alphaLabel")); alphaLabel->setText(tr("Alpha percent:")); alphaLabel->setGeometry(QRect(420, 100, 121, 20)); alphaLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); htimeLabel = new QLabel(dialog); htimeLabel->setObjectName(QString::fromUtf8("htimeLabel")); if (recipe->hops.at(recipe->hops_row).useat == 5) // Dry-hop htimeLabel->setText(tr("Time in days:")); else if (recipe->hops.at(recipe->hops_row).useat == 2 || recipe->hops.at(recipe->hops_row).useat == 4) // Boil or whirlpool htimeLabel->setText(tr("Time in minutes:")); else htimeLabel->setText(""); htimeLabel->setGeometry(QRect(10, 130, 141, 20)); htimeLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); QLabel *useatLabel = new QLabel(dialog); useatLabel->setObjectName(QString::fromUtf8("useatLabel")); useatLabel->setText(tr("Use at:")); useatLabel->setGeometry(QRect(10, 160, 141, 20)); useatLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); QLabel *formLabel = new QLabel(dialog); formLabel->setObjectName(QString::fromUtf8("formLabel")); formLabel->setText(tr("Hop form:")); formLabel->setGeometry(QRect(380, 160, 121, 20)); formLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); QLabel *selectLabel = new QLabel(dialog); selectLabel->setObjectName(QString::fromUtf8("selectLabel")); selectLabel->setText(tr("Select hop:")); selectLabel->setGeometry(QRect(10, 70, 141, 20)); selectLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); QLabel *instockLabel = new QLabel(dialog); instockLabel->setObjectName(QString::fromUtf8("instockLabel")); instockLabel->setText(tr("In stock:")); instockLabel->setGeometry(QRect(525, 70, 121, 20)); instockLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); QLabel *ibuLabel = new QLabel(dialog); ibuLabel->setObjectName(QString::fromUtf8("maxLabel")); ibuLabel->setText(tr("Bitterness IBU:")); ibuLabel->setGeometry(QRect(420, 130, 121, 20)); ibuLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); hselectEdit = new QComboBox(dialog); hselectEdit->setObjectName(QString::fromUtf8("selectEdit")); hselectEdit->setGeometry(QRect(160, 70, 371, 23)); hnameEdit = new QLineEdit(dialog); hnameEdit->setObjectName(QString::fromUtf8("hnameEdit")); hnameEdit->setText(recipe->hops.at(recipe->hops_row).name); hnameEdit->setGeometry(QRect(160, 10, 511, 23)); hnameEdit->setReadOnly(true); horiginEdit = new QLineEdit(dialog); horiginEdit->setObjectName(QString::fromUtf8("horiginEdit")); horiginEdit->setText(recipe->hops.at(recipe->hops_row).origin); horiginEdit->setGeometry(QRect(160, 40, 511, 23)); horiginEdit->setReadOnly(true); hamountEdit = new QDoubleSpinBox(dialog); hamountEdit->setObjectName(QString::fromUtf8("hamountEdit")); hamountEdit->setGeometry(QRect(160, 100, 121, 24)); hamountEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); hamountEdit->setAccelerated(true); hamountEdit->setDecimals(1); hamountEdit->setMaximum(1000000.0); hamountEdit->setSingleStep(0.5); hamountEdit->setValue(recipe->hops.at(recipe->hops_row).amount * 1000.0); halphaEdit = new QDoubleSpinBox(dialog); halphaEdit->setObjectName(QString::fromUtf8("halphaEdit")); halphaEdit->setGeometry(QRect(550, 100, 121, 24)); halphaEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); halphaEdit->setAccelerated(true); halphaEdit->setDecimals(1); halphaEdit->setMaximum(100.0); halphaEdit->setSingleStep(0.1); halphaEdit->setValue(recipe->hops.at(recipe->hops_row).alpha); htimeEdit = new QSpinBox(dialog); htimeEdit->setObjectName(QString::fromUtf8("htimeEdit")); htimeEdit->setGeometry(QRect(160, 130, 121, 24)); htimeEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); htimeEdit->setAccelerated(true); htimeEdit->setMaximum(10000.0); if (recipe->hops.at(recipe->hops_row).useat == 2 || recipe->hops.at(recipe->hops_row).useat == 4) { // Boil or whirlpool htimeEdit->setValue(recipe->hops.at(recipe->hops_row).time); htimeEdit->setReadOnly(false); } else if (recipe->hops.at(recipe->hops_row).useat == 5){ // Dry-hop htimeEdit->setValue(recipe->hops.at(recipe->hops_row).time / 1440); htimeEdit->setReadOnly(false); } else { htimeEdit->setReadOnly(true); } useatEdit = new QComboBox(dialog); useatEdit->setObjectName(QString::fromUtf8("useatEdit")); useatEdit->setGeometry(QRect(160, 160, 161, 23)); useatEdit->addItem(tr("Mash")); useatEdit->addItem(tr("First wort")); useatEdit->addItem(tr("Boil")); useatEdit->addItem(tr("Aroma")); useatEdit->addItem(tr("Whirlpool")); useatEdit->addItem(tr("Dry hop")); useatEdit->addItem(tr("Bottling")); useatEdit->setCurrentIndex(recipe->hops.at(recipe->hops_row).useat); hformEdit = new QComboBox(dialog); hformEdit->setObjectName(QString::fromUtf8("formEdit")); hformEdit->setGeometry(QRect(510, 160, 161, 23)); hformEdit->addItem(tr("Pellet")); hformEdit->addItem(tr("Plug")); hformEdit->addItem(tr("Leaf")); hformEdit->addItem(tr("Wet leaf")); hformEdit->addItem(tr("Cryo")); hformEdit->addItem(tr("Extract")); hformEdit->setCurrentIndex(recipe->hops.at(recipe->hops_row).form); hinstockEdit = new QCheckBox(dialog); hinstockEdit->setObjectName(QString::fromUtf8("hinstockEdit")); hinstockEdit->setGeometry(QRect(655, 70, 85, 21)); hinstockEdit->setChecked(true); ibuEdit = new QDoubleSpinBox(dialog); ibuEdit->setObjectName(QString::fromUtf8("ibuEdit")); ibuEdit->setGeometry(QRect(550, 130, 121, 24)); ibuEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); ibuEdit->setReadOnly(true); ibuEdit->setButtonSymbols(QAbstractSpinBox::NoButtons); ibuEdit->setDecimals(1); double ibu = Utils::toIBU(recipe->hops.at(recipe->hops_row).useat, recipe->hops.at(recipe->hops_row).form, recipe->preboil_sg, recipe->est_og, recipe->batch_size, recipe->hops.at(recipe->hops_row).amount, recipe->hops.at(recipe->hops_row).time, recipe->hops.at(recipe->hops_row).alpha, recipe->ibu_method, 0, recipe->hops.at(recipe->hops_row).time, 0, recipe->boil_time, 0, 0, 0, recipe->hops.at(recipe->hops_row).utilisation, recipe->hops.at(recipe->hops_row).bu_factor); ibuEdit->setValue(ibu); hop_instock_changed(true); connect(hselectEdit, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &EditRecipe::hop_select_changed); connect(hamountEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditRecipe::hop_amount_changed); connect(halphaEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditRecipe::hop_alpha_changed); connect(htimeEdit, QOverload<int>::of(&QSpinBox::valueChanged), this, &EditRecipe::hop_time_changed); connect(useatEdit, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &EditRecipe::hop_useat_changed); connect(hformEdit, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &EditRecipe::hop_form_changed); connect(hinstockEdit, &QCheckBox::stateChanged, this, &EditRecipe::hop_instock_changed); connect(buttonBox, SIGNAL(rejected()), dialog, SLOT(reject())); connect(buttonBox, SIGNAL(accepted()), dialog, SLOT(accept())); dialog->setModal(true); dialog->exec(); if (dialog->result() == QDialog::Rejected) { qDebug() << "reject and rollback"; recipe->hops[recipe->hops_row] = backup; } else { /* Clear time if hop is not used for boil, whirlpool or dry-hop. */ if (! (recipe->hops.at(recipe->hops_row).useat == 2 || recipe->hops.at(recipe->hops_row).useat == 4 || recipe->hops.at(recipe->hops_row).useat == 5)) { if (recipe->hops.at(recipe->hops_row).time) { recipe->hops[recipe->hops_row].time = 0; is_changed(); } } } disconnect(hselectEdit, nullptr, nullptr, nullptr); disconnect(hamountEdit, nullptr, nullptr, nullptr); disconnect(halphaEdit, nullptr, nullptr, nullptr); disconnect(htimeEdit, nullptr, nullptr, nullptr); disconnect(useatEdit, nullptr, nullptr, nullptr); disconnect(hformEdit, nullptr, nullptr, nullptr); disconnect(hinstockEdit, nullptr, nullptr, nullptr); disconnect(buttonBox, nullptr, nullptr, nullptr); emit refreshAll(); } void EditRecipe::adjustHops(double factor) { double amount; if (recipe->hops.size() == 0) return; for (int i = 0; i < recipe->hops.size(); i++) { amount = recipe->hops.at(i).amount * factor; recipe->hops[i].amount = amount; } }