Qt: Set background image on QTextDocument using HTML to generate pdf file - html

i am wrapping my head in this problem for a few time.
I need to create a report by creating a pdf file with some data on it.
So my plan was to instead of using the QTextCursor, i use HTML + CSS to create the content in my pdf file.
Unfortunately I can't go with the QWebEngine widgets solution because I am compiling into MinGW and setting the MVSC 2017 environment is a huge mess.
Sadly i have to go with the QTextDocument and his HTML subset support.
My problem is I can't put a background image in my pdf file.
I want to put this image as a background image:
What make me crazy is that I use the css property to display a background image in my pdf file.
background-image: url(:/images/blue-gradient-background.jpg);
And it seems that Qt is taking this into account but it still don't display the background.
Have a look:
The first pdf file don't contain the css property background image on the html content but the second does and you can see that the size of the file is bigger so it has considered the css property.
But it hasn't displayed the background:
On the left is the first file and on the right is the second file with the css property.
I use a html file in the ressource to generate the report :
<!DOCTYPE html>
<html>
<style>
body {
background-image: url(:/images/blue-gradient-background.jpg);
}
h1 {
color: blue;
}
#table-content {
}
#table-content table {
margin: 1em
}
</style>
<body>
<div align="center"><h1>[title-template]</h1></div>
<div align="center" id="table-content">[table-template]</div>
</body>
</html>
This html file is open and read in the constructor of the class:
FileEditor::FileEditor()
{
QFile htmlTemplate(":/html/report.html");
if (htmlTemplate.open(QIODevice::ReadOnly | QIODevice::Text))
{
QTextStream in(&htmlTemplate);
m_reportPageHTMLTemplate = in.readAll();
}
}
Then i use a custom class with this function that use QPrinter and QPainter to write the data:
void FileEditor::writeReportPdfFile(const QString &i_path, const S12xConf &i_s12xConf, const S12xData &i_s12xData, const BenchTestData &i_benchTestData)
{
QDir directory(i_path); // we create a QDir with the path
if (!directory.exists()) // if the directory does not exist then
{
directory.mkpath("."); // we create the path
}
QString fileName = getCurrentHourDate() + "_S12xNG_Test_Report.pdf";
QPrinter pdfPrinter(QPrinter::HighResolution);
pdfPrinter.setOutputFormat(QPrinter::PdfFormat);
pdfPrinter.setPageSize(QPageSize(QPageSize::A4));
pdfPrinter.setOutputFileName(i_path + "/" + fileName);
pdfPrinter.setFullPage(true);
QPainter painter(&pdfPrinter);
painter.setBackgroundMode(Qt::OpaqueMode);
QTextDocument measuresDoc;
QTextDocument averagesDoc;
QTextDocument inOutDoc;
measuresDoc.documentLayout()->setPaintDevice(&pdfPrinter);
measuresDoc.setPageSize(pdfPrinter.pageRect().size());
averagesDoc.documentLayout()->setPaintDevice(&pdfPrinter);
averagesDoc.setPageSize(pdfPrinter.pageRect().size());
inOutDoc.documentLayout()->setPaintDevice(&pdfPrinter);
inOutDoc.setPageSize(pdfPrinter.pageRect().size());
setMeasuresTextDocument(&measuresDoc);
setAveragesTextDocument(&averagesDoc);
setInputsOutputsTextDocument(&inOutDoc);
measuresDoc.drawContents(&painter); // We print TextDocument of the Measures into the document
pdfPrinter.newPage(); // We inject the current page and continue printing on new page
averagesDoc.drawContents(&painter); // We print the TextDocument of the Averages into the document
pdfPrinter.newPage(); // We inject the current page and continue printing on new page
inOutDoc.drawContents(&painter); // We print the TextDocument of the Inputs/Outputs into the document
measuresDoc.undo();
averagesDoc.undo();
inOutDoc.undo();
}
Here is the function to add the html data into the measures QTextDocument:
void FileEditor::setMeasuresTextDocument(QTextDocument *o_measuresDoc)
{
QString htmlContent = m_reportPageHTMLTemplate;
htmlContent.replace("[title-template]","I. Measures Data");
o_measuresDoc->setHtml(htmlContent);
}
So what i am doing wrong?
Thanks in advance for your responses.

I have found the answer!
it is about the drawContents method of QTextDocument.
There is a second parameter that you need to add in order to see the background image in your document.
It's the a QRectF object that represend the size of the rect that the background image will be clipped into.
void QTextDocument::drawContents(QPainter *p, const QRectF &rect = QRectF())
Draws the content of the document with painter p, clipped to rect. If rect is a null rectangle (default) then the document is painted unclipped.
So what I did is:
easuresDoc.drawContents(&painter, pdfPrinter.paperRect()); // We print TextDocument of the Measures into the document
pdfPrinter.newPage(); // We inject the current page and continue printing on new page
averagesDoc.drawContents(&painter, pdfPrinter.paperRect()); // We print the TextDocument of the Averages into the document
pdfPrinter.newPage(); // We inject the current page and continue printing on new page
inOutDoc.drawContents(&painter, pdfPrinter.paperRect()); // We print the TextDocument of the Inputs/Outputs into the document
pdfPrinter.paperRect is the rectangle of the page without the margin.
Also if you want the background image to be printed scaled with no repeat than you need to put the printer into QPrinter::PrinterResolution
QPrinter pdfPrinter(QPrinter::PrinterResolution);

Related

HTML2CANVAS image to be sent via email

This is what i am trying to achieve
When a button is pressed on a specific div in a HTML page, it goes to the HTML2CANVAS function and creates a canvas img. Now i need to attach this image to the body and open an outlook compose box.
1) How to send mail with image embeded in the body from within a web page?
2) How to convert canvas as a displayable image?
This function is the answer to your second question. This function converts a div into a base64 image and on complete render it displays the image to a div or you can do accordingly as you want.
function getImage(){
html2canvas($("#divID"), {
onrendered: function(canvas) {
// For image
var ctx=canvas.getContext("2d");
// ctx.webkitImageSmoothingEnabled = false;
// ctx.mozImageSmoothingEnabled = false;
ctx.imageSmoothingEnabled = false;
var convertedImage;
$.when(convertedImage = canvas.toDataURL('image/jpg')).promise().done(function(){
$('#finalImg').prop('src', convertedImage)
});
}
});
}
And the answer to your first question is also the same this converted image can be sent as a image in mail.
But you cannot send a MIME type in mailto body it can only contains plain text as body..
for further reference here is a link
Sending mail from HTML page with image in the body

Navigate within webpage in WebView control

I'm trying to navigate within a webpage that has been loaded from a remote server in my WebView control (Cocoa application). I would like to navigate to a particular tag that i can see in the HTML code of that page. The purpose of this all is to show the part of the HTML page that is of my interest at the top of the WebView control.
I know that in HTML code you can navigate by using something like #MIDDLE, #TOP etc. However, is this possible to do from outside of the HTML code using the WebView API?
Thanks for your reply in advance!
I found the answer to my question with the help of an other question (How to scroll HTML page to given anchor using jQuery or Javascript?).
The piece of code below does the trick for me. It searches for HTML elements with attribute: class = "container" in the HTML data that is loaded in the WebView component self.webView.
-(void) scrollMyImportantHTMLPartInView
{
// Get a list of HTML elements that contain attribute class = "container" (eg. <div class "container">)
DOMNodeList *nodeList = [[[self.webView mainFrame] DOMDocument] getElementsByClassName: #"container"];
if( nodeList && nodeList.length >= 1 ) {
// get the first node (class = "container") from the list
DOMNode *domNode = [nodeList item:0];
// Make sure it's a DOM element type
if( domNode.nodeType == DOM_ELEMENT_NODE ) {
// It's now save to cast from DOMNode* to DOMElement*
DOMElement* domElement = (DOMElement*) domNode;
// Scroll begining of HTML node into view
[domElement scrollIntoView: YES];
}
}
}

generating pdf from mysql with dynamic column width according to content length

am using FPDF library to generate pdf files from the database, and am extending PDF_MySQL_Table class to autmatically arrange data to the table. but i have 17 columns to display..so it overlaps each other..how can i make it expand to fit the content???
here is my code:
<?php
require('../fpdf/mysql_table.php');
require_once('../db/connect.php');
// Page header
class PDF extends PDF_MySQL_Table
{
function Header()
{
// Logo
$this->Image('../fpdf/ccm_inner_logo.png',10,8,33);
// Arial bold 15
$this->SetFont('Arial','B',15);
// Move to the right
$this->Cell(30);
// Title
$this->Cell(120,15,'Member Information',1,0,'C');
// Line break
$this->Ln(20);
}
}
$pdf=new PDF();
$pdf->AddPage();
//First table: put all columns automatically
$pdf->Table("select * from members");
$pdf->AddPage();
$pdf->Output();
?>
any help???
instead of cell you have to use multicell checkout this link
http://www.fpdf.org/en/script/script3.php might help you

find HTMLEditor cursor pointer for inserting image

as said in topic: JavaFX HTMLEditor - Insert image function
if want to insert image should add below tag to htmlText of htmlEditor
"<img src=\"" + getClass().getResource(PicName[i])) + "\" width=\"" + target.getImage().getWidth() + "\"height=\"" + target.getImage().getHeight() + "\">")
but if want to add image in cursor position how to do it?
You can achieve this in the following way
Use the ScenicView to explore the HTMLEditor
Get WebView inside HTMLEditor
Get WebEngine of that WebView
Run a JavaScript Code to Insert an image to the caret pos using WebEngine
How To Replace HTML using JS
Link to Original Post
function insertHtmlAtCursor(html) {
var range, node;
if (window.getSelection && window.getSelection().getRangeAt) {
range = window.getSelection().getRangeAt(0);
node = range.createContextualFragment(html);
range.insertNode(node);
} else if (document.selection && document.selection.createRange) {
document.selection.createRange().pasteHTML(html);
}
}
How to Execute JS Code Guide
Node webNode = htmlEditor.lookup(".web-view");
if (webNode instanceof WebView) {
WebView webView = (WebView) webNode;
WebEngine engine = webView.getEngine();
engine.executeScript("alert('helo')"); // add js code here
}
text fileds are have a linear datastructure and can have a sequential position and corresponding location in its view.
but for html view the displayed object location on screen to location in the text mapping is a bit difficult so thats why the html editor cant determine the cursor position
im working on some other workaround to insert image at given cursor position.
try to insert a dummy text as a placeholder like ###inserImage#### then replace it with the actual image tag <img src="file:\c:\testhtmleditor\sample01.jpg" />..
Let's try this piece of code
#FXML private HTMLEditor editor;
...
public void insertTextToCurrentFeatureCursorPosition(String text) {
WebView webView = (WebView) editor.lookup(".web-view");
WebPage webPage = Accessor.getPageFor(webView.getEngine());
webPage.executeCommand("insertHTML", text);
}
Where text is the HTML code which wraps the image

LibTiff.NET append mode bug?

I've started using LibTiff.NET for writing tiff IPTC tags lately and discovered strange behavior on some files that i have here. I'm using sample code that ships with LibTiff.NET binaries, and it works fine with most of the images, but some files are having image data corruption after these lines:
class Program
{
private const TiffTag TIFFTAG_GDAL_METADATA = (TiffTag)42112;
private static Tiff.TiffExtendProc m_parentExtender;
public static void TagExtender(Tiff tif)
{
TiffFieldInfo[] tiffFieldInfo =
{
new TiffFieldInfo(TIFFTAG_GDAL_METADATA, -1, -1, TiffType.ASCII,
FieldBit.Custom, true, false, "GDALMetadata"),
};
tif.MergeFieldInfo(tiffFieldInfo, tiffFieldInfo.Length);
if (m_parentExtender != null)
m_parentExtender(tif);
}
public static void Main(string[] args)
{
// Register the extender callback
// It's a good idea to keep track of the previous tag extender (if any) so that we can call it
// from our extender allowing a chain of customizations to take effect.
m_parentExtender = Tiff.SetTagExtender(TagExtender);
string destFile = #"d:\00000641(tiffed).tif";
File.Copy(#"d:\00000641.tif", destFile);
//Console.WriteLine("Hello World!");
// TODO: Implement Functionality Here
using (Tiff image = Tiff.Open(destFile, "a"))
{
// we should rewind to first directory (first image) because of append mode
image.SetDirectory(0);
// set the custom tag
string value = "<GDALMetadata>\n<Item name=\"IMG_GUID\">" +
"817C0168-0688-45CD-B799-CF8C4DE9AB2B</Item>\n<Item" +
" name=\"LAYER_TYPE\" sample=\"0\">athematic</Item>\n</GDALMetadata>";
image.SetField(TIFFTAG_GDAL_METADATA, value);
// rewrites directory saving new tag
image.CheckpointDirectory();
}
// restore previous tag extender
Tiff.SetTagExtender(m_parentExtender);
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
}
After opening i see mostly blank white image or multiple black and white lines instead of text that have been written there (i don't need to read\write tags to produce this behavior). I noticed this happens when image already has a custom tag (console window alerts about it) or one of tags have got 'bad value' (console window in this case says 'vsetfield:%pathToTiffFile%: bad value 0 for "%TagName%" tag').
Original image: http://dl.dropbox.com/u/1476402/00000641.tif
Image after LibTiff.NET: http://dl.dropbox.com/u/1476402/00000641%28tiffed%29.tif
I would be grateful for any help provided.
You probably should not use CheckpointDirectory method for files opened in append mode. Try using RewriteDirectory method instead.
It will rewrite the directory, but instead of place it at it's old
location (as WriteDirectory() would) it will place them at the end of
the file, correcting the pointer from the preceeding directory or file
header to point to it's new location. This is particularly important
in cases where the size of the directory and pointed to data has
grown, so it won’t fit in the space available at the old location.
Note that this will result in the loss of the previously used
directory space.