src/EditRecipe.cpp

changeset 101
1d14d3bf2465
parent 100
d11a3e713e3b
child 102
b017001850df
--- a/src/EditRecipe.cpp	Fri Apr 01 17:25:42 2022 +0200
+++ b/src/EditRecipe.cpp	Sat Apr 02 23:01:13 2022 +0200
@@ -44,6 +44,15 @@
     ui->ibu_methodEdit->addItem("Rager");
     ui->ibu_methodEdit->addItem("Daniels");
 
+    ui->beerstyleEdit->addItem("");	// First add a dummy
+    query.prepare("SELECT style_guide,style_letter,name FROM profile_styles ORDER BY style_guide,style_letter,name");
+    query.exec();
+    query.first();
+    for (int i = 0; i < query.size(); i++) {
+	ui->beerstyleEdit->addItem(query.value(0).toString()+" "+query.value(1).toString()+" "+query.value(2).toString());
+	query.next();
+    }
+
     if (id >= 0) {
 	query.prepare("SELECT * FROM recipes WHERE record = :recno");
 	query.bindValue(":recno", id);
@@ -56,7 +65,7 @@
 	ui->st_guideEdit->setText(query.value(5).toString());
 	ui->st_catEdit->setText(query.value(6).toString());
 	ui->st_catnrEdit->setText(query.value(7).toString());
-	ui->st_typeEdit->setText(query.value(8).toString());
+	ui->st_typeEdit->setText(s_types[query.value(8).toInt()]);
 
 	ui->nameEdit->setText(query.value(21).toString());
 	ui->notesEdit->setPlainText(query.value(22).toString());
@@ -67,18 +76,22 @@
 	ui->efficiencyEdit->setValue(query.value(27).toDouble());
 
 	ui->est_ogEdit->setValue(query.value(28).toDouble());
+	ui->est_og2Edit->setValue(query.value(28).toDouble());
+	ui->est_og3Edit->setValue(query.value(28).toDouble());
 	ui->est_ogShow->setRange(query.value(9).toDouble(), query.value(10).toDouble());
 	ui->est_ogShow->setPrecision(3);
 	ui->est_ogShow->setMarkerTextIsValue(true);
 	ui->est_ogShow->setValue(query.value(28).toDouble());
 
 	ui->est_fgEdit->setValue(query.value(29).toDouble());
+	ui->est_fg3Edit->setValue(query.value(29).toDouble());
         ui->est_fgShow->setRange(query.value(11).toDouble(), query.value(12).toDouble());
         ui->est_fgShow->setPrecision(3);
         ui->est_fgShow->setMarkerTextIsValue(true);
         ui->est_fgShow->setValue(query.value(29).toDouble());
 
 	ui->est_abvEdit->setValue(query.value(30).toDouble());
+	ui->est_abv2Edit->setValue(query.value(30).toDouble());
         ui->est_abvShow->setRange(query.value(19).toDouble(), query.value(20).toDouble());
         ui->est_abvShow->setPrecision(1);
         ui->est_abvShow->setMarkerTextIsValue(true);
@@ -87,6 +100,8 @@
 	QColor color = Utils::ebc_to_color(query.value(31).toInt());
 	ui->est_colorEdit->setValue(query.value(31).toDouble());
 	ui->est_colorEdit->setStyleSheet(Utils::ebc_to_style(query.value(31).toInt()));
+	ui->est_color2Edit->setValue(query.value(31).toDouble());
+        ui->est_color2Edit->setStyleSheet(Utils::ebc_to_style(query.value(31).toInt()));
         ui->est_colorShow->setPrecision(0);
         ui->est_colorShow->setMarkerTextIsValue(true);
 	ui->est_colorShow->setRange(query.value(15).toDouble(), query.value(16).toDouble());
@@ -95,6 +110,7 @@
 	ui->color_methodEdit->setCurrentIndex(query.value(32).toInt());
 
 	ui->est_ibuEdit->setValue(query.value(33).toDouble());
+	ui->est_ibu2Edit->setValue(query.value(33).toDouble());
         ui->est_ibuShow->setPrecision(0);
         ui->est_ibuShow->setMarkerTextIsValue(true);
         ui->est_ibuShow->setRange(query.value(13).toDouble(), query.value(14).toDouble());
@@ -156,30 +172,104 @@
 	// 81 wa_acid_name
 	// 82 wa_acid_perc
 	// 83 wa_base_name
-	// 84 json_fermentables
+
+	/*
+	 * Progress bars.
+	 * perc_maltShow  pmalts = mashkg / (dataRecord.boil_size / 3) * 100;
+	 * perc_sugarsShow if (row.f_type == 1 && row.f_added < 4)      // Sugar
+	 *                      psugar += row.f_percentage;
+	 * perc_caraShow  if (row.f_graintype == 2 && row.f_added < 4) // Crystal
+	 * 			pcara += row.f_percentage;
+	 * lintner  if (row.f_added == 0 && (row.f_type == 0 || row.f_type == 4) && row.f_color < 50)
+	 * 		lintner += row.f_diastatic_power * row.f_amount;
+	 * lintner = parseFloat(lintner / mashkg)
+	 *
+	 * perc_malts	range(0, 120)
+	 * 		stop: 90, color: '#008C00' 
+	 * 		stop: 100, color: '#EB7331'
+	 * 		stop: 120, color: '#FF0000'
+	 *
+	 * perc_sugars	range(0, 50)
+	 * 		stop: 20, color: '#008C00'
+	 * 		stop: 50, color: '#FF0000'
+	 * perc_cara	range(0, 50)
+	 * 		stop: 25, color: '#008C00'
+	 * 		stop: 50, color: '#FF0000'
+	 * lintner	range(0, 200)
+	 * 		stop: 30, color: '#FF0000'	red
+	 * 		stop: 40, color: '#EB7331'	orange
+	 * 		stop: 200, color: '#008C00'	green
+	 */
+
+//	ui->lintnerShow->setValue(52);
+	if (ui->lintnerShow->value() < 30)
+	    ui->lintnerShow->setStyleSheet(bar_red);
+	else if (ui->lintnerShow->value() < 40)
+	    ui->lintnerShow->setStyleSheet(bar_orange);
+	else
+	    ui->lintnerShow->setStyleSheet(bar_green);
+
+	QJsonParseError parseError;
+        const auto& json = query.value(84).toString();
+	if (!json.trimmed().isEmpty()) {
+            const auto& formattedJson = QString("%1").arg(json);
+            this->fermentables = QJsonDocument::fromJson(formattedJson.toUtf8(),  &parseError);
+            if (parseError.error != QJsonParseError::NoError)
+                qDebug() << "Parse error: " << parseError.errorString() << "at" << parseError.offset ;
+        } else {
+	    qDebug() << "empty fermentables";
+	}
+
 	// 85 json_hops
 	// 86 json_miscs
 	// 87 json_yeasts
 	// 88 json_mashs
     } else {
 	/* Set some defaults */
+
+	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());
+	this->mashs = QJsonDocument::fromJson(formattedJson.toUtf8());
     }
 
+    // All signals from tab "Generic"
     connect(ui->lockedEdit, &QCheckBox::stateChanged, this, &EditRecipe::is_changed);
-
     connect(ui->nameEdit, &QLineEdit::textChanged, this, &EditRecipe::is_changed);
     connect(ui->notesEdit, SIGNAL(textChanged()), this, SLOT(is_changed()));
     connect(ui->typeEdit, &QComboBox::currentTextChanged, this, &EditRecipe::is_changed);
     connect(ui->batch_sizeEdit, &QDoubleSpinBox::textChanged, this, &EditRecipe::is_changed);
     connect(ui->boil_timeEdit, &QSpinBox::textChanged, this, &EditRecipe::is_changed);
     connect(ui->efficiencyEdit, &QDoubleSpinBox::textChanged, this, &EditRecipe::is_changed);
-
+    connect(ui->beerstyleEdit, &QComboBox::currentTextChanged, this, &EditRecipe::style_changed);
+    connect(ui->est_ogEdit, &QDoubleSpinBox::textChanged, this, &EditRecipe::is_changed);
     connect(ui->color_methodEdit, &QComboBox::currentTextChanged, this, &EditRecipe::is_changed);
+    connect(ui->ibu_methodEdit, &QComboBox::currentTextChanged, this, &EditRecipe::is_changed);
 
-    connect(ui->ibu_methodEdit, &QComboBox::currentTextChanged, this, &EditRecipe::is_changed);
+    // All signals from tab "Fermentables"
+    connect(ui->est_og2Edit, &QDoubleSpinBox::textChanged, this, &EditRecipe::is_changed);
+//    connect(ui->fermentablesTable, SIGNAL(cellChanged(int, int)), this, SLOT(cell_Changed(int, int)));
+
+    // All signals from tab "Hops"
+//    connect(ui->hopsTable, SIGNAL(cellChanged(int, int)), this, SLOT(cell_Changed(int, int)));
+
+    // All signals from tab "Miscs"
+//    connect(ui->hopsTable, SIGNAL(cellChanged(int, int)), this, SLOT(cell_Changed(int, int)));
+
+    // All signals from tab "Yeasts"
+//    connect(ui->hopsTable, SIGNAL(cellChanged(int, int)), this, SLOT(cell_Changed(int, int)));
+
+    // All signals from tab "Mash"
+//    connect(ui->hopsTable, SIGNAL(cellChanged(int, int)), this, SLOT(cell_Changed(int, int)));
+
+    // All signals from tab "Water"
 
     ui->saveButton->setEnabled(false);
     ui->deleteButton->setEnabled((id >= 0) ? true:false);
+
+    emit refreshAll();
 }
 
 
@@ -192,6 +282,230 @@
 }
 
 
+void EditRecipe::refreshFermentables()
+{
+    QString w;
+    QWidget* pWidget;
+    QHBoxLayout* pLayout;
+    QTableWidgetItem *item;
+    QLabel *label;
+    double  d;
+    int j;
+    int total = 0;
+
+    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. */
+    this->ignoreChanges = true;
+
+    const QStringList labels({tr("Fermentable"), tr("EBC"), tr("Type"), tr("Graintype"), tr("When"), tr("Yield"), tr("Amount"), tr("Procent"), tr("100%"), tr("Button")});
+    ui->fermentablesTable->setColumnCount(10);
+    ui->fermentablesTable->setColumnWidth(0, 350);     /* Fermentable	*/
+    ui->fermentablesTable->setColumnWidth(1,  50);     /* Color		*/
+    ui->fermentablesTable->setColumnWidth(2,  75);     /* Type		*/
+    ui->fermentablesTable->setColumnWidth(3,  75);     /* Graintype	*/
+    ui->fermentablesTable->setColumnWidth(4,  75);     /* Added		*/
+    ui->fermentablesTable->setColumnWidth(5,  75);     /* Yield		*/
+    ui->fermentablesTable->setColumnWidth(6,  75);     /* Amount	*/
+    ui->fermentablesTable->setColumnWidth(7,  60);     /* Procent	*/
+    ui->fermentablesTable->setColumnWidth(8,  50);     /* 100%		*/
+    ui->fermentablesTable->setColumnWidth(9,  80);     /* Button	*/
+    ui->fermentablesTable->setHorizontalHeaderLabels(labels);
+    ui->fermentablesTable->verticalHeader()->hide();
+    ui->fermentablesTable->setRowCount(this->fermentables.array().size());
+
+    if (this->fermentables.isArray()) {
+	for (int i = 0; i < this->fermentables.array().size(); i++) {
+            QJsonObject obj = this->fermentables.array().at(i).toObject();
+
+	    w = obj["f_supplier"].toString()+" / "+obj["f_name"].toString();
+            ui->fermentablesTable->setItem(i, 0, new QTableWidgetItem(w));
+
+	    if (obj["f_color"].isString())
+                d = QString(obj["f_color"].toString()).toDouble();
+            else
+                d = obj["f_color"].toDouble();
+            w = QString("%1").arg(d, 1, 'f', 0, '0');
+            item = new QTableWidgetItem(w);
+            item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+            ui->fermentablesTable->setItem(i, 1, item);
+
+	    if (obj["f_type"].isString())
+                j = QString(obj["f_type"].toString()).toInt();
+            else
+                j = obj["f_type"].toInt();
+	    item = new QTableWidgetItem(f_types[j]);
+	    item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter);
+	    ui->fermentablesTable->setItem(i, 2, item);
+
+	    if (obj["f_graintype"].isString())
+                j = QString(obj["f_graintype"].toString()).toInt();
+            else
+                j = obj["f_graintype"].toInt();
+            item = new QTableWidgetItem(f_graintypes[j]);
+            item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter);
+            ui->fermentablesTable->setItem(i, 3, item);
+
+	    if (obj["f_added"].isString())
+                j = QString(obj["f_added"].toString()).toInt();
+            else
+                j = obj["f_added"].toInt();
+            item = new QTableWidgetItem(f_added[j]);
+            item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter);
+            ui->fermentablesTable->setItem(i, 4, item);
+
+	    if (obj["f_yield"].isString())
+                d = QString(obj["f_yield"].toString()).toDouble();
+            else
+                d = obj["f_yield"].toDouble();
+            w = QString("%1%").arg(d, 2, 'f', 1, '0');
+            item = new QTableWidgetItem(w);
+            item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+            ui->fermentablesTable->setItem(i, 5, item);
+
+	    if (obj["f_amount"].isString())
+                d = QString(obj["f_amount"].toString()).toDouble();
+            else
+                d = obj["f_amount"].toDouble();
+            w = QString("%1 Kg").arg(d, 4, 'f', 3, '0');
+            item = new QTableWidgetItem(w);
+            item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+            ui->fermentablesTable->setItem(i, 6, item);
+
+	    if (obj["f_percentage"].isString())
+                d = QString(obj["f_percentage"].toString()).toDouble();
+            else
+                d = obj["f_percentage"].toDouble();
+            w = QString("%1%").arg(d, 2, 'f', 1, '0');
+            item = new QTableWidgetItem(w);
+            item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+            ui->fermentablesTable->setItem(i, 7, item);
+
+	    if (obj["f_adjust_to_total_100"].toString().toInt()) {
+            	pWidget = new QWidget();
+            	label = new QLabel;
+            	label->setPixmap(QPixmap(":icons/silk/tick.png"));
+            	pLayout = new QHBoxLayout(pWidget);
+            	pLayout->addWidget(label);
+            	pLayout->setAlignment(Qt::AlignCenter);
+            	pLayout->setContentsMargins(0, 0, 0, 0);
+            	pWidget->setLayout(pLayout);
+            	ui->fermentablesTable->setCellWidget(i, 8, pWidget);
+            } else {
+            	ui->fermentablesTable->removeCellWidget(i, 8);
+            }
+
+	    /* Add the Delete row button */
+            pWidget = new QWidget();
+            QPushButton* btn_edit = new QPushButton();
+            btn_edit->setObjectName(QString("%1").arg(i));  /* Send row with the button */
+            btn_edit->setText(tr("Delete"));
+            connect(btn_edit, SIGNAL(clicked()), this, SLOT(on_deleteFermentRow_clicked()));
+            pLayout = new QHBoxLayout(pWidget);
+            pLayout->addWidget(btn_edit);
+            pLayout->setContentsMargins(5, 0, 5, 0);
+            pWidget->setLayout(pLayout);
+            ui->fermentablesTable->setCellWidget(i, 9, pWidget);
+	}
+    }
+
+    this->ignoreChanges = false;
+}
+
+
+void EditRecipe::refreshHops()
+{
+}
+
+
+void EditRecipe::refreshMiscs()
+{
+}
+
+
+void EditRecipe::refreshYeasts()
+{
+}
+
+
+void EditRecipe::refreshMashs()
+{
+}
+
+
+void EditRecipe::refreshAll()
+{
+    refreshFermentables();
+
+    calcFermentables();
+}
+
+
+void EditRecipe::calcFermentables()
+{
+    int		i;
+    bool	my_100 = false;
+    double	psugar = 0, pcara = 0, d, s = 0, x;
+    double	vol = 0;		// Volume sugars after boil
+    double	addedS = 0;		// Added sugars after boil
+    double	addedmass = 0;		// Added mass after boil
+    double	mvol = 0;		// Mash volume
+    double	lintner = 0;		// Total recipe lintner
+    double	mashkg = 0;
+    double	sugarsf = 0;		// fermentable sugars mash + boil
+    double	sugarsm = 0;		// fermentable sugars in mash
+    double	sugardensity = 1.611;	// kg/l in solution
+    QJsonObject obj;
+
+    qDebug() << "calcFermentables()";
+
+    // Get mashtemp and mashtime from the Mash schedule.
+
+    if (this->fermentables.array().size() < 1) {
+	qDebug() << "  no fermentables, return.";
+	return;
+    }
+
+    for (i = 0; i < this->fermentables.array().size(); i++) {
+	obj = this->fermentables.array().at(i).toObject();
+	if (obj["f_adjust_to_total_100"].toInt()) {
+	    my_100 = 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
+	    if (mvol > 0) {							// If mash volume is known
+		mvol += obj["f_amount"].toDouble() * obj["f_moisture"].toDouble() / 100;
+		s += d;
+	    }
+	    d = ui->efficiencyEdit->value() / 100 * d;
+	    sugarsm += d;
+	    mashkg += obj["f_amount"].toDouble();
+	}
+	if (obj["f_added"].toInt() == 0 || obj["f_added"].toInt() == 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 (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 (obj["f_added"].toInt() < 4) {
+	    // colors
+	}
+    }
+
+    qDebug() << "  lintner" << lintner << "  mashkg" << mashkg << "final" << round(lintner / mashkg);
+    ui->lintnerShow->setValue(round(lintner / mashkg));
+}
+
+
 /*
  * Window header, mark any change with '**'
  */
@@ -288,12 +602,57 @@
 }
 
 
+/*
+ * New beerstyle is selected.
+ */
+void EditRecipe::style_changed()
+{
+    QSqlQuery query;
+
+    if (ui->beerstyleEdit->currentIndex() < 1)
+	return;
+
+    query.prepare("SELECT * FROM profile_styles ORDER BY style_guide,style_letter,name");
+    query.exec();
+    query.first();
+    // Skip to the record index.
+    for (int i = 0; i < (ui->beerstyleEdit->currentIndex() - 1); i++) {
+        query.next();
+    }
+    // Set relevant fields and update ranges.
+    ui->st_nameEdit->setText(query.value(1).toString());
+    ui->st_catEdit->setText(query.value(2).toString());
+    ui->st_catnrEdit->setText(query.value(3).toString());
+    ui->st_groupEdit->setText(query.value(4).toString());
+    ui->st_guideEdit->setText(query.value(5).toString());
+    ui->st_typeEdit->setText(s_types[query.value(6).toInt()]);
+    ui->est_ogShow->setRange(query.value(7).toDouble(), query.value(8).toDouble());
+    ui->est_fgShow->setRange(query.value(9).toDouble(), query.value(10).toDouble());
+    ui->est_ibuShow->setRange(query.value(11).toDouble(), query.value(12).toDouble());
+    ui->est_colorShow->setRange(query.value(13).toDouble(), query.value(14).toDouble());
+    ui->est_carbShow->setRange(query.value(15).toDouble(), query.value(16).toDouble());
+    ui->est_abvShow->setRange(query.value(17).toDouble(), query.value(18).toDouble());
+
+    is_changed();
+}
+
+
 void EditRecipe::time_changed()
 {
     is_changed();
 }
 
 
+void EditRecipe::on_deleteFermentRow_clicked()
+{
+    QPushButton *pb = qobject_cast<QPushButton *>(QObject::sender());
+    int row = pb->objectName().toInt();
+    qDebug() << "Delete row" << row;
+    ui->fermentablesTable->removeRow(row);
+//    make_Json();
+}
+
+
 void EditRecipe::on_quitButton_clicked()
 {
     if (this->textIsChanged) {

mercurial