src/EditRecipeTab5.cpp

Mon, 18 Jul 2022 17:04:02 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Mon, 18 Jul 2022 17:04:02 +0200
changeset 359
dfbb012c631c
parent 301
fe6346211b5b
child 395
7212b980a527
permissions
-rw-r--r--

Redesign of the water tabs in product and recipe editors. Prepare for sparge water salt additions. Acid additions are now automatic or manual for mash and sparge. Fixed error in acid calculation strength. Fixed phophoric SG value.

/**
 * EditRecipe.cpp is part of bmsapp.
 *
 * tab 5, yeasts.
 *
 * 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 yeaste 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::yeast_sort_test(const Yeasts &D1, const Yeasts &D2)
{
    if (D1.use > D2.use)
	return false;
    if (D1.use < D2.use)
	return true;
    return (D1.amount > D2.amount);
}


void EditRecipe::refreshYeasts()
{
    QString w;
    QWidget* pWidget;
    QHBoxLayout* pLayout;
    QTableWidgetItem *item;

    qDebug() << "refreshYeasts" << recipe->yeasts.size();
    std::sort(recipe->yeasts.begin(), recipe->yeasts.end(), yeast_sort_test);

    const QStringList labels({tr("Yeast"), tr("Laboratory"), tr("Code"), tr("Type"), tr("Use for"), tr("Min. °C"), tr("Max. °C"),
		              tr("Tol. %"), tr("Attn. %"), tr("Amount"), tr("Delete"), tr("Edit") });

    ui->yeastsTable->setColumnCount(12);
    ui->yeastsTable->setColumnWidth(0, 200);	/* Yeast	*/
    ui->yeastsTable->setColumnWidth(1, 125);	/* Laboratory	*/
    ui->yeastsTable->setColumnWidth(2,  80);	/* Code		*/
    ui->yeastsTable->setColumnWidth(3,  80);	/* Type		*/
    ui->yeastsTable->setColumnWidth(4, 100);	/* Usage	*/
    ui->yeastsTable->setColumnWidth(5,  60);	/* Min. 	*/
    ui->yeastsTable->setColumnWidth(6,  60);	/* Max.		*/
    ui->yeastsTable->setColumnWidth(7,  60);	/* Tolerance	*/
    ui->yeastsTable->setColumnWidth(8,  60);	/* Attenuation	*/
    ui->yeastsTable->setColumnWidth(9,  90);	/* Amount	*/
    ui->yeastsTable->setColumnWidth(10, 80);	/* Delete	*/
    ui->yeastsTable->setColumnWidth(11, 80);	/* Edit		*/
    ui->yeastsTable->setHorizontalHeaderLabels(labels);
    ui->yeastsTable->verticalHeader()->hide();
    ui->yeastsTable->setRowCount(recipe->yeasts.size());

    for (int i = 0; i < recipe->yeasts.size(); i++) {

	ui->yeastsTable->setItem(i, 0, new QTableWidgetItem(recipe->yeasts.at(i).name));
	ui->yeastsTable->setItem(i, 1, new QTableWidgetItem(recipe->yeasts.at(i).laboratory));
	ui->yeastsTable->setItem(i, 2, new QTableWidgetItem(recipe->yeasts.at(i).product_id));

	item = new QTableWidgetItem(QCoreApplication::translate("YeastForm", g_yeast_forms[recipe->yeasts.at(i).form]));
        item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter);
        ui->yeastsTable->setItem(i, 3, item);

        item = new QTableWidgetItem(QCoreApplication::translate("YeastUse", g_yeast_use[recipe->yeasts.at(i).use]));
        item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter);
        ui->yeastsTable->setItem(i, 4, item);

	item = new QTableWidgetItem(QString("%1").arg(recipe->yeasts.at(i).min_temperature, 2, 'f', 1, '0'));
	item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
        ui->yeastsTable->setItem(i, 5, item);

	item = new QTableWidgetItem(QString("%1").arg(recipe->yeasts.at(i).max_temperature, 2, 'f', 1, '0'));
        item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
        ui->yeastsTable->setItem(i, 6, item);

	item = new QTableWidgetItem(QString("%1").arg(recipe->yeasts.at(i).tolerance, 2, 'f', 1, '0'));
        item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
        ui->yeastsTable->setItem(i, 7, item);

	item = new QTableWidgetItem(QString("%1").arg(recipe->yeasts.at(i).attenuation, 2, 'f', 1, '0'));
        item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
        ui->yeastsTable->setItem(i, 8, item);

	if (recipe->yeasts.at(i).form == 0)
            item = new QTableWidgetItem(QString("%1 pack").arg(recipe->yeasts.at(i).amount, 1, 'f', 0, '0'));
	else if (recipe->yeasts.at(i).form == 1)
	    item = new QTableWidgetItem(QString("%1 gr").arg(recipe->yeasts.at(i).amount * 1000.0, 3, 'f', 2, '0'));
	else
	    item = new QTableWidgetItem(QString("%1 ml").arg(recipe->yeasts.at(i).amount * 1000.0, 3, 'f', 2, '0'));
        item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
        ui->yeastsTable->setItem(i, 9, item);

	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(deleteYeastRow_clicked()));
        pLayout = new QHBoxLayout(pWidget);
        pLayout->addWidget(btn_dele);
        pLayout->setContentsMargins(5, 0, 5, 0);
        pWidget->setLayout(pLayout);
        ui->yeastsTable->setCellWidget(i, 10, 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(editYeastRow_clicked()));
        pLayout = new QHBoxLayout(pWidget);
        pLayout->addWidget(btn_edit);
        pLayout->setContentsMargins(5, 0, 5, 0);
        pWidget->setLayout(pLayout);
        ui->yeastsTable->setCellWidget(i, 11, pWidget);
    }
}


/*
 * The results are not stored line in EditProduct. This is just a hint.
 */
void EditRecipe::calcYeast()
{
    double sg = recipe->est_og;
    double plato = Utils::sg_to_plato(sg);
    double volume = recipe->batch_size * 0.9;	// Volume min trub chiller loss.
    bool maybe_starter = false;
    double pitchrate = 0.75;
    double initcells = 0;

    qDebug() << "calcYeast()";
    ui->yeastProcedure->setCurrentIndex(0);

    if (recipe->yeasts.size() == 0)
	return;		// No yeast in recipe.

    for (int i = 0; i < recipe->yeasts.size(); i++) {
	if (recipe->yeasts.at(i).use == 0) {		// Primary
	    if (recipe->yeasts.at(i).form == 1) {
		/*
		 * Dry yeast, build the formule with the yeast parameters.
		 * Based on https://www.lallemandbrewing.com/en/canada/brewers-corner/brewing-tools/pitching-rate-calculator/
		 */
		ui->yeastProcedure->setCurrentIndex(2);
		ui->lo_gr_hlEdit->setValue(recipe->yeasts.at(i).gr_hl_lo);
		ui->hi_gr_hlEdit->setValue(recipe->yeasts.at(i).gr_hl_hi);
		ui->lo_sgEdit->setValue(recipe->yeasts.at(i).sg_lo);
		ui->hi_sgEdit->setValue(recipe->yeasts.at(i).sg_hi);
		double og = recipe->yeasts.at(i).sg_lo;
		double f1 = recipe->yeasts.at(i).gr_hl_lo / 100.0;
		double f2 = round(f1 / 5 * 1000000.0) / 1000000.0;
     		double multiplier = (sg <= og) ? f1 : (f1 + f2 * (sg - og) / 0.008);
		qDebug() << "  sg:" << sg << "og:" << og << "f1:" << f1 << "f2:" << f2 << "multiplier:" << multiplier;
     		double yeast_grams = round(volume * multiplier * 100.0) / 100.0; // * (100 / dataRecord.starter_viability), 2);
     		double yeast_gr_hl = round((yeast_grams / (volume * 0.01)) * 100.0) / 100.0;
		ui->need_grEdit->setValue(yeast_grams);
		ui->pitch_grEdit->setValue(yeast_gr_hl);
     		qDebug() << "  need" << yeast_grams << "grams, gr/hl:" << yeast_gr_hl;
		return;
	    } else {
		/*
		 * Liquid, slant, culture etc.
		 * pitchrate see https://www.brewersfriend.com/yeast-pitch-rate-and-starter-calculator/
		 * and http://braukaiser.com/blog/blog/2012/11/03/estimating-yeast-growth/
		 */
		ui->yeastProcedure->setCurrentIndex(1);
		if (recipe->yeasts.at(i).type == 0) {		// Lager yeast
		    pitchrate = 1.5;
		    if (sg > 1.060)
			pitchrate = 2.0;
		} else if (recipe->yeasts.at(i).type == 6) {	// Real Kveik
		    pitchrate = 0.075;
		} else {
		    pitchrate = 0.75;
		    if (sg > 1.060)
			pitchrate = 1.0;
		}
		if (recipe->yeasts.at(i).form == 0)
		    initcells = (recipe->yeasts.at(i).cells / 1000000000) * recipe->yeasts.at(i).amount * 0.97;	// 97% viability assumed.
		else
		    initcells = (recipe->yeasts.at(i).cells / 1000000) * recipe->yeasts.at(i).amount * 0.97;

		double needed = round(pitchrate * volume * plato * 10.0) / 10.0;
		double starter = 0;
		if (needed > initcells) {
		    maybe_starter = true;
		    starter = round(needed / 2.0) / 100.0;	// A very rough starter size estimate.
		}

		ui->pitchrateEdit->setValue(pitchrate);
		ui->initcellsEdit->setValue(initcells);
		ui->targetcellsEdit->setValue(needed);
		ui->starterEdit->setValue(starter);

		qDebug() << "  pitchrate:" << pitchrate << "needed:" << needed << "initcells:" << initcells << "starter" << maybe_starter << "size" << starter;
	    }
	    break;
	}
    }
}


void EditRecipe::addYeastRow_clicked()
{
    Yeasts newy;

    qDebug() << "Add yeast row";

    for (int i = 0; i < recipe->yeasts.size(); i++) {
        if (recipe->yeasts.at(i).amount == 0)
            return;     // Add only one at a time.
    }

    newy.name = "Select one";
    newy.laboratory = "";
    newy.product_id = "";
    newy.amount = 0;
    newy.type = 0;
    newy.form = 0;
    newy.min_temperature = 0;
    newy.max_temperature = 0;
    newy.flocculation = 0;
    newy.attenuation = 0;
    newy.cells = 0;
    newy.tolerance = 0;
    newy.inventory = 0;
    newy.use = 0;
    newy.sta1 = false;
    newy.bacteria = false;
    newy.harvest_top = false;
    newy.harvest_time = 0;
    newy.pitch_temperature = 0;
    newy.pofpos = false;
    newy.zymocide = 0;
    newy.gr_hl_lo = 0;
    newy.sg_lo = 0;
    newy.gr_hl_hi = 0;
    newy.sg_hi = 0;
    newy.cost = 0;

    recipe->yeasts.append(newy);
    emit refreshAll();
}


void EditRecipe::deleteYeastRow_clicked()
{
    if (recipe->locked || recipe->yeasts.size() < 1)
	return;

    QPushButton *pb = qobject_cast<QPushButton *>(QObject::sender());
    int row = pb->objectName().toInt();
    qDebug() << "Delete yeast row" << row << recipe->yeasts.size();

    int rc = QMessageBox::warning(this, tr("Delete yeast"), tr("Delete %1").arg(recipe->yeasts.at(row).name),
                    QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
    if (rc == QMessageBox::No)
        return;

    recipe->yeasts.removeAt(row);
    is_changed();
    emit refreshAll();
}


void EditRecipe::yeast_amount_changed(double val)
{
    QTableWidgetItem *item;

    qDebug() << "yeast_amount_changed()" << recipe->yeasts_row << val;

    if (recipe->yeasts.at(recipe->yeasts_row).form == 0) {
	recipe->yeasts[recipe->yeasts_row].amount = val;
        item = new QTableWidgetItem(QString("%1 pack").arg(val, 1, 'f', 0, '0'));
    } else if (recipe->yeasts.at(recipe->yeasts_row).form == 1) {
	recipe->yeasts[recipe->yeasts_row].amount = val / 1000.0;
        item = new QTableWidgetItem(QString("%1 gr").arg(val, 3, 'f', 2, '0'));
    } else {
        recipe->yeasts[recipe->yeasts_row].amount = val / 1000.0;
        item = new QTableWidgetItem(QString("%1 ml").arg(val, 3, 'f', 2, '0'));
    }
    item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
    ui->yeastsTable->setItem(recipe->yeasts_row, 9, item);

    calcYeast();
    is_changed();
}


void EditRecipe::yeast_select_changed(int val)
{
    QSqlQuery query;
    bool instock = yinstockEdit->isChecked();
    QString w;
    QTableWidgetItem *item;

    if (val < 1)
        return;

    qDebug() << "yeast_select_changed()" << recipe->yeasts_row << val << instock;

    /*
     * Search the yeast pointed by the index and instock flag.
     */
    QString sql = "SELECT name,laboratory,product_id,type,form,min_temperature,max_temperature,flocculation,attenuation,"
	          "cells,tolerance,sta1,bacteria,harvest_top,harvest_time,pitch_temperature,pofpos,zymocide,"
		  "gr_hl_lo,sg_lo,gr_hl_hi,sg_hi,cost FROM inventory_yeasts ";
    if (instock)
        sql.append("WHERE inventory > 0 ");
    sql.append("ORDER BY laboratory,product_id,name");
    query.prepare(sql);
    query.exec();
    query.first();
    for (int i = 0; i < (val - 1); i++) {
        query.next();
    }
    qDebug() << "found" << query.value(0).toString() << query.value(2).toString();

    /*
     * Replace the yeast record contents
     */
    recipe->yeasts[recipe->yeasts_row].name = query.value(0).toString();
    recipe->yeasts[recipe->yeasts_row].laboratory = query.value(1).toString();
    recipe->yeasts[recipe->yeasts_row].product_id = query.value(2).toString();
    recipe->yeasts[recipe->yeasts_row].type = query.value(3).toInt();
    recipe->yeasts[recipe->yeasts_row].form = query.value(4).toInt();
    recipe->yeasts[recipe->yeasts_row].min_temperature = query.value(5).toDouble();
    recipe->yeasts[recipe->yeasts_row].max_temperature = query.value(6).toDouble();
    recipe->yeasts[recipe->yeasts_row].flocculation = query.value(7).toInt();
    recipe->yeasts[recipe->yeasts_row].attenuation = query.value(8).toDouble();
    recipe->yeasts[recipe->yeasts_row].cells = query.value(9).toDouble();
    recipe->yeasts[recipe->yeasts_row].tolerance = query.value(10).toDouble();
    recipe->yeasts[recipe->yeasts_row].sta1 = query.value(11).toInt() ? true:false;
    recipe->yeasts[recipe->yeasts_row].bacteria = query.value(12).toInt() ? true:false;
    recipe->yeasts[recipe->yeasts_row].harvest_top = query.value(13).toInt() ? true:false;
    recipe->yeasts[recipe->yeasts_row].harvest_time = query.value(14).toInt();
    recipe->yeasts[recipe->yeasts_row].pitch_temperature = query.value(15).toDouble();
    recipe->yeasts[recipe->yeasts_row].pofpos = query.value(16).toInt() ? true:false;
    recipe->yeasts[recipe->yeasts_row].zymocide = query.value(17).toInt();
    recipe->yeasts[recipe->yeasts_row].gr_hl_lo = query.value(18).toInt();
    recipe->yeasts[recipe->yeasts_row].sg_lo = query.value(19).toDouble();
    recipe->yeasts[recipe->yeasts_row].gr_hl_hi = query.value(20).toInt();
    recipe->yeasts[recipe->yeasts_row].sg_hi = query.value(21).toDouble();
    recipe->yeasts[recipe->yeasts_row].cost = query.value(22).toDouble();

    /*
     * Update the visible fields
     */
    ynameEdit->setText(recipe->yeasts.at(recipe->yeasts_row).name);
    ylaboratoryEdit->setText(recipe->yeasts.at(recipe->yeasts_row).laboratory);
    yproduct_idEdit->setText(recipe->yeasts.at(recipe->yeasts_row).product_id);
    if (recipe->yeasts.at(recipe->yeasts_row).form == 0) {
	yamountEdit->setDecimals(0);
	yamountEdit->setSingleStep(1.0);
	yamountLabel->setText(tr("Total packs:"));
    } else if (recipe->yeasts.at(recipe->yeasts_row).form == 1) {
	yamountEdit->setDecimals(1);
    	yamountEdit->setSingleStep(0.5);
	yamountLabel->setText(tr("Amount in gr:"));
    } else {
	yamountEdit->setDecimals(1);
	yamountEdit->setSingleStep(0.5);
	yamountLabel->setText(tr("Amount in ml:"));
    }

    ui->yeastsTable->setItem(recipe->yeasts_row, 0, new QTableWidgetItem(recipe->yeasts.at(recipe->yeasts_row).name));
    ui->yeastsTable->setItem(recipe->yeasts_row, 1, new QTableWidgetItem(recipe->yeasts.at(recipe->yeasts_row).laboratory));
    ui->yeastsTable->setItem(recipe->yeasts_row, 2, new QTableWidgetItem(recipe->yeasts.at(recipe->yeasts_row).product_id));

    item = new QTableWidgetItem(QCoreApplication::translate("YeastForm", g_yeast_forms[recipe->yeasts.at(recipe->yeasts_row).form]));
    item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter);
    ui->yeastsTable->setItem(recipe->yeasts_row, 3, item);

    item = new QTableWidgetItem(QString("%1").arg(recipe->yeasts.at(recipe->yeasts_row).min_temperature, 2, 'f', 1, '0'));
    item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
    ui->yeastsTable->setItem(recipe->yeasts_row, 5, item);

    item = new QTableWidgetItem(QString("%1").arg(recipe->yeasts.at(recipe->yeasts_row).max_temperature, 2, 'f', 1, '0'));
    item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
    ui->yeastsTable->setItem(recipe->yeasts_row, 6, item);

    item = new QTableWidgetItem(QString("%1").arg(recipe->yeasts.at(recipe->yeasts_row).tolerance, 2, 'f', 1, '0'));
    item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
    ui->yeastsTable->setItem(recipe->yeasts_row, 7, item);

    item = new QTableWidgetItem(QString("%1").arg(recipe->yeasts.at(recipe->yeasts_row).attenuation, 2, 'f', 1, '0'));
    item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
    ui->yeastsTable->setItem(recipe->yeasts_row, 8, item);

    calcYeast();
    is_changed();
}


void EditRecipe::yeast_instock_changed(bool val)
{
    QSqlQuery query;

    qDebug() << "yeast_instock_changed()" << recipe->yeasts_row << val;

    this->yselectEdit->setCurrentIndex(-1);
    this->yselectEdit->clear();
    QString sql = "SELECT name,laboratory,product_id,inventory FROM inventory_yeasts ";
    if (val)
        sql.append("WHERE inventory > 0 ");
    sql.append("ORDER BY laboratory,product_id,name");
    query.prepare(sql);
    query.exec();
    query.first();
    this->yselectEdit->addItem("");      // Start with empty value
    for (int i = 0; i < query.size(); i++) {
        this->yselectEdit->addItem(query.value(1).toString()+" - "+query.value(2).toString()+" "+query.value(0).toString() + 
                        QString(" (%1 gr)").arg(query.value(3).toDouble() * 1000.0, 2, 'f', 1, '0'));
        query.next();
    }
}


void EditRecipe::yeast_useat_changed(int val)
{
    qDebug() << "yeast_useat_changed()" << recipe->yeasts_row << val;

    recipe->yeasts[recipe->yeasts_row].use = val;
    QTableWidgetItem *item = new QTableWidgetItem(QCoreApplication::translate("YeastUse", g_yeast_use[val]));
    item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter);
    ui->yeastsTable->setItem(recipe->yeasts_row, 5, item);
    is_changed();
    emit refreshAll();
}


void EditRecipe::editYeastRow_clicked()
{
    QSqlQuery query;

    if (recipe->locked)
	return;

    QPushButton *pb = qobject_cast<QPushButton *>(QObject::sender());
    recipe->yeasts_row = pb->objectName().toInt();
    qDebug() << "Edit yeast row" << recipe->yeasts_row;
    Yeasts backup = recipe->yeasts.at(recipe->yeasts_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("Yeast name:"));
    nameLabel->setGeometry(QRect(10, 10, 141, 20));
    nameLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
    QLabel *laboratoryLabel = new QLabel(dialog);
    laboratoryLabel->setObjectName(QString::fromUtf8("laboratoryLabel"));
    laboratoryLabel->setText(tr("Laboratory:"));
    laboratoryLabel->setGeometry(QRect(10, 40, 141, 20));
    laboratoryLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
    QLabel *product_idLabel = new QLabel(dialog);
    product_idLabel->setObjectName(QString::fromUtf8("product_idLabel"));
    product_idLabel->setText(tr("Laboratory:"));
    product_idLabel->setGeometry(QRect(10, 70, 141, 20));
    product_idLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
    QLabel *selectLabel = new QLabel(dialog);
    selectLabel->setObjectName(QString::fromUtf8("selectLabel"));
    selectLabel->setText(tr("Select yeast:"));
    selectLabel->setGeometry(QRect(10,100, 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,100, 121, 20));
    instockLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
    yamountLabel = new QLabel(dialog);
    yamountLabel->setObjectName(QString::fromUtf8("amountLabel"));
    if (recipe->yeasts.at(recipe->yeasts_row).form == 0)
	yamountLabel->setText(tr("Total packs:"));
    else if (recipe->yeasts.at(recipe->yeasts_row).form == 1)
	yamountLabel->setText(tr("Amount in gr:"));
    else
	yamountLabel->setText(tr("Amount in ml:"));
    yamountLabel->setGeometry(QRect(10, 130, 141, 20));
    yamountLabel->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);

    ynameEdit = new QLineEdit(dialog);
    ynameEdit->setObjectName(QString::fromUtf8("ynameEdit"));
    ynameEdit->setText(recipe->yeasts.at(recipe->yeasts_row).name);
    ynameEdit->setGeometry(QRect(160, 10, 511, 23));
    ynameEdit->setReadOnly(true);
    ylaboratoryEdit = new QLineEdit(dialog);
    ylaboratoryEdit->setObjectName(QString::fromUtf8("ylaboratoryEdit"));
    ylaboratoryEdit->setText(recipe->yeasts.at(recipe->yeasts_row).laboratory);
    ylaboratoryEdit->setGeometry(QRect(160, 40, 511, 23));
    ylaboratoryEdit->setReadOnly(true);
    yproduct_idEdit = new QLineEdit(dialog);
    yproduct_idEdit->setObjectName(QString::fromUtf8("yproduct_idEdit"));
    yproduct_idEdit->setText(recipe->yeasts.at(recipe->yeasts_row).product_id);
    yproduct_idEdit->setGeometry(QRect(160, 70, 511, 23));
    yproduct_idEdit->setReadOnly(true);
    yselectEdit = new QComboBox(dialog);
    yselectEdit->setObjectName(QString::fromUtf8("selectEdit"));
    yselectEdit->setGeometry(QRect(160,100, 371, 23));
    yinstockEdit = new QCheckBox(dialog);
    yinstockEdit->setObjectName(QString::fromUtf8("yinstockEdit"));
    yinstockEdit->setGeometry(QRect(655,100, 85, 21));
    yinstockEdit->setChecked(true);
    yamountEdit = new QDoubleSpinBox(dialog);
    yamountEdit->setObjectName(QString::fromUtf8("yamountEdit"));
    yamountEdit->setGeometry(QRect(160, 130, 121, 24));
    yamountEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
    yamountEdit->setAccelerated(true);
    if (recipe->yeasts.at(recipe->yeasts_row).form == 0) {
	yamountEdit->setDecimals(0);
        yamountEdit->setSingleStep(1.0);
	yamountEdit->setValue(recipe->yeasts.at(recipe->yeasts_row).amount);
    } else if (recipe->yeasts.at(recipe->yeasts_row).form == 1) {
    	yamountEdit->setDecimals(1);
    	yamountEdit->setSingleStep(0.5);
	yamountEdit->setValue(recipe->yeasts.at(recipe->yeasts_row).amount * 1000.0);
    } else {
	yamountEdit->setDecimals(1);
        yamountEdit->setSingleStep(0.5);
	yamountEdit->setValue(recipe->yeasts.at(recipe->yeasts_row).amount * 1000.0);
    }
    yamountEdit->setMaximum(1000000000.0);
    useatEdit = new QComboBox(dialog);
    useatEdit->setObjectName(QString::fromUtf8("useatEdit"));
    useatEdit->setGeometry(QRect(160, 160, 161, 23));
    useatEdit->addItem(tr("Primary"));
    useatEdit->addItem(tr("Secondary"));
    useatEdit->addItem(tr("Tertiary"));
    useatEdit->addItem(tr("Bottle"));
    useatEdit->setCurrentIndex(recipe->yeasts.at(recipe->yeasts_row).use);

    yeast_instock_changed(true);

    connect(yselectEdit, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &EditRecipe::yeast_select_changed);
    connect(yamountEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditRecipe::yeast_amount_changed);
    connect(useatEdit, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &EditRecipe::yeast_useat_changed);
    connect(yinstockEdit, &QCheckBox::stateChanged, this, &EditRecipe::yeast_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->yeasts[recipe->yeasts_row] = backup;
    } else {

    }

    disconnect(yselectEdit, nullptr, nullptr, nullptr);
    disconnect(yamountEdit, nullptr, nullptr, nullptr);
    disconnect(useatEdit, nullptr, nullptr, nullptr);
    disconnect(yinstockEdit, nullptr, nullptr, nullptr);
    disconnect(buttonBox, nullptr, nullptr, nullptr);

    emit refreshAll();
}


void EditRecipe::adjustYeasts(double factor)
{
    double amount;

    if (recipe->yeasts.size() == 0)
	return;

    for (int i = 0; i < recipe->yeasts.size(); i++) {
	if (recipe->yeasts.at(i).form == 1) { // Only adjust dry yeast
	    amount = recipe->yeasts.at(i).amount * factor;
	    recipe->yeasts[i].amount = amount;
	}
    }
}

mercurial