Added change beerstyle, the fermentables table, and first part of calcFermentables to the recipe editor.

Sat, 02 Apr 2022 23:01:13 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Sat, 02 Apr 2022 23:01:13 +0200
changeset 101
1d14d3bf2465
parent 100
d11a3e713e3b
child 102
b017001850df

Added change beerstyle, the fermentables table, and first part of calcFermentables to the recipe editor.

src/EditRecipe.cpp file | annotate | diff | comparison | revisions
src/EditRecipe.h file | annotate | diff | comparison | revisions
src/RangedSlider.cpp file | annotate | diff | comparison | revisions
ui/EditRecipe.ui file | annotate | diff | comparison | revisions
--- 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) {
--- a/src/EditRecipe.h	Fri Apr 01 17:25:42 2022 +0200
+++ b/src/EditRecipe.h	Sat Apr 02 23:01:13 2022 +0200
@@ -2,7 +2,8 @@
 #define _EDITRECIPE_H
 
 #include <QDialog>
-
+#include <QStringList>
+#include <QJsonDocument>
 
 namespace Ui {
 class EditRecipe;
@@ -24,14 +25,32 @@
     void on_quitButton_clicked();
     void on_deleteButton_clicked();
     void is_changed();
+    void style_changed();
     void time_changed();
+    void refreshFermentables();
+    void refreshHops();
+    void refreshMiscs();
+    void refreshYeasts();
+    void refreshMashs();
+    void refreshAll();
+    void on_deleteFermentRow_clicked();
 
 private:
     Ui::EditRecipe *ui;
+    QStringList s_types = { tr("Lager"), tr("Ale"), tr("Mead"), tr("Wheat"), tr("Mixed"), tr("Cider") };
+    QStringList f_types = { tr("Grain"), tr("Sugar"), tr("Extract"), tr("Dry extract"), tr("Adjunct") };
+    QStringList f_graintypes = { tr("Base"), tr("Roast"), tr("Crystal"), tr("Kilned"), tr("Sour Malt"), tr("Special"), tr("No malt")};
+    QStringList f_added = { tr("Mash"), tr("Boil"), tr("Fermentation"), tr("Lagering"), tr("Bottle"), tr("Kegs") };
+    QString bar_red = "QProgressBar::chunk {background: #FF0000;}";
+    QString bar_orange = "QProgressBar::chunk {background: #EB7331;}";
+    QString bar_green = "QProgressBar::chunk {background: #008C00;}";
     int recno, lasttime = 0;
     bool textIsChanged = false;
+    bool ignoreChanges = false;
+    QJsonDocument fermentables, hops, miscs, yeasts, mashs;
 
     void WindowTitle();
+    void calcFermentables();
 };
 
 #endif
--- a/src/RangedSlider.cpp	Fri Apr 01 17:25:42 2022 +0200
+++ b/src/RangedSlider.cpp	Sat Apr 02 23:01:13 2022 +0200
@@ -105,7 +105,6 @@
 
     if (_markerTextIsValue) {
 	_markerText = QString("%1").arg(value, 0, 'f', _prec);
-	qDebug() << _markerText;
     }
 
     update();
--- a/ui/EditRecipe.ui	Fri Apr 01 17:25:42 2022 +0200
+++ b/ui/EditRecipe.ui	Sat Apr 02 23:01:13 2022 +0200
@@ -84,7 +84,7 @@
        <rect>
         <x>0</x>
         <y>0</y>
-        <width>1131</width>
+        <width>1128</width>
         <height>501</height>
        </rect>
       </property>
@@ -95,7 +95,7 @@
        <enum>QTabWidget::Rounded</enum>
       </property>
       <property name="currentIndex">
-       <number>0</number>
+       <number>1</number>
       </property>
       <property name="elideMode">
        <enum>Qt::ElideNone</enum>
@@ -629,7 +629,7 @@
          <rect>
           <x>510</x>
           <y>350</y>
-          <width>201</width>
+          <width>141</width>
           <height>23</height>
          </rect>
         </property>
@@ -649,7 +649,7 @@
          <rect>
           <x>510</x>
           <y>200</y>
-          <width>201</width>
+          <width>226</width>
           <height>23</height>
          </rect>
         </property>
@@ -807,7 +807,7 @@
          <rect>
           <x>510</x>
           <y>380</y>
-          <width>201</width>
+          <width>141</width>
           <height>23</height>
          </rect>
         </property>
@@ -1013,6 +1013,22 @@
          <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
         </property>
        </widget>
+       <widget class="QLabel" name="beerstyleLabel">
+        <property name="geometry">
+         <rect>
+          <x>370</x>
+          <y>200</y>
+          <width>131</width>
+          <height>20</height>
+         </rect>
+        </property>
+        <property name="text">
+         <string>Select style:</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+       </widget>
       </widget>
       <widget class="QWidget" name="fermentables">
        <attribute name="icon">
@@ -1022,6 +1038,265 @@
        <attribute name="title">
         <string>Fermentables</string>
        </attribute>
+       <widget class="QLabel" name="est_color2Label">
+        <property name="geometry">
+         <rect>
+          <x>0</x>
+          <y>10</y>
+          <width>131</width>
+          <height>20</height>
+         </rect>
+        </property>
+        <property name="text">
+         <string>Color EBC:</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+       </widget>
+       <widget class="QDoubleSpinBox" name="est_color2Edit">
+        <property name="geometry">
+         <rect>
+          <x>140</x>
+          <y>10</y>
+          <width>71</width>
+          <height>24</height>
+         </rect>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+        <property name="readOnly">
+         <bool>true</bool>
+        </property>
+        <property name="buttonSymbols">
+         <enum>QAbstractSpinBox::NoButtons</enum>
+        </property>
+        <property name="accelerated">
+         <bool>false</bool>
+        </property>
+        <property name="decimals">
+         <number>0</number>
+        </property>
+        <property name="minimum">
+         <double>0.000000000000000</double>
+        </property>
+        <property name="maximum">
+         <double>400.000000000000000</double>
+        </property>
+        <property name="singleStep">
+         <double>1.000000000000000</double>
+        </property>
+       </widget>
+       <widget class="QLabel" name="est_og2Label">
+        <property name="geometry">
+         <rect>
+          <x>0</x>
+          <y>40</y>
+          <width>131</width>
+          <height>20</height>
+         </rect>
+        </property>
+        <property name="text">
+         <string>Estimated OG:</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+       </widget>
+       <widget class="QDoubleSpinBox" name="est_og2Edit">
+        <property name="geometry">
+         <rect>
+          <x>140</x>
+          <y>40</y>
+          <width>71</width>
+          <height>24</height>
+         </rect>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+        <property name="buttonSymbols">
+         <enum>QAbstractSpinBox::UpDownArrows</enum>
+        </property>
+        <property name="accelerated">
+         <bool>true</bool>
+        </property>
+        <property name="decimals">
+         <number>3</number>
+        </property>
+        <property name="minimum">
+         <double>0.980000000000000</double>
+        </property>
+        <property name="maximum">
+         <double>2.000000000000000</double>
+        </property>
+        <property name="singleStep">
+         <double>0.001000000000000</double>
+        </property>
+       </widget>
+       <widget class="QLabel" name="perc_mashLabel">
+        <property name="geometry">
+         <rect>
+          <x>440</x>
+          <y>10</y>
+          <width>131</width>
+          <height>20</height>
+         </rect>
+        </property>
+        <property name="text">
+         <string>Mash tun %:</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+       </widget>
+       <widget class="QLabel" name="perc_sugarLabel">
+        <property name="geometry">
+         <rect>
+          <x>440</x>
+          <y>40</y>
+          <width>131</width>
+          <height>20</height>
+         </rect>
+        </property>
+        <property name="text">
+         <string>Sugars %:</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+       </widget>
+       <widget class="QLabel" name="perc_caraLabel">
+        <property name="geometry">
+         <rect>
+          <x>440</x>
+          <y>70</y>
+          <width>131</width>
+          <height>20</height>
+         </rect>
+        </property>
+        <property name="text">
+         <string>Cara/crystal %:</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+       </widget>
+       <widget class="QLabel" name="lintnerLabel">
+        <property name="geometry">
+         <rect>
+          <x>440</x>
+          <y>100</y>
+          <width>131</width>
+          <height>20</height>
+         </rect>
+        </property>
+        <property name="text">
+         <string>Lintner:</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+       </widget>
+       <widget class="QTableWidget" name="fermentablesTable">
+        <property name="geometry">
+         <rect>
+          <x>10</x>
+          <y>130</y>
+          <width>1101</width>
+          <height>331</height>
+         </rect>
+        </property>
+       </widget>
+       <widget class="QProgressBar" name="lintnerShow">
+        <property name="geometry">
+         <rect>
+          <x>580</x>
+          <y>100</y>
+          <width>381</width>
+          <height>20</height>
+         </rect>
+        </property>
+        <property name="maximum">
+         <number>200</number>
+        </property>
+        <property name="value">
+         <number>24</number>
+        </property>
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="format">
+         <string>%v lintner</string>
+        </property>
+       </widget>
+       <widget class="QProgressBar" name="perc_mashShow">
+        <property name="geometry">
+         <rect>
+          <x>580</x>
+          <y>10</y>
+          <width>381</width>
+          <height>20</height>
+         </rect>
+        </property>
+        <property name="maximum">
+         <number>120</number>
+        </property>
+        <property name="value">
+         <number>24</number>
+        </property>
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="format">
+         <string>%v%</string>
+        </property>
+       </widget>
+       <widget class="QProgressBar" name="perc_sugarsShow">
+        <property name="geometry">
+         <rect>
+          <x>580</x>
+          <y>40</y>
+          <width>381</width>
+          <height>20</height>
+         </rect>
+        </property>
+        <property name="maximum">
+         <number>50</number>
+        </property>
+        <property name="value">
+         <number>24</number>
+        </property>
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="format">
+         <string>%v%</string>
+        </property>
+       </widget>
+       <widget class="QProgressBar" name="perc_caraShow">
+        <property name="geometry">
+         <rect>
+          <x>580</x>
+          <y>70</y>
+          <width>381</width>
+          <height>20</height>
+         </rect>
+        </property>
+        <property name="maximum">
+         <number>50</number>
+        </property>
+        <property name="value">
+         <number>24</number>
+        </property>
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="format">
+         <string>%v%</string>
+        </property>
+       </widget>
       </widget>
       <widget class="QWidget" name="hops">
        <attribute name="icon">
@@ -1031,6 +1306,142 @@
        <attribute name="title">
         <string>Hops</string>
        </attribute>
+       <widget class="QLabel" name="est_ibu2Label">
+        <property name="geometry">
+         <rect>
+          <x>0</x>
+          <y>10</y>
+          <width>131</width>
+          <height>20</height>
+         </rect>
+        </property>
+        <property name="text">
+         <string>Bitterness IBU:</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+       </widget>
+       <widget class="QDoubleSpinBox" name="est_ibu2Edit">
+        <property name="geometry">
+         <rect>
+          <x>140</x>
+          <y>10</y>
+          <width>71</width>
+          <height>24</height>
+         </rect>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+        <property name="readOnly">
+         <bool>true</bool>
+        </property>
+        <property name="buttonSymbols">
+         <enum>QAbstractSpinBox::NoButtons</enum>
+        </property>
+        <property name="accelerated">
+         <bool>false</bool>
+        </property>
+        <property name="decimals">
+         <number>0</number>
+        </property>
+        <property name="minimum">
+         <double>0.000000000000000</double>
+        </property>
+        <property name="maximum">
+         <double>400.000000000000000</double>
+        </property>
+        <property name="singleStep">
+         <double>1.000000000000000</double>
+        </property>
+       </widget>
+       <widget class="QLabel" name="hop_tasteLabel">
+        <property name="geometry">
+         <rect>
+          <x>220</x>
+          <y>10</y>
+          <width>131</width>
+          <height>20</height>
+         </rect>
+        </property>
+        <property name="text">
+         <string>Hop taste:</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+       </widget>
+       <widget class="QLabel" name="hop_aromaLabel">
+        <property name="geometry">
+         <rect>
+          <x>670</x>
+          <y>10</y>
+          <width>131</width>
+          <height>20</height>
+         </rect>
+        </property>
+        <property name="text">
+         <string>Hop aroma:</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+       </widget>
+       <widget class="QProgressBar" name="hop_tasteShow">
+        <property name="geometry">
+         <rect>
+          <x>360</x>
+          <y>10</y>
+          <width>301</width>
+          <height>20</height>
+         </rect>
+        </property>
+        <property name="maximum">
+         <number>100</number>
+        </property>
+        <property name="value">
+         <number>24</number>
+        </property>
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="format">
+         <string>%v%</string>
+        </property>
+       </widget>
+       <widget class="QProgressBar" name="hop_aromaShow">
+        <property name="geometry">
+         <rect>
+          <x>810</x>
+          <y>10</y>
+          <width>301</width>
+          <height>20</height>
+         </rect>
+        </property>
+        <property name="maximum">
+         <number>100</number>
+        </property>
+        <property name="value">
+         <number>24</number>
+        </property>
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="format">
+         <string>%v%</string>
+        </property>
+       </widget>
+       <widget class="QTableWidget" name="hopsTable">
+        <property name="geometry">
+         <rect>
+          <x>10</x>
+          <y>50</y>
+          <width>1101</width>
+          <height>411</height>
+         </rect>
+        </property>
+       </widget>
       </widget>
       <widget class="QWidget" name="miscs">
        <attribute name="icon">
@@ -1040,6 +1451,16 @@
        <attribute name="title">
         <string>Miscs</string>
        </attribute>
+       <widget class="QTableWidget" name="miscsTable">
+        <property name="geometry">
+         <rect>
+          <x>10</x>
+          <y>10</y>
+          <width>1101</width>
+          <height>451</height>
+         </rect>
+        </property>
+       </widget>
       </widget>
       <widget class="QWidget" name="yeasts">
        <attribute name="icon">
@@ -1049,6 +1470,216 @@
        <attribute name="title">
         <string>Yeasts</string>
        </attribute>
+       <widget class="QLabel" name="est_og3Label">
+        <property name="geometry">
+         <rect>
+          <x>50</x>
+          <y>10</y>
+          <width>131</width>
+          <height>20</height>
+         </rect>
+        </property>
+        <property name="text">
+         <string>Estimated OG:</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+       </widget>
+       <widget class="QDoubleSpinBox" name="est_og3Edit">
+        <property name="geometry">
+         <rect>
+          <x>190</x>
+          <y>10</y>
+          <width>71</width>
+          <height>24</height>
+         </rect>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+        <property name="buttonSymbols">
+         <enum>QAbstractSpinBox::NoButtons</enum>
+        </property>
+        <property name="accelerated">
+         <bool>true</bool>
+        </property>
+        <property name="decimals">
+         <number>3</number>
+        </property>
+        <property name="minimum">
+         <double>0.980000000000000</double>
+        </property>
+        <property name="maximum">
+         <double>2.000000000000000</double>
+        </property>
+        <property name="singleStep">
+         <double>0.001000000000000</double>
+        </property>
+       </widget>
+       <widget class="QLabel" name="est_fg3Label">
+        <property name="geometry">
+         <rect>
+          <x>50</x>
+          <y>40</y>
+          <width>131</width>
+          <height>20</height>
+         </rect>
+        </property>
+        <property name="text">
+         <string>Estimated FG:</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+       </widget>
+       <widget class="QDoubleSpinBox" name="est_fg3Edit">
+        <property name="geometry">
+         <rect>
+          <x>190</x>
+          <y>40</y>
+          <width>71</width>
+          <height>24</height>
+         </rect>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+        <property name="buttonSymbols">
+         <enum>QAbstractSpinBox::NoButtons</enum>
+        </property>
+        <property name="accelerated">
+         <bool>true</bool>
+        </property>
+        <property name="decimals">
+         <number>3</number>
+        </property>
+        <property name="minimum">
+         <double>0.980000000000000</double>
+        </property>
+        <property name="maximum">
+         <double>2.000000000000000</double>
+        </property>
+        <property name="singleStep">
+         <double>0.001000000000000</double>
+        </property>
+       </widget>
+       <widget class="QLabel" name="est_abv2Label">
+        <property name="geometry">
+         <rect>
+          <x>570</x>
+          <y>10</y>
+          <width>131</width>
+          <height>20</height>
+         </rect>
+        </property>
+        <property name="text">
+         <string>Alcohol Volume:</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+       </widget>
+       <widget class="QDoubleSpinBox" name="est_abv2Edit">
+        <property name="geometry">
+         <rect>
+          <x>710</x>
+          <y>10</y>
+          <width>71</width>
+          <height>24</height>
+         </rect>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+        <property name="readOnly">
+         <bool>true</bool>
+        </property>
+        <property name="buttonSymbols">
+         <enum>QAbstractSpinBox::NoButtons</enum>
+        </property>
+        <property name="accelerated">
+         <bool>false</bool>
+        </property>
+        <property name="suffix">
+         <string> %</string>
+        </property>
+        <property name="decimals">
+         <number>1</number>
+        </property>
+        <property name="minimum">
+         <double>0.000000000000000</double>
+        </property>
+        <property name="maximum">
+         <double>80.000000000000000</double>
+        </property>
+        <property name="singleStep">
+         <double>0.100000000000000</double>
+        </property>
+       </widget>
+       <widget class="QLabel" name="est_svgLabel">
+        <property name="geometry">
+         <rect>
+          <x>550</x>
+          <y>40</y>
+          <width>151</width>
+          <height>20</height>
+         </rect>
+        </property>
+        <property name="text">
+         <string>Appearant Attenuation:</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+       </widget>
+       <widget class="QDoubleSpinBox" name="est_svgEdit">
+        <property name="geometry">
+         <rect>
+          <x>710</x>
+          <y>40</y>
+          <width>71</width>
+          <height>24</height>
+         </rect>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+        <property name="readOnly">
+         <bool>true</bool>
+        </property>
+        <property name="buttonSymbols">
+         <enum>QAbstractSpinBox::NoButtons</enum>
+        </property>
+        <property name="accelerated">
+         <bool>false</bool>
+        </property>
+        <property name="suffix">
+         <string> %</string>
+        </property>
+        <property name="decimals">
+         <number>1</number>
+        </property>
+        <property name="minimum">
+         <double>0.000000000000000</double>
+        </property>
+        <property name="maximum">
+         <double>80.000000000000000</double>
+        </property>
+        <property name="singleStep">
+         <double>0.100000000000000</double>
+        </property>
+       </widget>
+       <widget class="QTableWidget" name="yeastsTable">
+        <property name="geometry">
+         <rect>
+          <x>10</x>
+          <y>90</y>
+          <width>1101</width>
+          <height>371</height>
+         </rect>
+        </property>
+       </widget>
       </widget>
       <widget class="QWidget" name="mash">
        <attribute name="icon">
@@ -1058,6 +1689,16 @@
        <attribute name="title">
         <string>Mash</string>
        </attribute>
+       <widget class="QTableWidget" name="mashsTable">
+        <property name="geometry">
+         <rect>
+          <x>10</x>
+          <y>70</y>
+          <width>1101</width>
+          <height>391</height>
+         </rect>
+        </property>
+       </widget>
       </widget>
       <widget class="QWidget" name="water">
        <attribute name="icon">

mercurial