diff src/main.cpp @ 114:a5c8741b8662

Initial prototype support for printing list of users + print preview dialog. Has some issues currently.
author Matti Hamalainen <ccr@tnsp.org>
date Wed, 05 Jul 2017 12:48:55 +0300
parents 907f2ddf6801
children 71cfb7d96cfc
line wrap: on
line diff
--- a/src/main.cpp	Wed Jul 05 09:52:10 2017 +0300
+++ b/src/main.cpp	Wed Jul 05 12:48:55 2017 +0300
@@ -9,6 +9,9 @@
 #include <QApplication>
 #include <QMessageBox>
 #include <QSettings>
+#include <QPrintDialog>
+#include <QPrintPreviewDialog>
+#include <QProgressDialog>
 #include "main.h"
 #include "ui_mainwindow.h"
 #include "ui_editperson.h"
@@ -337,6 +340,8 @@
     new QShortcut(QKeySequence(Qt::Key_PageDown), this, SLOT(selectRowNext()));
 
     new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Return), this, SLOT(focusDebtEdit()));
+
+    new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_P), this, SLOT(on_button_Print_clicked()));
 }
 
 
@@ -506,6 +511,228 @@
 }
 
 
+void SyntilistaMainWindow::on_button_Print_clicked()
+{
+    // Create a printer object and force some basic settings
+    QPrinter printer(QPrinter::HighResolution);
+    printer.setPageSize(QPageSize(QPageSize::A4));
+    printer.setColorMode(QPrinter::GrayScale);
+    printer.setResolution(300);
+
+    // We need to get the page count here, and also need it again in
+    // printDocument(), but there is no sane way to pass that there,
+    // so some code duplication is unfortunately necessary
+    SLPageInfo pinfo;
+    pinfo.npages = 0;
+    pinfo.nlinesPerPage = 0;
+
+    QPixmap tmpPixmap(1000, 1300);
+    QPainter tmpPainter;
+    tmpPainter.begin(&tmpPixmap);
+    bool ret = printDocumentPage(pinfo, 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.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);
+
+    // Again, get the page info here .. we need the number of lines per page
+    SLPageInfo pinfo;
+    pinfo.npages = 0;
+    pinfo.nlinesPerPage = 0;
+
+    QPixmap tmpPixmap(1000, 1300);
+    QPainter tmpPainter;
+    tmpPainter.begin(&tmpPixmap);
+    bool ret = printDocumentPage(pinfo, true, -1, &tmpPainter, printer);
+    tmpPainter.end();
+
+    if (!ret)
+        return;
+
+    // Setup rest of the progress dialog here
+    progress.setWindowModality(Qt::ApplicationModal);
+    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(pinfo, false, page, &painter, printer);
+        progress.setValue(page);
+        firstPage = false;
+    }
+
+    painter.end();
+}
+
+
+bool SyntilistaMainWindow::printDocumentPage(SLPageInfo &pinfo, 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
+    if (!getPageInfo)
+    {
+        // Otherwise we can limit to given page number
+        querystr += QStringLiteral(" LIMIT %1 OFFSET %2").
+            arg(pinfo.nlinesPerPage).
+            arg((npage - 1) * pinfo.nlinesPerPage);
+    }
+
+    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();
+    if (!getPageInfo)
+    {
+        pt->scale(
+            printer->pageRect().width() / 1000.0f,
+            printer->pageRect().height() / 1300.0f);
+    }
+
+    QFont font1("Arial", 5);
+    SLDrawContext ctx(pt);
+    ctx.setFont(font1);
+
+    int nline = 0;
+    while (query.next())
+    {
+        PersonInfo info;
+        slGetPersonInfoRec(query, info);
+
+        // Check for end of page
+        // KLUDGE for now
+        if (getPageInfo &&
+            ctx.m_pos.y() + (ctx.boundRect().height() * 4) >= 1300.0f / 2.0f)
+        {
+            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, "Etunimi");
+            ctx.drawText( 200,  230, "Sukunimi");
+            ctx.drawText( 450,  190, "Lisätty");
+            ctx.drawText( 650,  190, "Päivitetty");
+            ctx.drawText( 870,  120, "Tase");
+            ctx.lf();
+
+            pt->drawLine(0, ctx.m_pos.y(), 1000, 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,
+                1000,
+                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, 1240);
+        ctx.drawText(0, 1000,
+            QStringLiteral("Sivu %1 / %2").
+            arg(npage).arg(printer->toPage()),
+            Qt::AlignHCenter);
+    }
+
+    pt->restore();
+    return true;
+}
+
+
 void SyntilistaMainWindow::on_button_DeletePerson_clicked()
 {
     if (currPerson.id <= 0)