Print the contents of QWebFrame with header and footer - c++

I want to print a QWebView with a header and a footer. I'm using the class QPrintPreviewDialog to preview the print.
I saw how solve this issue the projects phantomjs and wkhtmltopdf but it seems a little excessive the need to include in my project a modified version of WebKit.
Apparentyly printing headers and footers with Qt and Webkit it's an issue not enterely solved:
https://bugs.webkit.org/show_bug.cgi?id=30357
https://bugreports.qt.io/browse/QTBUG-29619
https://wiki.qt.io/Qt_project_org_faq (Question 229)
A priori I don't know how many pages I am going to print. Currently I am subclassing QPrinter and reimplementing the newPage() method. It's an awful hack but nearly works. The issue i'm facing is that everything that it is printed outside the pageRect it is shown like blurred. The watermark effect is only present in the preview not in the printed result, but the low quaility is present always.
There is something i can do to print headers with better quality, without bring all WebKit to my project?.
The difference that I suspect is introducing the problem is that I use QWebView::render instead of QWebView::print. QCustomPrinter has an associated QPainter before printing the header ( the QPainter associated when the content was printed ). Therefore I can't invoke QWebVieww:print when printing the headers because that method tries to associate a new QPainter to QPrinter.
void CustomPrinter::printHeader()
{
QPainter & painter =*this->paintEngine()->painter();
QWebView v;
v.setContent("<html> "
"<body>"
" asdadasdasdasd "
"</body>"
"</html>");
v.setFixedSize(this->pageRect().size());
v.render(&painter,QPoint(0,- 95),QRegion(0,0,this->pageRect().width(),95));
}
EDIT (based on Kuba Ober answer):
Using QTextDocument instead of QWebView solves the quality issue.
void CustomPrinter::printHeader()
{
QPainter * painter =p->paintEngine()->painter();
painter->save();
QTextDocument v;
v.setHtml(QString::fromStdString(_impresion.cabecera()));
QRectF r =this->pageRect();
r.moveTo(0,0);
r.setHeight(95);
painter->translate(0,-95);
v.drawContents(painter,r);
painter->restore();
}
I share a minimun example of what i'm talking about. The CustomPrinter class prints the header.
https://www.dropbox.com/s/2vifzk8rs6scrx5/stackExample.tar.gz?dl=0

Related

Qt stylesheet to use an image from memory

Qt stylesheets allow customizing of icons, for example the drop-down icon in a combo box. But all examples and docs which I have yet seen require having the image stored in a url. Then you can write for example QComboBox::down-arrow { image: url(path-to-file.png); }.
My question is: isn't there any trick which would allow to work around the fact that the file must be stored somewhere and use for example a pixmap from the memory?
I am asking because recently I found a nice hack which allows using QPixmap data to be used when displaying images in widgets which otherwise accept richtext (HTML formatted). See this code:
QPixmap preview;
// ... generate the pixmap here
QByteArray data;
QBuffer buffer(&data);
preview.save(&buffer, "PNG");
QString img = QStringLiteral("<img src='data:image/png;base64, %1'/>").arg(QString::fromLatin1(data.toBase64()));
//... and now you can display the image anywhere Qt accepts HTML formatted text,
// e.g. in QToolTip (which is my usecase).
This way I can use data from memory without saving it to file.
I am curious if there isn't any similar trick for images used in Qt style sheets.
There's nothing special, just put path to your image:
setStyleSheet("background-image: url(/path/to/file.png);");

Print a textEdit in Qt

How can I print the text available in a textEdit using Qt creator (C++)? Please help me with this. I created a note pad using a textEdit. Now I want to print the note pad content. That mean the text typed in textEdit. So please help me.
please mention header files that I need to include as well.
Here is something I tried previous. but it's not working. so please help me with this.
void MainWindow::on_action_Print_triggered()
{
QString textFromField = ui->txtEdit->toPlainText();
QPrinter printer(QPrinter::HighResolution);
printer.setOutputFileName("print.ps");
QPainter painter;
painter.begin(&printer);
printer.newPage();
painter.end();
}
QTextEdit already has method which allows you print it's content, so you don't need QPainter. Use this (I printed pdf as example):
QPrinter printer(QPrinter::HighResolution);
printer.setOutputFormat(QPrinter::PdfFormat);
printer.setOutputFileName("outputt.pdf");
ui->textEdit->print(&printer);
print()
And of course you need
#include <QPrinter>
but I think that it is already added in your project.

Qt QGraphicsScene does not fitInView() with scrollbars

QGraphicsView::fitInView() seems to ignore the presence of scrollbars, that apparently are overlaid. (It also uses a hardcoded 2 pixel margin.)
There is a related bug report (https://bugreports.qt-project.org/browse/QTBUG-1047) stating that calling fitInView() twice would resolve the problem.
In my case, it does not. Only triggering it twice manually fits regarding the scrollbars. This does not work:
void myGraphicsView::mousePressEvent(QMouseEvent *event) {
if( event->button() == Qt::LeftButton ) {
QGraphicsItem* clicked = scene()->itemAt( mapToScene( event->pos() ) );
qDebug() << clicked << clicked->boundingRect();
fitInView( clicked, Qt::KeepAspectRatio);
fitInView( clicked, Qt::KeepAspectRatio); // doesn't work for me
QGraphicsView::mousePressEvent(event);
return;
}
}
Is there another workaround?
Qt 4.8.1 with MSVC2010
Calling fitInView() twice does work, but you have to let Qt process its events between the two calls.
This also means you end up redrawing the graphicsview twice.
To avoid this, what I do is:
Disable updates
Call fitInView
Call QApplication::processEvents()
Call fitInView again
Enable updates
In your code it would look like this:
bool updateState = updatesEnabled();
setUpdatesEnabled(false);
fitInView(clicked, Qt::KeepAspectRatio);
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
fitInView(clicked, Qt::KeepAspectRatio);
setUpdatesEnabled(updateState);
The cause could be this (at least it looks like it is in the bug report): https://bugreports.qt.io/browse/QTBUG-42331 - please vote on it on the qt bug tracker to up its priority.
In short, fitInView has hardcoded margins and this can cause all kinds of havoc - the least of which is that now you lose a few pixels of display area and might also force unnecessary rescaling. It can cause runaway resizing and weird instabilities such as what the QTBUG-1047 bug submitter described.
You can fix the problem by reimplementing fitInView, based on the existing implementation but removing it's ridiculous margins. An example of that is available here in python, based on the original C++ version:
https://github.com/nevion/pyqimageview/blob/master/qimageview/widget.py#L276
Let me know if it fixes your problem! That way we can close out that since-2007 bug too.

Qt QPrinter setPaperSize does not work properly

I am trying to create a Windows application (but will eventually port it to linux also, so cross-compatibility is important if possible) that will take a picture from a webcam and can print without using a printDialog box, but I am having an issue selecting a paper size. I would like the paper size to be set to 4" x 6" which is the A6 format, but when I use setPaperSize(QtPrinter::A6) it seems to default to the letter format. It does not always default to letter with all printers though, it looks like each printer handles the command differently, but most default to letter. I believe this may be an issue with Qt and printer compatibility with the drivers.
My question is: Does anyone know a way to set the printer to 4" by 6" in Qt that should work with all printers?
My code is shown below.
void MainWindow::Print() {
QPainter painter;
QPrinter *printer = new QPrinter(QPrinter::HighResolution);
printer->setPaperSize(QPrinter::A6);
if (!painter.begin(printer)) {
qWarning("Failed to open file");
return;
}
painter.fillRect(QRectF(QPointF(108,118),QPointF(110+352, 120+352)), Qt::black);
painter.fillRect(QRectF(QPointF(109,119),QPointF(109+352, 119+352)), Qt::white);
ui->graphicsView->scene()->render(&painter, QRectF(110,120, 350, 350), QRectF(0,0, ui->graphicsView->scene()->width(), ui->graphicsView->scene()->height()), Qt::IgnoreAspectRatio);
painter.drawText(110, 110, "Test");
painter.end();
}
I have tried the following for resizing the paper
printer->setPaperSize(QPrinter::A6)
printer->setPageSize(QPrinter::A6)
printer->setPaperSize(QSizeF(4.0, 6.0), QPrinter::Inch)
none of those seemed to work. If anyone could help me with this issue I would be very greateful
setPaperSize relies on information received from the printer driver, so to be really printer independant, calculare pageRects yourself.
See the pageRect and the paperRect property together with the fullPage property of QPrinter.
See also my answer to Printing pagerect issues where there is a (wrong) starting example of printing arbitrary print rects and how to fix the code given with the question.

Qt QTextEdit line numbers

I'm working on a code editor for GLSL in Qt and I'm having problems with showing the line numbers of a QTextEdit. I undestand the example from Qt Code Editor Example but this part
QTextBlock block = firstVisibleBlock();
int blockNumber = block.blockNumber();
int top = (int) blockBoundingGeometry(block).translated(contentOffset()).top();
int bottom = top + (int) blockBoundingRect(block).height();
doesn't really combine well with a QTextEdit given the fact that I don't have the firstBisibleBlock, blockBoundingGeometry and blockBoundingRect methods. I know the blocks are kept in a QTextDocument but that class doesn't have these methods either.
I tried searching for an example but every time someone asks this question he is directed to that same link.
Could anyone help me?
Thanks
The example uses QPlainTextEdit and accesses firstVisibleBlock() etc protected functions.
Take a look at the source code for QPlainTextEdit and see what IT does to implement these functions. It looks as though they are implemented in terms of the document (at least firstVisibleBlock() does).
Alternatively, copy the example and derive from QPlainTextEdit yourself and don't use QTextEdit.