src/PrinterDialog.cpp

Sun, 24 Apr 2022 22:22:22 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Sun, 24 Apr 2022 22:22:22 +0200
changeset 159
231f5c8002e3
parent 158
24bc2de721d9
child 160
2b62a032079f
permissions
-rw-r--r--

Added the largest part of print recipe.

/**
 * Printer.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 "PrinterDialog.h"
#include "Utils.h"
#include "EditRecipe.h"
#include "config.h"
#include "global.h"

#include <QPrintPreviewDialog>
#include <QDebug>
#include <QtSql>


PrinterDialog::PrinterDialog(int job, int rec, QWidget* parent) : QDialog(parent)
{
    qDebug() << "PrinterDialog start job" << job << "rec" << rec;

    p_job = job;
    p_rec = rec;

    QPrinter printer(QPrinter::ScreenResolution);
    QPrintPreviewDialog preview(&printer, this);
    connect(&preview, &QPrintPreviewDialog::paintRequested, this, &PrinterDialog::printDocument);
    preview.exec();
}


PrinterDialog::~PrinterDialog() {}


void PrinterDialog::printDocument(QPrinter *printer)
{
    qDebug() << "PrinterDialog printDocument()";

    QRect rectangle;
    QRect boundingRect;
    QPainter painter;
    QString w;
    QSqlQuery query;

    const QColor c_header(255, 150, 100, 255);
    const QColor c_line1( 210, 245, 255, 255);
    const QColor c_line2( 255, 255, 210, 255);
    const QColor f_line(  250, 195,  65, 255);
    const QColor h_line(  100, 250,  65, 255);
    const QColor y_line(  175, 175, 255, 255);
    const QColor mw_line( 240, 140, 130, 255);
    const QColor mf_line(  95, 180,  25, 255);
    const QColor ms_line( 240, 250,  65, 255);
    const QColor mo_line( 210, 245, 255, 255);
    const QColor m_line(  175, 175, 255, 255); // also y_line
    const QColor w_line(  120, 255, 250, 255);

    const QStringList y_unit({tr("pkg"), tr("gr"), tr("ml"), tr("ml"), tr("ml"), tr("ml"), tr("gr")});
    const QStringList ibu_method({ "Tinseth", "Rager", "Daniels", "Garetz", "Mosher", "Noonan" });
    const QStringList color_method({ "Morey", "Mosher", "Daniels", "Halberstadt", "Naudts" });

    painter.begin(printer);
    qreal y = 0;

    if (p_job == PR_SUPPLIES) {
	/*
	 * Print supplies in stock
	 */
	double	tot_fermentables = 0, tot_hops = 0, tot_yeasts = 0, tot_miscs = 0;

	printHeader(&painter);
	y = 120;
	/* Fermentables supplies header */
	painter.setFont(QFont("Helvetica", 9, QFont::Bold));
	painter.setPen(Qt::black);
	painter.fillRect(  0, y,   735, 20, c_header);
	painter.drawText(  0, y+4,  90, 20, Qt::AlignLeft, tr("Type"));
	painter.drawText( 90, y+4, 100, 20, Qt::AlignLeft, tr("Supplier"));
	painter.drawText(190, y+4, 270, 20, Qt::AlignLeft, tr("Fermentable"));
	painter.drawText(460, y+4, 115, 20, Qt::AlignRight, tr("Stock"));
	painter.drawText(575, y+4,  80, 20, Qt::AlignRight, tr("Price/Kg"));
	painter.drawText(655, y+4,  80, 20, Qt::AlignRight, tr("Value"));
	y += 20;
	painter.setFont(QFont("Helvetica", 9, QFont::Normal));
	query.exec("SELECT type,name,supplier,inventory,cost FROM inventory_fermentables WHERE inventory > 0 ORDER BY type,supplier,name");
	query.first();
	for (int i = 0 ; i < query.size() ; i++ ) {
	    if ((y + 20) > painter.device()->height()) {
                printer->newPage();
		printHeader(&painter);
                y = 120;
            }
	    painter.fillRect(  0, y,   735, 20, (i % 2) ? c_line1:c_line2);
	    painter.drawText(  0, y+4,  90, 20, Qt::AlignLeft, fermentable_types[query.value(0).toInt()]);
	    painter.drawText( 90, y+4, 100, 20, Qt::AlignLeft, query.value(2).toString());
	    painter.drawText(190, y+4, 270, 20, Qt::AlignLeft, query.value(1).toString());
	    w = QString("%1 kg").arg(query.value(3).toDouble(), 10, 'f', 3);
	    painter.drawText(460, y+4, 115, 20, Qt::AlignRight, w);
	    w = QString("%1 €").arg(query.value(4).toDouble(), 8, 'f', 2);
	    painter.drawText(575, y+4,  80, 20, Qt::AlignRight, w);
	    w = QString("%1 €").arg(query.value(3).toDouble() * query.value(4).toDouble(), 8, 'f', 2);
	    tot_fermentables += (query.value(3).toDouble() * query.value(4).toDouble());
	    painter.drawText(655, y+4,  80, 20, Qt::AlignRight, w);
	    query.next();
	    y += 20;
	}
	painter.fillRect(  0, y,   735, 20, c_header);
	painter.drawText(  0, y+4, 100, 20, Qt::AlignLeft, tr("Total"));
	w = QString("%1 €").arg(tot_fermentables, 8, 'f', 2);
	painter.drawText(655, y+4,  80, 20, Qt::AlignRight, w);
	y += 20;

	/* Hops supplies */
	query.exec("SELECT name,form,origin,inventory,cost FROM inventory_hops WHERE inventory > 0 ORDER BY origin,name");
        query.first();
	if ((y + 80 + (query.size() * 20)) > painter.device()->height()) {	/* Rows + header + footer + blank */
	    printer->newPage();
	    printHeader(&painter);
	    y = 120;
	} else {
	    y += 40;
	}
        painter.setFont(QFont("Helvetica", 9, QFont::Bold));
        painter.setPen(Qt::black);
        painter.fillRect(  0, y,   735, 20, c_header);
        painter.drawText(  0, y+4, 120, 20, Qt::AlignLeft, tr("Country"));
	painter.drawText(120, y+4, 260, 20, Qt::AlignLeft, tr("Hop name"));
	painter.drawText(380, y+4,  80, 20, Qt::AlignLeft, tr("Form"));
	painter.drawText(460, y+4, 115, 20, Qt::AlignRight, tr("Stock"));
        painter.drawText(575, y+4,  80, 20, Qt::AlignRight, tr("Price/Kg"));
        painter.drawText(655, y+4,  80, 20, Qt::AlignRight, tr("Value"));
	y += 20;
        painter.setFont(QFont("Helvetica", 9, QFont::Normal));
	for (int i = 0; i < query.size(); i++) {
	    if ((y + 20) > painter.device()->height()) {
		printer->newPage();
		printHeader(&painter);
		y = 120;
	    }
	    painter.fillRect(  0, y,   735, 20, (i % 2) ? c_line1:c_line2);
            painter.drawText(  0, y+4, 120, 20, Qt::AlignLeft, query.value(2).toString());
	    painter.drawText(120, y+4, 260, 20, Qt::AlignLeft, query.value(0).toString());
	    painter.drawText(380, y+4,  80, 20, Qt::AlignLeft, hop_forms[query.value(1).toInt()]);
	    if (query.value(3).toDouble() < 0.6)
		w = QString("%1 gr").arg(query.value(3).toDouble() * 1000.0, 10, 'f', 1);
	    else
	        w = QString("%1 kg").arg(query.value(3).toDouble(), 10, 'f', 3);
            painter.drawText(460, y+4, 115, 20, Qt::AlignRight, w);
            w = QString("%1 €").arg(query.value(4).toDouble(), 8, 'f', 2);
            painter.drawText(575, y+4,  80, 20, Qt::AlignRight, w);
            w = QString("%1 €").arg(query.value(3).toDouble() * query.value(4).toDouble(), 8, 'f', 2);
            tot_hops += (query.value(3).toDouble() * query.value(4).toDouble());
            painter.drawText(655, y+4,  80, 20, Qt::AlignRight, w);
            query.next();
            y += 20;
	}
	painter.fillRect(  0, y,   735, 20, c_header);
        painter.drawText(  0, y+4, 100, 20, Qt::AlignLeft, tr("Total"));
        w = QString("%1 €").arg(tot_hops, 8, 'f', 2);
        painter.drawText(655, y+4,  80, 20, Qt::AlignRight, w);
	y += 20;

	/* Yeasts supplies */
	query.exec("SELECT name,laboratory,product_id,form,inventory,cost FROM inventory_yeasts WHERE inventory > 0 ORDER BY laboratory,product_id");
        query.first();
	if ((y + 80 + (query.size() * 20)) > painter.device()->height()) {      /* Rows + header + footer + blank */
            printer->newPage();
            printHeader(&painter);
            y = 120;
        } else {
            y += 40;
        }
        painter.setFont(QFont("Helvetica", 9, QFont::Bold));
        painter.setPen(Qt::black);
        painter.fillRect(  0, y,   735, 20, c_header);
        painter.drawText(  0, y+4, 120, 20, Qt::AlignLeft, tr("Laboratory"));
        painter.drawText(120, y+4, 120, 20, Qt::AlignLeft, tr("Product"));
        painter.drawText(240, y+4, 220, 20, Qt::AlignLeft, tr("Yeast"));
        painter.drawText(460, y+4, 115, 20, Qt::AlignRight, tr("Stock"));
        painter.drawText(575, y+4,  80, 20, Qt::AlignRight, tr("Price/Kg"));
        painter.drawText(655, y+4,  80, 20, Qt::AlignRight, tr("Value"));
        y += 20;
        painter.setFont(QFont("Helvetica", 9, QFont::Normal));
	for (int i = 0; i < query.size(); i++) {
	    if ((y + 20) > painter.device()->height()) {
                printer->newPage();
		printHeader(&painter);
                y = 120;
            }
            painter.fillRect(  0, y,   735, 20, (i % 2) ? c_line1:c_line2);
            painter.drawText(  0, y+4, 120, 20, Qt::AlignLeft, query.value(1).toString());
	    painter.drawText(120, y+4, 120, 20, Qt::AlignLeft, query.value(2).toString());
	    painter.drawText(240, y+4, 220, 20, Qt::AlignLeft, query.value(0).toString());
	    if (query.value(3).toInt() == 0)
		w = QString("%1 %2").arg(query.value(4).toDouble(), 10, 'f', 1).arg(y_unit[query.value(3).toInt()]);
	    else
		w = QString("%1 %2").arg(query.value(4).toDouble() * 1000.0, 10, 'f', 1).arg(y_unit[query.value(3).toInt()]);
            painter.drawText(460, y+4, 115, 20, Qt::AlignRight, w);
            w = QString("%1 €").arg(query.value(5).toDouble(), 8, 'f', 2);
            painter.drawText(575, y+4,  80, 20, Qt::AlignRight, w);
            w = QString("%1 €").arg(query.value(4).toDouble() * query.value(5).toDouble(), 8, 'f', 2);
            tot_yeasts += (query.value(4).toDouble() * query.value(5).toDouble());
            painter.drawText(655, y+4,  80, 20, Qt::AlignRight, w);
            query.next();
            y += 20;
	}
	painter.fillRect(  0, y,   735, 20, c_header);
        painter.drawText(  0, y+4, 100, 20, Qt::AlignLeft, tr("Total"));
        w = QString("%1 €").arg(tot_yeasts, 8, 'f', 2);
        painter.drawText(655, y+4,  80, 20, Qt::AlignRight, w);
        y += 20;

	/* Miscs supplies */
	query.exec("SELECT name,type,amount_is_weight,inventory,cost FROM inventory_miscs WHERE inventory > 0 ORDER BY type,name");
        query.first();
	if ((y + 80 + (query.size() * 20)) > painter.device()->height()) {      /* Rows + header + footer + blank */
            printer->newPage();
            printHeader(&painter);
            y = 120;
        } else {
            y += 40;
        }
        painter.setFont(QFont("Helvetica", 9, QFont::Bold));
        painter.setPen(Qt::black);
        painter.fillRect(  0, y,   735, 20, c_header);
        painter.drawText(  0, y+4, 120, 20, Qt::AlignLeft, tr("Type"));
        painter.drawText(120, y+4, 340, 20, Qt::AlignLeft, tr("Ingredient"));
        painter.drawText(460, y+4, 115, 20, Qt::AlignRight, tr("Stock"));
        painter.drawText(575, y+4,  80, 20, Qt::AlignRight, tr("Price/Kg"));
        painter.drawText(655, y+4,  80, 20, Qt::AlignRight, tr("Value"));
        y += 20;
        painter.setFont(QFont("Helvetica", 9, QFont::Normal));
	for (int i = 0; i < query.size(); i++) {
            if ((y + 20) > painter.device()->height()) {
                printer->newPage();
                printHeader(&painter);
                y = 120;
            }
            painter.fillRect(  0, y,   735, 20, (i % 2) ? c_line1:c_line2);
            painter.drawText(  0, y+4, 120, 20, Qt::AlignLeft, misc_types[query.value(1).toInt()]);
            painter.drawText(120, y+4, 340, 20, Qt::AlignLeft, query.value(0).toString());
            if (query.value(2).toInt())
                w = QString("%1 gr").arg(query.value(3).toDouble() * 1000.0, 10, 'f', 1);
            else
                w = QString("%1 ml").arg(query.value(3).toDouble() * 1000.0, 10, 'f', 1);
            painter.drawText(460, y+4, 115, 20, Qt::AlignRight, w);
            w = QString("%1 €").arg(query.value(4).toDouble(), 8, 'f', 2);
            painter.drawText(575, y+4,  80, 20, Qt::AlignRight, w);
            w = QString("%1 €").arg(query.value(3).toDouble() * query.value(4).toDouble(), 8, 'f', 2);
            tot_miscs += (query.value(3).toDouble() * query.value(4).toDouble());
            painter.drawText(655, y+4,  80, 20, Qt::AlignRight, w);
            query.next();
            y += 20;
        }
	painter.fillRect(  0, y,   735, 20, c_header);
        painter.drawText(  0, y+4, 100, 20, Qt::AlignLeft, tr("Total"));
        w = QString("%1 €").arg(tot_miscs, 8, 'f', 2);
        painter.drawText(655, y+4,  80, 20, Qt::AlignRight, w);
        y += 20;

    } else if (p_job == PR_YEASTBANK) {
	/*
	 * Print yeast in the private yeast bank.
	 */
	printHeader(&painter);
        y = 120;

	painter.setFont(QFont("Helvetica", 9, QFont::Bold));
        painter.setPen(Qt::black);
        painter.fillRect(  0, y,   735, 20, c_header);
        painter.drawText(  0, y+4, 200, 20, Qt::AlignLeft, tr("Yeast"));
        painter.drawText(200, y+4, 230, 20, Qt::AlignLeft, tr("Description"));
	painter.drawText(430, y+4,  80, 20, Qt::AlignCenter, tr("Type"));
	painter.drawText(510, y+4,  80, 20, Qt::AlignCenter, tr("Form"));
        painter.drawText(590, y+4,  70, 20, Qt::AlignRight, tr("Stock"));
        painter.drawText(665, y+4,  70, 20, Qt::AlignLeft, tr("Date"));
        y += 20;
        painter.setFont(QFont("Helvetica", 9, QFont::Normal));
	query.prepare("SELECT name,type,form,inventory,production_date,short_desc "
		       "FROM inventory_yeasts WHERE inventory > 0 AND laboratory = :my_lab ORDER BY product_id");
	query.bindValue(":my_lab", my_yeastlab);
	query.exec();
        query.first();
	for (int i = 0; i < query.size(); i++) {
	    painter.fillRect(  0, y,   735, 20, (i % 2) ? c_line1:c_line2);
            painter.drawText(  0, y+4, 200, 20, Qt::AlignLeft, query.value(0).toString());
	    painter.drawText(200, y+4, 230, 20, Qt::AlignLeft, query.value(5).toString());
	    painter.drawText(430, y+4,  80, 20, Qt::AlignCenter, yeast_types[query.value(1).toInt()]);
	    painter.drawText(510, y+4,  80, 20, Qt::AlignCenter, yeast_forms[query.value(2).toInt()]);

	    if (query.value(2).toInt() == 0)
                w = QString("%1 %2").arg(query.value(3).toDouble(), 10, 'f', 1).arg(y_unit[query.value(2).toInt()]);
            else
                w = QString("%1 %2").arg(query.value(3).toDouble() * 1000.0, 10, 'f', 1).arg(y_unit[query.value(2).toInt()]);
	    painter.drawText(590, y+4,  70, 20, Qt::AlignRight, w);
	    painter.drawText(665, y+4,  70, 20, Qt::AlignLeft, query.value(4).toString());
	    query.next();
	    y += 20;
	}
    } else if (p_job == PR_RECIPE) {

	printHeader(&painter);
        y = 120;
	/* Fermentables supplies header */
        painter.setFont(QFont("Helvetica", 9, QFont::Bold));
        painter.setPen(Qt::black);
        painter.fillRect(  0, y,   735, 20, c_header);
        painter.drawText(  0, y+4, 735, 20, Qt::AlignCenter, tr("Recipe overview"));
	y += 20;
        painter.setFont(QFont("Helvetica", 9, QFont::Normal));
	painter.fillRect(  0, y,   300, 20, c_line1);
	painter.drawText(  0, y+4, 120, 20, Qt::AlignLeft, tr("Brew type"));
	painter.drawText(120, y+4, 180, 20, Qt::AlignLeft, recipe_types[recipe->type]);
	painter.fillRect(435, y,   300, 20, c_line1);
        painter.drawText(435, y+4, 120, 20, Qt::AlignLeft, tr("Efficiency"));
        painter.drawText(555, y+4, 180, 20, Qt::AlignLeft, QString("%1 %").arg(recipe->efficiency, 1, 'f', 1));
	y += 20;
	painter.fillRect(  0, y,   300, 20, c_line1);
        painter.drawText(  0, y+4, 120, 20, Qt::AlignLeft, tr("Boil time"));
        painter.drawText(120, y+4, 180, 20, Qt::AlignLeft, QString("%1 minutes.").arg(recipe->boil_time, 1, 'f', 0));
	painter.fillRect(435, y,   300, 20, c_line1);
        painter.drawText(435, y+4, 120, 20, Qt::AlignLeft, tr("Batch size"));
        painter.drawText(555, y+4, 180, 20, Qt::AlignLeft, QString("%1 L.").arg(recipe->batch_size, 1, 'f', 1));
	y += 20;
	painter.fillRect(  0, y,   300, 20, c_line1);
        painter.drawText(  0, y+4, 120, 20, Qt::AlignLeft, tr("Start SG"));
        painter.drawText(120, y+4,  90, 20, Qt::AlignLeft, QString("%1").arg(recipe->est_og, 1, 'f', 3));
	painter.drawText(210, y+4,  90, 20, Qt::AlignLeft, QString("(%1 - %2)").arg(recipe->st_og_min, 1, 'f', 3).arg(recipe->st_og_max, 1, 'f', 3));
        painter.fillRect(435, y,   300, 20, c_line1);
        painter.drawText(435, y+4, 120, 20, Qt::AlignLeft, tr("End SG"));
        painter.drawText(555, y+4,  90, 20, Qt::AlignLeft, QString("%1").arg(recipe->est_fg, 1, 'f', 3));
	painter.drawText(645, y+4,  90, 20, Qt::AlignLeft, QString("(%1 - %2)").arg(recipe->st_fg_min, 1, 'f', 3).arg(recipe->st_fg_max, 1, 'f', 3));
	y += 20;
	painter.fillRect(  0, y,   300, 20, c_line1);
        painter.drawText(  0, y+4, 120, 20, Qt::AlignLeft, tr("Estimated Alcohol"));
        painter.drawText(120, y+4,  90, 20, Qt::AlignLeft, QString("%1%").arg(recipe->est_abv, 1, 'f', 1));
	painter.drawText(210, y+4,  90, 20, Qt::AlignLeft, QString("(%1 - %2)").arg(recipe->st_abv_min, 1, 'f', 1).arg(recipe->st_abv_max, 1, 'f', 1));
        painter.fillRect(435, y,   300, 20, c_line1);
        painter.drawText(435, y+4, 120, 20, Qt::AlignLeft, tr("Estimated CO2 vol"));
        painter.drawText(555, y+4,  90, 20, Qt::AlignLeft, QString("%1").arg(recipe->est_carb, 1, 'f', 1));
	painter.drawText(645, y+4,  90, 20, Qt::AlignLeft, QString("(%1 - %2)").arg(recipe->st_carb_min, 1, 'f', 1).arg(recipe->st_carb_max, 1, 'f', 1));
	y += 20;
	painter.fillRect(  0, y,   120, 20, c_line1);
        painter.drawText(  0, y+4, 120, 20, Qt::AlignLeft, tr("Color (") + color_method[recipe->color_method] + ")");
	painter.fillRect(120, y,   180, 20, Utils::ebc_to_color(recipe->est_color));
	if (recipe->est_color > 30)
	    painter.setPen(Qt::white);
        painter.drawText(120, y+4,  90, 20, Qt::AlignLeft, QString("%1 EBC").arg(recipe->est_color, 1, 'f', 0));
	painter.drawText(210, y+4,  90, 20, Qt::AlignLeft, QString("(%1 - %2)").arg(recipe->st_color_min, 1, 'f', 0).arg(recipe->st_color_max, 1, 'f', 0));
	painter.setPen(Qt::black);
        painter.fillRect(435, y,   300, 20, c_line1);
        painter.drawText(435, y+4, 120, 20, Qt::AlignLeft, tr("IBU (") + ibu_method[recipe->ibu_method] + ")");
        painter.drawText(555, y+4,  90, 20, Qt::AlignLeft, QString("%1").arg(recipe->est_ibu, 1, 'f', 1));
	painter.drawText(645, y+4,  90, 20, Qt::AlignLeft, QString("(%1 - %2)").arg(recipe->st_ibu_min, 1, 'f', 0).arg(recipe->st_ibu_max, 1, 'f', 0));
	y += 40;

	/* Fermentables */
        painter.setFont(QFont("Helvetica", 9, QFont::Bold));
        painter.setPen(Qt::black);
        painter.fillRect(  0, y,   735, 20, c_header);
        painter.drawText(  0, y+4, 260, 20, Qt::AlignLeft, tr("Fermentable"));
        painter.drawText(265, y+4,  70, 20, Qt::AlignRight, tr("Percent"));
        painter.drawText(340, y+4,  70, 20, Qt::AlignRight, tr("Yield"));
        painter.drawText(415, y+4,  90, 20, Qt::AlignLeft, tr("Type"));
        painter.drawText(510, y+4,  90, 20, Qt::AlignLeft, tr("Use at"));
        painter.drawText(605, y+4,  60, 20, Qt::AlignRight, tr("Amount"));
	painter.drawText(670, y+4,  60, 20, Qt::AlignRight, tr("Cost"));
        y += 20;
	painter.setFont(QFont("Helvetica", 9, QFont::Normal));
	double cost_fermentables = 0;
	QString soort, amount, use;
	for (int i = 0; i < recipe->fermentables.size(); i++) {
	    double cost = recipe->fermentables.at(i).f_amount * recipe->fermentables.at(i).f_cost;
	    cost_fermentables += cost;

	    if (recipe->fermentables.at(i).f_type == 0)
		soort = fermentable_graintypes[recipe->fermentables.at(i).f_graintype];
	    else
		soort = fermentable_types[recipe->fermentables.at(i).f_type];

	    if (recipe->fermentables.at(i).f_amount > 100)
		amount = QString("%1 kg").arg(recipe->fermentables.at(i).f_amount, 1, 'f', 1);
	    else if (recipe->fermentables.at(i).f_amount > 10)
		amount = QString("%1 kg").arg(recipe->fermentables.at(i).f_amount, 1, 'f', 2);
	    else
		amount = QString("%1 gr").arg(recipe->fermentables.at(i).f_amount * 1000, 1, 'f', 0);

	    painter.fillRect(  0, y,   735, 20, f_line);

	    painter.drawText(  0, y+4, 260, 20, Qt::AlignLeft,	recipe->fermentables.at(i).f_name +
			    					QString(", %1 EBC (").arg(recipe->fermentables.at(i).f_color, 1, 'f', 0) +
								recipe->fermentables.at(i).f_supplier + ")");
	    painter.drawText(265, y+4,  70, 20, Qt::AlignRight, QString("%1%").arg(recipe->fermentables.at(i).f_percentage, 1, 'f', 1));
	    painter.drawText(340, y+4,  70, 20, Qt::AlignRight, QString("%1%").arg(recipe->fermentables.at(i).f_yield, 1, 'f', 1));
	    painter.drawText(415, y+4,  90, 20, Qt::AlignLeft,  soort);
	    painter.drawText(510, y+4,  90, 20, Qt::AlignLeft,  fermentable_added[recipe->fermentables.at(i).f_added]);
	    painter.drawText(605, y+4,  60, 20, Qt::AlignRight, amount);
	    painter.drawText(670, y+4,  60, 20, Qt::AlignRight, QString("%1 €").arg(cost, 1, 'f', 3));
	    y += 20;
	}
	painter.fillRect(670, y,    60, 20, c_line1);
	painter.drawText(670, y+4,  60, 20, Qt::AlignRight, QString("%1 €").arg(cost_fermentables, 1, 'f', 3));
	y += 40;

	/* Hops */
	painter.setFont(QFont("Helvetica", 9, QFont::Bold));
        painter.fillRect(  0, y,   735, 20, c_header);
        painter.drawText(  0, y+4, 260, 20, Qt::AlignLeft, tr("Hop"));
        painter.drawText(265, y+4,  70, 20, Qt::AlignRight, tr("Alpha"));
        painter.drawText(340, y+4,  70, 20, Qt::AlignRight, tr("IBU"));
        painter.drawText(415, y+4,  90, 20, Qt::AlignLeft, tr("Type"));
        painter.drawText(510, y+4,  90, 20, Qt::AlignLeft, tr("Use at"));
        painter.drawText(605, y+4,  60, 20, Qt::AlignRight, tr("Amount"));
        painter.drawText(670, y+4,  60, 20, Qt::AlignRight, tr("Cost"));
        y += 20;
	painter.setFont(QFont("Helvetica", 9, QFont::Normal));
	double cost_hops = 0;
	for (int i = 0; i < recipe->hops.size(); i++) {

	    double cost = recipe->hops.at(i).h_amount * recipe->hops.at(i).h_cost;
	    cost_hops += cost;
	    double ibu = Utils::toIBU(recipe->hops.at(i).h_useat, recipe->hops.at(i).h_form, recipe->preboil_sg, recipe->batch_size,
			    	      recipe->hops.at(i).h_amount, recipe->hops.at(i).h_time, recipe->hops.at(i).h_alpha,
				      recipe->ibu_method, 0, recipe->hops.at(i).h_time, 0);

	    if (recipe->hops.at(i).h_useat == 2 || recipe->hops.at(i).h_useat == 4)	// Boil or Whirlpool
		use = hop_useat[recipe->hops.at(i).h_useat] + QString(" %1 min").arg(recipe->hops.at(i).h_time);
	    else if (recipe->hops.at(i).h_useat == 5)					// Dryhop
		use = hop_useat[recipe->hops.at(i).h_useat] + QString(" %1 days").arg(recipe->hops.at(i).h_time / 1440);
	    else
		use = hop_useat[recipe->hops.at(i).h_useat];

	    if (recipe->hops.at(i).h_amount > 1)
		amount = QString("%1 kg").arg(recipe->hops.at(i).h_amount, 1, 'f', 3);
	    else
		amount = QString("%1 gr").arg(recipe->hops.at(i).h_amount * 1000, 1, 'f', 1);

	    painter.fillRect(  0, y,   735, 20, h_line);
	    painter.drawText(  0, y+4, 260, 20, Qt::AlignLeft,  recipe->hops.at(i).h_name + " (" + recipe->hops.at(i).h_origin + ")");
	    painter.drawText(265, y+4,  70, 20, Qt::AlignRight, QString("%1%").arg(recipe->hops.at(i).h_alpha, 1, 'f', 1));
	    painter.drawText(340, y+4,  70, 20, Qt::AlignRight, QString("%1").arg(ibu, 1, 'f', 1));
	    painter.drawText(415, y+4,  90, 20, Qt::AlignLeft,  hop_forms[recipe->hops.at(i).h_form]);
	    painter.drawText(510, y+4,  90, 20, Qt::AlignLeft,	use);
	    painter.drawText(605, y+4,  60, 20, Qt::AlignRight, amount);
            painter.drawText(670, y+4,  60, 20, Qt::AlignRight, QString("%1 €").arg(cost, 1, 'f', 3));
	    y += 20;
	}
	painter.fillRect(670, y,    60, 20, c_line1);
        painter.drawText(670, y+4,  60, 20, Qt::AlignRight, QString("%1 €").arg(cost_hops, 1, 'f', 3));
        y += 40;

	/* Yeasts */
        painter.setFont(QFont("Helvetica", 9, QFont::Bold));
        painter.fillRect(  0, y,   735, 20, c_header);
        painter.drawText(  0, y+4, 335, 20, Qt::AlignLeft, tr("Yeast"));
        painter.drawText(340, y+4,  70, 20, Qt::AlignRight, tr("Attn"));
        painter.drawText(415, y+4,  90, 20, Qt::AlignLeft, tr("Type"));
        painter.drawText(510, y+4,  90, 20, Qt::AlignLeft, tr("Use at"));
        painter.drawText(605, y+4,  60, 20, Qt::AlignRight, tr("Amount"));
        painter.drawText(670, y+4,  60, 20, Qt::AlignRight, tr("Cost"));
        y += 20;
        painter.setFont(QFont("Helvetica", 9, QFont::Normal));
        double cost_yeasts = 0;
	for (int i = 0; i < recipe->yeasts.size(); i++) {
	    double cost = recipe->yeasts.at(i).y_amount * recipe->yeasts.at(i).y_cost;
	    cost_yeasts += cost;

	    if (recipe->yeasts.at(i).y_form == 0)
		amount = QString("%1 pack").arg(recipe->yeasts.at(i).y_amount, 1, 'f', 0);
	    else if (recipe->yeasts.at(i).y_form == 1 || recipe->yeasts.at(i).y_form == 6)
		amount = QString("%1 gr").arg(recipe->yeasts.at(i).y_amount * 1000.0, 1, 'f', 1);
	    else
		amount = QString("%1 ml").arg(recipe->yeasts.at(i).y_amount * 1000.0, 1, 'f', 1);

	    painter.fillRect(  0, y,   735, 20, y_line);
            painter.drawText(  0, y+4, 260, 20, Qt::AlignLeft,  recipe->yeasts.at(i).y_laboratory + " " +
			    					recipe->yeasts.at(i).y_product_id + " (" +
								recipe->yeasts.at(i).y_name + ")");
	    painter.drawText(340, y+4,  70, 20, Qt::AlignRight, QString("%1%").arg(recipe->yeasts.at(i).y_attenuation, 1, 'f', 1));
	    painter.drawText(415, y+4,  90, 20, Qt::AlignLeft,	yeast_forms[recipe->yeasts.at(i).y_form]);
	    painter.drawText(510, y+4,  90, 20, Qt::AlignLeft,	yeast_use[recipe->yeasts.at(i).y_use]);
	    painter.drawText(605, y+4,  60, 20, Qt::AlignRight,	amount);
	    painter.drawText(670, y+4,  60, 20, Qt::AlignRight, QString("%1 €").arg(cost, 1, 'f', 3));
	    y += 20;
	}
	painter.fillRect(670, y,    60, 20, c_line1);
        painter.drawText(670, y+4,  60, 20, Qt::AlignRight, QString("%1 €").arg(cost_yeasts, 1, 'f', 3));
        y += 40;

	/* Miscs */
        painter.setFont(QFont("Helvetica", 9, QFont::Bold));
        painter.fillRect(  0, y,   735, 20, c_header);
        painter.drawText(  0, y+4, 410, 20, Qt::AlignLeft, tr("Misc ingredient"));
        painter.drawText(415, y+4,  90, 20, Qt::AlignLeft, tr("Type"));
        painter.drawText(510, y+4,  90, 20, Qt::AlignLeft, tr("Use at"));
        painter.drawText(605, y+4,  60, 20, Qt::AlignRight, tr("Amount"));
        painter.drawText(670, y+4,  60, 20, Qt::AlignRight, tr("Cost"));
        y += 20;
        painter.setFont(QFont("Helvetica", 9, QFont::Normal));
        double cost_miscs = 0;
	for (int i = 0; i < recipe->miscs.size(); i++) {
	    double cost = recipe->miscs.at(i).m_amount * recipe->miscs.at(i).m_cost;
	    cost_miscs += cost;

	    if (recipe->miscs.at(i).m_use_use == 2)
		use = misc_uses[recipe->miscs.at(i).m_use_use] + QString(" %1 min").arg(recipe->miscs.at(i).m_time);
	    else
		use = misc_uses[recipe->miscs.at(i).m_use_use];

	    if (recipe->miscs.at(i).m_type == 4)					// Water agent
		painter.fillRect(  0, y,   735, 20, mw_line);
	    else if (recipe->miscs.at(i).m_type == 3)					// Fining
		painter.fillRect(  0, y,   735, 20, mf_line);
	    else if (recipe->miscs.at(i).m_type < 3 || recipe->miscs.at(i).m_type == 5)	// Spice, Herb, Flavour, Yeast nutrient
		painter.fillRect(  0, y,   735, 20, ms_line);
	    else
	    	painter.fillRect(  0, y,   735, 20, mo_line);
            painter.drawText(  0, y+4, 410, 20, Qt::AlignLeft,  recipe->miscs.at(i).m_name);
	    painter.drawText(415, y+4,  90, 20, Qt::AlignLeft,	misc_types[recipe->miscs.at(i).m_type]);
	    painter.drawText(510, y+4,  90, 20, Qt::AlignLeft,	use);
	    painter.drawText(605, y+4,  60, 20, Qt::AlignRight,
			    QString("%1 %2").arg(recipe->miscs.at(i).m_amount * 1000.0, 1, 'f', 1).arg(recipe->miscs.at(i).m_amount_is_weight ? "gr":"ml"));
	    painter.drawText(670, y+4,  60, 20, Qt::AlignRight, QString("%1 €").arg(cost, 1, 'f', 3));
	    y += 20;
	}
	painter.fillRect(670, y,    60, 20, c_line1);
        painter.drawText(670, y+4,  60, 20, Qt::AlignRight, QString("%1 €").arg(cost_miscs, 1, 'f', 3));
        y += 40;

	/* Mash */
        painter.setFont(QFont("Helvetica", 9, QFont::Bold));
        painter.fillRect(  0, y,   735, 20, c_header);
        painter.drawText(  0, y+4, 160, 20, Qt::AlignLeft, tr("Mash step"));
	painter.drawText(165, y+4,  90, 20, Qt::AlignLeft, tr("Step type"));
        painter.drawText(260, y+4,  60, 20, Qt::AlignRight, tr("Start °C"));
	painter.drawText(325, y+4,  60, 20, Qt::AlignRight, tr("End °C"));
	painter.drawText(390, y+4,  60, 20, Qt::AlignRight, tr("Time"));
        painter.drawText(455, y+4,  60, 20, Qt::AlignRight, tr("Ramp"));
	painter.drawText(520, y+4,  60, 20, Qt::AlignRight, tr("L/kg"));
        painter.drawText(585, y+4,  70, 20, Qt::AlignRight, tr("Inf/dec L."));
        painter.drawText(660, y+4,  70, 20, Qt::AlignRight, tr("Inf/dec °C"));
        y += 20;
        painter.setFont(QFont("Helvetica", 9, QFont::Normal));
	for (int i = 0; i < recipe->mashs.size(); i++) {
	    painter.fillRect(  0, y,   735, 20, m_line);
	    painter.drawText(  0, y+4, 160, 20, Qt::AlignLeft,	recipe->mashs.at(i).step_name);
	    painter.drawText(165, y+4,  90, 20, Qt::AlignLeft,	step_types[recipe->mashs.at(i).step_type]);
	    painter.drawText(260, y+4,  60, 20, Qt::AlignRight, QString("%1").arg(recipe->mashs.at(i).step_temp, 1, 'f', 1));
	    painter.drawText(325, y+4,  60, 20, Qt::AlignRight,	QString("%1").arg(recipe->mashs.at(i).end_temp, 1, 'f', 1));
	    painter.drawText(390, y+4,  60, 20, Qt::AlignRight,	QString("%1").arg(recipe->mashs.at(i).step_time, 1, 'f', 0));
	    painter.drawText(455, y+4,  60, 20, Qt::AlignRight, QString("%1").arg(recipe->mashs.at(i).ramp_time, 1, 'f', 0));
	    painter.drawText(520, y+4,  60, 20, Qt::AlignRight, QString("%1").arg(recipe->mashs.at(i).step_wg_ratio, 1, 'f', 2));
	    if (recipe->mashs.at(i).step_type != 1) {
		painter.drawText(585, y+4,  70, 20, Qt::AlignRight, QString("%1").arg(recipe->mashs.at(i).step_infuse_amount, 1, 'f', 1));
		painter.drawText(660, y+4,  70, 20, Qt::AlignRight, QString("%1").arg(recipe->mashs.at(i).step_infuse_temp, 1, 'f', 1));
	    }
	    y += 20;
	}
    }


    painter.end();
}



void PrinterDialog::printHeader(QPainter *painter)
{
    QPixmap outPixmap = QPixmap();
    outPixmap.loadFromData(my_logoByteArray);
    int w = outPixmap.width();
    int h = outPixmap.height();
    /* Make sure to keep the logo aspect ratio */
    if (w == h) {
	painter->drawPixmap(0, 0, 100, 100, outPixmap);
    } else if (w > h) {
	painter->drawPixmap(0, 0, 100, (h * 100) / w, outPixmap);
    } else {
	painter->drawPixmap(0, 0, (w * 100) / h, 100, outPixmap);
    }

    /* The fat header line */
    painter->setFont(QFont("Helvetica",18, QFont::Bold));
    if (p_job == PR_SUPPLIES) {
	painter->drawText(120, 0,  500, 40, Qt::AlignLeft, tr("Inventory") + " " + my_brewery_name);
    } else if (p_job == PR_YEASTBANK) {
	painter->drawText(120, 0,  500, 40, Qt::AlignLeft, tr("Yeastbank") + " " + my_brewery_name);
    } else if (p_job == PR_RECIPE) {
	painter->drawText(120, 0,  500, 40, Qt::AlignLeft, recipe->name);
    } else {
        painter->drawText(120, 0,  500, 40, Qt::AlignLeft, "?? " + my_brewery_name);
    }
    /* The first normal header line */
    painter->setFont(QFont("Helvetica",10, QFont::Normal));
    painter->drawText(120,35,  80, 20, Qt::AlignLeft, tr("Date and time"));
    painter->drawText(200,35, 400, 20, Qt::AlignLeft, ": " + QDateTime::currentDateTime().toString("dd-MM-yyyy hh:mm"));
    if (p_job == PR_RECIPE) {
	painter->drawText(120,55,  80, 20, Qt::AlignLeft, tr("Beer style"));
    	painter->drawText(200,55, 400, 20, Qt::AlignLeft, ": " + recipe->st_name);
    }
    /* The report itself may print more lines from y = 55. */
}

mercurial