src/EditProductTab6.cpp

changeset 195
9887278c4fbe
parent 179
512f492358e3
child 196
f7954f2d4451
--- a/src/EditProductTab6.cpp	Wed May 04 13:49:37 2022 +0200
+++ b/src/EditProductTab6.cpp	Thu May 05 17:20:06 2022 +0200
@@ -89,22 +89,24 @@
         item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
         ui->yeastsTable->setItem(i, 8, item);
 
-	if (product->yeasts.at(i).y_form == 0)
+	if (product->yeasts.at(i).y_form == YEAST_FORMS_LIQUID)
             item = new QTableWidgetItem(QString("%1 pack").arg(product->yeasts.at(i).y_amount, 1, 'f', 0, '0'));
-	else if (product->yeasts.at(i).y_form == 1)
+	else if (product->yeasts.at(i).y_form == YEAST_FORMS_DRY || product->yeasts.at(i).y_form == YEAST_FORMS_DRIED)
 	    item = new QTableWidgetItem(QString("%1 gr").arg(product->yeasts.at(i).y_amount * 1000.0, 3, 'f', 2, '0'));
 	else
 	    item = new QTableWidgetItem(QString("%1 ml").arg(product->yeasts.at(i).y_amount * 1000.0, 3, 'f', 2, '0'));
         item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
         ui->yeastsTable->setItem(i, 9, item);
 
-	if (product->yeasts.at(i).y_form == 0)
+	if (product->yeasts.at(i).y_form == YEAST_FORMS_LIQUID)
             item = new QTableWidgetItem(QString("%1 pack").arg(product->yeasts.at(i).y_inventory, 1, 'f', 0, '0'));
-        else if (product->yeasts.at(i).y_form == 1)
+        else if (product->yeasts.at(i).y_form == YEAST_FORMS_DRY || product->yeasts.at(i).y_form == YEAST_FORMS_DRIED)
             item = new QTableWidgetItem(QString("%1 gr").arg(product->yeasts.at(i).y_inventory * 1000.0, 3, 'f', 2, '0'));
         else
             item = new QTableWidgetItem(QString("%1 ml").arg(product->yeasts.at(i).y_inventory * 1000.0, 3, 'f', 2, '0'));
         item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+	if (product->yeasts.at(i).y_inventory < product->yeasts.at(i).y_amount)
+	    item->setForeground(QBrush(QColor(Qt::red)));
         ui->yeastsTable->setItem(i, 10, item);
 
 	pWidget = new QWidget();
@@ -132,27 +134,62 @@
 }
 
 
+void EditProduct::initYeast()
+{
+    ui->est_og4Edit->setValue(product->est_og);
+    ui->est_fg3Edit->setValue(product->est_fg);
+    ui->est_abv2Edit->setValue(product->est_abv);
+    ui->productionEdit->setText(product->yeast_prod_date.toString("dd MMM yyyy"));
+    ui->conditionShow->setValue(product->starter_viability);
+    ui->startersgEdit->setValue(product->starter_sg);
+    ui->pitchrateEdit->setValue(product->yeast_pitchrate);
+
+    ui->yeastsTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
+
+    for (int i = 0; i < starters.size(); i++) {
+	ui->stmethodEdit->addItem(starters[i]);
+    }
+    ui->stmethodEdit->setCurrentIndex(product->starter_type);
+}
+
+
 /*
- * The results are not stored line in EditProduct. This is just a hint.
+ * Calculate the needed yeast for this batch.
  */
 void EditProduct::calcYeast()
 {
-    double sg = product->est_og;
-    double plato = Utils::sg_to_plato(sg);
-    double volume = product->batch_size * 0.9;	// Volume min trub chiller loss.
+    double sg = product->brew_fermenter_sg;
+    double use_cells;
+    double needed = 0;
+    double initcells = 0;
     bool maybe_starter = false;
-    double pitchrate = 0.75;
-    double initcells = 0;
 
     qDebug() << "calcYeast()";
     ui->yeastProcedure->setCurrentIndex(0);
 
+    if (sg <= 1.0001 && product->fg > 1.000)
+	sg = product->fg;
+    else if (sg <= 1.0001)
+	sg = product->est_og;
+    double plato = Utils::sg_to_plato(sg);
+
+    double volume = product->brew_fermenter_volume;
+    if (volume > 0) {
+	if (product->brew_fermenter_extrawater > 0)
+	    volume += product->brew_fermenter_extrawater;
+    } else {
+	volume = product->batch_size - product->eq_trub_chiller_loss;
+    }
+
+    // Also in calcFermentables()
+   //$('#yeast_cells').val(initcells);
+
     if (product->yeasts.size() == 0)
 	return;		// No yeast in product.
 
     for (int i = 0; i < product->yeasts.size(); i++) {
-	if (product->yeasts.at(i).y_use == 0) {		// Primary
-	    if (product->yeasts.at(i).y_form == 1) {
+	if (product->yeasts.at(i).y_use == YEAST_USE_PRIMARY) {		// Primary
+	    if (product->yeasts.at(i).y_form == YEAST_FORMS_DRY) {
 		/*
 		 * Dry yeast, build the formule with the yeast parameters.
 		 * Based on https://www.lallemandbrewing.com/en/canada/brewers-corner/brewing-tools/pitching-rate-calculator/
@@ -180,39 +217,446 @@
 		 * and http://braukaiser.com/blog/blog/2012/11/03/estimating-yeast-growth/
 		 */
 		ui->yeastProcedure->setCurrentIndex(1);
-		if (product->yeasts.at(i).y_type == 0) {		// Lager yeast
-		    pitchrate = 1.5;
-		    if (sg > 1.060)
-			pitchrate = 2.0;
-		} else if (product->yeasts.at(i).y_type == 6) {	// Real Kveik
-		    pitchrate = 0.075;
-		} else {
-		    pitchrate = 0.75;
-		    if (sg > 1.060)
-			pitchrate = 1.0;
+		if (product->yeast_pitchrate == 0) {
+		    /*
+		     * No pitchrate yet, do a educated guess ..
+		     */
+		    if (product->yeasts.at(i).y_type == YEAST_TYPES_LAGER) {
+		    	product->yeast_pitchrate = 1.5;
+		    	if (sg > 1.060)
+			    product->yeast_pitchrate = 2.0;
+		    } else if (product->yeasts.at(i).y_type == YEAST_TYPES_KVEIK) {	// Real Kveik
+		    	product->yeast_pitchrate = 0.075;
+		    } else {
+		    	product->yeast_pitchrate = 0.75;
+		    	if (sg > 1.060)
+			    product->yeast_pitchrate = 1.0;
+		    }
+		    is_changed();
+		    ui->pitchrateEdit->setValue(product->yeast_pitchrate);
 		}
-		if (product->yeasts.at(i).y_form == 0)
+
+		initcells = (product->yeasts.at(i).y_cells / 1000000) * product->yeasts.at(i).y_amount * 0.97;	// cells / ml.
+		if (product->yeasts.at(i).y_form == YEAST_FORMS_LIQUID)
 		    initcells = (product->yeasts.at(i).y_cells / 1000000000) * product->yeasts.at(i).y_amount * 0.97;	// 97% viability assumed.
-		else
-		    initcells = (product->yeasts.at(i).y_cells / 1000000) * product->yeasts.at(i).y_amount * 0.97;
 
-		double needed = round(pitchrate * volume * plato * 10.0) / 10.0;
-		double starter = 0;
+		needed = round(product->yeast_pitchrate * volume * plato * 10.0) / 10.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;
+		qDebug() << "  pitchrate:" << product->yeast_pitchrate << "needed:" << needed << "initcells:" << initcells << "starter" << maybe_starter;
 	    }
 	    break;
 	}
     }
+
+    if (maybe_starter != product->starter_enable) {
+	product->starter_enable = maybe_starter;
+	qDebug() << "  Set starter enable" << maybe_starter;
+	is_changed();
+    }
+
+    if (product->starter_enable) {
+	qDebug() << "  Starter calculate..";
+
+	const QStringList labels({tr("Method"), tr("Volume"), tr("Inj. factor"), tr("New cells"), tr("Total cells"), tr("Grow factor"), "" });
+	ui->starterTable->show();
+	ui->starterTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
+	ui->starterTable->clear();
+	ui->starterTable->setColumnCount(7);
+	ui->starterTable->setRowCount(0);
+	ui->starterTable->setColumnWidth(0, 130);	/* Method	*/
+	ui->starterTable->setColumnWidth(1,  90);	/* Volume	*/
+	ui->starterTable->setColumnWidth(2,  90);	/* Inj. factor	*/
+	ui->starterTable->setColumnWidth(3,  90);	/* New cells	*/
+	ui->starterTable->setColumnWidth(4,  90);	/* Total cells	*/
+	ui->starterTable->setColumnWidth(5,  90);	/* Grow factor	*/
+	ui->starterTable->setColumnWidth(6,  30);	/* Edit button	*/
+	ui->starterTable->setHorizontalHeaderLabels(labels);
+	calcSteps(product->starter_type, initcells, needed);
+    } else {
+	ui->starterTable->hide();
+    }
+}
+
+
+/*
+ * http://braukaiser.com/blog/blog/2012/11/03/estimating-yeast-growth/
+ *
+ * stype: 0=stirred, 1=shaken, 2=simple
+ * totcells: initial cells
+ * egrams: gram extract
+ */
+double EditProduct::getGrowthRate(int stype, double totcells, double egrams)
+{
+    /* Cells per grams extract (B/g) */
+    double cpe = totcells / egrams;
+
+    if (cpe > 3.5)
+        return 0;       // no growth
+    if (stype == STARTERS_SIMPLE)
+        return 0.4;     // simple starter
+    if (stype == STARTERS_SHAKEN)
+        return 0.62;    // shaken starter
+    if (cpe <= 1.4)     // stirred starter
+        return 1.4;
+    return 2.33 - (.67 * cpe);
+};
+
+
+StepResult EditProduct::calcStep(double svol, int stype, double start)
+{
+    StepResult res;
+    double gperpoint = 2.72715;	//number of grams of extract per point of starter gravity per liter
+    double irate = round(start / svol * 10000.0) / 10.0;
+    double egrams = (product->starter_sg - 1) * svol * gperpoint;
+    double grate = getGrowthRate(stype, start, egrams);
+    double ncells = round(egrams * grate * 10.0) / 10.0;
+    double totcells = ncells + start;
+
+    res.svol = svol;
+    res.irate = irate;
+    res.ncells = ncells;
+    res.totcells = totcells;
+    res.growf = round((ncells / start) * 100.0) / 100.0;
+    qDebug() << "  calcStep(" << svol << "," << stype << "," << start << ") irate" << irate
+	     << "ncells" << res.ncells << "totcells" << res.totcells << "growf" << res.growf;
+    return res;
+}
+
+
+/*
+ * Calculate all starter steps.
+ * stype: final starter type: 0 = stirred, 1 = shaked, 2 = simple.
+ * start: initial cells in billions
+ * needed: needed cells in billions
+ *
+ * result: all values updated.
+ */
+void EditProduct::calcSteps(int stype, double start, double needed)
+{
+    int	i, step, svol;
+    int	lasti = 0;
+    /* Erlenmeyer sizes */
+    const int uvols[] { 20, 40, 60, 80, 100, 150, 200, 250, 375, 500, 625, 750, 875, 1000, 1250, 1500, 2000, 2500, 3000, 4000, 5000 };
+    int mvols = sizeof(uvols);
+    StepResult result;
+    QTableWidgetItem *item;
+    QWidget* pWidget;
+    QHBoxLayout* pLayout;
+    double tcells = start;
+    QIcon iconT;
+
+    iconT.addFile(QString::fromUtf8(":/icons/silk/pencil.png"), QSize(), QIcon::Normal, QIcon::Off);
+
+    if ((product->prop1_volume + product->prop2_volume + product->prop3_volume + product->prop4_volume) == 0) {
+	/*
+	 * Auto calculate the starter.
+	 */
+	qDebug() << "  calcSteps() auto";
+
+	if (start > needed)
+	    return;
+
+	for (step = 1; step < 5; step++) {
+	    qDebug() << "  step" << step;
+
+	    for (i = lasti; i <= mvols; i++) {
+		lasti = i;
+		svol = uvols[lasti];
+		result = calcStep(svol, stype, tcells);
+		if (result.irate < 25) {
+		    // inocculation rate too low, backup one step and break out.
+		    lasti = i - 1;
+		    svol = uvols[lasti];
+		    result = calcStep(svol, stype, tcells);
+		    break;
+		}
+		if (result.totcells > needed || i == mvols) {	// hit the target or loops done
+		    break;
+		}
+	    }
+	    ui->starterTable->setRowCount(step);
+	    item = new QTableWidgetItem(starters[stype]);
+	    item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter);
+	    ui->starterTable->setItem(step -1, 0, item);
+
+	    item = new QTableWidgetItem(QString("%1").arg(result.svol / 1000.0, 4, 'f', 3, '0'));	// To liters
+	    item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+	    ui->starterTable->setItem(step -1, 1, item);
+
+	    item = new QTableWidgetItem(QString("%1").arg(result.irate, 2, 'f', 1, '0'));
+	    item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+            ui->starterTable->setItem(step -1, 2, item);
+
+	    item = new QTableWidgetItem(QString("%1").arg(result.ncells, 2, 'f', 1, '0'));
+            item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+            ui->starterTable->setItem(step -1, 3, item);
+
+	    item = new QTableWidgetItem(QString("%1").arg(result.totcells, 2, 'f', 1, '0'));
+            item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+            ui->starterTable->setItem(step -1, 4, item);
+
+	    item = new QTableWidgetItem(QString("%1").arg(result.growf, 3, 'f', 2, '0'));
+            item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+            ui->starterTable->setItem(step -1, 5, item);
+
+	    pWidget = new QWidget();
+            QToolButton* btn_edit = new QToolButton();
+            btn_edit->setObjectName(QString("%1").arg(step - 1));  /* Send row with the button */
+	    btn_edit->setIcon(iconT);
+            connect(btn_edit, SIGNAL(clicked()), this, SLOT(yeast_starter_edit_clicked()));
+            pLayout = new QHBoxLayout(pWidget);
+            pLayout->addWidget(btn_edit);
+            pLayout->setContentsMargins(5, 0, 5, 0);
+            pWidget->setLayout(pLayout);
+            ui->starterTable->setCellWidget(step -1, 6, pWidget);
+
+	    if (step == 1) {
+		product->prop1_type = product->starter_type;
+		product->prop1_volume = result.svol / 1000.0;
+	    } else if (step == 2) {
+		product->prop2_type = product->starter_type;
+                product->prop2_volume = result.svol / 1000.0;
+	    } else if (step == 3) {
+                product->prop3_type = product->starter_type;
+                product->prop3_volume = result.svol / 1000.0;
+            } else if (step == 4) {
+                product->prop4_type = product->starter_type;
+                product->prop4_volume = result.svol / 1000.0;
+            }
+
+	    tcells = result.totcells;
+	    if (result.totcells > needed)	// Hit the target
+		return;
+	}
+
+    } else {
+	/*
+	 * Recalculate the starter.
+	 */
+	qDebug() << "  calcSteps() recalculate";
+
+	if (product->prop1_volume > 0) {
+	    result = calcStep(product->prop1_volume * 1000, product->prop1_type, tcells);
+	    ui->starterTable->setRowCount(1);
+	    item = new QTableWidgetItem(starters[product->prop1_type]);
+	    item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter);
+	    ui->starterTable->setItem(0, 0, item);
+
+            item = new QTableWidgetItem(QString("%1").arg(result.svol / 1000.0, 4, 'f', 3, '0'));       // To liters
+            item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+            ui->starterTable->setItem(0, 1, item);
+
+            item = new QTableWidgetItem(QString("%1").arg(result.irate, 2, 'f', 1, '0'));
+            item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+            ui->starterTable->setItem(0, 2, item);
+
+            item = new QTableWidgetItem(QString("%1").arg(result.ncells, 2, 'f', 1, '0'));
+            item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+            ui->starterTable->setItem(0, 3, item);
+
+            item = new QTableWidgetItem(QString("%1").arg(result.totcells, 2, 'f', 1, '0'));
+            item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+            ui->starterTable->setItem(0, 4, item);
+
+            item = new QTableWidgetItem(QString("%1").arg(result.growf, 3, 'f', 2, '0'));
+            item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+            ui->starterTable->setItem(0, 5, item);
+
+	    pWidget = new QWidget();
+            QToolButton* btn_edit = new QToolButton();
+            btn_edit->setObjectName(QString("0"));  /* Send row with the button */
+            btn_edit->setIcon(iconT);
+            connect(btn_edit, SIGNAL(clicked()), this, SLOT(yeast_starter_edit_clicked()));
+            pLayout = new QHBoxLayout(pWidget);
+            pLayout->addWidget(btn_edit);
+            pLayout->setContentsMargins(5, 0, 5, 0);
+            pWidget->setLayout(pLayout);
+            ui->starterTable->setCellWidget(0, 6, pWidget);
+
+	    tcells = result.totcells;
+	    if (result.totcells > needed) {	// Hit the target
+		product->prop2_volume = product->prop3_volume = product->prop4_volume = 0;
+		product->prop2_type = product->prop3_type = product->prop4_type = 0;
+                return;
+	    } else if (product->prop2_volume == 0) {	// Extra step needed, start with the same size.
+		product->prop2_volume = product->prop1_volume;
+		product->prop2_type = product->prop1_type;
+	    }
+	}
+	if (product->prop2_volume > 0) {
+            result = calcStep(product->prop2_volume * 1000, product->prop2_type, tcells);
+            ui->starterTable->setRowCount(2);
+	    item = new QTableWidgetItem(starters[product->prop2_type]);
+	    item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter);
+	    ui->starterTable->setItem(1, 0, item);
+
+            item = new QTableWidgetItem(QString("%1").arg(result.svol / 1000.0, 4, 'f', 3, '0'));       // To liters
+            item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+            ui->starterTable->setItem(1, 1, item);
+
+            item = new QTableWidgetItem(QString("%1").arg(result.irate, 2, 'f', 1, '0'));
+            item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+            ui->starterTable->setItem(1, 2, item);
+
+            item = new QTableWidgetItem(QString("%1").arg(result.ncells, 2, 'f', 1, '0'));
+            item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+            ui->starterTable->setItem(1, 3, item);
+
+            item = new QTableWidgetItem(QString("%1").arg(result.totcells, 2, 'f', 1, '0'));
+            item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+            ui->starterTable->setItem(1, 4, item);
+
+            item = new QTableWidgetItem(QString("%1").arg(result.growf, 3, 'f', 2, '0'));
+            item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+            ui->starterTable->setItem(1, 5, item);
+
+	    pWidget = new QWidget();
+            QToolButton* btn_edit = new QToolButton();
+            btn_edit->setObjectName(QString("1"));  /* Send row with the button */
+            btn_edit->setIcon(iconT);
+            connect(btn_edit, SIGNAL(clicked()), this, SLOT(yeast_starter_edit_clicked()));
+            pLayout = new QHBoxLayout(pWidget);
+            pLayout->addWidget(btn_edit);
+            pLayout->setContentsMargins(5, 0, 5, 0);
+            pWidget->setLayout(pLayout);
+            ui->starterTable->setCellWidget(1, 6, pWidget);
+
+            tcells = result.totcells;
+            if (result.totcells > needed) {     // Hit the target
+                product->prop3_volume = product->prop4_volume = 0;
+                product->prop3_type = product->prop4_type = 0;
+                return;
+            } else if (product->prop3_volume == 0) {    // Extra step needed, start with the same size.
+                product->prop3_volume = product->prop2_volume;
+                product->prop3_type = product->prop2_type;
+            }
+        }
+	if (product->prop3_volume > 0) {
+            result = calcStep(product->prop3_volume * 1000, product->prop3_type, tcells);
+            ui->starterTable->setRowCount(3);
+	    item = new QTableWidgetItem(starters[product->prop3_type]);
+	    item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter);
+	    ui->starterTable->setItem(2, 0, item);
+
+            item = new QTableWidgetItem(QString("%1").arg(result.svol / 1000.0, 4, 'f', 3, '0'));       // To liters
+            item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+            ui->starterTable->setItem(2, 1, item);
+
+            item = new QTableWidgetItem(QString("%1").arg(result.irate, 2, 'f', 1, '0'));
+            item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+            ui->starterTable->setItem(2, 2, item);
+
+            item = new QTableWidgetItem(QString("%1").arg(result.ncells, 2, 'f', 1, '0'));
+            item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+            ui->starterTable->setItem(2, 3, item);
+
+            item = new QTableWidgetItem(QString("%1").arg(result.totcells, 2, 'f', 1, '0'));
+            item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+            ui->starterTable->setItem(2, 4, item);
+
+            item = new QTableWidgetItem(QString("%1").arg(result.growf, 3, 'f', 2, '0'));
+            item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+            ui->starterTable->setItem(2, 5, item);
+
+	    pWidget = new QWidget();
+            QToolButton* btn_edit = new QToolButton();
+            btn_edit->setObjectName(QString("2"));  /* Send row with the button */
+            btn_edit->setIcon(iconT);
+            connect(btn_edit, SIGNAL(clicked()), this, SLOT(yeast_starter_edit_clicked()));
+            pLayout = new QHBoxLayout(pWidget);
+            pLayout->addWidget(btn_edit);
+            pLayout->setContentsMargins(5, 0, 5, 0);
+            pWidget->setLayout(pLayout);
+            ui->starterTable->setCellWidget(2, 6, pWidget);
+
+            tcells = result.totcells;
+            if (result.totcells > needed) {     // Hit the target
+                product->prop4_volume = 0;
+                product->prop4_type = 0;
+                return;
+            } else if (product->prop4_volume == 0) {    // Extra step needed, start with the same size.
+                product->prop4_volume = product->prop3_volume;
+                product->prop4_type = product->prop3_type;
+            }
+        }
+	if (product->prop4_volume > 0) {
+            result = calcStep(product->prop4_volume * 1000, product->prop4_type, tcells);
+            ui->starterTable->setRowCount(4);
+	    item = new QTableWidgetItem(starters[product->prop4_type]);
+	    item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter);
+	    ui->starterTable->setItem(3, 0, item);
+
+            item = new QTableWidgetItem(QString("%1").arg(result.svol / 1000.0, 4, 'f', 3, '0'));       // To liters
+            item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+            ui->starterTable->setItem(3, 1, item);
+
+            item = new QTableWidgetItem(QString("%1").arg(result.irate, 2, 'f', 1, '0'));
+            item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+            ui->starterTable->setItem(3, 2, item);
+
+            item = new QTableWidgetItem(QString("%1").arg(result.ncells, 2, 'f', 1, '0'));
+            item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+            ui->starterTable->setItem(3, 3, item);
+
+            item = new QTableWidgetItem(QString("%1").arg(result.totcells, 2, 'f', 1, '0'));
+            item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+            ui->starterTable->setItem(3, 4, item);
+
+            item = new QTableWidgetItem(QString("%1").arg(result.growf, 3, 'f', 2, '0'));
+            item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+            ui->starterTable->setItem(3, 5, item);
+
+	    pWidget = new QWidget();
+            QToolButton* btn_edit = new QToolButton();
+            btn_edit->setObjectName(QString("3"));  /* Send row with the button */
+            btn_edit->setIcon(iconT);
+            connect(btn_edit, SIGNAL(clicked()), this, SLOT(yeast_starter_edit_clicked()));
+            pLayout = new QHBoxLayout(pWidget);
+            pLayout->addWidget(btn_edit);
+            pLayout->setContentsMargins(5, 0, 5, 0);
+            pWidget->setLayout(pLayout);
+            ui->starterTable->setCellWidget(3, 6, pWidget);
+        }
+    }
+}
+
+
+void EditProduct::yeast_prod_date_clicked()
+{
+}
+
+
+void EditProduct::yeast_method_changed(int val)
+{
+    qDebug() << "yeast_method_changed" << val;
+    product->starter_type = val;
+    calcYeast();
+    is_changed();
+}
+
+
+void EditProduct::yeast_starter_sg_changed(double val)
+{
+    qDebug() << "yeast_starter_sg_changed" << val;
+    product->starter_sg = val;
+    calcYeast();
+    is_changed();
+}
+
+
+void EditProduct::yeast_pitchrate_button_clicked()
+{
+}
+
+
+void EditProduct::yeast_starter_edit_clicked()
+{
+    QToolButton *pb = qobject_cast<QToolButton *>(QObject::sender());
+    int row = pb->objectName().toInt();
+    qDebug() << "yeast_starter_edit_clicked" << row;
 }
 
 
@@ -594,7 +1038,7 @@
 	return;
 
     for (int i = 0; i < product->yeasts.size(); i++) {
-	if (product->yeasts.at(i).y_form == 1) { // Only adjust dry yeast
+	if (product->yeasts.at(i).y_form == YEAST_FORMS_DRY) { // Only adjust dry yeast
 	    amount = product->yeasts.at(i).y_amount * factor;
 	    product->yeasts[i].y_amount = amount;
 	}

mercurial