Fermentables are loaded in the main recipe record in a QList. The refresh table function does the sorting, on added moment (mash first), amount and finally color of the malt. Removed the old hidden table columns. Do all manipulation on the recipe record with QList arrays. The ferment_amount_changed() slot is complete. The whole recipe editor is going in the right direction.

Wed, 06 Apr 2022 20:26:47 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Wed, 06 Apr 2022 20:26:47 +0200
changeset 110
224be4d9f8eb
parent 109
1ce50e72a6b1
child 111
04f5a7c5a1dc

Fermentables are loaded in the main recipe record in a QList. The refresh table function does the sorting, on added moment (mash first), amount and finally color of the malt. Removed the old hidden table columns. Do all manipulation on the recipe record with QList arrays. The ferment_amount_changed() slot is complete. The whole recipe editor is going in the right direction.

src/EditRecipe.cpp file | annotate | diff | comparison | revisions
src/EditRecipe.h file | annotate | diff | comparison | revisions
--- a/src/EditRecipe.cpp	Wed Apr 06 12:10:33 2022 +0200
+++ b/src/EditRecipe.cpp	Wed Apr 06 20:26:47 2022 +0200
@@ -20,6 +20,7 @@
 #include "Utils.h"
 
 
+
 EditRecipe::EditRecipe(int id, QWidget *parent) : QDialog(parent), ui(new Ui::EditRecipe)
 {
     QSqlQuery query;
@@ -27,7 +28,6 @@
     qDebug() << "EditRecipe record:" << id;
     recipe = new Recipe;
     ui->setupUi(this);
-    recipe->fermentables_records = recipe->hops_records = recipe->misc_records = recipe->yeasts_records = recipe->mashs_records = 0;
     recipe->fermentables_current = recipe->hops_current = recipe->misc_current = recipe->yeasts_current = recipe->mashs_current = -1;
     recipe->fermentables_use100 = false;
     this->recno = id;
@@ -154,9 +154,41 @@
         const auto& f_json = query.value(84).toString();
 	if (!f_json.trimmed().isEmpty()) {
             const auto& formattedJson = QString("%1").arg(f_json);
-            this->fermentables = QJsonDocument::fromJson(formattedJson.toUtf8(),  &parseError);
-            if (parseError.error != QJsonParseError::NoError)
+            QJsonDocument fermentables = QJsonDocument::fromJson(formattedJson.toUtf8(),  &parseError);
+            if (parseError.error != QJsonParseError::NoError) {
                 qDebug() << "Parse error: " << parseError.errorString() << "at" << parseError.offset ;
+	    } else if (fermentables.isArray()) {
+		for (int i = 0; i < fermentables.array().size(); i++) {
+		    QJsonObject obj = fermentables.array().at(i).toObject();
+		    Fermentables f;
+		    f.f_name = obj["f_name"].toString();
+		    f.f_origin = obj["f_origin"].toString();
+		    f.f_supplier = obj["f_supplier"].toString();
+		    f.f_amount = obj["f_amount"].toDouble();
+		    f.f_cost = obj["f_cost"].toDouble();
+		    f.f_type = obj["f_type"].toInt();
+		    f.f_yield = obj["f_yield"].toDouble();
+		    f.f_color = obj["f_color"].toDouble();
+		    f.f_coarse_fine_diff = obj["f_coarse_fine_diff"].toDouble();
+		    f.f_moisture = obj["f_moisture"].toDouble();
+		    f.f_diastatic_power = obj["f_diastatic_power"].toDouble();
+		    f.f_protein = obj["f_protein"].toDouble();
+		    f.f_dissolved_protein = obj["f_dissolved_protein"].toDouble();
+		    f.f_max_in_batch = obj["f_max_in_batch"].toDouble();
+		    f.f_graintype = obj["f_graintype"].toInt();
+		    f.f_added = obj["f_added"].toInt();
+		    f.f_recommend_mash = obj["f_recommend_mash"].toInt() ? true:false;
+		    f.f_add_after_boil = obj["f_add_after_boil"].toInt() ? true:false;
+		    f.f_adjust_to_total_100 = obj["f_adjust_to_total_100"].toInt() ? true:false;
+		    f.f_percentage = obj["f_percentage"].toDouble();
+		    f.f_di_ph = obj["f_di_ph"].toDouble();
+		    f.f_acid_to_ph_57 = obj["f_acid_to_ph_57"].toDouble();
+		    if (f.f_adjust_to_total_100)
+			recipe->fermentables_use100 = true;
+		    recipe->fermentables.append(f);
+		}
+		qDebug() << "fermentables" << recipe->fermentables.size();
+	    }
         } else {
 	    qDebug() << "empty fermentables";
 	}
@@ -195,14 +227,12 @@
         if (!ma_json.trimmed().isEmpty()) {
             const auto& formattedJson = QString("%1").arg(ma_json);
             QJsonDocument mashs = QJsonDocument::fromJson(formattedJson.toUtf8(),  &parseError);
-            if (parseError.error != QJsonParseError::NoError)
+            if (parseError.error != QJsonParseError::NoError) {
                 qDebug() << "Parse error: " << parseError.errorString() << "at" << parseError.offset ;
-
-	    if (mashs.isArray()) {
+	    } else if (mashs.isArray()) {
         	for (int i = 0; i < mashs.array().size(); i++) {
             	    QJsonObject obj = mashs.array().at(i).toObject();
-
-		    qDebug() << i << obj;
+//		    qDebug() << i << obj;
 		    Mashs m;
 		    m.step_name = obj["step_name"].toString();
 		    m.step_type = obj["step_type"].toInt();
@@ -220,13 +250,7 @@
         } else {
             qDebug() << "empty mashs";
         }
-	recipe->mashs_records = recipe->mashs.size();
-
-//	qDebug() << query.value(88).toString();
-//	if (recipe->mashs.size()) {
-	    qDebug() << recipe->mashs.size();
-//	}
-	//qDebug() << recipe->mashs;
+	qDebug() << "mashs" << recipe->mashs.size();
 
     } else {
 	/* Set some defaults */
@@ -298,7 +322,6 @@
 	recipe->wa_base_name = 0;
 
 	const auto& formattedJson = QString("[]");
-	this->fermentables = QJsonDocument::fromJson(formattedJson.toUtf8());
 	this->hops = QJsonDocument::fromJson(formattedJson.toUtf8());
 	this->miscs = QJsonDocument::fromJson(formattedJson.toUtf8());
 	this->yeasts = QJsonDocument::fromJson(formattedJson.toUtf8());
@@ -388,7 +411,6 @@
     connect(ui->perc_sugarsShow, &QProgressBar::valueChanged, this, &EditRecipe::on_perc_sugars_valueChanged);
     connect(ui->perc_caraShow, &QProgressBar::valueChanged, this, &EditRecipe::on_perc_cara_valueChanged);
     connect(ui->lintnerShow, &QProgressBar::valueChanged, this, &EditRecipe::on_lintner_valueChanged);
-    connect(ui->fermentablesTable, SIGNAL(cellChanged(int, int)), this, SLOT(cell_Fermentable_changed(int, int)));
 
     // All signals from tab "Hops"
 //    connect(ui->hopsTable, SIGNAL(cellChanged(int, int)), this, SLOT(cell_Changed(int, int)));
@@ -420,6 +442,12 @@
 }
 
 
+bool EditRecipe::ferment_sort_test(const Fermentables &D1, const Fermentables &D2)
+{
+    return (D1.f_added <= D2.f_added) && (D1.f_amount >= D2.f_amount) && (D1.f_color < D2.f_color);
+}
+
+
 void EditRecipe::refreshFermentables()
 {
     QString w;
@@ -427,18 +455,19 @@
     QHBoxLayout* pLayout;
     QTableWidgetItem *item;
     QLabel *label;
-    double  d;
-    int j;
-    int total = 0;
+
+    qDebug() << "refreshFermentables" << recipe->fermentables.size();
+    std::sort(recipe->fermentables.begin(), recipe->fermentables.end(), ferment_sort_test);
 
-    qDebug() << "refreshFermentables" << this->fermentables << this->fermentables.isArray() << this->fermentables.array().size();
-    /* 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. */
+    /*
+     * 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("Supplier"), tr("Fermentable"), tr("EBC"), tr("Type"), tr("Graintype"), tr("When"), tr("Yield"),
 		    	      tr("Amount"), tr("Procent"), tr("100%"), tr("Delete"), tr("Edit") });
-    ui->fermentablesTable->setColumnCount(30);
+    ui->fermentablesTable->setColumnCount(12);
     ui->fermentablesTable->setColumnWidth(0, 150);     /* Supplier	*/
     ui->fermentablesTable->setColumnWidth(1, 225);     /* Fermentable	*/
     ui->fermentablesTable->setColumnWidth(2,  50);     /* Color		*/
@@ -451,49 +480,45 @@
     ui->fermentablesTable->setColumnWidth(9,  50);     /* 100%		*/
     ui->fermentablesTable->setColumnWidth(10, 80);     /* Delete	*/
     ui->fermentablesTable->setColumnWidth(11, 80);     /* Edit		*/
-    for (int i = 12; i < 30; i++)
-    	ui->fermentablesTable->setColumnHidden(i, true);
     ui->fermentablesTable->setHorizontalHeaderLabels(labels);
     ui->fermentablesTable->verticalHeader()->hide();
-    ui->fermentablesTable->setRowCount(this->fermentables.array().size());
+    ui->fermentablesTable->setRowCount(recipe->fermentables.size());
 
-    if (this->fermentables.isArray()) {
-	for (int i = 0; i < this->fermentables.array().size(); i++) {
-            QJsonObject obj = this->fermentables.array().at(i).toObject();
+    for (int i = 0; i < recipe->fermentables.size(); i++) {
 
-            ui->fermentablesTable->setItem(i, 0, new QTableWidgetItem(obj["f_supplier"].toString()));
-            ui->fermentablesTable->setItem(i, 1, new QTableWidgetItem(obj["f_name"].toString()));
+	ui->fermentablesTable->setItem(i, 0, new QTableWidgetItem(recipe->fermentables.at(i).f_supplier));
+	ui->fermentablesTable->setItem(i, 1, new QTableWidgetItem(recipe->fermentables.at(i).f_name));
 
-            w = QString("%1").arg(obj["f_color"].toDouble(), 1, 'f', 0, '0');
-            item = new QTableWidgetItem(w);
-            item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
-            ui->fermentablesTable->setItem(i, 2, item);
+        w = QString("%1").arg(recipe->fermentables.at(i).f_color, 1, 'f', 0, '0');
+        item = new QTableWidgetItem(w);
+        item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+        ui->fermentablesTable->setItem(i, 2, item);
 
-	    item = new QTableWidgetItem(f_types[obj["f_type"].toInt()]);
-	    item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter);
-	    ui->fermentablesTable->setItem(i, 3, item);
+	item = new QTableWidgetItem(f_types[recipe->fermentables.at(i).f_type]);
+	item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter);
+	ui->fermentablesTable->setItem(i, 3, item);
 
-            item = new QTableWidgetItem(f_graintypes[obj["f_graintype"].toInt()]);
-            item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter);
-            ui->fermentablesTable->setItem(i, 4, item);
+        item = new QTableWidgetItem(f_graintypes[recipe->fermentables.at(i).f_graintype]);
+        item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter);
+        ui->fermentablesTable->setItem(i, 4, item);
 
-            item = new QTableWidgetItem(f_added[obj["f_added"].toInt()]);
-            item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter);
-            ui->fermentablesTable->setItem(i, 5, item);
+        item = new QTableWidgetItem(f_added[recipe->fermentables.at(i).f_added]);
+        item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter);
+        ui->fermentablesTable->setItem(i, 5, item);
 
-            item = new QTableWidgetItem(QString("%1%").arg(obj["f_yield"].toDouble(), 2, 'f', 1, '0'));
-            item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
-            ui->fermentablesTable->setItem(i, 6, item);
+        item = new QTableWidgetItem(QString("%1%").arg(recipe->fermentables.at(i).f_yield, 2, 'f', 1, '0'));
+        item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+        ui->fermentablesTable->setItem(i, 6, item);
 
-            item = new QTableWidgetItem(QString("%1 Kg").arg(obj["f_amount"].toDouble(), 4, 'f', 3, '0'));
-            item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
-            ui->fermentablesTable->setItem(i, 7, item);
+        item = new QTableWidgetItem(QString("%1 Kg").arg(recipe->fermentables.at(i).f_amount, 4, 'f', 3, '0'));
+        item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+        ui->fermentablesTable->setItem(i, 7, item);
 
-            item = new QTableWidgetItem(QString("%1%").arg(obj["f_percentage"].toDouble(), 2, 'f', 1, '0'));
-            item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
-            ui->fermentablesTable->setItem(i, 8, item);
+        item = new QTableWidgetItem(QString("%1%").arg(recipe->fermentables.at(i).f_percentage, 2, 'f', 1, '0'));
+        item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+        ui->fermentablesTable->setItem(i, 8, item);
 
-	    if (obj["f_adjust_to_total_100"].toInt()) {
+	if (recipe->fermentables.at(i).f_adjust_to_total_100) {
 		pWidget = new QWidget();
             	label = new QLabel;
             	label->setPixmap(QPixmap(":icons/silk/tick.png"));
@@ -503,56 +528,33 @@
             	pLayout->setContentsMargins(0, 0, 0, 0);
             	pWidget->setLayout(pLayout);
             	ui->fermentablesTable->setCellWidget(i, 9, pWidget);
-	    } else {
+	} else {
 		ui->fermentablesTable->removeCellWidget(i, 9);
-	    }
-
-	    /* 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_deleteFermentRow_clicked()));
-            pLayout = new QHBoxLayout(pWidget);
-            pLayout->addWidget(btn_dele);
-            pLayout->setContentsMargins(5, 0, 5, 0);
-            pWidget->setLayout(pLayout);
-            ui->fermentablesTable->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(on_editFermentRow_clicked()));
-	    pLayout = new QHBoxLayout(pWidget);
-            pLayout->addWidget(btn_edit);
-	    pLayout->setContentsMargins(5, 0, 5, 0);
-            pWidget->setLayout(pLayout);
-            ui->fermentablesTable->setCellWidget(i, 11, pWidget);
+	/* 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_deleteFermentRow_clicked()));
+        pLayout = new QHBoxLayout(pWidget);
+        pLayout->addWidget(btn_dele);
+        pLayout->setContentsMargins(5, 0, 5, 0);
+        pWidget->setLayout(pLayout);
+        ui->fermentablesTable->setCellWidget(i, 10, pWidget);
 
-	    /* Hidden columns */
-            ui->fermentablesTable->setItem(i, 12, new QTableWidgetItem(QString("%1").arg(obj["f_acid_to_ph_57"].toDouble(), 6, 'f', 5, '0')));
-            ui->fermentablesTable->setItem(i, 13, new QTableWidgetItem(QString("%1").arg(obj["f_add_after_boil"].toInt(), 1, 'f', 0, '0')));
-            ui->fermentablesTable->setItem(i, 14, new QTableWidgetItem(QString("%1").arg(obj["f_coarse_fine_diff"].toDouble(), 2, 'f', 1, '0')));
-            ui->fermentablesTable->setItem(i, 15, new QTableWidgetItem(QString("%1").arg(obj["f_cost"].toDouble(), 3, 'f', 2, '0')));
-            ui->fermentablesTable->setItem(i, 16, new QTableWidgetItem(QString("%1").arg(obj["f_di_ph"].toDouble(), 6, 'f', 5, '0')));
-            ui->fermentablesTable->setItem(i, 17, new QTableWidgetItem(QString("%1").arg(obj["f_diastatic_power"].toDouble(), 6, 'f', 5, '0')));
-            ui->fermentablesTable->setItem(i, 18, new QTableWidgetItem(QString("%1").arg(obj["f_dissolved_protein"].toDouble(), 2, 'f', 1, '0')));
-            ui->fermentablesTable->setItem(i, 19, new QTableWidgetItem(QString("%1").arg(obj["f_moisture"].toDouble(), 2, 'f', 1, '0')));
-	    ui->fermentablesTable->setItem(i, 20, new QTableWidgetItem(obj["f_origin"].toString()));
-	    ui->fermentablesTable->setItem(i, 21, new QTableWidgetItem(QString("%1").arg(obj["f_protein"].toDouble(), 2, 'f', 1, '0')));
-	    ui->fermentablesTable->setItem(i, 22, new QTableWidgetItem(QString("%1").arg(obj["f_recommend_mash"].toInt(), 1, 'f', 0, '0')));
-	    /* Again these because the visible ones have human readable strings added. */
-	    ui->fermentablesTable->setItem(i, 23, new QTableWidgetItem(QString("%1").arg(obj["f_amount"].toDouble(), 4, 'f', 3, '0')));
-	    ui->fermentablesTable->setItem(i, 24, new QTableWidgetItem(QString("%1").arg(obj["f_percentage"].toDouble(), 2, 'f', 1, '0')));
-	    ui->fermentablesTable->setItem(i, 25, new QTableWidgetItem(QString("%1").arg(obj["f_yield"].toDouble(), 2, 'f', 1, '0')));
-	    ui->fermentablesTable->setItem(i, 26, new QTableWidgetItem(QString("%1").arg(obj["f_max_in_batch"].toDouble(), 2, 'f', 1, '0')));
-	    ui->fermentablesTable->setItem(i, 27, new QTableWidgetItem(QString("%1").arg(obj["f_type"].toDouble(), 1, 'f', 0, '0')));
-	    ui->fermentablesTable->setItem(i, 28, new QTableWidgetItem(QString("%1").arg(obj["f_graintype"].toDouble(), 1, 'f', 0, '0')));
-	    ui->fermentablesTable->setItem(i, 29, new QTableWidgetItem(QString("%1").arg(obj["f_added"].toDouble(), 1, 'f', 0, '0')));
-	}
+	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_editFermentRow_clicked()));
+	pLayout = new QHBoxLayout(pWidget);
+        pLayout->addWidget(btn_edit);
+	pLayout->setContentsMargins(5, 0, 5, 0);
+        pWidget->setLayout(pLayout);
+        ui->fermentablesTable->setCellWidget(i, 11, pWidget);
     }
-
     this->ignoreChanges = false;
 }
 
@@ -607,7 +609,6 @@
     QJsonObject obj;
 
     qDebug() << "calcFermentables()";
-    use_to100 = false;
 
     /*
      * Get average mashtemp and mashtime from the Mash schedule.
@@ -629,44 +630,42 @@
 	qDebug() << "  no mash schedule";
     }
 
-    if (this->fermentables.array().size() < 1) {
+    if (recipe->fermentables.size() < 1) {
 	qDebug() << "  no fermentables, return.";
 	return;
     }
+    qDebug() << "  adjust to 100" << recipe->fermentables_use100;
 
-    for (i = 0; i < this->fermentables.array().size(); i++) {
-	obj = this->fermentables.array().at(i).toObject();
-	if (obj["f_adjust_to_total_100"].toInt())
-	    use_to100 = true;
-	if (obj["f_type"].toInt() == 1 && obj["f_added"].toInt() < 4)		// Sugars
-	    psugar += obj["f_percentage"].toDouble();
-	if (obj["f_graintype"].toInt() == 2 && obj["f_added"].toInt() < 4)	// Crystal/Cara
-	    pcara += obj["f_percentage"].toDouble();
-	d = obj["f_amount"].toDouble() * (obj["f_yield"].toDouble() / 100) * (1 - obj["f_moisture"].toDouble() / 100);
-	if (obj["f_added"].toInt() == 0) {					// Mash
+    for (i = 0; i < recipe->fermentables.size(); i++) {
+	if (recipe->fermentables.at(i).f_type == 1 && recipe->fermentables.at(i).f_added < 4)		// Sugars
+	    psugar += recipe->fermentables.at(i).f_percentage;
+	if (recipe->fermentables.at(i).f_graintype == 2 && recipe->fermentables.at(i).f_added < 4)	// Crystal/Cara
+	    pcara += recipe->fermentables.at(i).f_percentage;
+	d = recipe->fermentables.at(i).f_amount * (recipe->fermentables.at(i).f_yield / 100) * (1 - recipe->fermentables.at(i).f_moisture / 100);
+	if (recipe->fermentables.at(i).f_added == 0) {					// Mash
 	    if (mvol > 0) {							// If mash volume is known
-		mvol += obj["f_amount"].toDouble() * obj["f_moisture"].toDouble() / 100;
+		mvol += recipe->fermentables.at(i).f_amount * recipe->fermentables.at(i).f_moisture / 100;
 		s += d;
 	    }
 	    d = ui->efficiencyEdit->value() / 100 * d;
 	    sugarsm += d;
-	    mashkg += obj["f_amount"].toDouble();
+	    mashkg += recipe->fermentables.at(i).f_amount;
 	}
-	if (obj["f_added"].toInt() == 0 || obj["f_added"].toInt() == 1)		// Mash or boil
+	if (recipe->fermentables.at(i).f_added == 0 || recipe->fermentables.at(i).f_added == 1)		// Mash or boil
 	    sugarsf += d;
-	if (obj["f_added"].toInt() == 2 || obj["f_added"].toInt() == 3) {		// Fermentation or lagering
-	    x = (obj["f_yield"].toDouble() / 100) * (1 - obj["f_moisture"].toDouble() / 100);
-	    addedS += obj["f_amount"].toDouble() * x;
-	    addedmass += obj["f_amount"].toDouble();
-	    vol += (x * sugardensity + (1 - x) * 1) * obj["f_amount"].toDouble();
+	if (recipe->fermentables.at(i).f_added == 2 || recipe->fermentables.at(i).f_added == 3) {		// Fermentation or lagering
+	    x = (recipe->fermentables.at(i).f_yield / 100) * (1 - recipe->fermentables.at(i).f_moisture / 100);
+	    addedS += recipe->fermentables.at(i).f_amount * x;
+	    addedmass += recipe->fermentables.at(i).f_amount;
+	    vol += (x * sugardensity + (1 - x) * 1) * recipe->fermentables.at(i).f_amount;
 	}
-	if (obj["f_added"].toInt() == 0 && (obj["f_type"].toInt() == 0 || obj["f_type"].toInt() == 4) && obj["f_color"].toDouble() < 50) {
-	    lintner += obj["f_diastatic_power"].toDouble() * obj["f_amount"].toDouble();
+	if (recipe->fermentables.at(i).f_added == 0 && (recipe->fermentables.at(i).f_type == 0 || recipe->fermentables.at(i).f_type == 4) && recipe->fermentables.at(i).f_color < 50) {
+	    lintner += recipe->fermentables.at(i).f_diastatic_power * recipe->fermentables.at(i).f_amount;
 	}
-	if (obj["f_added"].toInt() < 4) {
-	    colort += obj["f_amount"].toDouble() * Utils::ebc_to_srm(obj["f_color"].toDouble());
-	    colorh += obj["f_amount"].toDouble() * obj["f_color"].toDouble() * Utils::get_kt(obj["f_color"].toDouble());
-	    colorn += (obj["f_percentage"].toDouble() / 100) * obj["f_color"].toDouble();	// For 8.6 Pt wort.
+	if (recipe->fermentables.at(i).f_added < 4) {
+	    colort += recipe->fermentables.at(i).f_amount * Utils::ebc_to_srm(recipe->fermentables.at(i).f_color);
+	    colorh += recipe->fermentables.at(i).f_amount * recipe->fermentables.at(i).f_color * Utils::get_kt(recipe->fermentables.at(i).f_color);
+	    colorn += (recipe->fermentables.at(i).f_percentage / 100) * recipe->fermentables.at(i).f_color;	// For 8.6 Pt wort.
 	}
     }
     qDebug() << "  colort" << colort << "colorh" << colorh << "colorn" << colorn;
@@ -754,9 +753,6 @@
     double alc = 1881.22 * fg * (og - fg) / (1.775 - og);
     double sug = 3550 * fg * (0.1808 * og + 0.8192 * fg - 1.0004);
     ui->calEdit->setValue(round((alc + sug) / (12 * 0.0295735296)));
-
-    // If to_100 then make all amount fields t/o and percent fields r/w
-
 }
 
 
@@ -1003,84 +999,46 @@
 }
 
 
+/* TODO: move this code to MySQL save */
 void EditRecipe::fermentable_Json()
 {
     QTableWidgetItem *item;
     QJsonArray array;
 
     qDebug() << "fermentable_Json()";
-    ui->fermentablesTable->sortItems(23, Qt::DescendingOrder);   // Sort on amount.
-    qDebug() << "fermentable_Json() 1";
 
-    for (int i = 0; i < ui->fermentablesTable->rowCount(); i++) {
+    for (int i = 0; i < recipe->fermentables.size(); i++) {
 
-	qDebug() << "fermentable_Json() 2" << i;
         QJsonObject obj;
-	item = ui->fermentablesTable->item(i, 12);
-	obj.insert("f_acid_to_ph_57", item->text().toDouble());
-	item = ui->fermentablesTable->item(i, 13);
-        obj.insert("f_add_after_boil", item->text().toDouble());
-	item = ui->fermentablesTable->item(i, 29);
-        obj.insert("f_added", item->text().toDouble());
-	item = ui->fermentablesTable->item(i, 9);
-        obj.insert("f_adjust_to_total_100", item->text().toDouble());
-	item = ui->fermentablesTable->item(i, 23);
-        obj.insert("f_amount", item->text().toDouble());
-	item = ui->fermentablesTable->item(i, 14);
-        obj.insert("f_coarse_fine_diff", item->text().toDouble());
-	item = ui->fermentablesTable->item(i, 2);
-        obj.insert("f_color", item->text().toDouble());
-	item = ui->fermentablesTable->item(i, 15);
-        obj.insert("f_cost", item->text().toDouble());
-	item = ui->fermentablesTable->item(i, 16);
-        obj.insert("f_di_ph", item->text().toDouble());
-	item = ui->fermentablesTable->item(i, 17);
-        obj.insert("f_diastatic_power", item->text().toDouble());
-	item = ui->fermentablesTable->item(i, 18);
-        obj.insert("f_dissolved_protein", item->text().toDouble());
-	item = ui->fermentablesTable->item(i, 28);
-        obj.insert("f_graintype", item->text().toDouble());
-	item = ui->fermentablesTable->item(i, 26);
-        obj.insert("f_max_in_batch", item->text().toDouble());
-	item = ui->fermentablesTable->item(i, 19);
-        obj.insert("f_moisture", item->text().toDouble());
-	item = ui->fermentablesTable->item(i, 1);
-        obj.insert("f_name", item->text());
-	item = ui->fermentablesTable->item(i, 20);
-        obj.insert("f_origin", item->text());
-	item = ui->fermentablesTable->item(i, 24);
-        obj.insert("f_percentage", item->text().toDouble());
-	item = ui->fermentablesTable->item(i, 21);
-        obj.insert("f_protein", item->text().toDouble());
-	item = ui->fermentablesTable->item(i, 22);
-        obj.insert("f_recommend_mash", item->text().toDouble());
-	item = ui->fermentablesTable->item(i, 0);
-        obj.insert("f_supplier", item->text());
-	item = ui->fermentablesTable->item(i, 27);
-        obj.insert("f_type", item->text().toDouble());
-	item = ui->fermentablesTable->item(i, 25);
-        obj.insert("f_yield", item->text().toDouble());
+	obj.insert("f_acid_to_ph_57", recipe->fermentables.at(i).f_acid_to_ph_57);
+        obj.insert("f_add_after_boil", recipe->fermentables.at(i).f_add_after_boil);
+        obj.insert("f_added", recipe->fermentables.at(i).f_added);
+        obj.insert("f_adjust_to_total_100", recipe->fermentables.at(i).f_adjust_to_total_100);
+        obj.insert("f_amount", recipe->fermentables.at(i).f_added);
+        obj.insert("f_coarse_fine_diff", recipe->fermentables.at(i).f_coarse_fine_diff);
+        obj.insert("f_color", recipe->fermentables.at(i).f_color);
+        obj.insert("f_cost", recipe->fermentables.at(i).f_cost);
+        obj.insert("f_di_ph", recipe->fermentables.at(i).f_di_ph);
+        obj.insert("f_diastatic_power", recipe->fermentables.at(i).f_diastatic_power);
+        obj.insert("f_dissolved_protein", recipe->fermentables.at(i).f_dissolved_protein);
+        obj.insert("f_graintype", recipe->fermentables.at(i).f_graintype);
+        obj.insert("f_max_in_batch", recipe->fermentables.at(i).f_max_in_batch);
+        obj.insert("f_moisture", recipe->fermentables.at(i).f_moisture);
+        obj.insert("f_name", recipe->fermentables.at(i).f_name);
+        obj.insert("f_origin", recipe->fermentables.at(i).f_origin);
+        obj.insert("f_percentage", recipe->fermentables.at(i).f_percentage);
+        obj.insert("f_protein", recipe->fermentables.at(i).f_protein);
+        obj.insert("f_recommend_mash", recipe->fermentables.at(i).f_recommend_mash);
+        obj.insert("f_supplier", recipe->fermentables.at(i).f_supplier);
+        obj.insert("f_type", recipe->fermentables.at(i).f_type);
+        obj.insert("f_yield", recipe->fermentables.at(i).f_yield);
 	qDebug() << "fermentable_Json" << i << obj;
 	array.append(obj);      /* Append this object */
     }
 
     qDebug() << array;
     /* Copy to the global array and refresh */
-    this->fermentables.setArray(array);
-    is_changed();
-    emit refreshAll();
-}
-
-
-void EditRecipe::cell_Fermentable_changed(int nRow, int nCol)
-{
-    if (this->ignoreChanges)
-        return;
-
-    qDebug() << "Cell at row " + QString::number(nRow) + " column " + QString::number(nCol) + " was changed.";
-
-    // TODO: some checks and auto fixes.
-//    make_Json();
+//    this->fermentables.setArray(array);
 }
 
 
@@ -1090,54 +1048,56 @@
     int row = pb->objectName().toInt();
     qDebug() << "Delete fermentable row" << row;
 
-    QJsonObject obj = this->fermentables.array().at(row).toObject();
-     qDebug() << obj;
-
-    int rc = QMessageBox::warning(this, tr("Delete fermentable"), tr("Delete %1").arg(obj["f_name"].toString()),
+    int rc = QMessageBox::warning(this, tr("Delete fermentable"), tr("Delete %1").arg(recipe->fermentables.at(row).f_name),
 		    QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
     if (rc == QMessageBox::No)
 	return;
 
     ui->fermentablesTable->removeRow(row);
 //    recalculate percentages
-    fermentable_Json();
+//    fermentable_Json();
 }
 
 
 void EditRecipe::ferment_amount_changed(double val)
 {
     QTableWidgetItem *item;
-    double	total = 0;
+    double	total = 0, perc;
+
+    if (recipe->fermentables_use100)
+	return;
 
     qDebug() << "ferment_amount_changed()" << editrow << val;
-
     this->ignoreChanges = true;
 
+    recipe->fermentables[editrow].f_amount = val;
     item = new QTableWidgetItem(QString("%1 Kg").arg(val, 4, 'f', 3, '0'));
     item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
     ui->fermentablesTable->setItem(editrow, 7, item);
 
-    item = new QTableWidgetItem(QString("%1").arg(val, 4, 'f', 3, '0'));
-    ui->fermentablesTable->setItem(editrow, 23, item);
-
-    for (int i = 0; i < ui->fermentablesTable->rowCount(); i++) {
-	item = ui->fermentablesTable->item(i, 23);
-	total += item->text().toDouble();
-    }
-    qDebug() << "total weight now" << total;
+    for (int i = 0; i < recipe->fermentables.size(); i++)
+	total += recipe->fermentables.at(i).f_amount;
 
-//    for (int i = 0; i < ui->fermentablesTable->rowCount(); i++) {
-//        item = ui->fermentablesTable->item(i, 23);
-//        total += item->text().toDouble();
-//    }
-
+    /*
+     * Recalculate the percentages
+     */
+    for (int i = 0; i < recipe->fermentables.size(); i++) {
+	perc = recipe->fermentables.at(i).f_amount / total * 100;
+	recipe->fermentables[i].f_percentage = perc;
+	item = new QTableWidgetItem(QString("%1%").arg(perc, 2, 'f', 1, '0'));
+        item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+        ui->fermentablesTable->setItem(i, 8, item);
+	if (i == editrow)
+	    this->pctEdit->setValue(perc);
+    }
     this->ignoreChanges = false;
-
-//    fermentable_Json();
 }
 
 void EditRecipe::ferment_pct_changed(double val)
 {
+    if (! recipe->fermentables_use100)
+        return;
+
     qDebug() << "ferment_pct_changed()" << val;
 }
 
@@ -1147,10 +1107,7 @@
     QPushButton *pb = qobject_cast<QPushButton *>(QObject::sender());
     editrow = pb->objectName().toInt();
     qDebug() << "Edit fermentable row" << editrow;
-    work = this->fermentables.array().at(editrow).toObject();
-    backup = this->fermentables.array().at(editrow).toObject();
-
-    qDebug() << work;
+    Fermentables backup = recipe->fermentables.at(editrow);
 
     QDialog* dialog = new QDialog(this);
     dialog->resize(738, 287);
@@ -1212,12 +1169,12 @@
     selectEdit->setGeometry(QRect(160, 70, 251, 23));
     nameEdit = new QLineEdit(dialog);
     nameEdit->setObjectName(QString::fromUtf8("nameEdit"));
-    nameEdit->setText(work["f_name"].toString());
+    nameEdit->setText(recipe->fermentables.at(editrow).f_name);
     nameEdit->setGeometry(QRect(160, 10, 511, 23));
     nameEdit->setReadOnly(true);
     supplierEdit = new QLineEdit(dialog);
     supplierEdit->setObjectName(QString::fromUtf8("supplierEdit"));
-    supplierEdit->setText(work["f_supplier"].toString());
+    supplierEdit->setText(recipe->fermentables.at(editrow).f_supplier);
     supplierEdit->setGeometry(QRect(160, 40, 511, 23));
     supplierEdit->setReadOnly(true);
     amountEdit = new QDoubleSpinBox(dialog);
@@ -1226,10 +1183,10 @@
     amountEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
     amountEdit->setAccelerated(true);
     amountEdit->setDecimals(3);
-    amountEdit->setReadOnly(use_to100);
+    amountEdit->setReadOnly(recipe->fermentables_use100);
     amountEdit->setMaximum(100000.0);
     amountEdit->setSingleStep(0.0010);
-    amountEdit->setValue(work["f_amount"].toDouble());
+    amountEdit->setValue(recipe->fermentables.at(editrow).f_amount);
     connect(amountEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditRecipe::ferment_amount_changed);
 
     pctEdit = new QDoubleSpinBox(dialog);
@@ -1238,8 +1195,8 @@
     pctEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
     pctEdit->setAccelerated(true);
     pctEdit->setDecimals(1);
-    if (use_to100) {
-    	if (work["f_adjust_to_total_100"].toInt())
+    if (recipe->fermentables_use100) {
+    	if (recipe->fermentables.at(editrow).f_adjust_to_total_100)
 	    pctEdit->setReadOnly(true);
     	else
     	    pctEdit->setReadOnly(false);
@@ -1248,7 +1205,7 @@
     }
     pctEdit->setMaximum(100.0);
     pctEdit->setSingleStep(0.1);
-    pctEdit->setValue(work["f_percentage"].toDouble());
+    pctEdit->setValue(recipe->fermentables.at(editrow).f_percentage);
     connect(pctEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditRecipe::ferment_pct_changed);
 
     addedEdit = new QComboBox(dialog);
@@ -1260,12 +1217,12 @@
     addedEdit->addItem(tr("Lagering"));
     addedEdit->addItem(tr("Bottle"));
     addedEdit->addItem(tr("Kegs"));
-    addedEdit->setCurrentIndex(work["f_added"].toInt());
+    addedEdit->setCurrentIndex(recipe->fermentables.at(editrow).f_added);
 
     to100Edit = new QCheckBox(dialog);
     to100Edit->setObjectName(QString::fromUtf8("to100Edit"));
     to100Edit->setGeometry(QRect(160, 160, 85, 21));
-    to100Edit->setChecked(work["f_adjust_to_total_100"].toInt() ? true:false);
+    to100Edit->setChecked(recipe->fermentables.at(editrow).f_adjust_to_total_100);
 
     instockEdit = new QCheckBox(dialog);
     instockEdit->setObjectName(QString::fromUtf8("instockEdit"));
@@ -1278,7 +1235,7 @@
     maxEdit->setReadOnly(true);
     maxEdit->setButtonSymbols(QAbstractSpinBox::NoButtons);
     maxEdit->setDecimals(1);
-    maxEdit->setValue(work["f_max_in_batch"].toDouble());
+    maxEdit->setValue(recipe->fermentables.at(editrow).f_max_in_batch);
 
     connect(buttonBox, SIGNAL(rejected()), dialog, SLOT(reject()));
     connect(buttonBox, SIGNAL(accepted()), dialog, SLOT(accept()));
@@ -1286,6 +1243,7 @@
     if (dialog->result() == QDialog::Rejected) {
 	qDebug() << "rejected";
 	// restore fermentbackup
+	// recalculate percentages
     } else {
 	qDebug() << "accepted";
 	// fermentrow to final
@@ -1295,6 +1253,7 @@
 
     // disconnect
     // return
+    emit refreshAll();
 }
 
 
--- a/src/EditRecipe.h	Wed Apr 06 12:10:33 2022 +0200
+++ b/src/EditRecipe.h	Wed Apr 06 20:26:47 2022 +0200
@@ -227,16 +227,11 @@
      * that belong with the loaded recipe data and are present to
      * make things easier.
      */
-    int		fermentables_records;	///< Total records
     int		fermentables_current;	///< Current record, -1 is invalid.
     bool	fermentables_use100;	///< Use percentages instead of amount
-    int		hops_records;
     int		hops_current;
-    int		misc_records;
     int		misc_current;
-    int		yeasts_records;
     int		yeasts_current;
-    int		mashs_records;
     int		mashs_current;
 };
 
@@ -269,7 +264,6 @@
     void refreshYeasts();
     void refreshMashs();
     void refreshAll();
-    void cell_Fermentable_changed(int nRow, int nCol);
     void ferment_amount_changed(double val);
     void ferment_pct_changed(double val);
     void on_deleteFermentRow_clicked();
@@ -292,18 +286,17 @@
     int recno, editrow;
     bool textIsChanged = false;
     bool ignoreChanges = false;
-    bool use_to100 = false;
     Recipe *recipe;
     /*
      * Variables for popup ingredients editing.
      */
-    QJsonDocument fermentables, hops, miscs, yeasts;
-    QJsonObject work, backup;
+    QJsonDocument hops, miscs, yeasts;
     QComboBox *selectEdit, *addedEdit;
     QLineEdit *nameEdit, *supplierEdit;
     QDoubleSpinBox *amountEdit, *pctEdit, *maxEdit;
     QCheckBox *to100Edit, *instockEdit;
 
+    static bool ferment_sort_test(const Fermentables &D1, const Fermentables &D2);
     void WindowTitle();
     void fermentable_Json();
     void calcFermentables();

mercurial