Added hop rows sorting. Added hop amount edit, hop time changed, hop select changed, hop instock change and hop use at changed. Added generic on hop editrow editor.

Mon, 11 Apr 2022 16:18:40 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Mon, 11 Apr 2022 16:18:40 +0200
changeset 126
3c013ef88a00
parent 125
2e79e0975e58
child 127
475c8b8df67f

Added hop rows sorting. Added hop amount edit, hop time changed, hop select changed, hop instock change and hop use at changed. Added generic on hop editrow editor.

src/EditRecipe.cpp file | annotate | diff | comparison | revisions
src/EditRecipe.h file | annotate | diff | comparison | revisions
--- a/src/EditRecipe.cpp	Sat Apr 09 21:50:19 2022 +0200
+++ b/src/EditRecipe.cpp	Mon Apr 11 16:18:40 2022 +0200
@@ -647,7 +647,17 @@
 
 bool EditRecipe::hop_sort_test(const Hops &D1, const Hops &D2)
 {
-    return (D1.h_useat <= D2.h_useat ) && (D1.h_time >= D2.h_time) && (D1.h_amount >= D2.h_amount);
+    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);
 }
 
 
@@ -659,7 +669,7 @@
     QTableWidgetItem *item;
 
     qDebug() << "refreshHops" << recipe->hops.size();
-    // std::sort(recipe->hops.begin(), recipe->hops.end(), hop_sort_test);
+    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
@@ -1592,6 +1602,21 @@
 }
 
 
+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_deleteFermentRow_clicked()
 {
     QPushButton *pb = qobject_cast<QPushButton *>(QObject::sender());
@@ -1625,6 +1650,24 @@
 }
 
 
+void EditRecipe::on_deleteHopRow_clicked()
+{
+    QPushButton *pb = qobject_cast<QPushButton *>(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::ferment_amount_changed(double val)
 {
     QTableWidgetItem *item;
@@ -1662,6 +1705,34 @@
     is_changed();
 }
 
+
+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::ferment_pct_changed(double val)
 {
     QTableWidgetItem *item;
@@ -1695,7 +1766,7 @@
     item = new QTableWidgetItem(QString("%1 Kg").arg(recipe->fermentables[recipe->fermentables_row].f_amount, 4, 'f', 3, '0'));
     item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
     ui->fermentablesTable->setItem(recipe->fermentables_row, 7, item);
-    this->amountEdit->setValue(recipe->fermentables[recipe->fermentables_row].f_amount);
+    this->famountEdit->setValue(recipe->fermentables[recipe->fermentables_row].f_amount);
 
     item = new QTableWidgetItem(QString("%1%").arg(recipe->fermentables[recipe->fermentables_row].f_percentage, 2, 'f', 1, '0'));
     item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
@@ -1713,6 +1784,41 @@
     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::ferment_to100_changed(bool val)
 {
     qDebug() << "ferment_to100_changed()" << recipe->fermentables_row << val << recipe->fermentables_use100;
@@ -1728,13 +1834,13 @@
         recipe->fermentables_use100 = true;
         recipe->fermentables[recipe->fermentables_row].f_adjust_to_total_100 = true;
 	pctEdit->setReadOnly(false);
-	amountEdit->setReadOnly(true);
+	famountEdit->setReadOnly(true);
     } else if (recipe->fermentables_use100 && recipe->fermentables[recipe->fermentables_row].f_adjust_to_total_100 && ! val) {
 	/* Scenario 2. */
 	recipe->fermentables[recipe->fermentables_row].f_adjust_to_total_100 = false;
 	recipe->fermentables_use100 = false;
 	pctEdit->setReadOnly(true);
-	amountEdit->setReadOnly(false);
+	famountEdit->setReadOnly(false);
     } else if (recipe->fermentables_use100 && ! recipe->fermentables[recipe->fermentables_row].f_adjust_to_total_100 && val) {
 	/* Scenario 3. */
 	for (int i = 0; i < recipe->fermentables.size(); i++) {
@@ -1757,7 +1863,7 @@
 void EditRecipe::ferment_select_changed(int val)
 {
     QSqlQuery query;
-    bool instock = instockEdit->isChecked();
+    bool instock = finstockEdit->isChecked();
     QString w;
     QTableWidgetItem *item;
 
@@ -1808,9 +1914,9 @@
     /*
      * Update the visible fields
      */
-    nameEdit->setText(recipe->fermentables.at(recipe->fermentables_row).f_name);
-    supplierEdit->setText(recipe->fermentables.at(recipe->fermentables_row).f_supplier);
-    maxEdit->setValue(recipe->fermentables.at(recipe->fermentables_row).f_max_in_batch);
+    fnameEdit->setText(recipe->fermentables.at(recipe->fermentables_row).f_name);
+    fsupplierEdit->setText(recipe->fermentables.at(recipe->fermentables_row).f_supplier);
+    fmaxEdit->setValue(recipe->fermentables.at(recipe->fermentables_row).f_max_in_batch);
 
     ui->fermentablesTable->setItem(recipe->fermentables_row, 0, new QTableWidgetItem(recipe->fermentables.at(recipe->fermentables_row).f_supplier));
     ui->fermentablesTable->setItem(recipe->fermentables_row, 1, new QTableWidgetItem(recipe->fermentables.at(recipe->fermentables_row).f_name));
@@ -1837,14 +1943,96 @@
     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::ferment_instock_changed(bool val)
 {
     QSqlQuery query;
 
     qDebug() << "ferment_instock_changed()" << recipe->fermentables_row << val;
 
-    this->selectEdit->setCurrentIndex(-1);
-    this->selectEdit->clear();
+    this->fselectEdit->setCurrentIndex(-1);
+    this->fselectEdit->clear();
     QString sql = "SELECT supplier,name,color,inventory FROM inventory_fermentables ";
     if (val)
 	sql.append("WHERE inventory > 0 ");
@@ -1852,14 +2040,39 @@
     query.prepare(sql);
     query.exec();
     query.first();
-    this->selectEdit->addItem("");	// Start with empty value
+    this->fselectEdit->addItem("");	// Start with empty value
     for (int i = 0; i < query.size(); i++) {
-        this->selectEdit->addItem(query.value(0).toString()+" - "+query.value(1).toString()+" ("+query.value(2).toString()+" EBC) "+
+        this->fselectEdit->addItem(query.value(0).toString()+" - "+query.value(1).toString()+" ("+query.value(2).toString()+" EBC) "+
 			QString("%1 kg").arg(query.value(3).toDouble(), 4, 'f', 3, '0'));
         query.next();
     }
 }
 
+
+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::ferment_added_changed(int val)
 {
     qDebug() << "ferment_added_changed()" << recipe->fermentables_row << val;
@@ -1884,6 +2097,36 @@
 }
 
 
+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_editFermentRow_clicked()
 {
     QSqlQuery query;
@@ -1948,30 +2191,30 @@
     maxLabel->setGeometry(QRect(420, 130, 121, 20));
     maxLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
 
-    selectEdit = new QComboBox(dialog);
-    selectEdit->setObjectName(QString::fromUtf8("selectEdit"));
-    selectEdit->setGeometry(QRect(160, 70, 371, 23));
+    fselectEdit = new QComboBox(dialog);
+    fselectEdit->setObjectName(QString::fromUtf8("fselectEdit"));
+    fselectEdit->setGeometry(QRect(160, 70, 371, 23));
 
-    nameEdit = new QLineEdit(dialog);
-    nameEdit->setObjectName(QString::fromUtf8("nameEdit"));
-    nameEdit->setText(recipe->fermentables.at(recipe->fermentables_row).f_name);
-    nameEdit->setGeometry(QRect(160, 10, 511, 23));
-    nameEdit->setReadOnly(true);
-    supplierEdit = new QLineEdit(dialog);
-    supplierEdit->setObjectName(QString::fromUtf8("supplierEdit"));
-    supplierEdit->setText(recipe->fermentables.at(recipe->fermentables_row).f_supplier);
-    supplierEdit->setGeometry(QRect(160, 40, 511, 23));
-    supplierEdit->setReadOnly(true);
-    amountEdit = new QDoubleSpinBox(dialog);
-    amountEdit->setObjectName(QString::fromUtf8("amountEdit"));
-    amountEdit->setGeometry(QRect(160, 100, 121, 24));
-    amountEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
-    amountEdit->setAccelerated(true);
-    amountEdit->setDecimals(3);
-    amountEdit->setReadOnly(recipe->fermentables_use100);
-    amountEdit->setMaximum(100000.0);
-    amountEdit->setSingleStep(0.0010);
-    amountEdit->setValue(recipe->fermentables.at(recipe->fermentables_row).f_amount);
+    fnameEdit = new QLineEdit(dialog);
+    fnameEdit->setObjectName(QString::fromUtf8("fnameEdit"));
+    fnameEdit->setText(recipe->fermentables.at(recipe->fermentables_row).f_name);
+    fnameEdit->setGeometry(QRect(160, 10, 511, 23));
+    fnameEdit->setReadOnly(true);
+    fsupplierEdit = new QLineEdit(dialog);
+    fsupplierEdit->setObjectName(QString::fromUtf8("fsupplierEdit"));
+    fsupplierEdit->setText(recipe->fermentables.at(recipe->fermentables_row).f_supplier);
+    fsupplierEdit->setGeometry(QRect(160, 40, 511, 23));
+    fsupplierEdit->setReadOnly(true);
+    famountEdit = new QDoubleSpinBox(dialog);
+    famountEdit->setObjectName(QString::fromUtf8("famountEdit"));
+    famountEdit->setGeometry(QRect(160, 100, 121, 24));
+    famountEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
+    famountEdit->setAccelerated(true);
+    famountEdit->setDecimals(3);
+    famountEdit->setReadOnly(recipe->fermentables_use100);
+    famountEdit->setMaximum(100000.0);
+    famountEdit->setSingleStep(0.0010);
+    famountEdit->setValue(recipe->fermentables.at(recipe->fermentables_row).f_amount);
 
     pctEdit = new QDoubleSpinBox(dialog);
     pctEdit->setObjectName(QString::fromUtf8("pctEdit"));
@@ -1991,44 +2234,44 @@
     pctEdit->setSingleStep(0.1);
     pctEdit->setValue(recipe->fermentables.at(recipe->fermentables_row).f_percentage);
 
-    addedEdit = new QComboBox(dialog);
-    addedEdit->setObjectName(QString::fromUtf8("addedEdit"));
-    addedEdit->setGeometry(QRect(160, 190, 161, 23));
-    addedEdit->addItem(tr("Mash"));
-    addedEdit->addItem(tr("Boil"));
-    addedEdit->addItem(tr("Fermentation"));
-    addedEdit->addItem(tr("Lagering"));
-    addedEdit->addItem(tr("Bottle"));
-    addedEdit->addItem(tr("Kegs"));
-    addedEdit->setCurrentIndex(recipe->fermentables.at(recipe->fermentables_row).f_added);
+    faddedEdit = new QComboBox(dialog);
+    faddedEdit->setObjectName(QString::fromUtf8("faddedEdit"));
+    faddedEdit->setGeometry(QRect(160, 190, 161, 23));
+    faddedEdit->addItem(tr("Mash"));
+    faddedEdit->addItem(tr("Boil"));
+    faddedEdit->addItem(tr("Fermentation"));
+    faddedEdit->addItem(tr("Lagering"));
+    faddedEdit->addItem(tr("Bottle"));
+    faddedEdit->addItem(tr("Kegs"));
+    faddedEdit->setCurrentIndex(recipe->fermentables.at(recipe->fermentables_row).f_added);
 
     to100Edit = new QCheckBox(dialog);
     to100Edit->setObjectName(QString::fromUtf8("to100Edit"));
     to100Edit->setGeometry(QRect(160, 160, 85, 21));
     to100Edit->setChecked(recipe->fermentables.at(recipe->fermentables_row).f_adjust_to_total_100);
 
-    instockEdit = new QCheckBox(dialog);
-    instockEdit->setObjectName(QString::fromUtf8("instockEdit"));
-    instockEdit->setGeometry(QRect(655, 70, 85, 21));
-    instockEdit->setChecked(true);
+    finstockEdit = new QCheckBox(dialog);
+    finstockEdit->setObjectName(QString::fromUtf8("instockEdit"));
+    finstockEdit->setGeometry(QRect(655, 70, 85, 21));
+    finstockEdit->setChecked(true);
 
-    maxEdit = new QDoubleSpinBox(dialog);
-    maxEdit->setObjectName(QString::fromUtf8("maxEdit"));
-    maxEdit->setGeometry(QRect(550, 130, 121, 24));
-    maxEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
-    maxEdit->setReadOnly(true);
-    maxEdit->setButtonSymbols(QAbstractSpinBox::NoButtons);
-    maxEdit->setDecimals(1);
-    maxEdit->setValue(recipe->fermentables.at(recipe->fermentables_row).f_max_in_batch);
+    fmaxEdit = new QDoubleSpinBox(dialog);
+    fmaxEdit->setObjectName(QString::fromUtf8("fmaxEdit"));
+    fmaxEdit->setGeometry(QRect(550, 130, 121, 24));
+    fmaxEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
+    fmaxEdit->setReadOnly(true);
+    fmaxEdit->setButtonSymbols(QAbstractSpinBox::NoButtons);
+    fmaxEdit->setDecimals(1);
+    fmaxEdit->setValue(recipe->fermentables.at(recipe->fermentables_row).f_max_in_batch);
 
     ferment_instock_changed(true);
 
-    connect(selectEdit, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &EditRecipe::ferment_select_changed);
-    connect(amountEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditRecipe::ferment_amount_changed);
+    connect(fselectEdit, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &EditRecipe::ferment_select_changed);
+    connect(famountEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditRecipe::ferment_amount_changed);
     connect(pctEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditRecipe::ferment_pct_changed);
-    connect(addedEdit, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &EditRecipe::ferment_added_changed);
+    connect(faddedEdit, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &EditRecipe::ferment_added_changed);
     connect(to100Edit, &QCheckBox::stateChanged, this, &EditRecipe::ferment_to100_changed);
-    connect(instockEdit, &QCheckBox::stateChanged, this, &EditRecipe::ferment_instock_changed);
+    connect(finstockEdit, &QCheckBox::stateChanged, this, &EditRecipe::ferment_instock_changed);
     connect(buttonBox, SIGNAL(rejected()), dialog, SLOT(reject()));
     connect(buttonBox, SIGNAL(accepted()), dialog, SLOT(accept()));
 
@@ -2054,12 +2297,181 @@
 	}
     }
 
-    disconnect(selectEdit, nullptr, nullptr, nullptr);
-    disconnect(amountEdit, nullptr, nullptr, nullptr);
+    disconnect(fselectEdit, nullptr, nullptr, nullptr);
+    disconnect(famountEdit, nullptr, nullptr, nullptr);
     disconnect(pctEdit, nullptr, nullptr, nullptr);
-    disconnect(addedEdit, nullptr, nullptr, nullptr);
+    disconnect(faddedEdit, nullptr, nullptr, nullptr);
     disconnect(to100Edit, nullptr, nullptr, nullptr);
-    disconnect(instockEdit, nullptr, nullptr, nullptr);
+    disconnect(finstockEdit, nullptr, nullptr, nullptr);
+    disconnect(buttonBox, nullptr, nullptr, nullptr);
+
+    emit refreshAll();
+}
+
+
+void EditRecipe::on_editHopRow_clicked()
+{
+    QSqlQuery query;
+
+    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);
+    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<int>::of(&QComboBox::currentIndexChanged), this, &EditRecipe::hop_select_changed);
+    connect(hamountEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditRecipe::hop_amount_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(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();
--- a/src/EditRecipe.h	Sat Apr 09 21:50:19 2022 +0200
+++ b/src/EditRecipe.h	Mon Apr 11 16:18:40 2022 +0200
@@ -11,6 +11,7 @@
 #include <QLineEdit>
 #include <QDialogButtonBox>
 #include <QList>
+#include <QLabel>
 
 
 /*
@@ -273,9 +274,17 @@
     void ferment_select_changed(int val);
     void ferment_instock_changed(bool val);
     void ferment_added_changed(int val);
+    void hop_amount_changed(double val);
+    void hop_time_changed(int val);
+    void hop_select_changed(int val);
+    void hop_instock_changed(bool val);
+    void hop_useat_changed(int val);
     void on_addFermentRow_clicked();
     void on_deleteFermentRow_clicked();
     void on_editFermentRow_clicked();
+    void on_addHopRow_clicked();
+    void on_deleteHopRow_clicked();
+    void on_editHopRow_clicked();
 
     void on_perc_mash_valueChanged(int value);
     void on_perc_sugars_valueChanged(int value);
@@ -308,10 +317,12 @@
     /*
      * Variables for popup ingredients editing.
      */
-    QComboBox *selectEdit, *addedEdit;
-    QLineEdit *nameEdit, *supplierEdit;
-    QDoubleSpinBox *amountEdit, *pctEdit, *maxEdit;
-    QCheckBox *to100Edit, *instockEdit;
+    QComboBox *fselectEdit, *faddedEdit, *hselectEdit,*haddedEdit, *useatEdit;
+    QLineEdit *fnameEdit, *fsupplierEdit, *hnameEdit, *horiginEdit;
+    QDoubleSpinBox *famountEdit, *pctEdit, *fmaxEdit, *hamountEdit, *ibuEdit;
+    QSpinBox *htimeEdit;
+    QCheckBox *to100Edit, *finstockEdit, *hinstockEdit;
+    QLabel *htimeLabel;
 
     void to100Fermentables(int row);
     static bool ferment_sort_test(const Fermentables &D1, const Fermentables &D2);

mercurial