src/EditProductTab5.cpp

Thu, 28 Apr 2022 22:49:13 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Thu, 28 Apr 2022 22:49:13 +0200
changeset 175
f1ed3a2a94e9
child 179
512f492358e3
permissions
-rw-r--r--

Initial import of EditProduct, the part from EditRecipe is ported.

/**
 * EditProduct.cpp is part of bmsapp.
 *
 * tab 5, miscs.
 *
 * 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/>.
 */


bool EditProduct::misc_sort_test(const Miscs &D1, const Miscs &D2)
{
    if (D1.m_use_use > D2.m_use_use)
	return false;
    if (D1.m_use_use < D2.m_use_use)
	return true;
    if (D1.m_type > D2.m_type)
	return false;
    if (D1.m_type < D2.m_type)
	return true;
    return (D1.m_amount > D2.m_amount);
}


void EditProduct::refreshMiscs()
{
    QString w;
    QWidget* pWidget;
    QHBoxLayout* pLayout;
    QTableWidgetItem *item;

    qDebug() << "refreshMiscs" << product->miscs.size();
    std::sort(product->miscs.begin(), product->miscs.end(), misc_sort_test);

    const QSignalBlocker blocker1(ui->bs_cacl2Edit);
    const QSignalBlocker blocker2(ui->bs_caso4Edit);
    const QSignalBlocker blocker3(ui->bs_mgso4Edit);
    const QSignalBlocker blocker4(ui->bs_naclEdit);
    const QSignalBlocker blocker5(ui->bs_mgcl2Edit);
    const QSignalBlocker blocker6(ui->bs_nahco3Edit);
    const QSignalBlocker blocker7(ui->bs_caco3Edit);
    const QSignalBlocker blocker8(ui->mw_acidPick);
    const QSignalBlocker blocker9(ui->mw_acidvolEdit);

    const QStringList labels({tr("Ingredient"), tr("Type"), tr("Use at"), tr("Time"), tr("Amount"), tr("Delete"), tr("Edit") });

    ui->miscsTable->setColumnCount(7);
    ui->miscsTable->setColumnWidth(0, 300);	/* Ingredient	*/
    ui->miscsTable->setColumnWidth(1, 100);	/* Type		*/
    ui->miscsTable->setColumnWidth(2, 100);	/* Added	*/
    ui->miscsTable->setColumnWidth(3,  75);	/* Time		*/
    ui->miscsTable->setColumnWidth(4,  90);	/* Amount	*/
    ui->miscsTable->setColumnWidth(5,  80);	/* Delete	*/
    ui->miscsTable->setColumnWidth(6,  80);	/* Edit		*/
    ui->miscsTable->setHorizontalHeaderLabels(labels);
    ui->miscsTable->verticalHeader()->hide();
    ui->miscsTable->setRowCount(product->miscs.size());

    for (int i = 0; i < product->miscs.size(); i++) {

	ui->miscsTable->setItem(i, 0, new QTableWidgetItem(product->miscs.at(i).m_name));

	item = new QTableWidgetItem(misc_types[product->miscs.at(i).m_type]);
        item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter);
        ui->miscsTable->setItem(i, 1, item);

	item = new QTableWidgetItem(misc_uses[product->miscs.at(i).m_use_use]);
        item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter);
        ui->miscsTable->setItem(i, 2, item);

	if (product->miscs.at(i).m_use_use == 2) {	// Boil
	    item = new QTableWidgetItem(QString("%1 min.").arg(product->miscs.at(i).m_time, 1, 'f', 0, '0'));
	} else if (product->miscs.at(i).m_use_use == 3 || product->miscs.at(i).m_use_use == 4) {	// Primary or secondary
	    item = new QTableWidgetItem(QString("%1 days.").arg(product->miscs.at(i).m_time / 1440, 1, 'f', 0, '0'));
	} else {
	    item = new QTableWidgetItem(QString(""));
	}
	item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
        ui->miscsTable->setItem(i, 3, item);

	if (product->miscs.at(i).m_amount_is_weight)
	    item = new QTableWidgetItem(QString("%1 gr").arg(product->miscs.at(i).m_amount * 1000.0, 3, 'f', 2, '0'));
	else
	    item = new QTableWidgetItem(QString("%1 ml").arg(product->miscs.at(i).m_amount * 1000.0, 3, 'f', 2, '0'));
	item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
        ui->miscsTable->setItem(i, 4, item);

	/*
	 * Add the Delete and Edit row buttons.
	 * Not for water agents, these are set on the water tab.
	 */
	if (product->miscs.at(i).m_type == 4) {
	    ui->miscsTable->removeCellWidget(i, 5);
	    ui->miscsTable->removeCellWidget(i, 6);
	} else {
            pWidget = new QWidget();
            QPushButton* btn_dele = new QPushButton();
            btn_dele->setObjectName(QString("%1").arg(i));  /* Send row with the button */
            btn_dele->setText(tr("Delete"));
            connect(btn_dele, SIGNAL(clicked()), this, SLOT(deleteMiscRow_clicked()));
            pLayout = new QHBoxLayout(pWidget);
            pLayout->addWidget(btn_dele);
            pLayout->setContentsMargins(5, 0, 5, 0);
            pWidget->setLayout(pLayout);
            ui->miscsTable->setCellWidget(i, 5, pWidget);

            pWidget = new QWidget();
            QPushButton* btn_edit = new QPushButton();
            btn_edit->setObjectName(QString("%1").arg(i));  /* Send row with the button */
            btn_edit->setText(tr("Edit"));
            connect(btn_edit, SIGNAL(clicked()), this, SLOT(editMiscRow_clicked()));
            pLayout = new QHBoxLayout(pWidget);
            pLayout->addWidget(btn_edit);
            pLayout->setContentsMargins(5, 0, 5, 0);
            pWidget->setLayout(pLayout);
            ui->miscsTable->setCellWidget(i, 6, pWidget);
	}

	/*
	 * Update the water agents.
	 */
	if (product->miscs.at(i).m_type == 4) {
	    if (product->miscs.at(i).m_name == "CaCl2") {
		ui->bs_cacl2Edit->setValue(product->miscs.at(i).m_amount * 1000.0);
	    } else if (product->miscs.at(i).m_name == "CaSO4") {
		ui->bs_caso4Edit->setValue(product->miscs.at(i).m_amount * 1000.0);
	    } else if (product->miscs.at(i).m_name == "MgSO4") {
		ui->bs_mgso4Edit->setValue(product->miscs.at(i).m_amount * 1000.0);
	    } else if (product->miscs.at(i).m_name == "NaCl") {
		ui->bs_naclEdit->setValue(product->miscs.at(i).m_amount * 1000.0);
	    } else if (product->miscs.at(i).m_name == "MgCl2") {
		ui->bs_mgcl2Edit->setValue(product->miscs.at(i).m_amount * 1000.0);
	    } else if (product->miscs.at(i).m_name == "NaHCO3") {
		ui->bs_nahco3Edit->setValue(product->miscs.at(i).m_amount * 1000.0);
	    } else if (product->miscs.at(i).m_name == "CaCO3") {
		ui->bs_caco3Edit->setValue(product->miscs.at(i).m_amount * 1000.0);
	    } else if (product->miscs.at(i).m_name == "Melkzuur" || product->miscs.at(i).m_name == "Lactic") {
		product->wa_acid_name = 0;
		product->wa_acid_perc = my_acids.at(0).AcidPrc;
		ui->mw_acidPick->setCurrentIndex(0);
		ui->mw_acidpercEdit->setValue(my_acids.at(0).AcidPrc);
		ui->mw_acidvolEdit->setValue(product->miscs.at(i).m_amount * 1000.0);
	    } else if (product->miscs.at(i).m_name == "Zoutzuur" || product->miscs.at(i).m_name == "Hydrochloric") {
                product->wa_acid_name = 1;
                product->wa_acid_perc = my_acids.at(1).AcidPrc;
		ui->mw_acidPick->setCurrentIndex(1);
                ui->mw_acidpercEdit->setValue(my_acids.at(1).AcidPrc);
                ui->mw_acidvolEdit->setValue(product->miscs.at(i).m_amount * 1000.0);
	    } else if (product->miscs.at(i).m_name == "Fosforzuur" || product->miscs.at(i).m_name == "Phosphoric") {
                product->wa_acid_name = 2;
                product->wa_acid_perc = my_acids.at(2).AcidPrc;
		ui->mw_acidPick->setCurrentIndex(2);
                ui->mw_acidpercEdit->setValue(my_acids.at(2).AcidPrc);
                ui->mw_acidvolEdit->setValue(product->miscs.at(i).m_amount * 1000.0);
	    } else if (product->miscs.at(i).m_name == "Zwavelzuur" || product->miscs.at(i).m_name == "Sulfuric") {
                product->wa_acid_name = 3;
                product->wa_acid_perc = my_acids.at(3).AcidPrc;
		ui->mw_acidPick->setCurrentIndex(3);
                ui->mw_acidpercEdit->setValue(my_acids.at(3).AcidPrc);
                ui->mw_acidvolEdit->setValue(product->miscs.at(i).m_amount * 1000.0);
	    }
	}
    }
}


/*
 * Manipulate the memory array and update the miscs table.
 */
void EditProduct::brewing_salt_sub(QString salt, double val)
{
    QTableWidgetItem *item;

    val = round(val * 100.0) / 100.0;
    if (val == 0) {
	/*
	 * Remove this salt if it is in the table.
	 */
	for (int i = 0; i < product->miscs.size(); i++) {
	    if (salt.contains(product->miscs.at(i).m_name)) {
		qDebug() << "  brewing_salt_sub delete" << salt;
		product->miscs.removeAt(i);
		refreshMiscs();
		return;
	    }
	}
	qDebug() << "  brewing_salt_sub delete error";
	return;
    }

    /*
     * First see if this salt is in the table.
     * If it is, update the amount.
     */
    for (int i = 0; i < product->miscs.size(); i++) {
	if (salt.contains(product->miscs.at(i).m_name)) {
	    product->miscs[i].m_amount = val / 1000.0;
	    if (product->miscs.at(i).m_amount_is_weight)
            	item = new QTableWidgetItem(QString("%1 gr").arg(val, 3, 'f', 2, '0'));
            else
	    	item = new QTableWidgetItem(QString("%1 ml").arg(val, 3, 'f', 2, '0'));
	    item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
	    ui->miscsTable->setItem(i, 4, item);
	    return;
	}
    }

    /*
     * We need a new entry. Search in the database is tricky because
     * we are here with possible more names for the same salt. The
     * name can be like 'Lactic Melkzuur'. So we select only the
     * brewing salts and manually check their names.
     */
    QSqlQuery query("SELECT * FROM inventory_miscs WHERE type = 4");
    while (query.next()) {
	if (salt.contains(query.value(1).toString())) {
	    qDebug() << "  found it, append";
	    Miscs m;
	    m.m_name = query.value(1).toString();
            m.m_amount = val / 1000.0;
            m.m_type = query.value(2).toInt();
            m.m_use_use = query.value(3).toInt();
            m.m_time = query.value(4).toDouble();
            m.m_amount_is_weight = query.value(5).toInt() ? true:false;
            m.m_cost = query.value(10).toDouble();
            product->miscs.append(m);
	    refreshMiscs();
	    return;
	}
    }

    qDebug() << "brewing_salt_sub, nothing done." << salt << val;
}


/*
 * Edit brewing salt and recalculate.
 */
void EditProduct::set_brewing_salt(QString salt, double val)
{
    val = round(val * 100.0) / 100.0;
    qDebug() << "set_brewing_salt" << salt << val;
    brewing_salt_sub(salt, val);
    calcWater();
    is_changed();
}


void EditProduct::addMiscRow_clicked()
{
    Miscs newm;

    for (int i = 0; i < product->miscs.size(); i++) {
        if (product->miscs.at(i).m_amount == 0)
            return;     // Add only one at a time.
    }

    newm.m_name = "Select one";
    newm.m_amount = 0;
    newm.m_type = 0;
    newm.m_use_use = 0;
    newm.m_time = 0;
    newm.m_amount_is_weight = true;
    newm.m_cost = 0;
    product->miscs.append(newm);
    is_changed();
    emit refreshAll();
}


void EditProduct::deleteMiscRow_clicked()
{
    if (product->locked || product->miscs.size() < 1)
	return;

    QPushButton *pb = qobject_cast<QPushButton *>(QObject::sender());
    int row = pb->objectName().toInt();
    qDebug() << "Delete misc row" << row << product->miscs.size();

    int rc = QMessageBox::warning(this, tr("Delete misc"), tr("Delete %1").arg(product->miscs.at(row).m_name),
                    QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
    if (rc == QMessageBox::No)
        return;

    product->miscs.removeAt(row);
    is_changed();
    emit refreshAll();
}


void EditProduct::misc_amount_changed(double val)
{
    QTableWidgetItem *item;

    qDebug() << "misc_amount_changed()" << product->miscs_row << val;

    product->miscs[product->miscs_row].m_amount = val / 1000.0;
    if (product->miscs.at(product->miscs_row).m_amount_is_weight) {
        item = new QTableWidgetItem(QString("%1 gr").arg(product->miscs.at(product->miscs_row).m_amount * 1000.0, 3, 'f', 2, '0'));
    } else {
        item = new QTableWidgetItem(QString("%1 ml").arg(product->miscs.at(product->miscs_row).m_amount * 1000.0, 3, 'f', 2, '0'));
    }
    item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
    ui->miscsTable->setItem(product->miscs_row, 4, item);

    is_changed();
}


void EditProduct::misc_time_changed(int val)
{
    QTableWidgetItem *item;

    qDebug() << "misc_time_changed()" << product->miscs_row << val;

    if (product->miscs.at(product->miscs_row).m_use_use == 2) {       // Boil
	product->miscs[product->miscs_row].m_time = val;
	item = new QTableWidgetItem(QString("%1 min.").arg(val, 1, 'f', 0, '0'));
    } else if (product->miscs.at(product->miscs_row).m_use_use == 3 || product->miscs.at(product->miscs_row).m_use_use == 4) {  // Primary or secondary
	product->miscs[product->miscs_row].m_time = val * 1440;
	item = new QTableWidgetItem(QString("%1 days.").arg(val, 1, 'f', 0, '0'));
    } else {
	item = new QTableWidgetItem(QString(""));
    }
    item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
    ui->miscsTable->setItem(product->miscs_row, 3, item);

    is_changed();
}


void EditProduct::misc_select_changed(int val)
{
    QSqlQuery query;
    bool instock = minstockEdit->isChecked();
    QString w;
    QTableWidgetItem *item;

    if (val < 1)
        return;

    qDebug() << "misc_select_changed()" << product->miscs_row << val << instock;

    /*
     * Search the misc ingredient pointed by the index and instock flag.
     */
    QString sql = "SELECT name,type,use_use,time,amount_is_weight,cost FROM inventory_miscs WHERE ";
    if (instock)
        sql.append("inventory > 0 AND ");
    sql.append("type != 4 ORDER BY name");
    qDebug() << sql;
    query.prepare(sql);
    query.exec();
    query.first();
    for (int i = 0; i < (val - 1); i++) {
        query.next();
    }
    qDebug() << "found" << query.value(0).toString();

    /*
     * Replace the misc record contents
     */
    product->miscs[product->miscs_row].m_name = query.value(0).toString();
    product->miscs[product->miscs_row].m_type = query.value(1).toInt();
    product->miscs[product->miscs_row].m_use_use = query.value(2).toInt();
    product->miscs[product->miscs_row].m_time = query.value(3).toDouble();
    product->miscs[product->miscs_row].m_amount_is_weight = query.value(4).toInt() ? true:false;
    product->miscs[product->miscs_row].m_cost = query.value(5).toDouble();

    /*
     * Update the visible fields
     */
    mnameEdit->setText(product->miscs.at(product->miscs_row).m_name);
    ui->miscsTable->setItem(product->miscs_row, 0, new QTableWidgetItem(product->miscs.at(product->miscs_row).m_name));

    item = new QTableWidgetItem(misc_types[product->miscs.at(product->miscs_row).m_type]);
    item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter);
    ui->miscsTable->setItem(product->miscs_row, 1, item);

    item = new QTableWidgetItem(misc_uses[product->miscs.at(product->miscs_row).m_use_use]);
    item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter);
    ui->miscsTable->setItem(product->miscs_row, 2, item);
    useatEdit->setCurrentIndex(product->miscs.at(product->miscs_row).m_use_use);

    if (product->miscs.at(product->miscs_row).m_use_use == 3 || product->miscs.at(product->miscs_row).m_use_use == 4) {     // Fermentation stages
        mtimeEdit->setValue(product->miscs.at(product->miscs_row).m_time / 1440);
        mtimeEdit->setReadOnly(false);
	mtimeLabel->setText(tr("Time in days:"));
	item = new QTableWidgetItem(QString("%1 days.").arg(product->miscs.at(product->miscs_row).m_time / 1440, 1, 'f', 0, '0'));
    } else if (product->miscs.at(product->miscs_row).m_use_use == 2) {    // Boil
        mtimeEdit->setValue(product->miscs.at(product->miscs_row).m_time);
        mtimeEdit->setReadOnly(false);
	mtimeLabel->setText(tr("Time in minutes:"));
	item = new QTableWidgetItem(QString("%1 min.").arg(product->miscs.at(product->miscs_row).m_time, 1, 'f', 0, '0'));
    } else {
        mtimeEdit->setReadOnly(true);
	mtimeLabel->setText("");
	item = new QTableWidgetItem(QString(""));
    }
    item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
    ui->miscsTable->setItem(product->miscs_row, 3, item);

    if (product->miscs.at(product->miscs_row).m_amount_is_weight) {
	mamountLabel->setText(tr("Amount in gr:"));
	item = new QTableWidgetItem(QString("%1 gr").arg(product->miscs.at(product->miscs_row).m_amount * 1000.0, 3, 'f', 2, '0'));
    } else {
	mamountLabel->setText(tr("Amount in ml:"));
	item = new QTableWidgetItem(QString("%1 ml").arg(product->miscs.at(product->miscs_row).m_amount * 1000.0, 3, 'f', 2, '0'));
    }
    item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
    ui->miscsTable->setItem(product->miscs_row, 4, item);

    is_changed();
    emit refreshAll();
}


void EditProduct::misc_instock_changed(bool val)
{
    QSqlQuery query;

    qDebug() << "misc_instock_changed()" << product->miscs_row << val;

    this->mselectEdit->setCurrentIndex(-1);
    this->mselectEdit->clear();
    QString sql = "SELECT name,type,amount_is_weight,inventory FROM inventory_miscs WHERE ";
    if (val)
        sql.append("inventory > 0 AND ");
    sql.append("type != 4 ORDER BY name");
    query.prepare(sql);
    query.exec();
    query.first();
    this->mselectEdit->addItem("");      // Start with empty value
    for (int i = 0; i < query.size(); i++) {
        this->mselectEdit->addItem(query.value(0).toString()+ " (" + misc_types[query.value(1).toInt()] + ") " +
                        QString("%1 %2").arg(query.value(3).toDouble() * 1000.0, 3, 'f', 2, '0').arg(query.value(2).toInt()?"gr":"ml"));
        query.next();
    }
}


void EditProduct::misc_useat_changed(int val)
{
    QTableWidgetItem *item;

    qDebug() << "misc_useat_changed" << val;
    product->miscs[product->miscs_row].m_use_use = val;
    item = new QTableWidgetItem(misc_uses[val]);
    item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter);
    ui->miscsTable->setItem(product->miscs_row, 2, item);

    if (val == 3 || val == 4) {     // Fermentation stages
	product->miscs[product->miscs_row].m_time = mtimeEdit->value() * 1440;
        mtimeEdit->setReadOnly(false);
        mtimeLabel->setText(tr("Time in days:"));
        item = new QTableWidgetItem(QString("%1 days.").arg(product->miscs.at(product->miscs_row).m_time / 1440, 1, 'f', 0, '0'));
    } else if (val == 2) {    // Boil
	product->miscs[product->miscs_row].m_time = mtimeEdit->value();
        mtimeEdit->setReadOnly(false);
        mtimeLabel->setText(tr("Time in minutes:"));
        item = new QTableWidgetItem(QString("%1 min.").arg(product->miscs.at(product->miscs_row).m_time, 1, 'f', 0, '0'));
    } else {
	product->miscs[product->miscs_row].m_time = 0;
	mtimeEdit->setValue(0);
        mtimeEdit->setReadOnly(true);
        mtimeLabel->setText("");
        item = new QTableWidgetItem(QString(""));
    }
    item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
    ui->miscsTable->setItem(product->miscs_row, 3, item);

    is_changed();
}


void EditProduct::editMiscRow_clicked()
{
    QSqlQuery query;

    if (product->locked)
	return;

    QPushButton *pb = qobject_cast<QPushButton *>(QObject::sender());
    product->miscs_row = pb->objectName().toInt();
    qDebug() << "Edit misc row" << product->miscs_row;
    Miscs backup = product->miscs.at(product->miscs_row);

    QDialog* dialog = new QDialog(this);
    dialog->resize(738, 230);
    QDialogButtonBox *buttonBox = new QDialogButtonBox(dialog);
    buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
    buttonBox->setGeometry(QRect(30, 180, 671, 32));
    buttonBox->setLayoutDirection(Qt::LeftToRight);
    buttonBox->setOrientation(Qt::Horizontal);
    buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
    buttonBox->setCenterButtons(true);

    QLabel *nameLabel = new QLabel(dialog);
    nameLabel->setObjectName(QString::fromUtf8("nameLabel"));
    nameLabel->setText(tr("Current ingredient:"));
    nameLabel->setGeometry(QRect(10, 10, 141, 20));
    nameLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);

    mamountLabel = new QLabel(dialog);
    mamountLabel->setObjectName(QString::fromUtf8("mamountLabel"));
    if (product->miscs.at(product->miscs_row).m_amount_is_weight)
    	mamountLabel->setText(tr("Amount in gr:"));
    else
	mamountLabel->setText(tr("Amount in ml:"));
    mamountLabel->setGeometry(QRect(10, 70, 141, 20));
    mamountLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);

    mtimeLabel = new QLabel(dialog);
    mtimeLabel->setObjectName(QString::fromUtf8("mtimeLabel"));
    if (product->miscs.at(product->miscs_row).m_use_use == 3 || product->miscs.at(product->miscs_row).m_use_use == 4)	// Fermentation stages
        mtimeLabel->setText(tr("Time in days:"));
    else if (product->miscs.at(product->miscs_row).m_use_use == 2)  // Boil
        mtimeLabel->setText(tr("Time in minutes:"));
    else
        mtimeLabel->setText("");
    mtimeLabel->setGeometry(QRect(10, 100, 141, 20));
    mtimeLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);

    QLabel *selectLabel = new QLabel(dialog);
    selectLabel->setObjectName(QString::fromUtf8("selectLabel"));
    selectLabel->setText(tr("Select ingredient:"));
    selectLabel->setGeometry(QRect(10, 40, 141, 20));
    selectLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
    QLabel *instockLabel = new QLabel(dialog);
    instockLabel->setObjectName(QString::fromUtf8("instockLabel"));
    instockLabel->setText(tr("In stock:"));
    instockLabel->setGeometry(QRect(525, 40, 121, 20));
    instockLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);

    mselectEdit = new QComboBox(dialog);
    mselectEdit->setObjectName(QString::fromUtf8("selectEdit"));
    mselectEdit->setGeometry(QRect(160, 40, 371, 23));

    mnameEdit = new QLineEdit(dialog);
    mnameEdit->setObjectName(QString::fromUtf8("mnameEdit"));
    mnameEdit->setText(product->miscs.at(product->miscs_row).m_name);
    mnameEdit->setGeometry(QRect(160, 10, 511, 23));
    mnameEdit->setReadOnly(true);

    mamountEdit = new QDoubleSpinBox(dialog);
    mamountEdit->setObjectName(QString::fromUtf8("mamountEdit"));
    mamountEdit->setGeometry(QRect(160, 70, 121, 24));
    mamountEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
    mamountEdit->setAccelerated(true);
    mamountEdit->setDecimals(2);
    mamountEdit->setMaximum(1000000.0);
    mamountEdit->setSingleStep(0.1);
    mamountEdit->setValue(product->miscs.at(product->miscs_row).m_amount * 1000.0);

    mtimeEdit = new QSpinBox(dialog);
    mtimeEdit->setObjectName(QString::fromUtf8("mtimeEdit"));
    mtimeEdit->setGeometry(QRect(160, 100, 121, 24));
    mtimeEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
    mtimeEdit->setAccelerated(true);
    mtimeEdit->setMaximum(10000.0);
    if (product->miscs.at(product->miscs_row).m_use_use == 3 || product->miscs.at(product->miscs_row).m_use_use == 4) {	// Fermentation stages
	mtimeEdit->setValue(product->miscs.at(product->miscs_row).m_time / 1440);
        mtimeEdit->setReadOnly(false);
    } else if (product->miscs.at(product->miscs_row).m_use_use == 2) {	// Boil
	mtimeEdit->setValue(product->miscs.at(product->miscs_row).m_time);
        mtimeEdit->setReadOnly(false);
    } else {
	mtimeEdit->setReadOnly(true);
    }

    useatEdit = new QComboBox(dialog);
    useatEdit->setObjectName(QString::fromUtf8("useatEdit"));
    useatEdit->setGeometry(QRect(160, 130, 161, 23));
    useatEdit->addItem(tr("Starter"));
    useatEdit->addItem(tr("Mash"));
    useatEdit->addItem(tr("Boil"));
    useatEdit->addItem(tr("Primary"));
    useatEdit->addItem(tr("Secondary"));
    useatEdit->addItem(tr("Bottling"));
    useatEdit->setCurrentIndex(product->miscs.at(product->miscs_row).m_use_use);

    minstockEdit = new QCheckBox(dialog);
    minstockEdit->setObjectName(QString::fromUtf8("minstockEdit"));
    minstockEdit->setGeometry(QRect(655, 40, 85, 21));
    minstockEdit->setChecked(true);

    misc_instock_changed(true);

    connect(mselectEdit, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &EditProduct::misc_select_changed);
    connect(mamountEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditProduct::misc_amount_changed);
    connect(mtimeEdit, QOverload<int>::of(&QSpinBox::valueChanged), this, &EditProduct::misc_time_changed);
    connect(useatEdit, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &EditProduct::misc_useat_changed);
    connect(minstockEdit, &QCheckBox::stateChanged, this, &EditProduct::misc_instock_changed);
    connect(buttonBox, SIGNAL(rejected()), dialog, SLOT(reject()));
    connect(buttonBox, SIGNAL(accepted()), dialog, SLOT(accept()));

    dialog->setModal(true);
    dialog->exec();
    if (dialog->result() == QDialog::Rejected) {
        qDebug() << "reject and rollback";
        product->miscs[product->miscs_row] = backup;
    } else {
        /* Clear time if misc is not used for boil or fermentation. */
        if (! (product->miscs.at(product->miscs_row).m_use_use == 2 ||
               product->miscs.at(product->miscs_row).m_use_use == 3 ||
               product->miscs.at(product->miscs_row).m_use_use == 4)) {
            if (product->miscs.at(product->miscs_row).m_time) {
                product->miscs[product->miscs_row].m_time = 0;
                is_changed();
            }
        }
    }

    disconnect(mselectEdit, nullptr, nullptr, nullptr);
    disconnect(mamountEdit, nullptr, nullptr, nullptr);
    disconnect(mtimeEdit, nullptr, nullptr, nullptr);
    disconnect(useatEdit, nullptr, nullptr, nullptr);
    disconnect(minstockEdit, nullptr, nullptr, nullptr);
    disconnect(buttonBox, nullptr, nullptr, nullptr);

    emit refreshAll();
}


void EditProduct::adjustMiscs(double factor)
{
    double amount;

    if (product->miscs.size() == 0)
	return;

    const QSignalBlocker blocker1(ui->bs_cacl2Edit);
    const QSignalBlocker blocker2(ui->bs_caso4Edit);
    const QSignalBlocker blocker3(ui->bs_mgso4Edit);
    const QSignalBlocker blocker4(ui->bs_naclEdit);
    const QSignalBlocker blocker5(ui->bs_mgcl2Edit);
    const QSignalBlocker blocker6(ui->bs_nahco3Edit);
    const QSignalBlocker blocker7(ui->bs_caco3Edit);
    const QSignalBlocker blocker9(ui->mw_acidvolEdit);

    for (int i = 0; i < product->miscs.size(); i++) {
	amount = product->miscs.at(i).m_amount * factor;
	product->miscs[i].m_amount = amount;

	/*
         * Update the water agents.
         */
        if (product->miscs.at(i).m_type == 4) {
            if (product->miscs.at(i).m_name == "CaCl2") {
                ui->bs_cacl2Edit->setValue(product->miscs.at(i).m_amount * 1000.0);
            } else if (product->miscs.at(i).m_name == "CaSO4") {
                ui->bs_caso4Edit->setValue(product->miscs.at(i).m_amount * 1000.0);
            } else if (product->miscs.at(i).m_name == "MgSO4") {
                ui->bs_mgso4Edit->setValue(product->miscs.at(i).m_amount * 1000.0);
            } else if (product->miscs.at(i).m_name == "NaCl") {
                ui->bs_naclEdit->setValue(product->miscs.at(i).m_amount * 1000.0);
            } else if (product->miscs.at(i).m_name == "MgCl2") {
                ui->bs_mgcl2Edit->setValue(product->miscs.at(i).m_amount * 1000.0);
            } else if (product->miscs.at(i).m_name == "NaHCO3") {
                ui->bs_nahco3Edit->setValue(product->miscs.at(i).m_amount * 1000.0);
            } else if (product->miscs.at(i).m_name == "CaCO3") {
                ui->bs_caco3Edit->setValue(product->miscs.at(i).m_amount * 1000.0);
            } else if (product->miscs.at(i).m_name == "Melkzuur" || product->miscs.at(i).m_name == "Lactic") {
                ui->mw_acidvolEdit->setValue(product->miscs.at(i).m_amount * 1000.0);
            } else if (product->miscs.at(i).m_name == "Zoutzuur" || product->miscs.at(i).m_name == "Hydrochloric") {
                ui->mw_acidvolEdit->setValue(product->miscs.at(i).m_amount * 1000.0);
            } else if (product->miscs.at(i).m_name == "Fosforzuur" || product->miscs.at(i).m_name == "Phosphoric") {
                ui->mw_acidvolEdit->setValue(product->miscs.at(i).m_amount * 1000.0);
            } else if (product->miscs.at(i).m_name == "Zwavelzuur" || product->miscs.at(i).m_name == "Sulfuric") {
                ui->mw_acidvolEdit->setValue(product->miscs.at(i).m_amount * 1000.0);
            }
        }
    }
}

mercurial