Added yeastpack editor. Expanded the database upgrade. On startup, recount the yeastpack used fields.

Mon, 30 Jan 2023 17:05:13 +0100

author
Michiel Broek <mbroek@mbse.eu>
date
Mon, 30 Jan 2023 17:05:13 +0100
changeset 480
94b3def5d778
parent 479
28f0e43e9f08
child 481
8a25dbe682eb

Added yeastpack editor. Expanded the database upgrade. On startup, recount the yeastpack used fields.

CMakeLists.txt file | annotate | diff | comparison | revisions
resources/icons.qrc file | annotate | diff | comparison | revisions
resources/icons/bms/yeastvial.png file | annotate | diff | comparison | revisions
src/EditYeastPack.cpp file | annotate | diff | comparison | revisions
src/EditYeastPack.h file | annotate | diff | comparison | revisions
src/InventoryYeastPacks.cpp file | annotate | diff | comparison | revisions
src/InventoryYeastPacks.h file | annotate | diff | comparison | revisions
src/MainWindow.cpp file | annotate | diff | comparison | revisions
src/MainWindow.h file | annotate | diff | comparison | revisions
src/global.h file | annotate | diff | comparison | revisions
translations/bmsapp_en.ts file | annotate | diff | comparison | revisions
translations/bmsapp_nl.ts file | annotate | diff | comparison | revisions
ui/EditYeastPack.ui file | annotate | diff | comparison | revisions
ui/MainWindow.ui file | annotate | diff | comparison | revisions
--- a/CMakeLists.txt	Sun Jan 29 14:40:43 2023 +0100
+++ b/CMakeLists.txt	Mon Jan 30 17:05:13 2023 +0100
@@ -197,6 +197,8 @@
     ${SRCDIR}/EditHop.cpp
     ${SRCDIR}/InventoryYeasts.cpp
     ${SRCDIR}/EditYeast.cpp
+    ${SRCDIR}/InventoryYeastPacks.cpp
+    ${SRCDIR}/EditYeastPack.cpp
     ${SRCDIR}/InventoryMiscs.cpp
     ${SRCDIR}/EditMisc.cpp
     ${SRCDIR}/InventoryWaters.cpp
@@ -263,6 +265,8 @@
     ${SRCDIR}/EditHop.h
     ${SRCDIR}/InventoryYeasts.h
     ${SRCDIR}/EditYeast.h
+    ${SRCDIR}/InventoryYeastPacks.h
+    ${SRCDIR}/EditYeastPack.h
     ${SRCDIR}/InventoryMiscs.h
     ${SRCDIR}/EditMisc.h
     ${SRCDIR}/InventoryWaters.h
@@ -324,6 +328,7 @@
     ${UIDIR}/EditFermentable.ui
     ${UIDIR}/EditHop.ui
     ${UIDIR}/EditYeast.ui
+    ${UIDIR}/EditYeastPack.ui
     ${UIDIR}/EditMisc.ui
     ${UIDIR}/EditWater.ui
     ${UIDIR}/EditEquipment.ui
--- a/resources/icons.qrc	Sun Jan 29 14:40:43 2023 +0100
+++ b/resources/icons.qrc	Mon Jan 30 17:05:13 2023 +0100
@@ -1019,6 +1019,7 @@
 	<file>icons/bms/printer.png</file>
 	<file>icons/bms/refractometer.png</file>
 	<file>icons/bms/science.png</file>
+	<file>icons/bms/yeastvial.png</file>
 	<file>icons/bms/water.png</file>
     </qresource>
 </RCC>
Binary file resources/icons/bms/yeastvial.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/EditYeastPack.cpp	Mon Jan 30 17:05:13 2023 +0100
@@ -0,0 +1,308 @@
+/**
+ * EditYeastPack.cpp is part of bmsapp.
+ *
+ * bmsapp is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * bmsapp is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include "EditYeastPack.h"
+#include "../ui/ui_EditYeastPack.h"
+#include "MainWindow.h"
+#include "global.h"
+
+
+EditYeastPack::EditYeastPack(int id, QWidget *parent) : QDialog(parent), ui(new Ui::EditYeastPack)
+{
+    QSqlQuery query;
+
+    qDebug() << "EditYeastPack record:" << id;
+    ui->setupUi(this);
+    this->recno = id;
+
+    WindowTitle();
+
+    ui->formEdit->addItem(tr("Liquid"));
+    ui->formEdit->addItem(tr("Dry"));
+    ui->formEdit->addItem(tr("Slant"));
+    ui->formEdit->addItem(tr("Culture"));
+    ui->formEdit->addItem(tr("Frozen"));
+    ui->formEdit->addItem(tr("Bottle"));
+    ui->formEdit->addItem(tr("Dried"));
+
+    if (id >= 0) {
+	query.prepare("SELECT * FROM inventory_yeastpack WHERE record = :recno");
+	query.bindValue(":recno", id);
+	query.exec();
+	query.next();
+
+	ui->laboratoryEdit->setText(query.value("laboratory").toString());
+	ui->packageEdit->setText(query.value("package").toString());
+	ui->formEdit->setCurrentIndex(query.value("form").toInt());
+	ui->notesEdit->setPlainText(query.value("notes").toString());
+	ui->cellsEdit->setValue(query.value("cells").toDouble() / 1000000000);
+	ui->viabilityEdit->setValue(query.value("viability").toDouble());
+	ui->maxEdit->setValue(query.value("max").toInt());
+	ui->sizeEdit->setValue(query.value("size").toDouble() * 1000);
+	ui->usedEdit->setValue(query.value("used").toInt());
+
+    } else {
+	/* Set some defaults */
+	ui->formEdit->setCurrentIndex(YEAST_FORMS_DRY);
+	ui->viabilityEdit->setValue(0.99);
+	ui->maxEdit->setValue(100);
+	ui->usedEdit->setValue(0);
+    }
+
+    PackSet();
+    Viability();
+    connect(ui->laboratoryEdit, &QLineEdit::textChanged, this, &EditYeastPack::is_changed);
+    connect(ui->formEdit, &QComboBox::currentTextChanged, this, &EditYeastPack::form_changed);
+    connect(ui->packageEdit, &QLineEdit::textChanged, this, &EditYeastPack::is_changed);
+    connect(ui->notesEdit, SIGNAL(textChanged()), this, SLOT(is_changed()));
+    connect(ui->cellsEdit, &QDoubleSpinBox::textChanged, this, &EditYeastPack::is_changed);
+    connect(ui->viabilityEdit, &QDoubleSpinBox::textChanged, this, &EditYeastPack::viability_changed);
+    connect(ui->maxEdit, &QSpinBox::textChanged, this, &EditYeastPack::viability_changed);
+    connect(ui->sizeEdit, &QDoubleSpinBox::textChanged, this, &EditYeastPack::is_changed);
+
+    ui->saveButton->setEnabled(false);
+}
+
+
+EditYeastPack::~EditYeastPack()
+{
+    delete ui;
+    emit entry_changed();
+}
+
+
+/*
+ * Window header, mark any change with '**'
+ */
+void EditYeastPack::WindowTitle()
+{
+    QString txt;
+
+    if (this->recno < 0) {
+	txt = QString(tr("BMSapp - Add new yeast package"));
+    } else {
+	txt = QString(tr("BMSapp - Edit yeast package %1").arg(this->recno));
+    }
+
+    if (this->textIsChanged) {
+	txt.append((QString(" **")));
+    }
+    setWindowTitle(txt);
+}
+
+
+void EditYeastPack::on_saveButton_clicked()
+{
+    QSqlQuery query;
+
+    /* If there are errors in the form, show a message and do "return;" */
+    if (ui->laboratoryEdit->text().length() < 2) {
+	QMessageBox::warning(this, tr("Edit Yeast Package"), tr("Laboratory name empty or too short."));
+	return;
+    }
+    if (ui->packageEdit->text().length() < 2) {
+        QMessageBox::warning(this, tr("Edit Yeast Package"), tr("Package name empty or too short."));
+        return;
+    }
+
+    if (this->textIsChanged) {
+    	if (this->recno == -1) {
+    	    query.prepare("INSERT INTO inventory_yeastpack SET laboratory=:laboratory, form=:form, "
+		"package=:package, notes=:notes, cells=:cells, viability=:viability, max=:max, "
+		"size=:size, used='0', uuid = :uuid");
+    	} else {
+	    query.prepare("UPDATE inventory_yeastpack SET laboratory=:laboratory, form=:form, "
+		"package=:package, notes=:notes, cells=:cells, viability=:viability, max=:max, "
+                "size=:size WHERE record = :recno");
+    	}
+	query.bindValue(":laboratory", ui->laboratoryEdit->text());
+	query.bindValue(":form", ui->formEdit->currentIndex());
+	query.bindValue(":package", ui->packageEdit->text());
+	query.bindValue(":notes", ui->notesEdit->toPlainText());
+	query.bindValue(":cells", QString("%1").arg(ui->cellsEdit->value() * 1000000000, 1, 'f', 0, '0'));
+	query.bindValue(":viability", QString("%1").arg(ui->viabilityEdit->value(), 5, 'f', 4, '0'));
+	query.bindValue(":max", ui->maxEdit->value());
+	query.bindValue(":size", QString("%1").arg(ui->sizeEdit->value() / 1000, 5, 'f', 4, '0'));
+	if (this->recno == -1) {
+	    query.bindValue(":uuid", QUuid::createUuid().toString().mid(1, 36));
+	} else {
+	    query.bindValue(":recno", this->recno);
+	}
+	query.exec();
+	if (query.lastError().isValid()) {
+	    qWarning() << "EditYeastPack" << query.lastError();
+	    QMessageBox::warning(this, tr("Database error"),
+                        tr("MySQL error: %1\n%2\n%3")
+                        .arg(query.lastError().nativeErrorCode())
+                        .arg(query.lastError().driverText())
+                        .arg(query.lastError().databaseText()));
+	} else {
+	    qDebug() << "EditYeastPack Saved";
+	}
+    }
+
+    ui->saveButton->setEnabled(false);
+    this->textIsChanged = false;
+    WindowTitle();
+}
+
+
+void EditYeastPack::on_cloneButton_clicked()
+{
+    QSqlQuery query;
+    query.prepare("INSERT INTO inventory_yeastpack SET laboratory=:laboratory, form=:form, "
+                "package=:package, notes=:notes, cells=:cells, viability=:viability, max=:max, "
+                "size=:size, used=:used, uuid=:uuid");
+    query.bindValue(":laboratory", ui->laboratoryEdit->text());
+    query.bindValue(":form", ui->formEdit->currentIndex());
+    query.bindValue(":package", ui->packageEdit->text() + " [copy]");
+    query.bindValue(":notes", ui->notesEdit->toPlainText());
+    query.bindValue(":cells", QString("%1").arg(ui->cellsEdit->value() * 1000000000, 1, 'f', 0, '0'));
+    query.bindValue(":viability", QString("%1").arg(ui->viabilityEdit->value(), 5, 'f', 4, '0'));
+    query.bindValue(":max", ui->maxEdit->value());
+    query.bindValue(":size", QString("%1").arg(ui->sizeEdit->value() / 1000, 5, 'f', 4, '0'));
+    query.bindValue(":used", ui->usedEdit->value());
+    query.bindValue(":uuid", QUuid::createUuid().toString().mid(1, 36));
+    query.exec();
+    if (query.lastError().isValid()) {
+	qWarning() << "EditYeastPack" << query.lastError();
+	QMessageBox::warning(this, tr("Database error"),
+                        tr("MySQL error: %1\n%2\n%3")
+                        .arg(query.lastError().nativeErrorCode())
+                        .arg(query.lastError().driverText())
+                        .arg(query.lastError().databaseText()));
+    } else {
+	qDebug() << "EditYeastPack Clone saved";
+    }
+}
+
+
+void EditYeastPack::on_deleteButton_clicked()
+{
+    QSqlQuery query;
+
+    int rc = QMessageBox::warning(this, tr("Delete yeast pack"), tr("Delete %1").arg(ui->packageEdit->text()),
+                    QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
+    if (rc == QMessageBox::No)
+        return;
+
+    query.prepare("DELETE FROM inventory_yeastpack WHERE record = :recno");
+    query.bindValue(":recno", this->recno);
+    query.exec();
+    if (query.lastError().isValid()) {
+	qWarning() << "EditYeastPack" << query.lastError();
+	QMessageBox::warning(this, tr("Database error"),
+                        tr("MySQL error: %1\n%2\n%3")
+                        .arg(query.lastError().nativeErrorCode())
+                        .arg(query.lastError().driverText())
+                        .arg(query.lastError().databaseText()));
+    } else {
+	qDebug() << "EditYeastPack Deleted" << this->recno;
+    }
+
+    this->close();
+    this->setResult(1);
+}
+
+
+void EditYeastPack::Viability()
+{
+    double vpm = ui->viabilityEdit->value();
+    double max = ui->maxEdit->value();
+    double degrade = 1 - ((1 - vpm) / 30.41);	/* viability degradation per day. */
+    double base = max;
+
+    for (int i = 0; i < 182; i++) {
+	base = base * degrade;
+    }
+    if (base > max)
+	base = max;
+
+    ui->resultEdit->setValue(base);
+    qDebug() << "Viability()" << vpm << max << degrade << base;
+}
+
+
+void EditYeastPack::PackSet()
+{
+    if (ui->formEdit->currentIndex() == YEAST_FORMS_DRY || ui->formEdit->currentIndex() == YEAST_FORMS_DRIED) {
+	ui->sizeEdit->setSuffix(tr(" gr"));
+    } else {
+	ui->sizeEdit->setSuffix(tr(" ml"));
+    }
+
+    /*
+     * TODO: The delete button may be enabled for records with used > 0 if
+     *       there are more records with the same laboratory and form.
+     *       There should always be at least one record, the rest is allowed to
+     *       be deleted. So, we need to count.
+     */
+
+    if (ui->usedEdit->value() > 0) {
+	ui->laboratoryEdit->setReadOnly(true);
+	ui->formEdit->setDisabled(true);
+	ui->deleteButton->setEnabled(false);
+	qDebug() << "PackSet blocked";
+    } else {
+	ui->laboratoryEdit->setReadOnly(false);
+	ui->formEdit->setDisabled(false);
+	ui->deleteButton->setEnabled(true);
+    }
+}
+
+
+void EditYeastPack::is_changed()
+{
+    ui->saveButton->setEnabled(true);
+    this->textIsChanged = true;
+    WindowTitle();
+}
+
+
+void EditYeastPack::form_changed()
+{
+    PackSet();
+    is_changed();
+}
+
+
+void EditYeastPack::viability_changed()
+{
+    Viability();
+    is_changed();
+}
+
+
+void EditYeastPack::on_quitButton_clicked()
+{
+    if (this->textIsChanged) {
+	int rc = QMessageBox::warning(this, tr("Yeast package changed"), tr("The yeast package has been modified. Save changes?"),
+                                QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Save);
+        switch (rc) {
+            case QMessageBox::Save:
+                        on_saveButton_clicked();
+                        break;  /* Saved and then Quit */
+            case QMessageBox::Discard:
+                        break;  /* Quit without Save */
+            case QMessageBox::Cancel:
+                        return; /* Return to the editor page */
+        }
+    }
+
+    this->close();
+    this->setResult(1);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/EditYeastPack.h	Mon Jan 30 17:05:13 2023 +0100
@@ -0,0 +1,41 @@
+#ifndef _EDITYEASTPACK_H
+#define _EDITYEASTPACK_H
+
+#include <QDialog>
+
+
+namespace Ui {
+class EditYeastPack;
+}
+
+class EditYeastPack : public QDialog
+{
+    Q_OBJECT
+
+signals:
+    void entry_changed();
+
+public:
+    explicit EditYeastPack(int id, QWidget *parent = 0);
+    ~EditYeastPack();
+
+private slots:
+    void on_saveButton_clicked();
+    void on_cloneButton_clicked();
+    void on_quitButton_clicked();
+    void on_deleteButton_clicked();
+    void is_changed();
+    void form_changed();
+    void viability_changed();
+
+private:
+    Ui::EditYeastPack *ui;
+    int recno, lasttime = 0;
+    bool textIsChanged = false;
+
+    void WindowTitle();
+    void PackSet();
+    void Viability();
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/InventoryYeastPacks.cpp	Mon Jan 30 17:05:13 2023 +0100
@@ -0,0 +1,175 @@
+/**
+ * InventoryYeastPacks.cpp is part of bmsapp.
+ *
+ * bmsapp is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * bmsapp is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include "InventoryYeastPacks.h"
+#include "EditYeastPack.h"
+#include "MainWindow.h"
+#include "config.h"
+#include "global.h"
+
+
+InventoryYeastPacks::InventoryYeastPacks(QWidget *parent) : QDialog(parent)
+{
+    qDebug() << "InventoryYeastPacks start";
+
+    gridLayout = new QGridLayout(this);
+    gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
+    tableYeastPacks = new QTableWidget(this);
+    tableYeastPacks->setObjectName(QString::fromUtf8("tableYeastPacks"));
+    tableYeastPacks->setEnabled(true);
+    QSizePolicy sizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
+    sizePolicy.setHorizontalStretch(0);
+    sizePolicy.setVerticalStretch(0);
+    tableYeastPacks->setSizePolicy(sizePolicy);
+    tableYeastPacks->setMinimumSize(QSize(824, 0));
+    gridLayout->addWidget(tableYeastPacks, 0, 0, 1, 1);
+
+    groupBox = new QGroupBox(this);
+    groupBox->setObjectName(QString::fromUtf8("groupBox"));
+    groupBox->setEnabled(true);
+    groupBox->setFlat(false);
+    horizontalLayout = new QHBoxLayout(groupBox);
+    horizontalLayout->setSpacing(6);
+    horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));
+    horizontalLayout->setContentsMargins(0, 0, 0, 0);
+
+    quitButton = new QPushButton(groupBox);
+    quitButton->setObjectName(QString::fromUtf8("quitButton"));
+    quitButton->setMinimumSize(QSize(80, 24));
+    quitButton->setText(tr("Quit"));
+    QIcon icon;
+    icon.addFile(QString::fromUtf8(":icons/silk/door_out.png"), QSize(), QIcon::Normal, QIcon::Off);
+    quitButton->setIcon(icon);
+    horizontalLayout->addWidget(quitButton, 0, Qt::AlignLeft);
+
+    exportButton = new QPushButton(groupBox);
+    exportButton->setObjectName(QString::fromUtf8("exportButton"));
+    exportButton->setMinimumSize(QSize(80, 24));
+    exportButton->setText(tr("Export"));
+    QIcon icon1;
+    icon1.addFile(QString::fromUtf8(":/icons/silk/database_save.png"), QSize(), QIcon::Normal, QIcon::Off);
+    exportButton->setIcon(icon1);
+    horizontalLayout->addWidget(exportButton, 0, Qt::AlignCenter);
+
+    insertButton = new QPushButton(groupBox);
+    insertButton->setObjectName(QString::fromUtf8("insertButton"));
+    insertButton->setMinimumSize(QSize(80, 24));
+    insertButton->setText(tr("New"));
+    QIcon icon3;
+    icon3.addFile(QString::fromUtf8(":icons/silk/table_row_insert.png"), QSize(), QIcon::Normal, QIcon::Off);
+    insertButton->setIcon(icon3);
+    horizontalLayout->addWidget(insertButton, 0, Qt::AlignRight);
+    gridLayout->addWidget(groupBox, 1, 0, 1, 1);
+
+    connect(quitButton, SIGNAL(clicked()), parent, SLOT(fromInventoryYeastPacks()));
+    connect(insertButton, SIGNAL(clicked()), this, SLOT(on_insertButton_clicked()));
+    connect(exportButton, SIGNAL(clicked()), this, SLOT(on_exportButton_clicked()));
+    connect(this, SIGNAL(setStatus(QString)), parent, SLOT(statusMsg(QString)));
+    emit refreshTable();
+}
+
+
+void InventoryYeastPacks::refreshTable()
+{
+    QString w;
+    QWidget* pWidget;
+    QLabel *label;
+    QHBoxLayout* pLayout;
+
+    qDebug() << "InventoryYeastPacks reload";
+
+    QSqlQuery query("SELECT * FROM inventory_yeastpack ORDER BY laboratory,package");
+    const QStringList labels({tr("Laboratory"), tr("Package"), tr("Form"), tr("Size"), tr("Edit")});
+
+    /* origin supplier name type graintype color yield inventory Edit */
+    this->tableYeastPacks->setColumnCount(5);
+    this->tableYeastPacks->setColumnWidth(0, 250);	/* Laboratory	*/
+    this->tableYeastPacks->setColumnWidth(1, 250);	/* Package	*/
+    this->tableYeastPacks->setColumnWidth(2, 100);	/* Form		*/
+    this->tableYeastPacks->setColumnWidth(3, 100);	/* Size		*/
+    this->tableYeastPacks->setColumnWidth(4, 100);	/* Edit button	*/
+    this->tableYeastPacks->setRowCount(query.size());
+    this->tableYeastPacks->setHorizontalHeaderLabels(labels);
+    this->tableYeastPacks->verticalHeader()->hide();
+
+    QTableWidgetItem *rightitem = new QTableWidgetItem();
+    rightitem->setTextAlignment(Qt::AlignRight);
+
+    query.first();
+    for (int ridx = 0 ; ridx < query.size() ; ridx++ ) {
+	this->tableYeastPacks->setItem(ridx, 0, new QTableWidgetItem(query.value("laboratory").toString()));	/* Laboratory */
+	this->tableYeastPacks->setItem(ridx, 1, new QTableWidgetItem(query.value("package").toString()));	/* Name	*/
+	this->tableYeastPacks->setItem(ridx, 2, new QTableWidgetItem(QCoreApplication::translate("YeastForm", g_yeast_forms[query.value("form").toInt()])));
+
+	w = QString("");
+	if (query.value("form").toInt() == 1 || query.value("form").toInt() == 6) {
+	  w = QString("%1 gram").arg(query.value("size").toDouble() * 1000, 2, 'f', 1, '0');
+	} else {
+	  w = QString("%1 ml").arg(query.value("size").toDouble() * 1000, 2, 'f', 1, '0');
+	}
+	QTableWidgetItem *item = new QTableWidgetItem(w);
+	item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+	this->tableYeastPacks->setItem(ridx, 3, item);
+
+	/* Add the Edit button */
+	pWidget = new QWidget();
+	QPushButton* btn_edit = new QPushButton();
+	btn_edit->setObjectName(QString("%1").arg(query.value(0).toString()));	/* Send record with the button */
+	btn_edit->setText(tr("Edit"));
+	connect(btn_edit, SIGNAL(clicked()), this, SLOT(on_editButton_clicked()));
+	pLayout = new QHBoxLayout(pWidget);
+	pLayout->addWidget(btn_edit);
+	pLayout->setContentsMargins(5, 0, 5, 0);
+	pWidget->setLayout(pLayout);
+	this->tableYeastPacks->setCellWidget(ridx, 4, pWidget);
+	query.next();
+    }
+    emit setStatus(QString(tr("Total items: %1")).arg(query.size()));
+}
+
+
+InventoryYeastPacks::~InventoryYeastPacks() {}
+
+
+void InventoryYeastPacks::edit(int recno)
+{
+    EditYeastPack dialog(recno, this);
+    /* Signal from editor if a refresh is needed */
+    connect(&dialog, SIGNAL(entry_changed()), this, SLOT(refreshTable()));
+    dialog.setModal(true);
+    dialog.exec();
+}
+
+
+void InventoryYeastPacks::on_editButton_clicked()
+{
+    QPushButton *pb = qobject_cast<QPushButton *>(QObject::sender());
+    int recno = pb->objectName().toInt();
+    edit(recno);
+}
+
+
+void InventoryYeastPacks::on_insertButton_clicked()
+{
+    edit(-1);
+}
+
+
+void InventoryYeastPacks::on_exportButton_clicked()
+{
+    QMessageBox::information(this, QGuiApplication::applicationDisplayName(), tr("BeerXML doesn't support export yeast packages."));
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/InventoryYeastPacks.h	Mon Jan 30 17:05:13 2023 +0100
@@ -0,0 +1,45 @@
+#ifndef _INVENTORYYEASTPACKS_H
+#define _INVENTORYYEASTPACKS_H
+
+#include <QDialog>
+#include <QtWidgets/QGridLayout>
+#include <QtWidgets/QGroupBox>
+#include <QtWidgets/QHBoxLayout>
+#include <QtWidgets/QHeaderView>
+#include <QtWidgets/QPushButton>
+#include <QtWidgets/QTableWidget>
+
+namespace Ui {
+class InventoryYeastPacks;
+}
+
+class InventoryYeastPacks : public QDialog
+{
+    Q_OBJECT
+
+public:
+    explicit InventoryYeastPacks(QWidget *parent = nullptr);
+    ~InventoryYeastPacks();
+
+signals:
+    void setStatus(QString);
+
+private slots:
+    void on_insertButton_clicked();
+    void on_editButton_clicked();
+    void on_exportButton_clicked();
+    void refreshTable(void);
+
+private:
+    QGridLayout *gridLayout;
+    QTableWidget *tableYeastPacks;
+    QGroupBox *groupBox;
+    QHBoxLayout *horizontalLayout;
+    QPushButton *quitButton;
+    QPushButton *exportButton;
+    QPushButton *insertButton;
+
+    void edit(int recno);
+};
+
+#endif
--- a/src/MainWindow.cpp	Sun Jan 29 14:40:43 2023 +0100
+++ b/src/MainWindow.cpp	Mon Jan 30 17:05:13 2023 +0100
@@ -21,6 +21,7 @@
 #include "InventoryFermentables.h"
 #include "InventoryHops.h"
 #include "InventoryYeasts.h"
+#include "InventoryYeastPacks.h"
 #include "InventoryMiscs.h"
 #include "InventoryWaters.h"
 #include "InventoryEquipments.h"
@@ -165,10 +166,12 @@
 {
     QSqlQuery query1, query2, query3, query4;
     int	count = 0;
+    bool added_packs = false;
 
     qDebug() << "updateDatabase() start";
 
     /*
+     * Version 0.4.0.
      * Make sure we have the inventory_yeastpack with initial records.
      */
     query1.exec("CREATE TABLE IF NOT EXISTS `inventory_yeastpack` ("
@@ -182,8 +185,10 @@
   		"`viability` double NOT NULL DEFAULT 0.99,"
 		"`max` tinyint(4) NOT NULL DEFAULT 100,"
   		"`size` float NOT NULL DEFAULT 0,"
+		"`used` int(11) NOT NULL DEFAULT 0,"
   		"PRIMARY KEY (`record`),"
   		"UNIQUE KEY `uuid` (`uuid`),"
+		"UNIQUE KEY `package` (`laboratory`,`form`,`package`),"
   		"KEY `lab_form` (`laboratory`,`form`) USING BTREE"
 		") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='Yeast packages data'");
     if (query1.lastError().isValid()) {
@@ -206,17 +211,31 @@
 	    	/* Should succeed */
 
 	    	query4.prepare("INSERT INTO inventory_yeastpack SET uuid=:uuid, laboratory=:laboratory, "
-			   "form=:form, package=:package, cells=:cells");
+			   "form=:form, package=:package, cells=:cells, viability=:viability, max=:max");
 	    	query4.bindValue(":uuid", QUuid::createUuid().toString().mid(1, 36));
 	    	query4.bindValue(":laboratory", query1.value("laboratory").toString());
 	    	query4.bindValue(":form", query1.value("form").toInt());
 	    	query4.bindValue(":package", g_yeast_forms[query1.value("form").toInt()]);
 	    	query4.bindValue(":cells", query3.value("cells").toDouble());
+		switch (query1.value("form").toInt()) {
+		    case YEAST_FORMS_LIQUID:	query4.bindValue(":viability", 0.80);
+						query4.bindValue(":max", 97);
+						break;
+		    case YEAST_FORMS_DRY:	query4.bindValue(":viability", 0.998);
+						query4.bindValue(":max", 100);
+						break;
+		    case YEAST_FORMS_DRIED:	query4.bindValue(":viability", 0.92);
+						query4.bindValue(":max", 100);
+						break;
+		    default:			query4.bindValue(":viability", 0.99);
+						query4.bindValue(":max", 97);
+		}
 	    	query4.exec();
 	    	if (query4.lastError().isValid()) {
 		    qWarning() << "  add yeastpack" << query4.lastError();
 	    	} else {
 		    count++;
+		    added_packs = true;
 	    	}
 	    }
     	}
@@ -226,17 +245,14 @@
 }
 
 
-/*
- * On the server where bmsd runs, there is a crontask.php that does these checks
- * too. Here we do some of the same commands so that we have the results sooner.
- * Currently this takes 6 to 9 mSecs.
- */
 void MainWindow::maintDataBase()
 {
-    QSqlQuery query;
+    QSqlQuery query, query1;
 
     /*
-     * Upgrade package values.
+     * On the server where bmsd runs, there is a crontask.php that does these checks
+     * too. Here we do some of the same commands so that we have the results sooner.
+     * Currently this takes 6 to 9 mSecs.
      */
     query.exec("UPDATE products SET package_volume = bottle_amount + keg_amount WHERE package_volume='0'");
     if (query.numRowsAffected())
@@ -267,6 +283,27 @@
     query.exec("UPDATE products SET stage=9 WHERE stage = 8 AND DATEDIFF(CURDATE(), package_date) > 41");
     if (query.numRowsAffected())
 	qInfo() << "Updated" << query.numRowsAffected() << "products to stage 9 (Taste)";
+
+    /*
+     * Count and update references in inventory_yeastpack to inventory_yeasts
+     */
+    query.exec("SELECT laboratory,form FROM inventory_yeastpack");
+    while (query.next()) {
+	query1.prepare("SELECT COUNT(*) FROM inventory_yeasts WHERE laboratory=:laboratory AND form=:form");
+	query1.bindValue(":laboratory", query.value("laboratory").toString());
+        query1.bindValue(":form", query.value("form").toInt());
+	query1.exec();
+	if (! query1.first()) {
+	    qWarning() << "SELECT COUNT(*) FROM inventory_yeasts";
+	} else {
+	    int count = query1.value("COUNT(*)").toInt();
+	    query1.prepare("UPDATE inventory_yeastpack SET used=:used WHERE laboratory=:laboratory AND form=:form");
+	    query1.bindValue(":used", count);
+	    query1.bindValue(":laboratory", query.value("laboratory").toString());
+            query1.bindValue(":form", query.value("form").toInt());
+	    query1.exec();
+	}
+    }
 }
 
 
@@ -709,6 +746,28 @@
 }
 
 
+void MainWindow::fromInventoryYeastPacks()
+{
+    ui->mainStack->setCurrentIndex(-1);
+    ui->mainStack->removeWidget(InventoryYeastPacksWindow);
+    delete InventoryYeastPacksWindow;
+    setWindowTitle( QString("BMSapp - %1").arg(VERSIONSTRING) );
+    ui->menuBar->setVisible(true);
+    statusBar()->clearMessage();
+}
+
+
+void MainWindow::on_actionYeastPacks_triggered()
+{
+    InventoryYeastPacksWindow = new InventoryYeastPacks(this);
+    int index = ui->mainStack->count();
+    ui->mainStack->addWidget(InventoryYeastPacksWindow);
+    ui->mainStack->setCurrentIndex(index);
+    setWindowTitle(QString("BMSapp - %1 - Inventory Yeasts").arg(VERSIONSTRING));
+    ui->menuBar->setVisible(false);
+}
+
+
 void MainWindow::fromInventoryMiscs()
 {
     ui->mainStack->setCurrentIndex(-1);
--- a/src/MainWindow.h	Sun Jan 29 14:40:43 2023 +0100
+++ b/src/MainWindow.h	Mon Jan 30 17:05:13 2023 +0100
@@ -6,6 +6,7 @@
 #include "InventoryFermentables.h"
 #include "InventoryHops.h"
 #include "InventoryYeasts.h"
+#include "InventoryYeastPacks.h"
 #include "InventoryMiscs.h"
 #include "InventoryWaters.h"
 #include "InventoryEquipments.h"
@@ -117,6 +118,7 @@
     InventoryFermentables *InventoryFermentablesWindow;
     InventoryHops *InventoryHopsWindow;
     InventoryYeasts *InventoryYeastsWindow;
+    InventoryYeastPacks *InventoryYeastPacksWindow;
     InventoryMiscs *InventoryMiscsWindow;
     InventoryWaters *InventoryWatersWindow;
     InventoryEquipments *InventoryEquipmentsWindow;
@@ -164,6 +166,7 @@
     void on_actionFermentables_triggered();
     void on_actionHops_triggered();
     void on_actionYeasts_triggered();
+    void on_actionYeastPacks_triggered();
     void on_actionMiscs_triggered();
     void on_actionWaters_triggered();
     void on_actionEquipments_triggered();
@@ -188,6 +191,7 @@
     void fromInventoryFermentables();
     void fromInventoryHops();
     void fromInventoryYeasts();
+    void fromInventoryYeastPacks();
     void fromInventoryMiscs();
     void fromInventoryWaters();
     void fromInventoryEquipments();
--- a/src/global.h	Sun Jan 29 14:40:43 2023 +0100
+++ b/src/global.h	Mon Jan 30 17:05:13 2023 +0100
@@ -184,6 +184,18 @@
 };
 
 
+struct YeastPacks
+{
+    QString	laboratory;
+    QString	package;
+    QString	notes;
+    int		form;
+    double	cells;
+    double	viability;
+    double	size;
+};
+
+
 struct MashSteps
 {
     QString	step_name;
--- a/translations/bmsapp_en.ts	Sun Jan 29 14:40:43 2023 +0100
+++ b/translations/bmsapp_en.ts	Mon Jan 30 17:05:13 2023 +0100
@@ -8410,6 +8410,227 @@
     </message>
 </context>
 <context>
+    <name>EditYeastPack</name>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="14"/>
+        <source>Dialog</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="29"/>
+        <source>Package:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="45"/>
+        <source>Notes:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="77"/>
+        <source>Notes and usage tips.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="96"/>
+        <source>Quit</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="116"/>
+        <source>Save</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="136"/>
+        <source>Delete</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="153"/>
+        <source>Form:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="169"/>
+        <source>Laboratory:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="217"/>
+        <source>Billion cells:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="272"/>
+        <source>Viability:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="313"/>
+        <source>Package size:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="335"/>
+        <source> xx</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="357"/>
+        <source>Used in yeasts:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="398"/>
+        <source>Max viability:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="414"/>
+        <source>For most 100% is good, some liquid yeast start at 97%</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="423"/>
+        <location filename="../ui/EditYeastPack.ui" line="460"/>
+        <source> %</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="445"/>
+        <source>The yeast health after 6 months.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="479"/>
+        <source>6 months health:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="204"/>
+        <source>Yeast laboratory</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="64"/>
+        <source>Name of the yeast package</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="255"/>
+        <source>Clone</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="33"/>
+        <source>Liquid</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="34"/>
+        <source>Dry</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="35"/>
+        <source>Slant</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="36"/>
+        <source>Culture</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="37"/>
+        <source>Frozen</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="38"/>
+        <source>Bottle</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="39"/>
+        <source>Dried</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="95"/>
+        <source>BMSapp - Add new yeast package</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="97"/>
+        <source>BMSapp - Edit yeast package %1</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="113"/>
+        <location filename="../src/EditYeastPack.cpp" line="117"/>
+        <source>Edit Yeast Package</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="113"/>
+        <source>Laboratory name empty or too short.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="117"/>
+        <source>Package name empty or too short.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="147"/>
+        <location filename="../src/EditYeastPack.cpp" line="182"/>
+        <location filename="../src/EditYeastPack.cpp" line="207"/>
+        <source>Database error</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="148"/>
+        <location filename="../src/EditYeastPack.cpp" line="183"/>
+        <location filename="../src/EditYeastPack.cpp" line="208"/>
+        <source>MySQL error: %1
+%2
+%3</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="197"/>
+        <source>Delete yeast pack</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="197"/>
+        <source>Delete %1</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="242"/>
+        <source> gr</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="244"/>
+        <source> ml</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="292"/>
+        <source>Yeast package changed</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="292"/>
+        <source>The yeast package has been modified. Save changes?</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
     <name>FermentableAdded</name>
     <message>
         <location filename="../src/global.cpp" line="118"/>
@@ -9214,6 +9435,60 @@
     </message>
 </context>
 <context>
+    <name>InventoryYeastPacks</name>
+    <message>
+        <location filename="../src/InventoryYeastPacks.cpp" line="52"/>
+        <source>Quit</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/InventoryYeastPacks.cpp" line="61"/>
+        <source>Export</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/InventoryYeastPacks.cpp" line="70"/>
+        <source>New</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/InventoryYeastPacks.cpp" line="95"/>
+        <source>Laboratory</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/InventoryYeastPacks.cpp" line="95"/>
+        <source>Form</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/InventoryYeastPacks.cpp" line="95"/>
+        <location filename="../src/InventoryYeastPacks.cpp" line="131"/>
+        <source>Edit</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/InventoryYeastPacks.cpp" line="95"/>
+        <source>Package</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/InventoryYeastPacks.cpp" line="95"/>
+        <source>Size</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/InventoryYeastPacks.cpp" line="140"/>
+        <source>Total items: %1</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/InventoryYeastPacks.cpp" line="173"/>
+        <source>BeerXML doesn&apos;t support export yeast packages.</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
     <name>InventoryYeasts</name>
     <message>
         <location filename="../src/InventoryYeasts.cpp" line="52"/>
@@ -9337,218 +9612,223 @@
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="89"/>
+        <location filename="../ui/MainWindow.ui" line="90"/>
         <source>Monitor</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="100"/>
+        <location filename="../ui/MainWindow.ui" line="101"/>
         <source>Products</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="104"/>
-        <location filename="../ui/MainWindow.ui" line="363"/>
+        <location filename="../ui/MainWindow.ui" line="105"/>
+        <location filename="../ui/MainWindow.ui" line="364"/>
         <source>Archive</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="117"/>
+        <location filename="../ui/MainWindow.ui" line="118"/>
         <source>Reports</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="133"/>
-        <location filename="../ui/MainWindow.ui" line="336"/>
+        <location filename="../ui/MainWindow.ui" line="134"/>
+        <location filename="../ui/MainWindow.ui" line="337"/>
         <source>Recipes</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="156"/>
+        <location filename="../ui/MainWindow.ui" line="157"/>
         <source>Exit</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="165"/>
+        <location filename="../ui/MainWindow.ui" line="166"/>
         <source>About</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="174"/>
+        <location filename="../ui/MainWindow.ui" line="175"/>
         <source>Suppliers</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="186"/>
+        <location filename="../ui/MainWindow.ui" line="187"/>
         <source>Fermentables</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="198"/>
+        <location filename="../ui/MainWindow.ui" line="199"/>
         <source>Hops</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="210"/>
+        <location filename="../ui/MainWindow.ui" line="211"/>
         <source>Yeasts</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="222"/>
+        <location filename="../ui/MainWindow.ui" line="223"/>
         <source>Miscs</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="234"/>
+        <location filename="../ui/MainWindow.ui" line="235"/>
         <source>Waters</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="246"/>
+        <location filename="../ui/MainWindow.ui" line="247"/>
         <source>Equipments</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="258"/>
+        <location filename="../ui/MainWindow.ui" line="259"/>
         <source>Supplies list</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="270"/>
+        <location filename="../ui/MainWindow.ui" line="271"/>
         <source>Yeast bank</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="282"/>
+        <location filename="../ui/MainWindow.ui" line="283"/>
         <source>Water profiles</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="294"/>
+        <location filename="../ui/MainWindow.ui" line="295"/>
         <source>Mash schedules</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="306"/>
+        <location filename="../ui/MainWindow.ui" line="307"/>
         <source>Beer styles</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="318"/>
+        <location filename="../ui/MainWindow.ui" line="319"/>
         <source>Fermentation schedules</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="327"/>
+        <location filename="../ui/MainWindow.ui" line="328"/>
         <source>Global settings</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="345"/>
+        <location filename="../ui/MainWindow.ui" line="346"/>
         <source>Import beerxml</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="354"/>
+        <location filename="../ui/MainWindow.ui" line="355"/>
         <source>In Production</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="372"/>
+        <location filename="../ui/MainWindow.ui" line="373"/>
         <source>On Name</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="381"/>
+        <location filename="../ui/MainWindow.ui" line="382"/>
         <source>On Code</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="390"/>
+        <location filename="../ui/MainWindow.ui" line="391"/>
         <source>On Date</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="399"/>
+        <location filename="../ui/MainWindow.ui" line="400"/>
         <source>On Beerstyle</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="408"/>
+        <location filename="../ui/MainWindow.ui" line="409"/>
         <source>Import beerXML</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="413"/>
+        <location filename="../ui/MainWindow.ui" line="414"/>
         <source>dummy</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="418"/>
+        <location filename="../ui/MainWindow.ui" line="419"/>
         <source>hh</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="423"/>
+        <location filename="../ui/MainWindow.ui" line="424"/>
         <source>hj</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="428"/>
+        <location filename="../ui/MainWindow.ui" line="429"/>
         <source>ll</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="433"/>
-        <location filename="../ui/MainWindow.ui" line="442"/>
+        <location filename="../ui/MainWindow.ui" line="434"/>
+        <location filename="../ui/MainWindow.ui" line="443"/>
         <source>Nodes</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="451"/>
+        <location filename="../ui/MainWindow.ui" line="452"/>
         <source>Fermenters</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="460"/>
+        <location filename="../ui/MainWindow.ui" line="461"/>
         <source>Carbonation</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="469"/>
+        <location filename="../ui/MainWindow.ui" line="470"/>
         <source>iSpindels</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="478"/>
+        <location filename="../ui/MainWindow.ui" line="479"/>
         <source>Total Production</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="487"/>
+        <location filename="../ui/MainWindow.ui" line="488"/>
         <source>Efficiency</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="496"/>
+        <location filename="../ui/MainWindow.ui" line="497"/>
         <source>Fermentation</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="505"/>
+        <location filename="../ui/MainWindow.ui" line="506"/>
         <source>Import brew log</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="514"/>
+        <location filename="../ui/MainWindow.ui" line="515"/>
         <source>Manual</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="517"/>
+        <location filename="../ui/MainWindow.ui" line="518"/>
         <source>F1</source>
         <translation type="unfinished"></translation>
     </message>
+    <message>
+        <location filename="../ui/MainWindow.ui" line="527"/>
+        <source>Yeast Packages</source>
+        <translation type="unfinished"></translation>
+    </message>
 </context>
 <context>
     <name>ManoMeter</name>
--- a/translations/bmsapp_nl.ts	Sun Jan 29 14:40:43 2023 +0100
+++ b/translations/bmsapp_nl.ts	Mon Jan 30 17:05:13 2023 +0100
@@ -9168,6 +9168,301 @@
     </message>
 </context>
 <context>
+    <name>EditYeastPack</name>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="14"/>
+        <source>Dialog</source>
+        <translation type="unfinished">Dialog</translation>
+    </message>
+    <message>
+        <source>Name:</source>
+        <translation type="obsolete">Naam:</translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="29"/>
+        <source>Package:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="45"/>
+        <source>Notes:</source>
+        <translation type="unfinished">Opmerkingen:</translation>
+    </message>
+    <message>
+        <source>Name of the yeast</source>
+        <translation type="obsolete">Naam van de gist</translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="64"/>
+        <source>Name of the yeast package</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="77"/>
+        <source>Notes and usage tips.</source>
+        <translation type="unfinished">Opmerkingen en gebruik tips.</translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="96"/>
+        <source>Quit</source>
+        <translation type="unfinished">Terug</translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="116"/>
+        <source>Save</source>
+        <translation type="unfinished">Bewaar</translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="136"/>
+        <source>Delete</source>
+        <translation type="unfinished">Verwijder</translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="153"/>
+        <source>Form:</source>
+        <translation type="unfinished">Vorm:</translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="169"/>
+        <source>Laboratory:</source>
+        <translation type="unfinished">Laboratorium:</translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="217"/>
+        <source>Billion cells:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="272"/>
+        <source>Viability:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="313"/>
+        <source>Package size:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="335"/>
+        <source> xx</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="357"/>
+        <source>Used in yeasts:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="398"/>
+        <source>Max viability:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="414"/>
+        <source>For most 100% is good, some liquid yeast start at 97%</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="423"/>
+        <location filename="../ui/EditYeastPack.ui" line="460"/>
+        <source> %</source>
+        <translation type="unfinished"> %</translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="445"/>
+        <source>The yeast health after 6 months.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="479"/>
+        <source>6 months health:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Best for:</source>
+        <translation type="obsolete">Geschikt voor:</translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="204"/>
+        <source>Yeast laboratory</source>
+        <translation type="unfinished">Gist laboratorium</translation>
+    </message>
+    <message>
+        <source>Billion cells/gram:</source>
+        <translation type="obsolete">Miljard cellen/gram:</translation>
+    </message>
+    <message>
+        <location filename="../ui/EditYeastPack.ui" line="255"/>
+        <source>Clone</source>
+        <translation type="unfinished">Kloon</translation>
+    </message>
+    <message>
+        <source>Spice</source>
+        <translation type="obsolete">Specerij</translation>
+    </message>
+    <message>
+        <source>Herb</source>
+        <translation type="obsolete">Kruid</translation>
+    </message>
+    <message>
+        <source>Flavor</source>
+        <translation type="obsolete">Smaakstof</translation>
+    </message>
+    <message>
+        <source>Fining</source>
+        <translation type="obsolete">Klaringsmiddel</translation>
+    </message>
+    <message>
+        <source>Water agent</source>
+        <translation type="obsolete">Brouwzout</translation>
+    </message>
+    <message>
+        <source>Yeast nutrient</source>
+        <translation type="obsolete">Gistvoeding</translation>
+    </message>
+    <message>
+        <source>Other</source>
+        <translation type="obsolete">Anders</translation>
+    </message>
+    <message>
+        <source>Starter</source>
+        <translation type="obsolete">Starter</translation>
+    </message>
+    <message>
+        <source>Mash</source>
+        <translation type="obsolete">Maischen</translation>
+    </message>
+    <message>
+        <source>Boil</source>
+        <translation type="obsolete">Koken</translation>
+    </message>
+    <message>
+        <source>Primary</source>
+        <translation type="obsolete">Hoofdgisting</translation>
+    </message>
+    <message>
+        <source>Bottling</source>
+        <translation type="obsolete">Bottelen</translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="33"/>
+        <source>Liquid</source>
+        <translation type="unfinished">Vloeibaar</translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="34"/>
+        <source>Dry</source>
+        <translation type="unfinished">Droog</translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="35"/>
+        <source>Slant</source>
+        <translation type="unfinished">Schuine buis</translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="36"/>
+        <source>Culture</source>
+        <translation type="unfinished">Slurry</translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="37"/>
+        <source>Frozen</source>
+        <translation type="unfinished">Ingevroren</translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="38"/>
+        <source>Bottle</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="39"/>
+        <source>Dried</source>
+        <translation type="unfinished">Gedroogd</translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="95"/>
+        <source>BMSapp - Add new yeast package</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="97"/>
+        <source>BMSapp - Edit yeast package %1</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Edit Misc</source>
+        <translation type="obsolete">Wijzig ingredient</translation>
+    </message>
+    <message>
+        <source>Name empty or too short.</source>
+        <translation type="obsolete">De naam is leeg of te kort.</translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="113"/>
+        <location filename="../src/EditYeastPack.cpp" line="117"/>
+        <source>Edit Yeast Package</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="113"/>
+        <source>Laboratory name empty or too short.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="117"/>
+        <source>Package name empty or too short.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="147"/>
+        <location filename="../src/EditYeastPack.cpp" line="182"/>
+        <location filename="../src/EditYeastPack.cpp" line="207"/>
+        <source>Database error</source>
+        <translation type="unfinished">Database fout</translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="148"/>
+        <location filename="../src/EditYeastPack.cpp" line="183"/>
+        <location filename="../src/EditYeastPack.cpp" line="208"/>
+        <source>MySQL error: %1
+%2
+%3</source>
+        <translation type="unfinished">MySQL fout: %1
+%2
+%3</translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="197"/>
+        <source>Delete yeast pack</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="197"/>
+        <source>Delete %1</source>
+        <translation type="unfinished">Verwijder %1</translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="242"/>
+        <source> gr</source>
+        <translation type="unfinished"> gr</translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="244"/>
+        <source> ml</source>
+        <translation type="unfinished"> ml</translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="292"/>
+        <source>Yeast package changed</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/EditYeastPack.cpp" line="292"/>
+        <source>The yeast package has been modified. Save changes?</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
     <name>FermentableAdded</name>
     <message>
         <location filename="../src/global.cpp" line="118"/>
@@ -10151,6 +10446,84 @@
     </message>
 </context>
 <context>
+    <name>InventoryYeastPacks</name>
+    <message>
+        <location filename="../src/InventoryYeastPacks.cpp" line="52"/>
+        <source>Quit</source>
+        <translation type="unfinished">Terug</translation>
+    </message>
+    <message>
+        <location filename="../src/InventoryYeastPacks.cpp" line="61"/>
+        <source>Export</source>
+        <translation type="unfinished">Exporteer</translation>
+    </message>
+    <message>
+        <location filename="../src/InventoryYeastPacks.cpp" line="70"/>
+        <source>New</source>
+        <translation type="unfinished">Nieuw</translation>
+    </message>
+    <message>
+        <location filename="../src/InventoryYeastPacks.cpp" line="95"/>
+        <source>Laboratory</source>
+        <translation type="unfinished">Laboratorium</translation>
+    </message>
+    <message>
+        <location filename="../src/InventoryYeastPacks.cpp" line="173"/>
+        <source>BeerXML doesn&apos;t support export yeast packages.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Product id</source>
+        <translation type="obsolete">Product code</translation>
+    </message>
+    <message>
+        <source>Name</source>
+        <translation type="obsolete">Naam</translation>
+    </message>
+    <message>
+        <location filename="../src/InventoryYeastPacks.cpp" line="95"/>
+        <source>Form</source>
+        <translation type="unfinished">Vorm</translation>
+    </message>
+    <message>
+        <source>Stock</source>
+        <translation type="obsolete">Voorraad</translation>
+    </message>
+    <message>
+        <location filename="../src/InventoryYeastPacks.cpp" line="95"/>
+        <location filename="../src/InventoryYeastPacks.cpp" line="131"/>
+        <source>Edit</source>
+        <translation type="unfinished">Wijzig</translation>
+    </message>
+    <message>
+        <location filename="../src/InventoryYeastPacks.cpp" line="95"/>
+        <source>Package</source>
+        <translation type="unfinished">Verpakken</translation>
+    </message>
+    <message>
+        <location filename="../src/InventoryYeastPacks.cpp" line="95"/>
+        <source>Size</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/InventoryYeastPacks.cpp" line="140"/>
+        <source>Total items: %1</source>
+        <translation type="unfinished">Totaal items: %1</translation>
+    </message>
+    <message>
+        <source>Save File</source>
+        <translation type="obsolete">Bestand opslaan</translation>
+    </message>
+    <message>
+        <source>No XML file selected.</source>
+        <translation type="obsolete">Geen XML bestand gekozen.</translation>
+    </message>
+    <message>
+        <source>XML export ready</source>
+        <translation type="obsolete">XML uitvoer gereed</translation>
+    </message>
+</context>
+<context>
     <name>InventoryYeasts</name>
     <message>
         <location filename="../src/InventoryYeasts.cpp" line="52"/>
@@ -10338,34 +10711,34 @@
         <translation>Inventaris</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="89"/>
+        <location filename="../ui/MainWindow.ui" line="90"/>
         <source>Monitor</source>
         <translation>Monitoren</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="100"/>
+        <location filename="../ui/MainWindow.ui" line="101"/>
         <source>Products</source>
         <translation>Productie</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="104"/>
-        <location filename="../ui/MainWindow.ui" line="363"/>
+        <location filename="../ui/MainWindow.ui" line="105"/>
+        <location filename="../ui/MainWindow.ui" line="364"/>
         <source>Archive</source>
         <translation>Archief</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="133"/>
-        <location filename="../ui/MainWindow.ui" line="336"/>
+        <location filename="../ui/MainWindow.ui" line="134"/>
+        <location filename="../ui/MainWindow.ui" line="337"/>
         <source>Recipes</source>
         <translation>Recepten</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="156"/>
+        <location filename="../ui/MainWindow.ui" line="157"/>
         <source>Exit</source>
         <translation>Afsluiten</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="165"/>
+        <location filename="../ui/MainWindow.ui" line="166"/>
         <source>About</source>
         <translation>Over</translation>
     </message>
@@ -10374,7 +10747,7 @@
         <translation type="vanished">Systemen</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="451"/>
+        <location filename="../ui/MainWindow.ui" line="452"/>
         <source>Fermenters</source>
         <translation>Vergisting</translation>
     </message>
@@ -10383,181 +10756,186 @@
         <translation type="vanished">CO2 meters</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="469"/>
+        <location filename="../ui/MainWindow.ui" line="470"/>
         <source>iSpindels</source>
         <translation>iSpindels</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="174"/>
+        <location filename="../ui/MainWindow.ui" line="175"/>
         <source>Suppliers</source>
         <translation>Leveranciers</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="117"/>
+        <location filename="../ui/MainWindow.ui" line="118"/>
         <source>Reports</source>
         <translation>Rapporten</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="186"/>
+        <location filename="../ui/MainWindow.ui" line="187"/>
         <source>Fermentables</source>
         <translation>Vergistbare ingredienten</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="198"/>
+        <location filename="../ui/MainWindow.ui" line="199"/>
         <source>Hops</source>
         <translation>Hoppen</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="210"/>
+        <location filename="../ui/MainWindow.ui" line="211"/>
         <source>Yeasts</source>
         <translation>Gisten</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="222"/>
+        <location filename="../ui/MainWindow.ui" line="223"/>
         <source>Miscs</source>
         <translation>Overige ingredienten</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="234"/>
+        <location filename="../ui/MainWindow.ui" line="235"/>
         <source>Waters</source>
         <translation>Water</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="246"/>
+        <location filename="../ui/MainWindow.ui" line="247"/>
         <source>Equipments</source>
         <translation>Brouw apparatuur</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="258"/>
+        <location filename="../ui/MainWindow.ui" line="259"/>
         <source>Supplies list</source>
         <translation>Voorraad lijst</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="270"/>
+        <location filename="../ui/MainWindow.ui" line="271"/>
         <source>Yeast bank</source>
         <translation>Gistbank lijst</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="282"/>
+        <location filename="../ui/MainWindow.ui" line="283"/>
         <source>Water profiles</source>
         <translation>Water profielen</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="294"/>
+        <location filename="../ui/MainWindow.ui" line="295"/>
         <source>Mash schedules</source>
         <translation>Maisch schemas</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="306"/>
+        <location filename="../ui/MainWindow.ui" line="307"/>
         <source>Beer styles</source>
         <translation>Bierstijlen</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="318"/>
+        <location filename="../ui/MainWindow.ui" line="319"/>
         <source>Fermentation schedules</source>
         <translation>Vergisting profielen</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="327"/>
+        <location filename="../ui/MainWindow.ui" line="328"/>
         <source>Global settings</source>
         <translation>Instellingen</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="345"/>
+        <location filename="../ui/MainWindow.ui" line="346"/>
         <source>Import beerxml</source>
         <translation>Importeer beerxml</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="354"/>
+        <location filename="../ui/MainWindow.ui" line="355"/>
         <source>In Production</source>
         <translation>In Productie</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="372"/>
+        <location filename="../ui/MainWindow.ui" line="373"/>
         <source>On Name</source>
         <translation>Op naam</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="381"/>
+        <location filename="../ui/MainWindow.ui" line="382"/>
         <source>On Code</source>
         <translation>Op code</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="390"/>
+        <location filename="../ui/MainWindow.ui" line="391"/>
         <source>On Date</source>
         <translation>Op datum</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="399"/>
+        <location filename="../ui/MainWindow.ui" line="400"/>
         <source>On Beerstyle</source>
         <translation>Op bierstijl</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="408"/>
+        <location filename="../ui/MainWindow.ui" line="409"/>
         <source>Import beerXML</source>
         <translation>Importeer beerXML</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="413"/>
+        <location filename="../ui/MainWindow.ui" line="414"/>
         <source>dummy</source>
         <translation></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="418"/>
+        <location filename="../ui/MainWindow.ui" line="419"/>
         <source>hh</source>
         <translation></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="423"/>
+        <location filename="../ui/MainWindow.ui" line="424"/>
         <source>hj</source>
         <translation></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="428"/>
+        <location filename="../ui/MainWindow.ui" line="429"/>
         <source>ll</source>
         <translation></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="433"/>
-        <location filename="../ui/MainWindow.ui" line="442"/>
+        <location filename="../ui/MainWindow.ui" line="434"/>
+        <location filename="../ui/MainWindow.ui" line="443"/>
         <source>Nodes</source>
         <translation>Systemen</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="460"/>
+        <location filename="../ui/MainWindow.ui" line="461"/>
         <source>Carbonation</source>
         <translation>Carbonatie</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="478"/>
+        <location filename="../ui/MainWindow.ui" line="479"/>
         <source>Total Production</source>
         <translation>Totaal productie</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="487"/>
+        <location filename="../ui/MainWindow.ui" line="488"/>
         <source>Efficiency</source>
         <translation>Rendement</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="496"/>
+        <location filename="../ui/MainWindow.ui" line="497"/>
         <source>Fermentation</source>
         <translation>Vergisting</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="505"/>
+        <location filename="../ui/MainWindow.ui" line="506"/>
         <source>Import brew log</source>
         <translation>Importeer brouwlog</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="514"/>
+        <location filename="../ui/MainWindow.ui" line="515"/>
         <source>Manual</source>
         <translation></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="517"/>
+        <location filename="../ui/MainWindow.ui" line="518"/>
         <source>F1</source>
         <translation></translation>
     </message>
+    <message>
+        <location filename="../ui/MainWindow.ui" line="527"/>
+        <source>Yeast Packages</source>
+        <translation type="unfinished"></translation>
+    </message>
 </context>
 <context>
     <name>ManoMeter</name>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/EditYeastPack.ui	Mon Jan 30 17:05:13 2023 +0100
@@ -0,0 +1,500 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>EditYeastPack</class>
+ <widget class="QDialog" name="EditYeastPack">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>1024</width>
+    <height>560</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Dialog</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="0" column="0">
+    <widget class="QWidget" name="topWidget" native="true">
+     <widget class="QLabel" name="packageLabel">
+      <property name="geometry">
+       <rect>
+        <x>115</x>
+        <y>130</y>
+        <width>121</width>
+        <height>20</height>
+       </rect>
+      </property>
+      <property name="text">
+       <string>Package:</string>
+      </property>
+      <property name="alignment">
+       <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+      </property>
+     </widget>
+     <widget class="QLabel" name="notesLabel">
+      <property name="geometry">
+       <rect>
+        <x>115</x>
+        <y>160</y>
+        <width>121</width>
+        <height>20</height>
+       </rect>
+      </property>
+      <property name="text">
+       <string>Notes:</string>
+      </property>
+      <property name="alignment">
+       <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+      </property>
+     </widget>
+     <widget class="QLineEdit" name="packageEdit">
+      <property name="geometry">
+       <rect>
+        <x>250</x>
+        <y>130</y>
+        <width>511</width>
+        <height>23</height>
+       </rect>
+      </property>
+      <property name="maxLength">
+       <number>128</number>
+      </property>
+      <property name="placeholderText">
+       <string>Name of the yeast package</string>
+      </property>
+     </widget>
+     <widget class="QPlainTextEdit" name="notesEdit">
+      <property name="geometry">
+       <rect>
+        <x>250</x>
+        <y>160</y>
+        <width>511</width>
+        <height>111</height>
+       </rect>
+      </property>
+      <property name="placeholderText">
+       <string>Notes and usage tips.</string>
+      </property>
+     </widget>
+     <widget class="QPushButton" name="quitButton">
+      <property name="geometry">
+       <rect>
+        <x>90</x>
+        <y>510</y>
+        <width>80</width>
+        <height>23</height>
+       </rect>
+      </property>
+      <property name="sizePolicy">
+       <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+        <horstretch>0</horstretch>
+        <verstretch>0</verstretch>
+       </sizepolicy>
+      </property>
+      <property name="text">
+       <string>Quit</string>
+      </property>
+      <property name="icon">
+       <iconset>
+        <normaloff>:icons/silk/door_out.png</normaloff>:icons/silk/door_out.png</iconset>
+      </property>
+     </widget>
+     <widget class="QPushButton" name="saveButton">
+      <property name="enabled">
+       <bool>false</bool>
+      </property>
+      <property name="geometry">
+       <rect>
+        <x>850</x>
+        <y>510</y>
+        <width>80</width>
+        <height>23</height>
+       </rect>
+      </property>
+      <property name="text">
+       <string>Save</string>
+      </property>
+      <property name="icon">
+       <iconset>
+        <normaloff>:icons/silk/disk.png</normaloff>:icons/silk/disk.png</iconset>
+      </property>
+     </widget>
+     <widget class="QPushButton" name="deleteButton">
+      <property name="enabled">
+       <bool>false</bool>
+      </property>
+      <property name="geometry">
+       <rect>
+        <x>596</x>
+        <y>510</y>
+        <width>80</width>
+        <height>23</height>
+       </rect>
+      </property>
+      <property name="text">
+       <string>Delete</string>
+      </property>
+      <property name="icon">
+       <iconset>
+        <normaloff>:icons/silk/delete.png</normaloff>:icons/silk/delete.png</iconset>
+      </property>
+     </widget>
+     <widget class="QLabel" name="formLabel">
+      <property name="geometry">
+       <rect>
+        <x>115</x>
+        <y>70</y>
+        <width>121</width>
+        <height>20</height>
+       </rect>
+      </property>
+      <property name="text">
+       <string>Form:</string>
+      </property>
+      <property name="alignment">
+       <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+      </property>
+     </widget>
+     <widget class="QLabel" name="laboratoryLabel">
+      <property name="geometry">
+       <rect>
+        <x>115</x>
+        <y>40</y>
+        <width>121</width>
+        <height>20</height>
+       </rect>
+      </property>
+      <property name="text">
+       <string>Laboratory:</string>
+      </property>
+      <property name="alignment">
+       <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+      </property>
+     </widget>
+     <widget class="QComboBox" name="formEdit">
+      <property name="geometry">
+       <rect>
+        <x>250</x>
+        <y>70</y>
+        <width>121</width>
+        <height>23</height>
+       </rect>
+      </property>
+      <property name="iconSize">
+       <size>
+        <width>0</width>
+        <height>0</height>
+       </size>
+      </property>
+     </widget>
+     <widget class="QLineEdit" name="laboratoryEdit">
+      <property name="geometry">
+       <rect>
+        <x>250</x>
+        <y>40</y>
+        <width>511</width>
+        <height>23</height>
+       </rect>
+      </property>
+      <property name="maxLength">
+       <number>128</number>
+      </property>
+      <property name="placeholderText">
+       <string>Yeast laboratory</string>
+      </property>
+     </widget>
+     <widget class="QLabel" name="cellsLabel">
+      <property name="geometry">
+       <rect>
+        <x>100</x>
+        <y>280</y>
+        <width>141</width>
+        <height>20</height>
+       </rect>
+      </property>
+      <property name="text">
+       <string>Billion cells:</string>
+      </property>
+      <property name="alignment">
+       <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+      </property>
+     </widget>
+     <widget class="QDoubleSpinBox" name="cellsEdit">
+      <property name="geometry">
+       <rect>
+        <x>250</x>
+        <y>280</y>
+        <width>121</width>
+        <height>24</height>
+       </rect>
+      </property>
+      <property name="alignment">
+       <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+      </property>
+      <property name="accelerated">
+       <bool>true</bool>
+      </property>
+      <property name="decimals">
+       <number>1</number>
+      </property>
+      <property name="maximum">
+       <double>500.000000000000000</double>
+      </property>
+     </widget>
+     <widget class="QPushButton" name="cloneButton">
+      <property name="geometry">
+       <rect>
+        <x>343</x>
+        <y>510</y>
+        <width>80</width>
+        <height>23</height>
+       </rect>
+      </property>
+      <property name="text">
+       <string>Clone</string>
+      </property>
+      <property name="icon">
+       <iconset resource="../../../../../../home/mbroek/MyProjects/bmsapp/resources/icons.qrc">
+        <normaloff>:/icons/silk/disk_multiple.png</normaloff>:/icons/silk/disk_multiple.png</iconset>
+      </property>
+     </widget>
+     <widget class="QLabel" name="viabilityLabel">
+      <property name="geometry">
+       <rect>
+        <x>100</x>
+        <y>310</y>
+        <width>141</width>
+        <height>20</height>
+       </rect>
+      </property>
+      <property name="text">
+       <string>Viability:</string>
+      </property>
+      <property name="alignment">
+       <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+      </property>
+     </widget>
+     <widget class="QDoubleSpinBox" name="viabilityEdit">
+      <property name="geometry">
+       <rect>
+        <x>250</x>
+        <y>310</y>
+        <width>121</width>
+        <height>24</height>
+       </rect>
+      </property>
+      <property name="alignment">
+       <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+      </property>
+      <property name="accelerated">
+       <bool>true</bool>
+      </property>
+      <property name="decimals">
+       <number>4</number>
+      </property>
+      <property name="maximum">
+       <double>1.000000000000000</double>
+      </property>
+      <property name="singleStep">
+       <double>0.001000000000000</double>
+      </property>
+     </widget>
+     <widget class="QLabel" name="sizeLabel">
+      <property name="geometry">
+       <rect>
+        <x>100</x>
+        <y>370</y>
+        <width>141</width>
+        <height>20</height>
+       </rect>
+      </property>
+      <property name="text">
+       <string>Package size:</string>
+      </property>
+      <property name="alignment">
+       <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+      </property>
+     </widget>
+     <widget class="QDoubleSpinBox" name="sizeEdit">
+      <property name="geometry">
+       <rect>
+        <x>250</x>
+        <y>370</y>
+        <width>121</width>
+        <height>24</height>
+       </rect>
+      </property>
+      <property name="alignment">
+       <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+      </property>
+      <property name="accelerated">
+       <bool>true</bool>
+      </property>
+      <property name="suffix">
+       <string> xx</string>
+      </property>
+      <property name="decimals">
+       <number>1</number>
+      </property>
+      <property name="maximum">
+       <double>50000.000000000000000</double>
+      </property>
+      <property name="singleStep">
+       <double>0.500000000000000</double>
+      </property>
+     </widget>
+     <widget class="QLabel" name="usedLabel">
+      <property name="geometry">
+       <rect>
+        <x>480</x>
+        <y>70</y>
+        <width>181</width>
+        <height>20</height>
+       </rect>
+      </property>
+      <property name="text">
+       <string>Used in yeasts:</string>
+      </property>
+      <property name="alignment">
+       <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+      </property>
+     </widget>
+     <widget class="QSpinBox" name="usedEdit">
+      <property name="geometry">
+       <rect>
+        <x>680</x>
+        <y>70</y>
+        <width>81</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>true</bool>
+      </property>
+      <property name="maximum">
+       <number>100000</number>
+      </property>
+     </widget>
+     <widget class="QLabel" name="maxLabel">
+      <property name="geometry">
+       <rect>
+        <x>100</x>
+        <y>340</y>
+        <width>141</width>
+        <height>20</height>
+       </rect>
+      </property>
+      <property name="text">
+       <string>Max viability:</string>
+      </property>
+      <property name="alignment">
+       <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+      </property>
+     </widget>
+     <widget class="QSpinBox" name="maxEdit">
+      <property name="geometry">
+       <rect>
+        <x>250</x>
+        <y>340</y>
+        <width>121</width>
+        <height>24</height>
+       </rect>
+      </property>
+      <property name="toolTip">
+       <string>For most 100% is good, some liquid yeast start at 97%</string>
+      </property>
+      <property name="alignment">
+       <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+      </property>
+      <property name="accelerated">
+       <bool>true</bool>
+      </property>
+      <property name="suffix">
+       <string> %</string>
+      </property>
+      <property name="minimum">
+       <number>80</number>
+      </property>
+      <property name="maximum">
+       <number>100</number>
+      </property>
+      <property name="value">
+       <number>100</number>
+      </property>
+     </widget>
+     <widget class="QDoubleSpinBox" name="resultEdit">
+      <property name="geometry">
+       <rect>
+        <x>680</x>
+        <y>340</y>
+        <width>81</width>
+        <height>24</height>
+       </rect>
+      </property>
+      <property name="toolTip">
+       <string>The yeast health after 6 months.</string>
+      </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>true</bool>
+      </property>
+      <property name="suffix">
+       <string> %</string>
+      </property>
+      <property name="decimals">
+       <number>1</number>
+      </property>
+      <property name="maximum">
+       <double>100.000000000000000</double>
+      </property>
+     </widget>
+     <widget class="QLabel" name="resultLabel">
+      <property name="geometry">
+       <rect>
+        <x>480</x>
+        <y>340</y>
+        <width>181</width>
+        <height>20</height>
+       </rect>
+      </property>
+      <property name="text">
+       <string>6 months health:</string>
+      </property>
+      <property name="alignment">
+       <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+      </property>
+     </widget>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <tabstops>
+  <tabstop>packageEdit</tabstop>
+  <tabstop>notesEdit</tabstop>
+  <tabstop>quitButton</tabstop>
+  <tabstop>deleteButton</tabstop>
+  <tabstop>saveButton</tabstop>
+ </tabstops>
+ <resources>
+  <include location="../../../../../../home/mbroek/MyProjects/bmsapp/resources/icons.qrc"/>
+ </resources>
+ <connections/>
+</ui>
--- a/ui/MainWindow.ui	Sun Jan 29 14:40:43 2023 +0100
+++ b/ui/MainWindow.ui	Mon Jan 30 17:05:13 2023 +0100
@@ -80,6 +80,7 @@
     <addaction name="separator"/>
     <addaction name="actionSuppliers"/>
     <addaction name="actionEquipments"/>
+    <addaction name="actionYeastPacks"/>
     <addaction name="separator"/>
     <addaction name="actionSupplies_list"/>
     <addaction name="actionYeast_bank"/>
@@ -517,6 +518,15 @@
     <string>F1</string>
    </property>
   </action>
+  <action name="actionYeastPacks">
+   <property name="icon">
+    <iconset resource="../resources/icons.qrc">
+     <normaloff>:/icons/bms/yeastvial.png</normaloff>:/icons/bms/yeastvial.png</iconset>
+   </property>
+   <property name="text">
+    <string>Yeast Packages</string>
+   </property>
+  </action>
  </widget>
  <layoutdefault spacing="6" margin="11"/>
  <resources>

mercurial