PDA

View Full Version : Printing using QTextLayout



ericV
24th November 2009, 10:22
Hello,

I have programmed a simple code editor, which uses the QSyntaxHighlighter.
And now i have a problem with my print method.

I had to implement a new one since I need to print a header and footer on each page and I also need to print the corresponding line numbers besides the text.

After much experimentation I have almost reached my "goal".

First i get the pageRect from the given QPrinter and calculate the size for the header, footer and line numbers from which i then get the actual draw area for the document.
Then I break down the QTextDocument into its QTextBlocks in order to iterate over them within the printing process. (using a while(block.isValid())... loop)

Within the loop i break down the blocks into QTextLayouts (for the case that a block has one or more linebraks) This is also important in order to find the proper horizontal position for the line number and for the case that a block needs to be broken up between page breaks.

My current problem shows its (ugly) face after a page break where the textLayout.draw(...) method decides to ignore the horizontal position the first line and draw a few pixels off target, invading the space for the next line.
This only occurs in the first line of pages 2 and up. Page 1 is printed properly.

Can anyone give me a hint why the draw Method would be ignoring the QPoint given to it?
I use the same horizontal offset when drawing the line number which is placed properly in the page.

Thank you for reading and maybe helping

Eric

ericV
24th November 2009, 10:52
So for better understandig i am uploading two images of a printed out pdf (I am using a PDF printer for debugging).

And some code:



void TextEditorWidget::printDocument(QPrinter *printer)
{
QTextDocument *document = editor->document();
//Header & Footer .... just building the strings...

QPainter printPainter(printer);
printPainter.setFont(f); //<- f: is the font used as standard in the QTextEdit
QRect pageRect = printer->pageRect();
QRect headerRect = printPainter.boundingRect(printPainter.window()/*pageRect*/,Qt::AlignLeft |Qt::AlignTop, printHeader);
QRect footerRect = printPainter.boundingRect(printPainter.window()/*pageRect*/,Qt::AlignBottom |Qt::AlignHCenter, footer);
QRect numbersRect = printPainter.boundingRect(printPainter.window()/*pageRect*/,Qt::AlignLeft,
QString::number(document->blockCount()));
pageRect.setTop(headerRect.height() +17);// adding a spacing
pageRect.setLeft(numbersRect.width() +8);
pageRect.setBottom(footerRect.top() -10);
pageRect.setRight(/*pageRect.left() + printer->pageRect().width()*/ printPainter.window().right());
document->setPageSize(pageRect.size());

QAbstractTextDocumentLayout *lay = document->documentLayout();
lay->setPaintDevice(printer);
int pages = lay->pageCount();

QTextBlock block = document->begin();
int pageNumber = 0;
int yOffset = 0;
bool newPage = true;
printPainter.setClipping(true); //thought this might have something to do with the porblem, but i couldnt see any difference whether set true or false

while(block.isValid()) //<- Iteration Loop
{
if(newPage)
{
++ pageNumber;
printPainter.drawText(QRect(QPoint(0,0),headerRect .size()),Qt::AlignLeft, printHeader);
printPainter.drawText(printPainter.window(),Qt::Al ignBottom|Qt::AlignHCenter,
footer.arg(QString::number(pageNumber),QString::nu mber(pages)));
yOffset = pageRect.top();
newPage = false;
}

QTextLayout *lT = block.layout();
for (int i=0; i< lT->lineCount(); i++) //Line Iteration usualy 1 line per Block
{
if(i==0) printPainter.drawText(QRect(QPoint(0,yOffset),numb ersRect.size()),Qt::AlignRight,
QString::number(block.blockNumber()+1));
lT->lineAt(i).draw(&printPainter,QPointF(pageRect.left(),yOffset));
}
yOffset += lT->boundingRect().height(); // Increment Horizontal offset by size of last Block
if (yOffset >= printPainter.window().bottom()- (footerRect.height()+17+10))

{
newPage = true;
printer->newPage();
}
block = block.next();
}
}

ericV
24th November 2009, 12:39
Update:

After some more debugging, I noticed that the QTextLine recieved a worng position for the lines where the error ocurred (usually QPiontF(0,0)) but here it recieved a QPointF(0,10)
I haven't figuered out why this happens, but at least I was able to reset it using the QTextLine::setPosition(...) method.

If anyone is working with this type of text drawing i must add that you will need to manage the position of the linebreaks as these will need a different y-coordinate (usualy linenumber * lineHeight)


Greetings