Tue, 19 Apr 2022 21:15:42 +0200
Implemented most parts of the mash editor.
src/EditRecipe.cpp | file | annotate | diff | comparison | revisions | |
src/EditRecipe.h | file | annotate | diff | comparison | revisions | |
src/EditRecipeTab6.cpp | file | annotate | diff | comparison | revisions | |
src/MainWindow.cpp | file | annotate | diff | comparison | revisions |
--- a/src/EditRecipe.cpp Tue Apr 19 11:17:16 2022 +0200 +++ b/src/EditRecipe.cpp Tue Apr 19 21:15:42 2022 +0200 @@ -684,7 +684,7 @@ // All signals from tab "Mash" ui->mashsTable->setEditTriggers(QAbstractItemView::NoEditTriggers); - //connect(ui->addMash, SIGNAL(clicked()), this, SLOT(addMashRow_clicked())); + connect(ui->addMash, SIGNAL(clicked()), this, SLOT(addMashRow_clicked())); //connect(ui->mash_pickEdit, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &EditRecipe::mash_select_changed); // All signals from tab "Water"
--- a/src/EditRecipe.h Tue Apr 19 11:17:16 2022 +0200 +++ b/src/EditRecipe.h Tue Apr 19 21:15:42 2022 +0200 @@ -320,6 +320,13 @@ void mw_ph_changed(double val); void mw_acid_changed(double val); void mw_type_changed(int val); + void step_name_changed(QString val); + void step_type_changed(int val); + void step_temp_changed(double val); + void end_temp_changed(double val); + void step_time_changed(double val); + void ramp_time_changed(double val); + void infuse_changed(double val); /* Modified progress bars */ void ferment_perc_mash_valueChanged(int value); @@ -361,11 +368,12 @@ * Variables for popup ingredients editing. */ QComboBox *fselectEdit, *faddedEdit, *hselectEdit,*haddedEdit, *useatEdit, *mselectEdit, *yselectEdit; - QLineEdit *fnameEdit, *fsupplierEdit, *hnameEdit, *horiginEdit, *mnameEdit, *ynameEdit, *ylaboratoryEdit, *yproduct_idEdit; + QLineEdit *fnameEdit, *fsupplierEdit, *hnameEdit, *horiginEdit, *mnameEdit, *ynameEdit, *ylaboratoryEdit, *yproduct_idEdit, *stepnameEdit; QDoubleSpinBox *famountEdit, *pctEdit, *fmaxEdit, *hamountEdit, *ibuEdit, *mamountEdit, *yamountEdit; + QDoubleSpinBox *steptempEdit, *endtempEdit, *steptimeEdit, *ramptimeEdit, *stepivolEdit, *stepitmpEdit; QSpinBox *htimeEdit, *mtimeEdit; QCheckBox *to100Edit, *finstockEdit, *hinstockEdit, *minstockEdit, *yinstockEdit; - QLabel *htimeLabel, *mtimeLabel, *mamountLabel; + QLabel *htimeLabel, *mtimeLabel, *mamountLabel, *ivolLabel, *itmpLabel; void to100Fermentables(int row); static bool ferment_sort_test(const Fermentables &D1, const Fermentables &D2);
--- a/src/EditRecipeTab6.cpp Tue Apr 19 11:17:16 2022 +0200 +++ b/src/EditRecipeTab6.cpp Tue Apr 19 21:15:42 2022 +0200 @@ -24,6 +24,10 @@ QWidget* pWidget; QHBoxLayout* pLayout; QTableWidgetItem *item; + QIcon down_icon, up_icon; + + down_icon.addFile(QString::fromUtf8(":/icons/silk/bullet_arrow_down.png"), QSize(), QIcon::Normal, QIcon::Off); + up_icon.addFile(QString::fromUtf8(":/icons/silk/bullet_arrow_up.png"), QSize(), QIcon::Normal, QIcon::Off); qDebug() << "refreshYeasts" << recipe->yeasts.size(); std::sort(recipe->yeasts.begin(), recipe->yeasts.end(), yeast_sort_test); @@ -100,27 +104,35 @@ item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); ui->mashsTable->setItem(i, 9, item); - pWidget = new QWidget(); - QPushButton* btn_up = new QPushButton(); - btn_up->setObjectName(QString("%1").arg(i)); /* Send row with the button */ - btn_up->setText(tr("U")); - connect(btn_up, SIGNAL(clicked()), this, SLOT(upMashRow_clicked())); - pLayout = new QHBoxLayout(pWidget); - pLayout->addWidget(btn_up); - pLayout->setContentsMargins(5, 0, 5, 0); - pWidget->setLayout(pLayout); - ui->mashsTable->setCellWidget(i, 10, pWidget); + if (i > 0) { + pWidget = new QWidget(); + QPushButton* btn_up = new QPushButton(); + btn_up->setObjectName(QString("%1").arg(i)); /* Send row with the button */ + btn_up->setIcon(up_icon); + connect(btn_up, SIGNAL(clicked()), this, SLOT(upMashRow_clicked())); + pLayout = new QHBoxLayout(pWidget); + pLayout->addWidget(btn_up); + pLayout->setContentsMargins(5, 0, 5, 0); + pWidget->setLayout(pLayout); + ui->mashsTable->setCellWidget(i, 10, pWidget); + } else { + ui->mashsTable->removeCellWidget(i, 10); + } - pWidget = new QWidget(); - QPushButton* btn_down = new QPushButton(); - btn_down->setObjectName(QString("%1").arg(i)); /* Send row with the button */ - btn_down->setText(tr("D")); - connect(btn_down, SIGNAL(clicked()), this, SLOT(downMashRow_clicked())); - pLayout = new QHBoxLayout(pWidget); - pLayout->addWidget(btn_down); - pLayout->setContentsMargins(5, 0, 5, 0); - pWidget->setLayout(pLayout); - ui->mashsTable->setCellWidget(i, 11, pWidget); + if (i < (recipe->mashs.size() - 1)) { + pWidget = new QWidget(); + QPushButton* btn_down = new QPushButton(); + btn_down->setObjectName(QString("%1").arg(i)); /* Send row with the button */ + btn_down->setIcon(down_icon); + connect(btn_down, SIGNAL(clicked()), this, SLOT(downMashRow_clicked())); + pLayout = new QHBoxLayout(pWidget); + pLayout->addWidget(btn_down); + pLayout->setContentsMargins(5, 0, 5, 0); + pWidget->setLayout(pLayout); + ui->mashsTable->setCellWidget(i, 11, pWidget); + } else { + ui->mashsTable->removeCellWidget(i, 11); + } pWidget = new QWidget(); QPushButton* btn_dele = new QPushButton(); @@ -149,26 +161,346 @@ void EditRecipe::addMashRow_clicked() { + Mashs newm; + + for (int i = 0; i < recipe->mashs.size(); i++) { + if (recipe->mashs.at(i).step_time == 0) + return; // Add only one at a time. + } + + newm.step_name = "Name me"; + newm.step_temp = newm.end_temp = 67.0; + newm.step_time = 20; + newm.ramp_time = 10; + if (recipe->mashs.size()) { + newm.step_volume = recipe->mashs.at(recipe->mashs.size() - 1).step_volume; + newm.step_wg_ratio = recipe->mashs.at(recipe->mashs.size() - 1).step_wg_ratio; + newm.step_type = recipe->mashs.at(recipe->mashs.size() - 1).step_type; + } else { + newm.step_volume = 0; + newm.step_wg_ratio = 0; + newm.step_type = 1; + } + newm.step_infuse_amount = newm.step_infuse_temp = 0; + + recipe->mashs.append(newm); + is_changed(); + emit refreshAll(); } void EditRecipe::deleteMashRow_clicked() { + QPushButton *pb = qobject_cast<QPushButton *>(QObject::sender()); + int row = pb->objectName().toInt(); + qDebug() << "Delete mash row" << row << recipe->mashs.size(); + + if (recipe->mashs.size() < 1) + return; + + int rc = QMessageBox::warning(this, tr("Delete mash step"), tr("Delete %1").arg(recipe->mashs.at(row).step_name), + QMessageBox::Yes | QMessageBox::No, QMessageBox::No); + if (rc == QMessageBox::No) + return; + + this->ignoreChanges = true; + recipe->mashs.removeAt(row); + this->ignoreChanges = false; + is_changed(); + emit refreshAll(); } void EditRecipe::upMashRow_clicked() { + QPushButton *pb = qobject_cast<QPushButton *>(QObject::sender()); + int row = pb->objectName().toInt(); + qDebug() << "Move up mash row" << row << recipe->mashs.size(); + + if (recipe->mashs.size() < 1) + return; } void EditRecipe::downMashRow_clicked() { + QPushButton *pb = qobject_cast<QPushButton *>(QObject::sender()); + int row = pb->objectName().toInt(); + qDebug() << "Move down mash row" << row << recipe->mashs.size(); + + if (recipe->mashs.size() < 1) + return; +} + + +void EditRecipe::step_name_changed(QString val) +{ + this->ignoreChanges = true; + recipe->mashs[recipe->mashs_row].step_name = val; + ui->mashsTable->setItem(recipe->mashs_row, 0, new QTableWidgetItem(val)); + this->ignoreChanges = false; + is_changed(); +} + + +void EditRecipe::step_type_changed(int val) +{ + qDebug() << "step_type_changed" << recipe->mashs_row << val; + + this->ignoreChanges = true; + recipe->mashs[recipe->mashs_row].step_type = val; + this->ignoreChanges = false; + ivolLabel->setVisible(recipe->mashs.at(recipe->mashs_row).step_type == 0); + stepivolEdit->setVisible(recipe->mashs.at(recipe->mashs_row).step_type == 0); + itmpLabel->setVisible(recipe->mashs.at(recipe->mashs_row).step_type == 0); + stepitmpEdit->setVisible(recipe->mashs.at(recipe->mashs_row).step_type == 0); + is_changed(); + emit refreshAll(); +} + + +void EditRecipe::step_temp_changed(double val) +{ + qDebug() << "step_temp_changed" << recipe->mashs_row << val; + this->ignoreChanges = true; + recipe->mashs[recipe->mashs_row].step_temp = val; + QTableWidgetItem *item = new QTableWidgetItem(QString("%1 °C").arg(val, 2, 'f', 1, '0')); + item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); + ui->mashsTable->setItem(recipe->mashs_row, 2, item); + this->ignoreChanges = false; + is_changed(); +} + + +void EditRecipe::end_temp_changed(double val) +{ + qDebug() << "end_temp_changed" << recipe->mashs_row << val; + this->ignoreChanges = true; + recipe->mashs[recipe->mashs_row].end_temp = val; + QTableWidgetItem *item = new QTableWidgetItem(QString("%1 °C").arg(val, 2, 'f', 1, '0')); + item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); + ui->mashsTable->setItem(recipe->mashs_row, 3, item); + this->ignoreChanges = false; + is_changed(); +} + + +void EditRecipe::step_time_changed(double val) +{ + qDebug() << "step_time_changed" << recipe->mashs_row << val; + this->ignoreChanges = true; + recipe->mashs[recipe->mashs_row].step_time = val; + QTableWidgetItem *item = new QTableWidgetItem(QString("%1 min").arg(val, 1, 'f', 0, '0')); + item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); + ui->mashsTable->setItem(recipe->mashs_row, 4, item); + this->ignoreChanges = false; + is_changed(); +} + + +void EditRecipe::ramp_time_changed(double val) +{ + qDebug() << "ramp_time_changed" << recipe->mashs_row << val; + this->ignoreChanges = true; + recipe->mashs[recipe->mashs_row].ramp_time = val; + QTableWidgetItem *item = new QTableWidgetItem(QString("%1 min").arg(val, 1, 'f', 0, '0')); + item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); + ui->mashsTable->setItem(recipe->mashs_row, 5, item); + this->ignoreChanges = false; + is_changed(); +} + + +void EditRecipe::infuse_changed(double val) +{ + qDebug() << "infuse_changed" << recipe->mashs_row << val; + this->ignoreChanges = true; + recipe->mashs[recipe->mashs_row].step_infuse_amount = val; + QTableWidgetItem *item = new QTableWidgetItem(QString("%1 L").arg(val, 1, 'f', 0, '0')); + item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); + ui->mashsTable->setItem(recipe->mashs_row, 6, item); + + /* + * Recalculate water volumes + */ + double volume = 0; + for (int i = 0; i < recipe->mashs.size(); i++) { + if (recipe->mashs.at(i).step_type == 0) { + volume += recipe->mashs.at(i).step_infuse_amount; + } + recipe->mashs[i].step_volume = volume; + } + recipe->w1_amount = volume - recipe->w2_amount; + recipe->wg_amount = volume; + ui->w1_volEdit->setValue(recipe->w1_amount); + + this->ignoreChanges = false; + is_changed(); + emit refreshAll(); } void EditRecipe::editMashRow_clicked() { + QSqlQuery query; + + QPushButton *pb = qobject_cast<QPushButton *>(QObject::sender()); + recipe->mashs_row = pb->objectName().toInt(); + qDebug() << "Edit mash row" << recipe->mashs_row; + Mashs backup = recipe->mashs.at(recipe->mashs_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("Step name:")); + nameLabel->setGeometry(QRect(10, 10, 141, 20)); + nameLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + stepnameEdit = new QLineEdit(dialog); + stepnameEdit->setObjectName(QString::fromUtf8("stepnameEdit")); + stepnameEdit->setText(recipe->mashs.at(recipe->mashs_row).step_name); + stepnameEdit->setGeometry(QRect(160, 10, 511, 23)); + + QLabel *typeLabel = new QLabel(dialog); + typeLabel->setObjectName(QString::fromUtf8("typeLabel")); + typeLabel->setText(tr("Step type:")); + typeLabel->setGeometry(QRect(10, 40, 141, 20)); + typeLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + QComboBox *typeEdit = new QComboBox(dialog); + typeEdit->setObjectName(QString::fromUtf8("typeEdit")); + typeEdit->setGeometry(QRect(160, 40, 161, 23)); + typeEdit->addItem(tr("Infusion")); + typeEdit->addItem(tr("Temperature")); + typeEdit->addItem(tr("Decoction")); + typeEdit->setCurrentIndex(recipe->mashs.at(recipe->mashs_row).step_type); + + QLabel *tempLabel = new QLabel(dialog); + tempLabel->setObjectName(QString::fromUtf8("tempLabel")); + tempLabel->setText(tr("Step start temp:")); + tempLabel->setGeometry(QRect(10, 70, 141, 20)); + tempLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + steptempEdit = new QDoubleSpinBox(dialog); + steptempEdit->setObjectName(QString::fromUtf8("steptempEdit")); + steptempEdit->setGeometry(QRect(160, 70, 121, 24)); + steptempEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + steptempEdit->setDecimals(1); + steptempEdit->setValue(recipe->mashs.at(recipe->mashs_row).step_temp); + + QLabel *endLabel = new QLabel(dialog); + endLabel->setObjectName(QString::fromUtf8("endLabel")); + endLabel->setText(tr("Step end temp:")); + endLabel->setGeometry(QRect(360, 70, 141, 20)); + endLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + endtempEdit = new QDoubleSpinBox(dialog); + endtempEdit->setObjectName(QString::fromUtf8("endtempEdit")); + endtempEdit->setGeometry(QRect(510, 70, 121, 24)); + endtempEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + endtempEdit->setDecimals(1); + endtempEdit->setValue(recipe->mashs.at(recipe->mashs_row).end_temp); + + QLabel *timeLabel = new QLabel(dialog); + timeLabel->setObjectName(QString::fromUtf8("timeLabel")); + timeLabel->setText(tr("Step rest time:")); + timeLabel->setGeometry(QRect(10, 100, 141, 20)); + timeLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + steptimeEdit = new QDoubleSpinBox(dialog); + steptimeEdit->setObjectName(QString::fromUtf8("steptimeEdit")); + steptimeEdit->setGeometry(QRect(160, 100, 121, 24)); + steptimeEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + steptimeEdit->setDecimals(0); + steptimeEdit->setValue(recipe->mashs.at(recipe->mashs_row).step_time); + + QLabel *rampLabel = new QLabel(dialog); + rampLabel->setObjectName(QString::fromUtf8("rampLabel")); + rampLabel->setText(tr("Step ramp time:")); + rampLabel->setGeometry(QRect(360, 100, 141, 20)); + rampLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + ramptimeEdit = new QDoubleSpinBox(dialog); + ramptimeEdit->setObjectName(QString::fromUtf8("ramptimeEdit")); + ramptimeEdit->setGeometry(QRect(510, 100, 121, 24)); + ramptimeEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + ramptimeEdit->setDecimals(0); + ramptimeEdit->setValue(recipe->mashs.at(recipe->mashs_row).ramp_time); + + /* + * Only used for Infusion steps. + */ + ivolLabel = new QLabel(dialog); + ivolLabel->setObjectName(QString::fromUtf8("ivolLabel")); + ivolLabel->setText(tr("Infusion volume:")); + ivolLabel->setGeometry(QRect(10, 130, 141, 20)); + ivolLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + ivolLabel->setVisible(recipe->mashs.at(recipe->mashs_row).step_type == 0); + stepivolEdit = new QDoubleSpinBox(dialog); + stepivolEdit->setObjectName(QString::fromUtf8("stepivolEdit")); + stepivolEdit->setGeometry(QRect(160, 130, 121, 24)); + stepivolEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + stepivolEdit->setVisible(recipe->mashs.at(recipe->mashs_row).step_type == 0); + stepivolEdit->setDecimals(1); + stepivolEdit->setSingleStep(0.5); + stepivolEdit->setValue(recipe->mashs.at(recipe->mashs_row).step_infuse_amount); + + itmpLabel = new QLabel(dialog); + itmpLabel->setObjectName(QString::fromUtf8("itmpLabel")); + itmpLabel->setText(tr("Infusion Temperature:")); + itmpLabel->setGeometry(QRect(360, 130, 141, 20)); + itmpLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + itmpLabel->setVisible(recipe->mashs.at(recipe->mashs_row).step_type == 0); + stepitmpEdit = new QDoubleSpinBox(dialog); + stepitmpEdit->setObjectName(QString::fromUtf8("stepitmpEdit")); + stepitmpEdit->setGeometry(QRect(510, 130, 121, 24)); + stepitmpEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + stepitmpEdit->setVisible(recipe->mashs.at(recipe->mashs_row).step_type == 0); + stepitmpEdit->setDecimals(1); + stepitmpEdit->setReadOnly(true); + stepitmpEdit->setButtonSymbols(QAbstractSpinBox::NoButtons); + stepitmpEdit->setValue(recipe->mashs.at(recipe->mashs_row).step_infuse_temp); + + connect(stepnameEdit, &QLineEdit::textEdited, this, &EditRecipe::step_name_changed); + connect(typeEdit, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &EditRecipe::step_type_changed); + connect(steptempEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditRecipe::step_temp_changed); + connect(endtempEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditRecipe::end_temp_changed); + connect(steptimeEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditRecipe::step_time_changed); + connect(ramptimeEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditRecipe::ramp_time_changed); + connect(stepivolEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditRecipe::infuse_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"; + recipe->mashs[recipe->mashs_row] = backup; + /* Rollback water volumes too */ + double volume = 0; + for (int i = 0; i < recipe->mashs.size(); i++) { + if (recipe->mashs.at(i).step_type == 0) { + volume += recipe->mashs.at(i).step_infuse_amount; + } + recipe->mashs[i].step_volume = volume; + } + recipe->w1_amount = volume - recipe->w2_amount; + recipe->wg_amount = volume; + ui->w1_volEdit->setValue(recipe->w1_amount); + } + + disconnect(stepnameEdit, nullptr, nullptr, nullptr); + disconnect(steptempEdit, nullptr, nullptr, nullptr); + disconnect(endtempEdit, nullptr, nullptr, nullptr); + disconnect(steptimeEdit, nullptr, nullptr, nullptr); + disconnect(ramptimeEdit, nullptr, nullptr, nullptr); + disconnect(stepivolEdit, nullptr, nullptr, nullptr); + disconnect(buttonBox, nullptr, nullptr, nullptr); + + emit refreshAll(); }