PDA

View Full Version : Qt Printing QTextDocument problem (truncated text)



giowck
18th April 2011, 22:12
Hello guys,

I' trying to print a QTextDocument with custom header and footer.
I found this nice code: http://developer.qt.nokia.com/faq/answer/is_it_possible_to_set_a_header_and_footer_when_pri nting_a_qtextdocument

It works great, except that sometimes the text gets truncated on half page, so that it's not readable... Look here the result: http://dl.dropbox.com/u/1511663/test.pdf between page 2 and 3!

I think this is something related to page size.. But I don't know how it can be fixed, what is the problem?

Hope you can help with some hints. I don't expect you write full code for me, but I hope you can help me with some hints!

My full code is attached as test.zip

Thanks

ps. this is a great forum, thanks!



#include <QtGui>

int main(int argc, char **argv)
{
QApplication a(argc, argv);
QString content;

content.append("here my html");

QTextDocument td;
td.setHtml(content);
QPrinter p;
//p.setPageMargins(20, 20, 5, 20, QPrinter::Millimeter);

bool pdf = true; //use pdf as output?

if (pdf) {
QString outFile = QFileDialog::getSaveFileName(0, "Save PDF file",
QDir::homePath(),
"PDF files (*.pdf)");
if (outFile.isEmpty())
exit(1);

if (!outFile.contains(".pdf"))
outFile.append(".pdf");

p.setOutputFileName(outFile);
} else {
QPrintDialog pd(&p, 0);
pd.exec();
}

td.setPageSize(p.pageRect().size());
QRect innerRect = p.pageRect();
innerRect.setTop(innerRect.top() + 20);
innerRect.setBottom(innerRect.bottom() - 30);
QRect contentRect = QRect(QPoint(0,0), td.size().toSize());
QRect currentRect = QRect(QPoint(0,0), innerRect.size());
QPainter painter(&p);
int count = 0;
painter.save();
painter.translate(0, 30);
while (currentRect.intersects(contentRect)) {
td.drawContents(&painter, currentRect);
count++;
currentRect.translate(0, currentRect.height());
painter.restore();
painter.drawText(10, 10, QString("Header %1").arg(count));
painter.drawText(10, p.pageRect().bottom() - 10, QString("Footer %1").arg(count));
painter.save();
painter.translate(0, -currentRect.height() * count + 30);
if (currentRect.intersects(contentRect))
p.newPage();
}
painter.restore();
painter.end();
return 0;
}

Berryblue031
19th April 2011, 11:02
Out of curiosity what happens if you call td.setpagesize before calling td.sethtml ?

You may need to use the QAbstractTextDocumentLayout::draw function instead of the one from QTextDocument to support things like page size td.documentLayout()->draw()



Ok I am changing my answer lol I just looked a bit closer at your code

The page size of the textdocument should be set to the size of the QRect you are painting it on you can't just go chopping at the paint rectangle and not expect clipping




QRect innerRect = p.pageRect();
innerRect.setTop(innerRect.top() + 20);
innerRect.setBottom(innerRect.bottom() - 30);
QRect contentRect = QRect(QPoint(0,0), td.size().toSize());
QRect currentRect = QRect(QPoint(0,0), innerRect.size());
td.setPageSize(currentRect.size());

giowck
19th April 2011, 17:38
Thank you,

I solved this by adding a margin to the printer:

p.setPageMargins(20, 20, 20, 20, QPrinter::Millimeter);


Added after 1 27 minutes:

Okay so now i found the working code. But now I want to paint a second QTextDocument with the same code (while loop) but i don't know how to do it, because the code was taken from that link (see above)

my code


printer->setPageMargins(20, 20, 5, 20, QPrinter::Millimeter);

QTextDocument mainReport;
mainReport.setHtml(*this->mainReportTextHtml);
mainReport.setPageSize(printer->pageRect().size());

QRect innerRect = printer->pageRect();
innerRect.setTop(innerRect.top());
innerRect.setBottom(innerRect.bottom());

QRect contentRect = QRect(QPoint(0,0), mainReport.size().toSize());
QRect currentRect = QRect(QPoint(0,0), innerRect.size());

QPainter painter(printer);
int pageCount = 0;

// main report
painter.save();
painter.translate(0, 30);

while (currentRect.intersects(contentRect)) {
mainReport.drawContents(&painter, currentRect);
pageCount++;
currentRect.translate(0, currentRect.height());
painter.restore();
painter.drawText(10, 10, QString("Header %1").arg(pageCount));
painter.drawText(10, printer->pageRect().bottom() - 10, QString("Footer %1").arg(pageCount));
painter.save();
painter.translate(0, - currentRect.height() * pageCount + 30);
if (currentRect.intersects(contentRect))
printer->newPage();
}

//now print the second textdocument
QTextDocument test;
test.setHtml(*this->secondReport);
test.setPageSize(printer->pageRect().size());

printer->newPage();
painter.restore();
painter.save();
painter.translate(0, 30);

contentRect = QRect(QPoint(0,0), test.size().toSize());
currentRect = QRect(QPoint(0,0), innerRect.size());

while (currentRect.intersects(contentRect)) {
test.drawContents(&painter, currentRect);
pageCount++;
currentRect.translate(0, currentRect.height());
painter.restore();
painter.drawText(10, 10, QString("Header %1").arg(pageCount));
painter.drawText(10, printer->pageRect().bottom() - 10, QString("Footer %1").arg(pageCount));
painter.save();
painter.translate(0, - currentRect.height() * pageCount + 30);
if (currentRect.intersects(contentRect))
printer->newPage();
}

painter.restore();
painter.end();


The problem: only the first page of the second qtextdocument gets printed followed by blank pages.
I mean I just want to reuse that working code for another qtextdocument...

Is there any Qt printing guru out there who can help me?

Thank you guys!

giowck
20th April 2011, 07:37
Solved this!

The problem was that the pageCount variable was used to calculate the offset for the draw.
Because i dind't set pageCount=0 for the new second QTextDocument, the offset result was wrong.

SO i introduced the new variable offset=0 for each new qtextdocument and now i works!

complete code:


printer->setPageMargins(20, 20, 5, 20, QPrinter::Millimeter);

QTextDocument mainReport;
mainReport.setHtml(*this->mainReportTextHtml);
mainReport.setPageSize(printer->pageRect().size());

QRect innerRect = printer->pageRect();
innerRect.setTop(innerRect.top());
innerRect.setBottom(innerRect.bottom());

QRect contentRect = QRect(QPoint(0,0), mainReport.size().toSize());
QRect currentRect = QRect(QPoint(0,0), innerRect.size());

QPainter painter(printer);
int pageCount = 0;

// main report
painter.save();
painter.translate(0, 30);

while (currentRect.intersects(contentRect)) {
mainReport.drawContents(&painter, currentRect);
pageCount++;
currentRect.translate(0, currentRect.height());
painter.restore();
painter.drawText(10, 10, QString("Header %1").arg(pageCount));
painter.drawText(10, printer->pageRect().bottom() - 10, QString("Footer %1").arg(pageCount));
painter.save();
painter.translate(0, - currentRect.height() * pageCount + 30);
if (currentRect.intersects(contentRect))
printer->newPage();
}

//now print the second textdocument
QTextDocument test;
test.setHtml(*this->proteinMeatTableHtml);
test.setPageSize(printer->pageRect().size());

printer->newPage();
painter.restore();
painter.save();
painter.translate(0, 30);

contentRect = QRect(QPoint(0,0), test.size().toSize());
currentRect = QRect(QPoint(0,0), innerRect.size());
int offset = 0;

while (currentRect.intersects(contentRect)) {
test.drawContents(&painter, currentRect);
pageCount++;
offset++;
currentRect.translate(0, currentRect.height());
painter.restore();
painter.drawText(10, 10, QString("Header %1").arg(pageCount));
painter.drawText(10, printer->pageRect().bottom() - 10, QString("Footer %1").arg(pageCount));
painter.save();
painter.translate(0, - currentRect.height() * offset + 30);
if (currentRect.intersects(contentRect))
printer->newPage();
}

painter.restore();
painter.end();