Files
qt6-migration-pipeline/Lts/Common/LtsPrinting/printing_base.cpp
T

1306 lines
30 KiB
C++
Executable File

#include "printing_base.h"
#include <ngltools/ngltools_filesystem.h>
#include <QDateTime>
#include <QFile>
#include <QUrl>
#include <QPair>
#include <QPrinter>
#include <QPrintDialog>
#include <QPrinterInfo>
#include <QPainter>
#include <QListView>
#include <QTextFrame>
#include <QTextFrameFormat>
#include <QTextDocument>
#include <QAbstractTextDocumentLayout>
#include <QTextBlock>
#include <QTableView>
#include <QTreeView>
#include <QTemporaryFile>
#include <nglsettings/nglsettings_settings.h>
#include <ngltools/ngltools_dtg.h>
#include <NGLLogger/NGLLoggerBootstrap.h>
#include <KDReports/KDReports.h>
namespace LtsPrinting
{
static inline double mmToInches(double mm) { return mm * 0.039370147; }
static inline double inchesToMM(double inches) { return inches * 25.4; }
bool LtsPrinting::Base::m_printToFile = false;
static int TitleDataHeight = 50;
static int DescriptionDataHeight = 50;
static void spanSizes(const QAbstractItemView *view,
const QModelIndex &ms,
int &rowSpanSize,
int &columnSpanSize,
QVector<QPair<int, int> > &spannedL);
Base::Base(QTextDocument &doc,
QWidget *dialogParent,
const QString &dialogTitle,
const QString &_fn,
QPrinter::PaperSize _ps,
QPrinter::Orientation _or,
QPrinter::ColorMode _cm)
: m_printer(new QPrinter),
m_painter(new QPainter),
m_iconFilenameNr(0),
m_tempdoc(nullptr),
leftmargin_(15.0), rightmargin_(15.0), topmargin_(15.0),
bottommargin_(15.0), spacing_(5.0),
headersize_(10), headerrule_(0.5), headertext_(HeaderText),
footersize_(10), footerrule_(0.5), footertext_(FooterText),
itemFontSize_(2),
m_settings(new NGL::Settings(NGL::findProjectConfigFile())),
m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("NGLPrinting")),
m_currentPage(1)
{
QString fn = _fn;
fn = fn.remove(QLatin1Char(' '));
fn = fn.remove(QLatin1String(".."));
fn = fn.remove(QLatin1Char('/'));
fn = m_settings->printPath() + fn;
if (!fn.endsWith(QLatin1String(".pdf"), Qt::CaseInsensitive))
fn += QLatin1String(".pdf");
#ifndef WIN32
m_printer->setOutputFileName(fn);
#endif
m_printer->setOutputFormat(QPrinter::NativeFormat);
m_printer->setPaperSize(_ps);
m_printer->setOrientation(_or);
m_printer->setColorMode(_cm);
m_printer->setFullPage(true);
QTextOption tOption = doc.defaultTextOption();
tOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
doc.setDefaultTextOption(tOption);
doc.setPageSize(QSizeF(printerPageSize()));
doc.setDefaultStyleSheet(styleSheet());
if (m_printToFile)
return;
QPrintDialog *dialog = new QPrintDialog(m_printer, dialogParent);
QAbstractPrintDialog::PrintDialogOptions op =
QAbstractPrintDialog::PrintToFile |
QAbstractPrintDialog::PrintSelection |
QAbstractPrintDialog::PrintPageRange |
QAbstractPrintDialog::PrintShowPageSize |
QAbstractPrintDialog::PrintCollateCopies;
dialog->setOptions(op);
QString title = dialogTitle;
if (_ps == QPrinter::A2) title += QLatin1String(" (A2)");
if (_ps == QPrinter::A3) title += QLatin1String(" (A3)");
if (_ps == QPrinter::A4) title += QLatin1String(" (A4)");
if (_ps == QPrinter::A5) title += QLatin1String(" (A5)");
dialog->setWindowTitle(title);
if (dialog->exec() != QDialog::Accepted)
{
delete m_printer;
m_printer = nullptr;
return;
}
m_painter->begin(m_printer);
}
Base::~Base()
{
delete m_printer;
delete m_painter;
delete m_tempdoc;
for (int nr = 0; nr < m_iconFilenameNr; ++nr)
QFile::remove(iconFilename(nr));
delete m_settings;
}
void Base::setPrintToFile(bool printToFile)
{
m_printToFile = printToFile;
}
QPrinter *Base::printer()
{
DEBUG_LOG(m_logger) << "Base::printer" ;
return m_printer;
}
QString Base::styleSheet()
{
QString ret;
return ret;
}
QSize Base::printerPageSize() const
{
return QSize(m_printer->pageRect().width() - 2 * DOC_MARGIN,
m_printer->pageRect().height() - 2 * DOC_MARGIN);
}
bool Base::newPage()
{
return m_printer->newPage();
}
QSize Base::contentPageSize() const
{
QSize ps(printerPageSize());
ps.setHeight(ps.height() - 50 - 50);
return ps;
}
void Base::printTitleData(QString &htmlStr, const QString &title, const QString &heading)
{
if (!title.isEmpty())
{
htmlStr += QLatin1String("<table width=\"100%\"><tr><td align=\"center\">") +
QLatin1Char('<') + heading + QLatin1Char('>') + title + QLatin1String("</") + heading + QLatin1Char('>') +
QLatin1String("</td></tr></table>");
}
}
bool Base::printListData(QString &str,
const QAbstractItemView *view,
const QString &title,
bool asIcons,
int iconExtent)
{
if (!view)
return false;
printTitleData(str, title);
QAbstractItemModel *vm = view->model();
if (!vm)
return false;
QItemSelectionModel *sm = view->selectionModel();
QModelIndexList mil;
if (m_printer->printRange() == QPrinter::Selection)
mil = sm->selectedRows();
else
{
int row = 0;
while (1)
{
QModelIndex mi = vm->index(row, 0, QModelIndex());
if (mi.isValid())
{
mil.append(mi);
row++;
continue;
}
break;
}
}
if (mil.count() == 0)
return false;
if (asIcons)
{
int elemWidth = iconExtent + 40;
int tableWidth = contentPageSize().width();
int nColums = tableWidth / elemWidth;
str += QLatin1String("<table border=\"0\" cellspacing=\"2\">") +
QLatin1String("<colgroup width=\"") + QString::number(elemWidth) + QLatin1String("\" ") +
QLatin1String("span=\"") + QString::number(nColums) + QLatin1String("\">") +
QLatin1String("</colgroup>") +
QLatin1String("<tbody>") +
QLatin1String("<tr>");
int columIdx = 0;
for (const QModelIndex &mi :qAsConst(mil))
{
if (columIdx >= nColums)
{
columIdx = 0;
str += QLatin1String("</tr><tr>");
}
str += QLatin1String("<td>");
printDecorationData(str, vm, mi, iconExtent / 2);
QVariant vdata = vm->data(mi, Qt::DisplayRole);
str += QLatin1String("<br />");
QString displayText;
if (vdata.isValid())
displayText = vdata.toString();
else
displayText = QLatin1Char(' ');
str += QLatin1String("<font size=-1>") + displayText + QLatin1String("</font>") +
QLatin1String("</td>");
++columIdx;
}
str += QLatin1String("</tr></tbody></table>");
}
else
{
for (const QModelIndex &mi :qAsConst(mil))
{
if (printItemData(str, vm, mi, iconExtent))
str += QLatin1String("<br />");
}
}
return true;
}
static QModelIndexList getItemChildren(const QAbstractItemModel *model,
const QTreeView *tv,
const QModelIndex &root)
{
QModelIndexList ret;
const int rc = model->rowCount(root);
ret.reserve(rc);
for (int row = 0; row < rc; ++row)
{
const QModelIndex mi = model->index(row, 0, root);
ret += mi;
if (tv->isExpanded(mi))
ret += getItemChildren(model, tv, mi);
}
return ret;
}
bool Base::printTableData(QString &str,
const QAbstractItemView *view,
const QString &title_,
const QSet<int> &suppressCols,
int iconExtent)
{
if (!view)
return false;
QString title = title_;
printTitleData(str, title.remove(QLatin1String("[*]")));
const QAbstractItemModel *imodel = view->model();
QModelIndexList mil;
if (m_printer->printRange() == QPrinter::Selection)
{
const QItemSelectionModel *sm = view->selectionModel();
mil += sm->selectedRows();
}
else
{
const QTreeView *tv = qobject_cast<const QTreeView *>(view);
if (tv)
{
const int rc = imodel->rowCount();
mil.reserve(rc);
for (int row = 0; row < rc; ++row)
{
QModelIndex mi = imodel->index(row, 0);
mil += mi;
if (tv->isExpanded(mi))
mil += getItemChildren(imodel, tv, mi);
}
}
else
{
const int rc = imodel->rowCount();
mil.reserve(rc);
for (int row = 0; row < rc; ++row)
mil.append(imodel->index(row, 0));
}
}
int colCount = imodel->columnCount();
QStringList tableHeader;
for (int i = 0; i < colCount; i++)
{
if (suppressCols.contains(i))
continue;
QVariant v = imodel->headerData(i, Qt::Horizontal);
if (v.isValid())
tableHeader.append(v.toString());
}
str += QLatin1String("<table border=\"1\" cellspacing=\"0\" cellpadding=\"3\" style=\"border-collapse:collapse\">") +
QLatin1String("<thead>") +
QLatin1String("<tr>");
for (const QString &s : qAsConst(tableHeader))
str += QLatin1String("<th scope=\"col\">") + s + QLatin1String("</th>");
str += QLatin1String("</tr></thead><tbody>");
QVector<QPair<int, int> > spannedL;
for (const QModelIndex &mi :qAsConst(mil))
{
str += QLatin1String("<tr>");
for (int ii = 0; ii < colCount; ii++)
{
if (suppressCols.contains(ii))
continue;
const QModelIndex ms = mi.sibling(mi.row(), ii);
if (spannedL.contains(qMakePair(ms.row(), ms.column())))
continue;
int rowSpanSize;
int columnSpanSize;
spanSizes(view, ms, rowSpanSize, columnSpanSize, spannedL);
printTableItemData(str, imodel, ms, rowSpanSize, columnSpanSize,
iconExtent);
}
str += QLatin1String("</tr>");
}
str += QLatin1String("</tbody></table>");
DEBUG_LOG(m_logger) << qPrintable(str) ;
return true;
}
void spanSizes(const QAbstractItemView *view,
const QModelIndex &ms,
int &rowSpanSize,
int &columnSpanSize,
QVector<QPair<int, int> > &spannedL)
{
rowSpanSize = 1;
columnSpanSize = 1;
const QTableView *tview = qobject_cast<const QTableView *>(view);
if (tview)
{
rowSpanSize = tview->rowSpan(ms.row(), ms.column());
columnSpanSize = tview->columnSpan(ms.row(), ms.column());
for (int row = ms.row(); row < ms.row() + rowSpanSize; ++row)
spannedL << qMakePair(row, ms.column());
for (int column = ms.column(); column < ms.column() + columnSpanSize; ++column)
spannedL << qMakePair(ms.row(), column);
}
}
bool Base::printTableItemData(QString &str,
const QAbstractItemModel *model,
const QModelIndex &mi,
int rowSpanSize,
int columnSpanSize,
int iconExtent)
{
QVariant vdata;
QString htmlString;
vdata = model->data(mi, Qt::BackgroundRole);
if (vdata.isValid())
{
QString bgColorString = vdata.value<QBrush>().color().name();
htmlString += QLatin1String("<td bgcolor=\"") + bgColorString + QLatin1Char('\"');
}
else
htmlString += QLatin1String("<td");
if (rowSpanSize > 1)
htmlString += QLatin1String(" rowspan=\"") + QString::number(rowSpanSize) + QLatin1Char('\"');
if (columnSpanSize > 1)
htmlString += QLatin1String(" colspan=\"") + QString::number(columnSpanSize) + QLatin1Char('\"');
htmlString += QLatin1Char('>');
printItemData(htmlString, model, mi, iconExtent);
htmlString += QLatin1String("</td>");
str += htmlString;
return true;
}
bool Base::printTreeData(QString &str,
const QAbstractItemView *view,
const QString &title,
const QSet<int> &suppressCols,
int iconExtent,
const QList<QString> &tabtexts)
{
if (!view)
return false;
printTitleData(str, title);
QAbstractItemModel *vm = view->model();
if (!vm)
return false;
QItemSelectionModel *sm = view->selectionModel();
QModelIndexList milColumn0;
if (m_printer->printRange() == QPrinter::Selection)
milColumn0 = sm->selectedRows();
else
{
int row = 0;
while (1)
{
QModelIndex mi = vm->index(row, 0);
if (mi.isValid())
{
milColumn0.append(mi);
row++;
continue;
}
break;
}
}
if (milColumn0.count() == 0)
return false;
str += QLatin1String("<table border=\"0\" cellspacing=\"2\" cellpadding=\"1\">") +
QLatin1String("<tbody><tr>");
QStringList tableHeader;
if (tabtexts.size() > 0)
tableHeader = tabtexts;
else
{
for (int i = 0; i < vm->columnCount(); i++)
{
if (suppressCols.contains(i))
continue;
QVariant v = vm->headerData(i, Qt::Horizontal);
if (v.isValid())
tableHeader.append(v.toString());
else
tableHeader.append(QString());
}
}
for (const QString &s : qAsConst(tableHeader))
str += QLatin1String("<th align=\"left\"><h4>") + s + QLatin1String("</h4></th>");
str += QLatin1String("</tr>");
for (const QModelIndex &miColumn0 : qAsConst(milColumn0))
printListPoint(str, view, vm, miColumn0, suppressCols, iconExtent);
str += QLatin1String("</tbody></table><br /><br />");
return true;
}
void Base::printListPoint(QString &str,
const QAbstractItemView *view,
const QAbstractItemModel *vm,
const QModelIndex &miColumn0,
const QSet<int> &suppressCols,
int iconExtent)
{
if (!miColumn0.isValid())
return;
str += QLatin1String("<tr>");
for (int column = 0; column < vm->columnCount(); column++)
{
if (suppressCols.contains(column))
continue;
QModelIndex ms = miColumn0.sibling(miColumn0.row(), column);
if (!ms.isValid())
continue;
str += QLatin1String("<td><dl>");
if (column == 0)
{
int hierCount = hierarchyCount(ms);
for (int genIdx = 0; genIdx < hierCount; ++genIdx)
str += QLatin1String("<dd><dl>");
str += QLatin1String("<dt>");
printItemData(str, vm, ms, iconExtent);
str += QLatin1String("</dt>");
for (int genIdx = 0; genIdx < hierCount; ++genIdx)
str += QLatin1String("</dl></dd>");
}
else
{
str += QLatin1String("<dt>");
printItemData(str, vm, ms, iconExtent);
str += QLatin1String("</dt>");
}
str += QLatin1String("</dl></td>");
}
str += QLatin1String("</tr>");
const QTreeView *tv = qobject_cast<const QTreeView *>(view);
const bool expanded = tv ? tv->isExpanded(miColumn0) : true;
if (expanded)
{
const int rc = vm->rowCount(miColumn0);
for (int row = 0; row < rc; row++)
{
QModelIndex cmi = vm->index(row, 0, miColumn0);
if (cmi.isValid())
printListPoint(str, view, vm, cmi, suppressCols, iconExtent);
}
}
}
int Base::hierarchyCount(const QModelIndex &child)
{
int count = 0;
const auto parent = child.parent();
if (parent.isValid())
count = hierarchyCount(parent) + 1;
return count;
}
bool Base::printItemData(QString &str,
const QAbstractItemModel *model,
const QModelIndex &mi,
int iconExtent)
{
QVariant vdata;
QString displayString;
QString htmlString;
vdata = model->data(mi, Qt::CheckStateRole);
if (vdata.isValid())
{
displayString += QLatin1String("<code>");
if (static_cast<Qt::CheckState>(vdata.toInt()))
displayString += QLatin1String("&otimes; ");
else
displayString += QLatin1String("&omicron; ");
displayString += QLatin1String("</code>");
}
printDecorationData(displayString, model, mi, iconExtent / 2);
displayString += QLatin1Char(' ');
vdata = model->data(mi, Qt::DisplayRole);
if (vdata.isValid())
displayString += vdata.toString();
QString fgColorString;
vdata = model->data(mi, Qt::TextColorRole);
if (vdata.isValid())
fgColorString = vdata.value<QColor>().name();
vdata = model->data(mi, Qt::ForegroundRole);
if (vdata.isValid())
fgColorString = vdata.value<QBrush>().color().name();
htmlString += QLatin1String("<font size=\"") + QString::number(itemFontSize_) + QLatin1Char('\"');
if (!fgColorString.isNull())
htmlString += QLatin1String(" color=\"") + fgColorString + QLatin1Char('\"');
htmlString += QLatin1Char('>') + displayString + QLatin1String("</font>");
str += htmlString;
return true;
}
void Base::printDecorationData(QString &str,
const QAbstractItemModel *model,
const QModelIndex &mi,
int iconExtent)
{
QVariant vdata = model->data(mi, Qt::DecorationRole);
if (vdata.isNull() || !vdata.isValid())
return;
QIcon icon = vdata.value<QIcon>();
if (icon.isNull())
return;
QString fn = iconFilename(m_iconFilenameNr++);
QPixmap pm = icon.pixmap(1000);
pm.save(fn);
str += QLatin1String("<img src=\"") + fn + QLatin1Char('\"') +
QLatin1String(" width=\"") + QString::number(iconExtent) + QLatin1Char('\"') +
QLatin1String(" height=\"") + QString::number(iconExtent) + QLatin1Char('\"') +
QLatin1String(" alt=\"icon\" />");
}
QString Base::iconFilename(int nr) const
{
return m_settings->printPath() + QLatin1String("icon_") + QString::number(nr) + QLatin1String(".png");
}
bool Base::printDocTextBlock(QTextDocument &doc,
const QString &text,
const QString &title)
{
QTextCursor cursor(&doc);
cursor.movePosition(QTextCursor::End);
if (!title.isEmpty())
{
QString htmlStr;
printTitleData(htmlStr, title);
cursor.insertHtml(htmlStr);
}
cursor.insertBlock();
QTextBlockFormat bf = cursor.blockFormat();
bf.setNonBreakableLines(false);
cursor.setBlockFormat(bf);
QTextCharFormat cf = cursor.blockCharFormat();
cf.setFontWeight(QFont::Normal);
cursor.setBlockCharFormat(cf);
cursor.insertText(text);
return true;
}
bool Base::printDocImage(QTextDocument &doc, const QImage &image,
const QString &title, const QString &description, const qreal alreadyUsedHeight) const
{
if (image.isNull())
return false;
QTextCursor cursor(&doc);
static int iImageCounter = 0;
QString name = QStringLiteral("printing://image_%1.png").arg(iImageCounter++);
doc.addResource(QTextDocument::ImageResource,
QUrl(name),
QVariant(image));
QString htmlStr;
if (!title.isEmpty())
printTitleData(htmlStr, title);
if (!description.isEmpty())
printTitleData(htmlStr, description, QLatin1String("h4"));
double rel = (double)image.height() / (double)image.width();
double dwMax = contentPageSize().width();
double dhMax = contentPageSize().height() - alreadyUsedHeight;
if (!title.isEmpty())
dhMax -= TitleDataHeight;
if (!description.isEmpty())
dhMax -= DescriptionDataHeight;
double dh = dhMax;
double dw = dwMax;
if (rel >= 1)
{
double new_dw = dhMax / rel;
if (new_dw > dwMax)
{
dh = dwMax * rel;
}
else
dw = new_dw;
}
else
{
double new_dh = dw * rel;
if (new_dh > dhMax)
{
dw = dhMax / rel;
}
else
dh = new_dh;
}
QTextImageFormat tif;
tif.setName(name);
tif.setHeight(dh);
tif.setWidth(dw);
cursor.insertHtml(htmlStr);
cursor.insertImage(tif);
return true;
}
bool Base::printReportData(QTextDocument &doc, KDReports::Report &report )
{
QTextCursor cursor(&doc);
cursor.movePosition(QTextCursor::End);
QTemporaryFile tempFile;
if (!tempFile.open())
return false;
if (!report.exportToHtml(tempFile.fileName()))
return false;
cursor.insertHtml(QString::fromUtf8(tempFile.readAll()));
return true;
}
QPrinter::PageSize Base::pageSize() const
{
return m_printer->pageSize();
}
void Base::setPageSize(QPrinter::PageSize size)
{
m_printer->setPageSize(size);
}
QPrinter::Orientation Base::orientation() const
{
return m_printer->orientation();
}
void Base::setOrientation(QPrinter::Orientation orientation)
{
m_printer->setOrientation(orientation);
}
double Base::leftMargin() const
{
return leftmargin_;
}
void Base::setLeftMargin(double margin)
{
if ((margin > 0) && (margin < m_printer->paperRect().width() / 2))
leftmargin_ = margin;
else
leftmargin_ = 0;
}
double Base::rightMargin() const
{
return rightmargin_;
}
void Base::setRightMargin(double margin)
{
if ((margin > 0) && (margin < m_printer->paperRect().width() / 2))
rightmargin_ = margin;
else
rightmargin_ = 0;
}
double Base::topMargin() const
{
return topmargin_;
}
void Base::setTopMargin(double margin)
{
if ((margin > 0) && (margin < m_printer->paperRect().height() / 4))
topmargin_ = margin;
else
topmargin_ = 0;
}
double Base::bottomMargin() const
{
return bottommargin_;
}
void Base::setBottomMargin(double margin)
{
if ((margin > 0) && (margin < m_printer->paperRect().height() / 4))
bottommargin_ = margin;
else
bottommargin_ = 0;
}
void Base::setMargins(double margin)
{
if ((margin > 0)
&& (margin < m_printer->paperRect().height() / 2)
&& (margin < m_printer->paperRect().width() / 2))
leftmargin_ = rightmargin_ = topmargin_ = bottommargin_ = margin;
else
leftmargin_ = rightmargin_ = topmargin_ = bottommargin_ = 0;
}
double Base::spacing() const
{
return spacing_;
}
void Base::setSpacing(double spacing)
{
if ((spacing > 0) && (spacing <= m_printer->paperRect().height() / 8))
spacing_ = spacing;
else
spacing_ = 0;
}
double Base::headerSize() const
{
return headersize_;
}
void Base::setHeaderSize(double size)
{
if ((size > 0) && (size <= m_printer->paperRect().height() / 8))
headersize_ = size;
else
headersize_ = 0;
}
double Base::headerRule() const
{
return headerrule_;
}
void Base::setHeaderRule(double pointsize)
{
headerrule_ = qMax(0.0, pointsize);
}
const QString &Base::headerText() const
{
return headertext_;
}
void Base::setHeaderText(const QString &text)
{
headertext_ = text;
}
double Base::footerSize() const
{
return footersize_;
}
void Base::setFooterSize(double size)
{
if ((size > 0) && (size <= m_printer->paperRect().height() / 8))
footersize_ = size;
else
footersize_ = 0;
}
double Base::footerRule() const
{
return footerrule_;
}
void Base::setFooterRule(double pointsize)
{
footerrule_ = qMax(0.0, pointsize);
}
const QString &Base::footerText() const
{
return footertext_;
}
void Base::setFooterText(const QString &text)
{
footertext_ = text;
}
void Base:: setItemFontSize(int itemFontSize)
{
itemFontSize_ = itemFontSize;
}
QRectF Base::paperRect(QPaintDevice *device)
{
QRectF rect = m_printer->paperRect();
rect.setWidth(rect.width() *
device->logicalDpiX() / m_printer->logicalDpiX());
rect.setHeight(rect.height() *
device->logicalDpiY() / m_printer->logicalDpiY());
return rect;
}
QRectF Base::contentRect(QPaintDevice *device)
{
QRectF rect = paperRect(device);
rect.adjust(mmToInches(leftmargin_) * device->logicalDpiX(),
mmToInches(topmargin_) * device->logicalDpiY(),
-mmToInches(rightmargin_) * device->logicalDpiX(),
-mmToInches(bottommargin_) * device->logicalDpiY());
if (headersize_ > 0)
{
rect.adjust(0, mmToInches(headersize_) * device->logicalDpiY(), 0, 0);
rect.adjust(0, mmToInches(spacing_) * device->logicalDpiY(), 0, 0);
}
if (footersize_ > 0)
{
rect.adjust(0, 0, 0, -mmToInches(footersize_) * device->logicalDpiY());
rect.adjust(0, 0, 0, -mmToInches(spacing_) * device->logicalDpiY());
}
return rect;
}
QRectF Base::headerRect(QPaintDevice *device)
{
QRectF rect = paperRect(device);
rect.adjust(mmToInches(leftmargin_) * device->logicalDpiX(),
mmToInches(topmargin_) * device->logicalDpiY(),
-mmToInches(rightmargin_) * device->logicalDpiX(), 0);
rect.setBottom(rect.top() +
mmToInches(headersize_) * device->logicalDpiY());
return rect;
}
QRectF Base::footerRect(QPaintDevice *device)
{
QRectF rect = paperRect(device);
rect.adjust(mmToInches(leftmargin_) * device->logicalDpiX(), 0,
-mmToInches(rightmargin_) * device->logicalDpiX(),
-mmToInches(bottommargin_) * device->logicalDpiY());
rect.setTop(rect.bottom() -
mmToInches(footersize_) * device->logicalDpiY());
return rect;
}
void Base::print(QTextDocument *doc)
{
m_tempdoc = doc->clone();
print();
delete m_tempdoc;
m_tempdoc = nullptr;
}
void Base::printSinglePage(QTextDocument *doc)
{
m_tempdoc = doc->clone();
printSinglePage();
delete m_tempdoc;
m_tempdoc = nullptr;
}
void Base::printSinglePage()
{
if (!m_printer || !m_tempdoc) return;
m_tempdoc->setUseDesignMetrics(true);
m_tempdoc->documentLayout()->setPaintDevice(m_printer);
m_tempdoc->setPageSize(contentRect(m_printer).size());
QTextFrameFormat fmt = m_tempdoc->rootFrame()->frameFormat();
fmt.setMargin(0);
m_tempdoc->rootFrame()->setFrameFormat(fmt);
int doccopies;
int pagecopies;
if (m_printer->collateCopies())
{
doccopies = 1;
pagecopies = m_printer->numCopies();
}
else
{
doccopies = m_printer->numCopies();
pagecopies = 1;
}
int firstpage = m_printer->fromPage();
int lastpage = m_printer->toPage();
if (firstpage == 0 && lastpage == 0)
{
firstpage = 1;
lastpage = m_tempdoc->pageCount();
}
bool ascending = true;
if (m_printer->pageOrder() == QPrinter::LastPageFirst)
{
int tmp = firstpage;
firstpage = lastpage;
lastpage = tmp;
ascending = false;
}
m_painter->setRenderHints(QPainter::Antialiasing |
QPainter::TextAntialiasing |
QPainter::SmoothPixmapTransform, true);
for (int dc = 0; dc < doccopies; dc++)
{
int pagenum = firstpage;
while (true)
{
for (int pc = 0; pc < pagecopies; pc++)
{
if (m_printer->printerState() == QPrinter::Aborted ||
m_printer->printerState() == QPrinter::Error)
return;
paintPage( m_tempdoc, pagenum);
if (pc < pagecopies - 1)
m_printer->newPage();
}
if (pagenum == lastpage)
break;
if (ascending)
pagenum++;
else
pagenum--;
{
m_printer->newPage();
}
}
if (dc < doccopies - 1)
{
m_printer->newPage();
}
}
}
void Base::printDone()
{
m_painter->end();
m_currentPage = 1;
}
void Base::print()
{
m_currentPage = 1;
printSinglePage();
m_painter->end();
m_currentPage = 1;
}
void Base::paintPage(QTextDocument *document,
int pagenum)
{
QRectF rect;
double onepoint = m_painter->device()->logicalDpiY() / 72.0;
if (headersize_ > 0)
{
rect = headerRect(m_painter->device());
if (headerrule_ > 0.0)
{
m_painter->save();
m_painter->translate(0, onepoint + (headerrule_ * onepoint / 2.0));
m_painter->setPen(QPen(Qt::black, headerrule_ * onepoint));
m_painter->drawLine(rect.bottomLeft(), rect.bottomRight());
m_painter->restore();
}
QString header = headertext_;
QString title = document->metaInformation(QTextDocument::DocumentTitle).remove(QLatin1String("[*]"));
header.replace(QLatin1String("&exercise;"), currentExerciseName());
header.replace(QLatin1String("&title;"), title);
header.replace(QLatin1String("&logo;"), m_settings->logoProject());
header.replace(QLatin1String("&logoHeight;"), QString::number(ProjectIconHeight));
m_painter->save();
m_painter->translate(rect.left(), rect.top());
QRectF clip(0, 0, rect.width(), rect.height());
QTextDocument doc;
doc.setUseDesignMetrics(true);
doc.setHtml(header);
doc.documentLayout()->setPaintDevice(m_painter->device());
doc.setPageSize(rect.size());
double newtop = clip.bottom() - doc.size().height();
clip.setHeight(doc.size().height());
m_painter->translate(0, newtop);
doc.drawContents(m_painter, clip);
m_painter->restore();
}
if (footersize_ > 0)
{
rect = footerRect(m_painter->device());
if (footerrule_ > 0.0)
{
m_painter->save();
m_painter->translate(0, -onepoint + (-footerrule_ * onepoint / 2.0));
m_painter->setPen(QPen(Qt::black, footerrule_ * onepoint));
m_painter->drawLine(rect.topLeft(), rect.topRight());
m_painter->restore();
}
QString footer = footertext_;
footer.replace(QLatin1String("&date;"), QObject::tr("Printed on: ") + DTG::toString(QDateTime::currentDateTime()) );
footer.replace(QLatin1String("&user;"), operatorName());
footer.replace(QLatin1String("&footertitle;"), footertitle_);
footer.replace(QLatin1String("&page;"), QString::number(m_currentPage++));
m_painter->save();
m_painter->translate(rect.left(), rect.top());
QRectF clip(0, 0, rect.width(), rect.height());
QTextDocument doc;
doc.setUseDesignMetrics(true);
doc.setHtml(footer);
doc.documentLayout()->setPaintDevice(m_painter->device());
doc.setPageSize(rect.size());
doc.drawContents(m_painter, clip);
m_painter->restore();
}
m_painter->save();
rect = contentRect(m_painter->device());
m_painter->translate(rect.left(), rect.top() - (pagenum - 1) * rect.height());
QRectF clip(0, (pagenum - 1) * rect.height(), rect.width(), rect.height());
document->drawContents(m_painter, clip);
m_painter->restore();
}
void Base::setCurrentExerciseName( const QString& exerciseName )
{
m_exerciseName = exerciseName;
}
QString Base::currentExerciseName() const
{
return m_exerciseName;
}
void Base::setOperatorName( const QString& operatorName )
{
m_operatorName = operatorName;
}
QString Base::operatorName() const
{
return m_operatorName;
}
QSize Base::pageSizeInMM()
{
QRectF rect = contentRect(m_printer);
return rect.size().toSize();
}
}