1306 lines
30 KiB
C++
Executable File
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("⊗ ");
|
|
else
|
|
displayString += QLatin1String("ο ");
|
|
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();
|
|
}
|
|
}
|