src/RecipesTree.cpp

Thu, 18 Aug 2022 20:34:15 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Thu, 18 Aug 2022 20:34:15 +0200
changeset 401
583148eb6e01
parent 336
e97f9e87d94b
permissions
-rw-r--r--

Init est_carb field for new products.

/**
 * RecipesTree.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 "RecipesTree.h"
#include "MainWindow.h"
#include "EditRecipe.h"
#include "config.h"
#include "Utils.h"


RecipesTree::RecipesTree(QWidget *parent) : QDialog(parent)
{
    qDebug() << "RecipesTree start";

    gridLayout = new QGridLayout(this);
    gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
    treeWidget = new QTreeWidget(this);
    treeWidget->setObjectName(QString::fromUtf8("treeWidget"));
    QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    sizePolicy.setHorizontalStretch(0);
    sizePolicy.setVerticalStretch(0);
    sizePolicy.setHeightForWidth(treeWidget->sizePolicy().hasHeightForWidth());
    treeWidget->setSizePolicy(sizePolicy);
    gridLayout->addWidget(treeWidget, 0, 0, 1, 1);

    recipeBox = new QGroupBox(this);
    recipeBox->setObjectName(QString::fromUtf8("recipeBox"));
    QSizePolicy sizePolicy3(QSizePolicy::Preferred, QSizePolicy::Expanding);
    sizePolicy3.setHorizontalStretch(0);
    sizePolicy3.setVerticalStretch(0);
    sizePolicy3.setHeightForWidth(recipeBox->sizePolicy().hasHeightForWidth());
    recipeBox->setSizePolicy(sizePolicy3);
    recipeBox->setMinimumSize(QSize(500, 0));

    volumeLabel = new QLabel(recipeBox);
    volumeLabel->setObjectName(QString::fromUtf8("volumeLabel"));
    volumeLabel->setGeometry(QRect(100, 30, 141, 20));
    volumeLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
    volumeLabel->setText(tr("Brew volume:"));
    efficiencyLabel = new QLabel(recipeBox);
    efficiencyLabel->setObjectName(QString::fromUtf8("efficiencyLabel"));
    efficiencyLabel->setGeometry(QRect(100, 120, 141, 20));
    efficiencyLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
    efficiencyLabel->setText(tr("Brewhouse efficiency:"));
    boilvolumeLabel = new QLabel(recipeBox);
    boilvolumeLabel->setObjectName(QString::fromUtf8("boilvolumeLabel"));
    boilvolumeLabel->setGeometry(QRect(100, 60, 141, 20));
    boilvolumeLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
    boilvolumeLabel->setText(tr("Boil volume:"));
    boiltimeLabel = new QLabel(recipeBox);
    boiltimeLabel->setObjectName(QString::fromUtf8("boiltimeLabel"));
    boiltimeLabel->setGeometry(QRect(100, 90, 141, 20));
    boiltimeLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
    boiltimeLabel->setText(tr("Boil time:"));
    ogLabel = new QLabel(recipeBox);
    ogLabel->setObjectName(QString::fromUtf8("ogLabel"));
    ogLabel->setGeometry(QRect(100, 150, 141, 20));
    ogLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
    ogLabel->setText(tr("Original gravity:"));
    fgLabel = new QLabel(recipeBox);
    fgLabel->setObjectName(QString::fromUtf8("fgLabel"));
    fgLabel->setGeometry(QRect(100, 180, 141, 20));
    fgLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
    fgLabel->setText(tr("Final gravity:"));
    abvLabel = new QLabel(recipeBox);
    abvLabel->setObjectName(QString::fromUtf8("abvLabel"));
    abvLabel->setGeometry(QRect(100, 210, 141, 20));
    abvLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
    abvLabel->setText(tr("Alcohol by Volume:"));
    co2Label = new QLabel(recipeBox);
    co2Label->setObjectName(QString::fromUtf8("co2Label"));
    co2Label->setGeometry(QRect(100, 240, 141, 20));
    co2Label->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
    co2Label->setText(tr("CO2 Volume:"));
    colorLabel = new QLabel(recipeBox);
    colorLabel->setObjectName(QString::fromUtf8("colorLabel"));
    colorLabel->setGeometry(QRect(100, 270, 141, 20));
    colorLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
    colorLabel->setText(tr("Color EBC:"));
    colormethodLabel = new QLabel(recipeBox);
    colormethodLabel->setObjectName(QString::fromUtf8("colormethodLabel"));
    colormethodLabel->setGeometry(QRect(100, 300, 141, 20));
    colormethodLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
    colormethodLabel->setText(tr("Color method:"));
    ibuLabel = new QLabel(recipeBox);
    ibuLabel->setObjectName(QString::fromUtf8("ibuLabel"));
    ibuLabel->setGeometry(QRect(100, 330, 141, 20));
    ibuLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
    ibuLabel->setText(tr("Bitterness IBU:"));
    ibumethodLabel = new QLabel(recipeBox);
    ibumethodLabel->setObjectName(QString::fromUtf8("ibumethodLabel"));
    ibumethodLabel->setGeometry(QRect(100, 360, 141, 20));
    ibumethodLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
    ibumethodLabel->setText(tr("Bitterness method:"));
    remarksLabel = new QLabel(recipeBox);
    remarksLabel->setObjectName(QString::fromUtf8("remarksLabel"));
    remarksLabel->setGeometry(QRect(30, 390, 101, 20));
    remarksLabel->setAlignment(Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter);
    remarksLabel->setText(tr("Remarks:"));

    volumeEdit = new QDoubleSpinBox(recipeBox);
    volumeEdit->setObjectName(QString::fromUtf8("volumeEdit"));
    volumeEdit->setGeometry(QRect(260, 30, 111, 24));
    volumeEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
    volumeEdit->setReadOnly(true);
    volumeEdit->setButtonSymbols(QAbstractSpinBox::NoButtons);
    volumeEdit->setDecimals(1);
    volumeEdit->setMaximum(100000.000000000000000);
    volumeEdit->setSuffix(tr(" L"));
    boilvolumeEdit = new QDoubleSpinBox(recipeBox);
    boilvolumeEdit->setObjectName(QString::fromUtf8("boilvolumeEdit"));
    boilvolumeEdit->setGeometry(QRect(260, 60, 111, 24));
    boilvolumeEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
    boilvolumeEdit->setReadOnly(true);
    boilvolumeEdit->setButtonSymbols(QAbstractSpinBox::NoButtons);
    boilvolumeEdit->setDecimals(1);
    boilvolumeEdit->setMaximum(100000.000000000000000);
    boilvolumeEdit->setSuffix(tr(" L"));
    efficiencyEdit = new QDoubleSpinBox(recipeBox);
    efficiencyEdit->setObjectName(QString::fromUtf8("efficiencyEdit"));
    efficiencyEdit->setGeometry(QRect(260, 120, 111, 24));
    efficiencyEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
    efficiencyEdit->setReadOnly(true);
    efficiencyEdit->setButtonSymbols(QAbstractSpinBox::NoButtons);
    efficiencyEdit->setDecimals(1);
    efficiencyEdit->setMaximum(100.000000000000000);
    efficiencyEdit->setSuffix(tr(" %"));
    ogEdit = new QDoubleSpinBox(recipeBox);
    ogEdit->setObjectName(QString::fromUtf8("ogEdit"));
    ogEdit->setGeometry(QRect(260, 150, 111, 24));
    ogEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
    ogEdit->setReadOnly(true);
    ogEdit->setButtonSymbols(QAbstractSpinBox::NoButtons);
    ogEdit->setDecimals(3);
    ogEdit->setMaximum(1.200000000000000);
    fgEdit = new QDoubleSpinBox(recipeBox);
    fgEdit->setObjectName(QString::fromUtf8("fgEdit"));
    fgEdit->setGeometry(QRect(260, 180, 111, 24));
    fgEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
    fgEdit->setReadOnly(true);
    fgEdit->setButtonSymbols(QAbstractSpinBox::NoButtons);
    fgEdit->setDecimals(3);
    fgEdit->setMaximum(1.200000000000000);
    abvEdit = new QDoubleSpinBox(recipeBox);
    abvEdit->setObjectName(QString::fromUtf8("abvEdit"));
    abvEdit->setGeometry(QRect(260, 210, 111, 24));
    abvEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
    abvEdit->setReadOnly(true);
    abvEdit->setButtonSymbols(QAbstractSpinBox::NoButtons);
    abvEdit->setDecimals(1);
    abvEdit->setMaximum(100.000000000000000);
    abvEdit->setSuffix(tr(" %"));
    co2Edit = new QDoubleSpinBox(recipeBox);
    co2Edit->setObjectName(QString::fromUtf8("co2Edit"));
    co2Edit->setGeometry(QRect(260, 240, 111, 24));
    co2Edit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
    co2Edit->setReadOnly(true);
    co2Edit->setButtonSymbols(QAbstractSpinBox::NoButtons);
    co2Edit->setDecimals(2);
    co2Edit->setMaximum(100.000000000000000);
    boiltimeEdit = new QSpinBox(recipeBox);
    boiltimeEdit->setObjectName(QString::fromUtf8("boiltimeEdit"));
    boiltimeEdit->setGeometry(QRect(260, 90, 111, 24));
    boiltimeEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
    boiltimeEdit->setReadOnly(true);
    boiltimeEdit->setButtonSymbols(QAbstractSpinBox::NoButtons);
    boiltimeEdit->setMaximum(1440);
    boiltimeEdit->setSuffix(tr(" min"));
    colorEdit = new QSpinBox(recipeBox);
    colorEdit->setObjectName(QString::fromUtf8("colorEdit"));
    colorEdit->setGeometry(QRect(260, 270, 111, 24));
    colorEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
    colorEdit->setReadOnly(true);
    colorEdit->setButtonSymbols(QAbstractSpinBox::NoButtons);
    colorEdit->setMaximum(1440);
    ibuEdit = new QSpinBox(recipeBox);
    ibuEdit->setObjectName(QString::fromUtf8("ibuEdit"));
    ibuEdit->setGeometry(QRect(260, 330, 111, 24));
    ibuEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
    ibuEdit->setReadOnly(true);
    ibuEdit->setButtonSymbols(QAbstractSpinBox::NoButtons);
    ibuEdit->setMaximum(1440);
    remarksEdit = new QPlainTextEdit(recipeBox);
    remarksEdit->setObjectName(QString::fromUtf8("remarksEdit"));
    remarksEdit->setGeometry(QRect(30, 410, 441, 111));
    remarksEdit->setReadOnly(true);
    colormethodEdit = new QLineEdit(recipeBox);
    colormethodEdit->setObjectName(QString::fromUtf8("colormethodEdit"));
    colormethodEdit->setGeometry(QRect(260, 300, 113, 23));
    colormethodEdit->setReadOnly(true);
    ibumethodEdit = new QLineEdit(recipeBox);
    ibumethodEdit->setObjectName(QString::fromUtf8("ibumethodEdit"));
    ibumethodEdit->setGeometry(QRect(260, 360, 113, 23));
    ibumethodEdit->setReadOnly(true);

    gridLayout->addWidget(recipeBox, 0, 1, 2, 1);

    groupBox = new QGroupBox(this);
    groupBox->setObjectName(QString::fromUtf8("groupBox"));
    QSizePolicy sizePolicy2(QSizePolicy::Preferred, QSizePolicy::Preferred);
    sizePolicy2.setHorizontalStretch(0);
    sizePolicy2.setVerticalStretch(0);
    sizePolicy2.setHeightForWidth(groupBox->sizePolicy().hasHeightForWidth());
    groupBox->setSizePolicy(sizePolicy2);
    groupBox->setMinimumSize(QSize(0, 0));
    horizontalLayout = new QHBoxLayout(groupBox);
    horizontalLayout->setSpacing(200);
    horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));
    horizontalLayout->setContentsMargins(0, 0, 0, 0);

    quitButton = new QPushButton(groupBox);
    quitButton->setObjectName(QString::fromUtf8("quitButton"));
    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);

    insertButton = new QPushButton(groupBox);
    insertButton->setObjectName(QString::fromUtf8("insertButton"));
    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);

    openButton = new QPushButton(groupBox);
    openButton->setObjectName(QString::fromUtf8("openButton"));
    openButton->setText(tr("Open"));
    QIcon icon1;
    icon1.addFile(QString::fromUtf8(":icons/silk/cup_go.png"), QSize(), QIcon::Normal, QIcon::Off);
    openButton->setIcon(icon1);
    horizontalLayout->addWidget(openButton);

    gridLayout->addWidget(groupBox, 1, 0, 1, 1);

    record = -2;
    connect(quitButton, SIGNAL(clicked()), parent, SLOT(fromRecipesTree()));
    connect(insertButton, SIGNAL(clicked()), this, SLOT(on_insertButton_clicked()));
    connect(openButton, SIGNAL(clicked()), this, SLOT(on_openButton_clicked()));
    connect(this, SIGNAL(setStatus(QString)), parent, SLOT(statusMsg(QString)));

    treeWidget->setColumnCount(4);
    treeWidget->setHeaderLabels({ tr("Guide"), tr("Group"), tr("Style"), tr("Recipe") });
    treeWidget->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
    treeWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);

    connect(treeWidget, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this, SLOT(on_item_clicked(QTreeWidgetItem*, int)));
    connect(treeWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(on_item_doubleclicked(QTreeWidgetItem*, int)));

    emit refreshTable();
}


void RecipesTree::refreshTable()
{
    QTreeWidgetItem *st_guide, *st_group, *st_name, *name;

    qDebug() << "RecipesTree reload";

    treeWidget->clear();

    QSqlQuery query0;
    query0.prepare("SELECT DISTINCT st_guide FROM recipes ORDER BY st_guide");
    query0.exec();
    while (query0.next()) {
	st_guide = new QTreeWidgetItem( QStringList( { query0.value(0).toString() } ));
	treeWidget->addTopLevelItem( st_guide );
	st_guide->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator);

	QSqlQuery query1;
	query1.prepare("SELECT DISTINCT st_letter FROM recipes WHERE st_guide=:guide ORDER BY st_letter");
	query1.bindValue(":guide", query0.value(0).toString());
	query1.exec();
	while (query1.next()) {
	    st_group = new QTreeWidgetItem(QStringList({ "", query1.value(0).toString() }));
	    st_group->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator);
	    st_guide->addChild( st_group );

	    QSqlQuery query2;
            query2.prepare("SELECT DISTINCT st_name FROM recipes WHERE st_guide=:guide AND st_letter=:group ORDER BY st_name");
            query2.bindValue(":guide", query0.value(0).toString());
	    query2.bindValue(":group", query1.value(0).toString());
            query2.exec();
	    while (query2.next()) {
		st_name = new QTreeWidgetItem(QStringList({ "", "", query2.value(0).toString() }));
		st_name->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator);
		st_group->addChild( st_name );

		QSqlQuery query3;
            	query3.prepare("SELECT name,record FROM recipes WHERE st_guide=:guide AND st_letter=:group AND st_name=:name ORDER BY name");
            	query3.bindValue(":guide", query0.value(0).toString());
            	query3.bindValue(":group", query1.value(0).toString());
		query3.bindValue(":name", query2.value(0).toString());
            	query3.exec();
		while (query3.next()) {
		    name = new QTreeWidgetItem(QStringList({ "", "", "", query3.value(0).toString(), query3.value(1).toString() }));
		    st_name->addChild( name );
		}
	    }
	    treeWidget->expandItem(st_group);
	}
	treeWidget->expandItem(st_guide);
    }

    QSqlQuery query("SELECT record FROM recipes");
    emit setStatus(QString(tr("Total items: %1")).arg(query.size()));

    showRecipe();
}


void RecipesTree::showRecipe()
{
    QString w;

    qDebug() << "showRecipe" << record;

    const QStringList c_method({"Morey", "Mosher", "Daniels", "Halberstadt", "Naudts" });

    /*
     * If no recipe is "pre" selected, return.
     */
    if (record < 1) {
    	recipeBox->setEnabled(false);
	return;
    }

    /*
     * Fill in basic details of the selected recipe.
     */
    QSqlQuery query;
    query.prepare("SELECT batch_size,boil_size,boil_time,efficiency,est_og,est_fg,est_abv,est_color,color_method,est_ibu,ibu_method,est_carb,notes,name "
		  "FROM recipes WHERE record=:record");
    query.bindValue(":record", record);
    query.exec();
    if (query.size() == 1) {
	query.first();
	volumeEdit->setValue(query.value(0).toDouble());
	boilvolumeEdit->setValue(query.value(1).toDouble());
	boiltimeEdit->setValue(query.value(2).toInt());
	efficiencyEdit->setValue(query.value(3).toDouble());
	ogEdit->setValue(query.value(4).toDouble());
	fgEdit->setValue(query.value(5).toDouble());
	abvEdit->setValue(query.value(6).toInt());
	colorEdit->setValue(query.value(7).toInt());
	colorEdit->setStyleSheet(Utils::ebc_to_style(query.value(7).toInt()));
	colormethodEdit->setText(c_method[query.value(8).toInt()]);
	ibuEdit->setValue(query.value(9).toInt());
	ibumethodEdit->setText(g_ibu_method[query.value(10).toInt()]);
	co2Edit->setValue(query.value(11).toDouble());
	remarksEdit->setPlainText(query.value(12).toString());
	recipeBox->setTitle(query.value(13).toString());
	recipeBox->setEnabled(true);
    } else {
	qDebug() << "Error getting recipe record" << record;
    }
}


RecipesTree::~RecipesTree() {}


void RecipesTree::edit(int recno)
{
    EditRecipe 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 RecipesTree::on_openButton_clicked()
{
    if (record > 0)
    	edit(record);
}


void RecipesTree::on_insertButton_clicked()
{
    edit(-1);
}


void RecipesTree::on_item_clicked(QTreeWidgetItem *item, int col)
{
    record = -2; // Invalid

    if (col == 0) {
        if (item->isExpanded()) {
	    treeWidget->collapseItem(item);
	} else {
	    treeWidget->expandItem(item);
	}
    } else if (col == 1) {
        if (item->isExpanded()) {
            treeWidget->collapseItem(item);
        } else {
            treeWidget->expandItem(item);
        }
    } else if (col == 2 && item->text(2).length()) {
	if (item->isExpanded()) {
	    item->setExpanded(false);
	} else {
	    item->setExpanded(true);
	}
    } else if (col == 3) {
    	/*
    	 * if a recipe name is selected then:
    	 *   item column 3 contains the recipe name,
    	 *   item column 4 contains the recipe record number.
    	 */
    	if (item->text(4).toInt() > 0) {
	    if (record != item->text(4).toInt()) {
	    	record = item->text(4).toInt();
	    	showRecipe();
	    }
    	}
    }
}


void RecipesTree::on_item_doubleclicked(QTreeWidgetItem *item, int col)
{
    if ((col == 3) && (item->text(4).toInt() > 0)) {
	edit(item->text(4).toInt());
    }
}

mercurial