PDA

View Full Version : Multi page report with QTextDocument



H Aßdøµ
15th February 2015, 05:48
I am using QTextDocument to generate html report and so far it works fine, now my report has multi sections witch is require each section on its own page, wrapping sections in table and then insert <div style=\"page-break-after:auto !important;\"></div> didn't work, as QTextDocument has limited support for html and css. also I did try to use QPaint, but this draws only the first page of my report.




void SemesterResultsReport::printDivisionStudentsNotes( ) {
QMap<int, int> divisionsList = SemesterResultsReport::getSelectedDivisions();

QPrinter *printer = new QPrinter(QPrinter::ScreenResolution);
printer->setFullPage(true);
printer->setResolution(90);
printer->setPaperSize(QPrinter::A4);
printer->setOrientation(QPrinter::Landscape);
printer->setPageMargins(5, 5, 5, 5, QPrinter::Millimeter);
/*printer->setOutputFormat(QPrinter::PdfFormat);
printer->setOutputFileName("sdf.pdf");*/


QPrintPreviewDialog *dlg = new QPrintPreviewDialog(printer, this);
connect(dlg, SIGNAL(paintRequested(QPrinter *)), this, SLOT(printOrder(QPrinter *)));
dlg->exec();
}


void SemesterResultsReport::printOrder(QPrinter *printer) {
QString strStream;
QTextStream out(&strStream);

QSqlQuery studentInfo, studentNotes;
QSqlRecord studentInfoRec, studentNotesRec;

QMap<int, int> selectedDivisions = SemesterResultsReport::getSelectedDivisions();
QMap<int, int>::const_iterator divisionId;

QTextDocument *document = new QTextDocument();
QTextCursor cursor(document);
QTextOption options;
options.setTextDirection(Qt::RightToLeft);
QSizeF paperSize;
paperSize.setWidth(printer->width());
paperSize.setHeight(printer->height());
document->setDefaultTextOption(options);
document->setPageSize(paperSize);

int mat_div = 0;
int level = 0;
int semester = ui.semestersList->currentText().toInt();
int school_year = 2015;
int numMaterials = 0;

// Report
out << "<!DOCTYPE html>"
<< "<html>\n"
<< "<head>"
<< "<title>ff</title>"
<< "<meta http-equiv=\"Content-Type\" content =\"text/html;charset=utf-8\" >"
<< "<style type=\"text/css\"> "
<< " html, body { margin: 5px; direction: rtl; width: 100% !important; align: right !important; float: right !important; }"
<< " *, p { font-family: \"Times New Roman\"; font-size: 16px; }"
<< " img { display: block; margin: 0 auto; }"
<< " p.title { font-weight: bold; font-size: 22px; align: center !important; }"
<< " table { border: 1; border-collapse: collapse; page-break-after:auto !important; width: 100% !important; align: right !important; float: right !important; }"
<< " th, td { border: 1px solid #000; padding: 0; align: center; page-break-inside:avoid; page-break-after:auto; }"
<< " tr { page-break-inside:avoid; page-break-after:auto !important; }"

<< " thead { display:table-header-group; }"
<< " tfoot { display:table-footer-group; }"
<< " .pagebreak { page-break-after:auto !important; } "
<< "</style>"
<< "</head>"
<< "<body>";
for (divisionId = selectedDivisions.constBegin(); divisionId != selectedDivisions.constEnd(); ++divisionId) {
mat_div = divisionId.key();
level = divisionId.value();
numMaterials = 0;

// Report header, get division materials to set as header
QStringList divisionMaterialsNames = SemesterResultsReport::getDivisionMaterialsNames(m at_div, level, school_year);
out << "<table float=\"right\" border=1 cellspacing=0 cellpadding=2>";
numMaterials = divisionMaterialsNames.size();
out << "<thead><tr bgcolor=#f0f0f0>";
for (int i = numMaterials - 1; i > -1; --i) {
out << "<th>" + divisionMaterialsNames[i] + "</th>";
}

out << "<th>" + QString("الإسم") + "</th>"
<< "<th>" + QString("اللقب") + "</th>"
<< "<th>" + QString("الرقم التسلسلي") + "</th>"
<< "</tr></thead>";

// Echo student info plus materials notes
QString fullName = ", fname, lname";
QString infoQuery = "SELECT Student.mat_stud as matStud" + fullName + " FROM Student, Class, Division WHERE Class.mat_div = Division.mat_div AND Class.mat_class = Student.mat_class AND school_year = " + QString::number(school_year) + " AND Class.level = " + QString::number(level) + " AND Division.mat_div = " + QString::number(mat_div);
studentInfo.exec(infoQuery);
studentInfoRec = studentInfo.record();
fullName.clear();
infoQuery = "SELECT Student.mat_stud as matStud FROM Student, Class, Division WHERE Class.mat_div = Division.mat_div AND Class.mat_class = Student.mat_class AND school_year = " + QString::number(school_year) + " AND Class.level = " + QString::number(level) + " AND Division.mat_div = " + QString::number(mat_div);
QString notesQuery = "SELECT materials_notes FROM Notes WHERE mat_stud IN (" + infoQuery + ") AND school_year = " + QString::number(school_year) + " AND level = " + QString::number(level) + " AND mat_div = " + QString::number(mat_div) + " AND semester = " + QString::number(semester);
studentNotes.exec(notesQuery);
studentNotesRec = studentNotes.record();
QStringList studentNotesList;
while (studentInfo.next()) {
out << "<tr>";
studentNotes.next();
studentNotesList = studentNotes.value(studentNotesRec.indexOf("materials_notes")).toString().split(",");
for (int i = 0; i < numMaterials; ++i) {
out << "<th>" + studentNotesList[i] + "</th>";
}

out << " <th>" + studentInfo.value(studentInfoRec.indexOf("lname")).toString() + "</th>"
<< " <th>" + studentInfo.value(studentInfoRec.indexOf("fname")).toString() + "</th>"
<< " <th>" + studentInfo.value(studentInfoRec.indexOf("matStud")).toString() + "</th>";

out << "</tr>";
}

// Close table tag, and insert new page, but it doesn't work
out << "</table><div style=\"page-break-after:auto !important;\"></div>";
}

// Finish report
out << "</body>"
<< "</html>";


/*
* Prepare QTextDocument
*/
document->setHtml(strStream);
document->print(printer);
// this makes only the first page printed
/*QPainter painter;
painter.begin(printer);
document->drawContents(&painter, printer->pageRect());
painter.end();*/
}

anda_skoa
15th February 2015, 07:28
If the method of filling a QTextDocument by HTML import doesn't provide all the necessary features, it might still be possible using QTextDocument's own API.

Alternatively you could look at using a report generator library, e.g KDReports https://github.com/KDAB/KDReports

Cheers,
_

ChrisW67
15th February 2015, 20:33
That attribute is in the supported HTML subset but it is may only be supported on <p> and <table> elements. The "auto" value leaves the decision up to the layout engine... You might want "always".

See the following post for another way to paginate from QTextDocument:
http://www.qtcentre.org/threads/57790-QPrinter-pages-not-breakering
You can use this method with a little thought to do things like headers and footers.

H Aßdøµ
15th February 2015, 23:45
I am looking for a simple solution as possible. QTextDocument has it's own API but to me is little bit complex to generate clean report.

@ChrisW67
I tried that too, but it s still not breaking pages. For the thread you refer to, I had read it, witch I am already trying to avoid because my knowledge in QTextDocument is and reports construction is limited.