diff -r 3c013ef88a00 -r 475c8b8df67f src/EditRecipeTab3.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/EditRecipeTab3.cpp Mon Apr 11 17:22:43 2022 +0200
@@ -0,0 +1,612 @@
+/**
+ * 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 .
+ */
+
+
+
+bool EditRecipe::hop_sort_test(const Hops &D1, const Hops &D2)
+{
+ if (D1.h_useat > D2.h_useat)
+ return false;
+ if (D1.h_useat < D2.h_useat)
+ return true;
+ /* Same useat moments, test time. */
+ if (D1.h_time < D2.h_time)
+ return false;
+ if (D1.h_time > D2.h_time)
+ return true;
+ /* Finally consider the amounts */
+ return (D1.h_amount > D2.h_amount);
+}
+
+
+void EditRecipe::refreshHops()
+{
+ QString w;
+ QWidget* pWidget;
+ QHBoxLayout* pLayout;
+ QTableWidgetItem *item;
+
+ qDebug() << "refreshHops" << recipe->hops.size();
+ std::sort(recipe->hops.begin(), recipe->hops.end(), hop_sort_test);
+
+ /*
+ * During filling the table turn off the cellChanged signal because every cell that is filled
+ * triggers the cellChanged signal. The QTableWidget has no better signal to use.
+ */
+ this->ignoreChanges = true;
+
+ 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, 75); /* Type */
+ ui->hopsTable->setColumnWidth(3, 75); /* 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, 75); /* 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).h_origin));
+ ui->hopsTable->setItem(i, 1, new QTableWidgetItem(recipe->hops.at(i).h_name));
+
+ item = new QTableWidgetItem(h_types[recipe->hops.at(i).h_type]);
+ item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter);
+ ui->hopsTable->setItem(i, 2, item);
+
+ item = new QTableWidgetItem(h_forms[recipe->hops.at(i).h_form]);
+ item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter);
+ ui->hopsTable->setItem(i, 3, item);
+
+ item = new QTableWidgetItem(QString("%1%").arg(recipe->hops.at(i).h_alpha, 2, 'f', 1, '0'));
+ item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+ ui->hopsTable->setItem(i, 4, item);
+
+ item = new QTableWidgetItem(h_useat[recipe->hops.at(i).h_useat]);
+ item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter);
+ ui->hopsTable->setItem(i, 5, item);
+
+ if (recipe->hops.at(i).h_useat == 2 || recipe->hops.at(i).h_useat == 4) { // Boil or whirlpool
+ item = new QTableWidgetItem(QString("%1 min.").arg(recipe->hops.at(i).h_time, 1, 'f', 0, '0'));
+ } else if (recipe->hops.at(i).h_useat == 5) { // Dry-hop
+ item = new QTableWidgetItem(QString("%1 days.").arg(recipe->hops.at(i).h_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).h_useat, recipe->hops.at(i).h_form, recipe->preboil_sg, recipe->batch_size, recipe->hops.at(i).h_amount,
+ recipe->hops.at(i).h_time, recipe->hops.at(i).h_alpha, recipe->ibu_method, 0, recipe->hops.at(i).h_time, 0);
+ 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).h_amount < 1.0) {
+ item = new QTableWidgetItem(QString("%1 gr").arg(recipe->hops.at(i).h_amount * 1000.0, 2, 'f', 1, '0'));
+ } else {
+ item = new QTableWidgetItem(QString("%1 kg").arg(recipe->hops.at(i).h_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(on_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(on_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);
+ }
+ this->ignoreChanges = false;
+}
+
+
+void EditRecipe::on_Flavour_valueChanged(int value)
+{
+ if (value < 20) {
+ ui->hop_tasteShow->setStyleSheet(bar_20);
+ ui->hop_tasteShow->setFormat(tr("Very low"));
+ } else if (value < 40) {
+ ui->hop_tasteShow->setStyleSheet(bar_40);
+ ui->hop_tasteShow->setFormat(tr("Low"));
+ } else if (value < 60) {
+ ui->hop_tasteShow->setStyleSheet(bar_60);
+ ui->hop_tasteShow->setFormat(tr("Moderate"));
+ } else if (value < 80) {
+ ui->hop_tasteShow->setStyleSheet(bar_80);
+ ui->hop_tasteShow->setFormat(tr("High"));
+ } else {
+ ui->hop_tasteShow->setStyleSheet(bar_100);
+ ui->hop_tasteShow->setFormat(tr("Very high"));
+ }
+}
+
+
+void EditRecipe::on_Aroma_valueChanged(int value)
+{
+ if (value < 20) {
+ ui->hop_aromaShow->setStyleSheet(bar_20);
+ ui->hop_aromaShow->setFormat(tr("Very low"));
+ } else if (value < 40) {
+ ui->hop_aromaShow->setStyleSheet(bar_40);
+ ui->hop_aromaShow->setFormat(tr("Low"));
+ } else if (value < 60) {
+ ui->hop_aromaShow->setStyleSheet(bar_60);
+ ui->hop_aromaShow->setFormat(tr("Moderate"));
+ } else if (value < 80) {
+ ui->hop_aromaShow->setStyleSheet(bar_80);
+ ui->hop_aromaShow->setFormat(tr("High"));
+ } else {
+ ui->hop_aromaShow->setStyleSheet(bar_100);
+ 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).h_useat, recipe->hops.at(i).h_form, recipe->preboil_sg, recipe->batch_size, recipe->hops.at(i).h_amount,
+ recipe->hops.at(i).h_time, recipe->hops.at(i).h_alpha, recipe->ibu_method, 0, recipe->hops.at(i).h_time, 0);
+ hop_flavour += Utils::hopFlavourContribution(recipe->hops.at(i).h_time, recipe->batch_size, recipe->hops.at(i).h_useat, recipe->hops.at(i).h_amount);
+ hop_aroma += Utils::hopAromaContribution(recipe->hops.at(i).h_time, recipe->batch_size, recipe->hops.at(i).h_useat, recipe->hops.at(i).h_amount);
+ }
+
+ 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;
+
+ recipe->est_ibu = ibus;
+ ui->est_ibuEdit->setValue(recipe->est_ibu);
+ ui->est_ibu2Edit->setValue(recipe->est_ibu);
+ ui->hop_tasteShow->setValue(hop_flavour);
+ ui->hop_aromaShow->setValue(hop_aroma);
+}
+
+
+void EditRecipe::on_addHopRow_clicked()
+{
+ Hops newh;
+
+ qDebug() << "Add hop row";
+
+ for (int i = 0; i < recipe->hops.size(); i++) {
+ if (recipe->hops.at(i).h_amount == 0 && recipe->hops.at(i).h_alpha == 0)
+ return; // Add only one at a time.
+ }
+
+ emit refreshAll();
+}
+
+
+void EditRecipe::on_deleteHopRow_clicked()
+{
+ QPushButton *pb = qobject_cast(QObject::sender());
+ int row = pb->objectName().toInt();
+ qDebug() << "Delete hop row" << row << recipe->hops.size();
+
+ if (recipe->hops.size() < 1)
+ return;
+
+ int rc = QMessageBox::warning(this, tr("Delete hop"), tr("Delete %1").arg(recipe->hops.at(row).h_name),
+ QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
+ if (rc == QMessageBox::No)
+ return;
+
+
+}
+
+
+void EditRecipe::hop_amount_changed(double val)
+{
+ QTableWidgetItem *item;
+
+ qDebug() << "hop_amount_changed()" << recipe->hops_row << val;
+ this->ignoreChanges = true;
+
+ recipe->hops[recipe->hops_row].h_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).h_useat, recipe->hops.at(recipe->hops_row).h_form, recipe->preboil_sg,
+ recipe->batch_size, recipe->hops.at(recipe->hops_row).h_amount, recipe->hops.at(recipe->hops_row).h_time,
+ recipe->hops.at(recipe->hops_row).h_alpha, recipe->ibu_method, 0, recipe->hops.at(recipe->hops_row).h_time, 0);
+
+ 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);
+
+ this->ignoreChanges = false;
+ calcIBUs();
+ is_changed();
+}
+
+
+void EditRecipe::hop_time_changed(int val)
+{
+ QTableWidgetItem *item;
+
+ qDebug() << "hop_time_changed()" << recipe->hops_row << val;
+
+ this->ignoreChanges = true;
+ recipe->hops[recipe->hops_row].h_time = val;
+
+ if (recipe->hops.at(recipe->hops_row).h_useat == 2 || recipe->hops.at(recipe->hops_row).h_useat == 4) { // Boil or whirlpool
+ item = new QTableWidgetItem(QString("%1 min.").arg(val, 1, 'f', 0, '0'));
+ } else if (recipe->hops.at(recipe->hops_row).h_useat == 5) { // Dry-hop
+ item = new QTableWidgetItem(QString("%1 days.").arg(val / 1440, 1, 'f', 0, '0'));
+ } else {
+ item = new QTableWidgetItem(QString(""));
+ }
+ item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+ ui->hopsTable->setItem(recipe->hops_row, 6, item);
+
+ double ibu = Utils::toIBU(recipe->hops.at(recipe->hops_row).h_useat, recipe->hops.at(recipe->hops_row).h_form, recipe->preboil_sg,
+ recipe->batch_size, recipe->hops.at(recipe->hops_row).h_amount, recipe->hops.at(recipe->hops_row).h_time,
+ recipe->hops.at(recipe->hops_row).h_alpha, recipe->ibu_method, 0, recipe->hops.at(recipe->hops_row).h_time, 0);
+
+ 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);
+
+ this->ignoreChanges = false;
+ calcIBUs();
+ is_changed();
+}
+
+
+void EditRecipe::hop_select_changed(int val)
+{
+ QSqlQuery query;
+ bool instock = hinstockEdit->isChecked();
+ QString w;
+ QTableWidgetItem *item;
+
+ if (val < 1)
+ return;
+
+ qDebug() << "hop_select_changed()" << recipe->fermentables_row << val << instock;
+
+ /*
+ * Search the hop pointed by the index and instock flag.
+ */
+ QString sql = "SELECT name,origin,alpha,beta,humulene,caryophyllene,cohumulone,myrcene,hsi,total_oil,type,form,cost 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();
+ }
+ qDebug() << "found" << query.value(1).toString() << query.value(0).toString();
+
+ /*
+ * Replace the hop record contents
+ */
+ this->ignoreChanges = true;
+ recipe->hops[recipe->hops_row].h_name = query.value(0).toString();
+ recipe->hops[recipe->hops_row].h_origin = query.value(1).toString();
+ recipe->hops[recipe->hops_row].h_alpha = query.value(2).toDouble();
+ recipe->hops[recipe->hops_row].h_beta = query.value(3).toDouble();
+ recipe->hops[recipe->hops_row].h_humulene = query.value(4).toDouble();
+ recipe->hops[recipe->hops_row].h_caryophyllene = query.value(5).toDouble();
+ recipe->hops[recipe->hops_row].h_cohumulone = query.value(6).toDouble();
+ recipe->hops[recipe->hops_row].h_myrcene = query.value(7).toDouble();
+ recipe->hops[recipe->hops_row].h_hsi = query.value(8).toDouble();
+ recipe->hops[recipe->hops_row].h_total_oil = query.value(9).toDouble();
+ recipe->hops[recipe->hops_row].h_type = query.value(10).toInt();
+ recipe->hops[recipe->hops_row].h_form = query.value(11).toInt();
+ recipe->hops[recipe->hops_row].h_cost = query.value(12).toDouble();
+
+ /*
+ * Update the visible fields
+ */
+ hnameEdit->setText(recipe->hops.at(recipe->hops_row).h_name);
+ horiginEdit->setText(recipe->hops.at(recipe->hops_row).h_origin);
+
+ double ibu = Utils::toIBU(recipe->hops.at(recipe->hops_row).h_useat, recipe->hops.at(recipe->hops_row).h_form, recipe->preboil_sg,
+ recipe->batch_size, recipe->hops.at(recipe->hops_row).h_amount, recipe->hops.at(recipe->hops_row).h_time,
+ recipe->hops.at(recipe->hops_row).h_alpha, recipe->ibu_method, 0, recipe->hops.at(recipe->hops_row).h_time, 0);
+ ibuEdit->setValue(ibu);
+
+ ui->hopsTable->setItem(recipe->hops_row, 0, new QTableWidgetItem(recipe->hops.at(recipe->hops_row).h_origin));
+ ui->hopsTable->setItem(recipe->hops_row, 1, new QTableWidgetItem(recipe->hops.at(recipe->hops_row).h_name));
+
+ item = new QTableWidgetItem(h_types[recipe->hops.at(recipe->hops_row).h_type]);
+ item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter);
+ ui->hopsTable->setItem(recipe->hops_row, 2, item);
+
+ item = new QTableWidgetItem(h_forms[recipe->hops.at(recipe->hops_row).h_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).h_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);
+
+ this->ignoreChanges = false;
+ calcIBUs();
+ is_changed();
+}
+
+
+void EditRecipe::hop_instock_changed(bool val)
+{
+ QSqlQuery query;
+
+ qDebug() << "hop_instock_changed()" << recipe->hops_row << val;
+
+ 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)
+{
+ qDebug() << "hop_useat_changed()" << recipe->hops_row << val;
+
+ this->ignoreChanges = true;
+ recipe->hops[recipe->hops_row].h_useat = val;
+ QTableWidgetItem *item = new QTableWidgetItem(h_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).h_time);
+ htimeEdit->setReadOnly(false);
+ } else if (val == 5) { // Dry-hop
+ htimeLabel->setText(tr("Time in days:"));
+ htimeEdit->setValue(recipe->hops.at(recipe->hops_row).h_time / 1440);
+ htimeEdit->setReadOnly(false);
+ } else {
+ htimeLabel->setText("");
+ htimeEdit->setValue(0);
+ htimeEdit->setReadOnly(true);
+ }
+
+ this->ignoreChanges = false;
+ is_changed();
+ emit refreshAll();
+}
+
+
+void EditRecipe::on_editHopRow_clicked()
+{
+ QSqlQuery query;
+
+ QPushButton *pb = qobject_cast(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);
+ htimeLabel = new QLabel(dialog);
+ htimeLabel->setObjectName(QString::fromUtf8("htimeLabel"));
+ if (recipe->hops.at(recipe->hops_row).h_useat == 5) // Dry-hop
+ htimeLabel->setText(tr("Time in days:"));
+ else if (recipe->hops.at(recipe->hops_row).h_useat == 2 || recipe->hops.at(recipe->hops_row).h_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 *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).h_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).h_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).h_amount * 1000.0);
+ 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).h_useat == 2 || recipe->hops.at(recipe->hops_row).h_useat == 4) { // Boil or whirlpool
+ htimeEdit->setValue(recipe->hops.at(recipe->hops_row).h_time);
+ htimeEdit->setReadOnly(false);
+ } else if (recipe->hops.at(recipe->hops_row).h_useat == 5){ // Dry-hop
+ htimeEdit->setValue(recipe->hops.at(recipe->hops_row).h_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->setCurrentIndex(recipe->hops.at(recipe->hops_row).h_useat);
+
+ 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).h_useat, recipe->hops.at(recipe->hops_row).h_form, recipe->preboil_sg,
+ recipe->batch_size, recipe->hops.at(recipe->hops_row).h_amount, recipe->hops.at(recipe->hops_row).h_time,
+ recipe->hops.at(recipe->hops_row).h_alpha, recipe->ibu_method, 0, recipe->hops.at(recipe->hops_row).h_time, 0);
+ ibuEdit->setValue(ibu);
+
+ hop_instock_changed(true);
+
+ connect(hselectEdit, QOverload::of(&QComboBox::currentIndexChanged), this, &EditRecipe::hop_select_changed);
+ connect(hamountEdit, QOverload::of(&QDoubleSpinBox::valueChanged), this, &EditRecipe::hop_amount_changed);
+ connect(htimeEdit, QOverload::of(&QSpinBox::valueChanged), this, &EditRecipe::hop_time_changed);
+ connect(useatEdit, QOverload::of(&QComboBox::currentIndexChanged), this, &EditRecipe::hop_useat_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).h_useat == 2 ||
+ recipe->hops.at(recipe->hops_row).h_useat == 4 ||
+ recipe->hops.at(recipe->hops_row).h_useat == 5)) {
+ if (recipe->hops.at(recipe->hops_row).h_time) {
+ recipe->hops[recipe->hops_row].h_time = 0;
+ is_changed();
+ }
+ }
+ }
+
+ disconnect(hselectEdit, nullptr, nullptr, nullptr);
+ disconnect(hamountEdit, nullptr, nullptr, nullptr);
+ disconnect(htimeEdit, nullptr, nullptr, nullptr);
+ disconnect(useatEdit, nullptr, nullptr, nullptr);
+ disconnect(hinstockEdit, nullptr, nullptr, nullptr);
+ disconnect(buttonBox, nullptr, nullptr, nullptr);
+
+ emit refreshAll();
+}
+
+