#include "printing_base.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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 > &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("
") + QLatin1Char('<') + heading + QLatin1Char('>') + title + QLatin1String("') + QLatin1String("
"); } } 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("") + QLatin1String("") + QLatin1String("") + QLatin1String("") + QLatin1String(""); int columIdx = 0; for (const QModelIndex &mi :qAsConst(mil)) { if (columIdx >= nColums) { columIdx = 0; str += QLatin1String(""); } str += QLatin1String(""); ++columIdx; } str += QLatin1String("
"); printDecorationData(str, vm, mi, iconExtent / 2); QVariant vdata = vm->data(mi, Qt::DisplayRole); str += QLatin1String("
"); QString displayText; if (vdata.isValid()) displayText = vdata.toString(); else displayText = QLatin1Char(' '); str += QLatin1String("") + displayText + QLatin1String("") + QLatin1String("
"); } else { for (const QModelIndex &mi :qAsConst(mil)) { if (printItemData(str, vm, mi, iconExtent)) str += QLatin1String("
"); } } 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 &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(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("") + QLatin1String("") + QLatin1String(""); for (const QString &s : qAsConst(tableHeader)) str += QLatin1String(""); str += QLatin1String(""); QVector > spannedL; for (const QModelIndex &mi :qAsConst(mil)) { str += QLatin1String(""); 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(""); } str += QLatin1String("
") + s + QLatin1String("
"); DEBUG_LOG(m_logger) << qPrintable(str) ; return true; } void spanSizes(const QAbstractItemView *view, const QModelIndex &ms, int &rowSpanSize, int &columnSpanSize, QVector > &spannedL) { rowSpanSize = 1; columnSpanSize = 1; const QTableView *tview = qobject_cast(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().color().name(); htmlString += QLatin1String(" 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(""); str += htmlString; return true; } bool Base::printTreeData(QString &str, const QAbstractItemView *view, const QString &title, const QSet &suppressCols, int iconExtent, const QList &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("") + QLatin1String(""); 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(""); str += QLatin1String(""); for (const QModelIndex &miColumn0 : qAsConst(milColumn0)) printListPoint(str, view, vm, miColumn0, suppressCols, iconExtent); str += QLatin1String("

") + s + QLatin1String("



"); return true; } void Base::printListPoint(QString &str, const QAbstractItemView *view, const QAbstractItemModel *vm, const QModelIndex &miColumn0, const QSet &suppressCols, int iconExtent) { if (!miColumn0.isValid()) return; str += QLatin1String(""); 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("
"); if (column == 0) { int hierCount = hierarchyCount(ms); for (int genIdx = 0; genIdx < hierCount; ++genIdx) str += QLatin1String("
"); str += QLatin1String("
"); printItemData(str, vm, ms, iconExtent); str += QLatin1String("
"); for (int genIdx = 0; genIdx < hierCount; ++genIdx) str += QLatin1String("
"); } else { str += QLatin1String("
"); printItemData(str, vm, ms, iconExtent); str += QLatin1String("
"); } str += QLatin1String("
"); } str += QLatin1String(""); const QTreeView *tv = qobject_cast(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(""); if (static_cast(vdata.toInt())) displayString += QLatin1String("⊗ "); else displayString += QLatin1String("ο "); displayString += QLatin1String(""); } 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().name(); vdata = model->data(mi, Qt::ForegroundRole); if (vdata.isValid()) fgColorString = vdata.value().color().name(); htmlString += QLatin1String("') + displayString + QLatin1String(""); 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(); if (icon.isNull()) return; QString fn = iconFilename(m_iconFilenameNr++); QPixmap pm = icon.pixmap(1000); pm.save(fn); str += QLatin1String("\"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(); } }