PDA

View Full Version : problem printing a multi page report



schnitzel
17th January 2011, 00:00
I can't wrap my mind around printing multiple pages using QPrintPreviewDialog. I searched the forum and the web, nothing helpful came up.

My goal is to print invoices, each page consists of a letter head at the top, followed by the details for the particular customer.

I have no trouble doing this for a single page but I wanted to get a preview with N invoices, each on a separate page.

Here is what I do now:



void MainWindow::prepHeader(QTextEdit &t)
{

t.append(QString("a nice letter head"));
t.append("\n");

t.append(QString("customer info\n"));

t.append("\n\n\n\n\n\n______________________________________ ________________________\n"); //divider and some spacing

}


void MainWindow::printReport(QTextEdit &pte, QString detail, bool bPreview)
{

QPrintPreviewDialog pvw(printer,this);

if (bPreview)
connect(&pvw, SIGNAL(paintRequested(QPrinter *)), SLOT(printPreview(QPrinter *)));

prepHeader(pte); //show a company specific letter head

pte.append(detail);


if (bPreview)
{
pvw.exec();
pvw.disconnect();
pte.clear();
}
else
pte.print(printer);

}

void MainWindow::printPreview(QPrinter *printer)
{
rpt.print(printer);

}

void MainWindow::printInvoice()
{
QString detail;
QTextStream strm(&detail);


strm << "customer details" << endl;

printReport(rpt, detail, true);

detail.clear();
}

marcvanriet
17th January 2011, 01:42
Hi,

What is the rpt variable that you use ? Your variable names are rather cryptic.

Typically, you write a method that prints your entire report, be it either 1 page or multiple pages. For starting a new page, just use QPrinter::newPage(). Something like this :


void CMainForm::paintMyReport( QPrinter * printer )
{
QPainter painter;
painter.begin(printer);

for( int nPage=0; nPage<m_nLastPage; nPage++ )
{
// print your page

if( nPage<m_nLastPage-1 )
printer->newPage();
}
painter.end();
}

If you want to print it with a preview, do this :

QPrintPreviewDialog dlgPrint;
connect( &dlgPrint, SIGNAL(paintRequested(QPrinter*)), SLOT(paintMyReport(QPrinter*)) );
dlgPrint.exec();

If you want to print it directly, do this :

QPrinter printer;
printer.setPrinterName( "CutePDF Writer" );
paintMyReport( &printer );

Regards,
Marc

schnitzel
17th January 2011, 04:33
Thanks Marc,

I got better results with your suggestions. Inside the pages loop, am I limited to using painter.drawText() or can I append text to a QTextEdit and then call
QTextEdit::print() ?

schnitzel
17th January 2011, 17:38
Consider this code:


void MainWindow::print(QPrinter *printer)
{
QTextEdit textEdit[2];

textEdit[0].append("First Page");
textEdit[1].append("Second page");


textEdit[0].print(printer);
printer->newPage();
textEdit[1].print(printer);

}

void MainWindow::on_pushButton_clicked()
{

QPrinter printer(QPrinter::HighResolution);
QPrintPreviewDialog preview(&printer,this);
connect(&preview, SIGNAL(paintRequested(QPrinter*)),SLOT(print(QPrin ter *)));
preview.exec();


}



I get a single page print preview showing 'second page' and a page number '1' at the bottom. :confused:

where did the first page go?

marcvanriet
18th January 2011, 01:09
Hi,
Afaik, printing must always be done with a QPainter object.

See Printing with Qt (http://doc.qt.nokia.com/4.7/printing.html), and then the section 'printing complex widgets'. It says how to print a QTextEdit and so.

Maybe if you do a QPainter.begin() as in my example, your first page won't get lost. I'm not sure.

Best regards,
Marc

schnitzel
18th January 2011, 01:29
Hi,
Afaik, printing must always be done with a QPainter object.

See Printing with Qt (http://doc.qt.nokia.com/4.7/printing.html), and then the section 'printing complex widgets'. It says how to print a QTextEdit and so.

Maybe if you do a QPainter.begin() as in my example, your first page won't get lost. I'm not sure.

Best regards,
Marc

QTextEdit seems to be an exception as it uses a QPrinter and the :: print method (see the table at the bottom of the page in your link).

I will play around a bit more later and post some more examples of what I've tried so far.

schnitzel
18th January 2011, 03:55
If I try the following:



void MainWindow::print(QPrinter *printer)
{
QTextEdit textEdit[2];

textEdit[0].append("\t\tFirst Page");
textEdit[1].append("\t\tSecond page");

QPainter painter;
painter.begin(printer);

textEdit[0].document()->drawContents(&painter, printer->pageRect());
printer->newPage();
textEdit[1].document()->drawContents(&painter, printer->pageRect());

painter.end();

}

void MainWindow::on_pushButton_clicked()
{

QPrinter printer(QPrinter::HighResolution);
QPrintPreviewDialog preview(&printer,this);
connect(&preview, SIGNAL(paintRequested(QPrinter*)),SLOT(print(QPrin ter *)));
preview.exec();
}


I get two blank pages... what am I doing wrong?

marcvanriet
18th January 2011, 20:41
Hi,

I get the same results. I think it has something to do with the printer resolution. In the code you just posted, put the following 2 lines in on_pushButton_clicked() after creating the printer object :

printer.setFullPage(true);
printer.setResolution( 90 );

You will see some text appearing now.

I don't know how it should be done properly with QTextEdit. I have always used QPainters drawText up to now.

Regards,
Marc

schnitzel
18th January 2011, 21:15
Hi,

I get the same results. I think it has something to do with the printer resolution. In the code you just posted, put the following 2 lines in on_pushButton_clicked() after creating the printer object :

printer.setFullPage(true);
printer.setResolution( 90 );

You will see some text appearing now.

I don't know how it should be done properly with QTextEdit. I have always used QPainters drawText up to now.

Regards,
Marc

Hmmm, still not working. Here is my current code:



void MainWindow::print(QPrinter *printer)
{
QTextEdit textEdit[2];

textEdit[0].append("\t\tFirst Page");
textEdit[1].append("\t\tSecond page");

QPainter painter;
painter.begin(printer);

textEdit[0].document()->drawContents(&painter, printer->pageRect());
printer->newPage();
textEdit[1].document()->drawContents(&painter, printer->pageRect());

painter.end();

}

void MainWindow::on_pushButton_clicked()
{

QPrinter printer(QPrinter::HighResolution);
printer.setFullPage(true);
printer.setResolution(90);

QPrintPreviewDialog preview(&printer,this);
connect(&preview, SIGNAL(paintRequested(QPrinter*)),SLOT(print(QPrin ter *)));
preview.exec();
}

marcvanriet
18th January 2011, 22:38
Found it (more or less).

Tried exactly your code, and appearently it doesn't work if your QTextEdit is just some object you create.
I did my tests using textedits that I had put on my dialog, and then it works.

Regards,
Marc

schnitzel
18th January 2011, 23:29
Found it (more or less).

Tried exactly your code, and appearently it doesn't work if your QTextEdit is just some object you create.
I did my tests using textedits that I had put on my dialog, and then it works.

Regards,
Marc

You're my hero... :D

I'm not quite sure yet how to deal with adding the QTextEdit - I can't just simply make it invisible on my window (already tried that). Making it invisible in the 'on_pushButton_clicked()' seems to work fine though.

Anyway, thanks so much for your help. This problem has been nagging me for a couple of days now.

schnitzel
22nd January 2011, 23:20
Ok, got a little further. The printpreview now works, but it isn't behaving the way I want. Now that I have added the QTextEdit to the main window, the text gets formatted according to the widget's dimension. I guess that is kind of expected. What I really wanted is to create a nice looking multi page report and my reason for using QTextEdit is the Richly formatted text. What I didn't anticipate is the way the text is depending on the QTextEdit widget's dimension. Is there no way for me to create nicely formatted text but defer line wrapping etc. until it gets drawn onto the printer/painter device?
Would I have to print to pdf in order to get what I want? I guess I could just try it, but I was wondering if I'm approaching this from the right direction.

Here is my latest code.



//Mainwindow constructor contains: printer = new QPrinter(QPrinter::ScreenResolution);

void MainWindow::print(QPrinter *printer)
{

QPainter painter;
painter.begin(printer);

ui->textEdit->append("first page this is a fairly long line to see what happens when it is being wrapped");
ui->textEdit->document()->drawContents(&painter, printer->pageRect());

printer->newPage();
ui->textEdit->clear();
ui->textEdit->append("second page");
ui->textEdit->document()->drawContents(&painter, printer->pageRect());
ui->textEdit->clear();

painter.end();
}

void MainWindow::on_pushButton_clicked()
{

QPrintPreviewDialog preview(printer,this);
connect(&preview, SIGNAL(paintRequested(QPrinter*)),SLOT(print(QPrin ter *)));
preview.exec();

}

schnitzel
23rd January 2011, 01:50
Ok, I figured out how to approach it.
I'm abandoning the entire appending to QTextEdit in favor of creating a QTextDocument and using HTML. Here is the code, in the hope that it will be helpful to somebody.



void MainWindow::print(QPrinter *printer)
{

QPainter painter;
painter.begin(printer);

QTextDocument doc;
doc.setHtml( "<p>A QTextDocument can be used to present formatted text "
"in a nice way.</p>"
"<p align=center>It can be <b>formatted</b> "
"<font size=+2>in</font> <i>different</i> ways.</p>"
"<p>The text can be really long and contain many "
"trying a really long line to see how it wraps "
"more text to see how long I can make this line show "
"paragraphs. It is properly wrapped and such...</p>" );

QRect rect = printer->pageRect();
doc.setTextWidth(rect.width());
doc.drawContents(&painter);
printer->newPage();


doc.drawContents(&painter);

painter.end();
}


Feel free to elaborate if there is a better way to achieve this.