view src/printing.cpp @ 217:58af72da7f60

Update copyrights.
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 02 Jan 2018 01:47:38 +0200
parents d119235d3df0
children 43a5e09bb832
line wrap: on
line source

//
// Syntilista - debt list/management database program
// Programmed and designed by Matti Hämäläinen <ccr@tnsp.org>
// (C) Copyright 2017-2018 Tecnic Software productions (TNSP)
//
// Distributed under 3-clause BSD style license, refer to
// included file "COPYING" for exact terms.
//
#include <QPrintDialog>
#include <QPrintPreviewDialog>
#include "main.h"

#define APP_PRINT_WIDTH        1000
#define APP_PRINT_HEIGHT       1300

#define APP_PRINT_WSCALE       1.01f
#define APP_PRINT_HSCALE       1.00f


void SyntilistaMainWindow::on_button_Print_clicked()
{
    // Create a printer object and force some basic settings
    QPrinter printer(QPrinter::HighResolution);
    printer.setResolution(300);
    printer.setPageSize(QPageSize(QPageSize::A4));
    printer.setPageMargins(QMarginsF(0.25f, 0.5f, 0.25f, 0.5f), QPageLayout::Inch);
    printer.setColorMode(QPrinter::GrayScale);

    // We need to get the page count and line counts per page here
    pinfo.npages = 0;
    pinfo.nlinesPerPage = 0;

    QPixmap tmpPixmap(APP_PRINT_WIDTH, APP_PRINT_HEIGHT);
    QPainter tmpPainter;
    tmpPainter.begin(&tmpPixmap);
    bool ret = printDocumentPage(true, -1, &tmpPainter, &printer);
    tmpPainter.end();

    if (!ret)
    {
        // Some kind of error occured
        return;
    }


    // Set available pages
    printer.setFromTo(1, pinfo.npages);

    // Create print preview dialog and show it
    QPrintPreviewDialog preview(&printer, this);
    preview.setWindowTitle(tr("Tulostuksen esikatselu"));
    preview.setWindowModality(Qt::ApplicationModal);
    preview.setSizeGripEnabled(true);

    connect(
        &preview,
        SIGNAL(paintRequested(QPrinter *)),
        this,
        SLOT(printDocument(QPrinter *)));

    preview.exec();
}


void SyntilistaMainWindow::printDocument(QPrinter *printer)
{
    // Create progress dialog
    QProgressDialog progress(
        tr("Tulostetaan ..."),
        tr("Peruuta"),
        0,
        1,
        this);

    progress.setWindowModality(Qt::ApplicationModal);

    // If from and to are 0, we are supposed to print all pages
    if (printer->fromPage() == 0 && printer->toPage() == 0)
        printer->setFromTo(1, pinfo.npages);

    // Setup rest of the progress dialog here
    progress.setMinimum(printer->fromPage() - 1);
    progress.setMaximum(printer->toPage());

    // Begin painting to the printer (or preview)
    QPainter painter;
    painter.begin(printer);

    bool firstPage = true;
    for (int page = printer->fromPage(); page <= printer->toPage(); page++)
    {
        if (!firstPage)
            printer->newPage();

        qApp->processEvents();
        if (progress.wasCanceled())
            break;

        printDocumentPage(false, page, &painter, printer);
        progress.setValue(page);
        firstPage = false;
    }

    painter.end();
}


bool SyntilistaMainWindow::printDocumentPage(const bool getPageInfo, const int npage, QPainter *pt, QPrinter *printer)
{
    // Form the SQL query for list of users
    QString querystr = QStringLiteral(
        "SELECT id,first_name,last_name,extra_info,added,updated, "
        "(SELECT TOTAL(value) FROM transactions WHERE transactions.person=people.id) AS balance "
        "FROM people ORDER BY last_name ASC,first_name ASC");

    // If we are fetching page info, we need to process all entries
    int noffset = (npage - 1) * pinfo.nlinesPerPage;
    if (!getPageInfo)
    {
        // Otherwise we can limit to given page number
        querystr += QStringLiteral(" LIMIT %1 OFFSET %2").
            arg(pinfo.nlinesPerPage).
            arg(noffset);
    }

    QSqlQuery query;
    query.prepare(querystr);
    query.setForwardOnly(true);
    query.exec();

    if (!slCheckAndReportSQLError("printDocumentPage()", query.lastError()))
    {
        slErrorMsg(
            tr("SQL-tietokantavirhe"),
            tr("Tietokantaa selattaessa tapahtui virhe."));

        return false;
    }

    pt->save();
    pt->scale(
        pt->device()->width() / ((float) APP_PRINT_WIDTH * APP_PRINT_WSCALE),
        pt->device()->height() /((float) APP_PRINT_HEIGHT * APP_PRINT_HSCALE));

    QFont font1;
    font1.setFamily("Arial");
    font1.setPixelSize(24);
    SLDrawContext ctx(pt);
    ctx.setFont(font1);

    int nline = 0, nperson = noffset;
    while (query.next())
    {
        SLPersonInfo info;
        slGetPersonInfoRec(query, info);
        nperson++;

        // Check for the end of page
        if (getPageInfo && ctx.lfq(10) >=
            APP_PRINT_HEIGHT - ctx.boundRect().height() * 1.5f)
        {
            if (nline > pinfo.nlinesPerPage)
                pinfo.nlinesPerPage = nline;

            pinfo.npages++;
            nline = 0;
        }

        if (nline == 0)
        {
            // If we are at the start of the page, we shall draw a header
            pt->setBrush(QBrush(Qt::black));
            pt->setPen(QPen(Qt::black, 3, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));

            ctx.setPos(0, 0);
            ctx.drawText(   5,  180, tr("Etunimi"));
            ctx.drawText( 200,  230, tr("Sukunimi"));
            ctx.drawText( 450,  190, tr("Lisätty"));
            ctx.drawText( 650,  190, tr("Päivitetty"));
            ctx.drawText( 870,  120, tr("Tase"));
            ctx.lf();

            pt->drawLine(0, ctx.m_pos.y(), APP_PRINT_WIDTH, ctx.m_pos.y());

            ctx.move(0, 5);
        }

        // Draw a gray bar under every second line
        if (nline % 2 == 0)
        {
            pt->fillRect(
                0,
                ctx.m_pos.y() - 1,
                APP_PRINT_WIDTH,
                ctx.boundRect().height() + 4,
                QColor(0, 0, 0, 40));
        }

        ctx.drawText(   5,  180, info.firstName);
        ctx.drawText( 200,  230, info.lastName);
        ctx.drawText( 450,  190, slDateTimeToStr(info.added));
        ctx.drawText( 650,  190, slDateTimeToStr(info.updated));
        ctx.drawText( 870,  120, slMoneyValueToStr(info.balance), Qt::AlignRight);

        ctx.lf(10);
        nline++;
    }

    query.finish();

    if (getPageInfo)
    {
        if (nline > pinfo.nlinesPerPage)
            pinfo.nlinesPerPage = nline;

        pinfo.npages++;
    }
    else
    {
        ctx.setPos(0, APP_PRINT_HEIGHT - ctx.boundRect().height());
        ctx.drawText(0, APP_PRINT_WIDTH,
            tr("Sivu %1 / %2 (%3 / %4) - Henkilöt %5 - %6 / %7").
            arg(npage - printer->fromPage() + 1).
            arg(printer->toPage() - printer->fromPage() + 1).
            arg(npage).
            arg(printer->toPage()).
            arg(noffset + 1).
            arg(nperson).
            arg(totalPeople),
            Qt::AlignHCenter);
    }

    pt->restore();
    return true;
}