24 #include <QAbstractTextDocumentLayout>
26 #include <QTextDocument>
31 : m_usesTabPositions(false)
33 m_document =
new QTextDocument;
34 m_document->setUseDesignMetrics(
true);
38 ChartTextObject::registerChartTextObjectHandler(m_document);
47 void KDReports::TextDocumentData::dumpTextValueCursors()
const
49 qDebug() <<
"Text value cursors: (document size=" << m_document->characterCount() <<
")";
50 QMultiMap<QString, TextValueData>::const_iterator it = m_textValueCursors.begin();
51 while (it != m_textValueCursors.end()) {
52 const TextValueData &data = *it;
53 if (data.cursor.isNull()) {
54 qDebug() << it.key() <<
"unresolved cursor at pos" << data.initialPosition;
56 qDebug() << it.key() <<
"QTextCursor currently at pos" << data.cursor.position() <<
"length" << data.valueLength;
64 resolveCursorPositions(mode);
67 void KDReports::TextDocumentData::resolveCursorPositions(ModificationMode mode)
73 auto it = m_textValueCursors.begin();
74 for (; it != m_textValueCursors.end(); ++it) {
75 TextValueData &data = *it;
76 if (data.cursor.isNull()) {
79 if (mode == Append && data.initialPosition >= m_document->characterCount() - 1) {
82 data.cursor = QTextCursor(m_document);
83 data.cursor.setPosition(data.initialPosition);
94 val.valueLength = valueLength;
95 val.elementType = html ? ElementTypeHtml : ElementTypeText;
96 val.initialPosition = pos;
97 m_textValueCursors.insert(
id, val);
102 aboutToModifyContents(Modify);
106 QMultiMap<QString, TextValueData>::iterator it = m_textValueCursors.find(
id);
107 while (it != m_textValueCursors.end() && it.key() ==
id) {
108 TextValueData &data = *it;
111 QTextCursor c(data.cursor);
112 const int oldPos = data.cursor.position();
113 c.setPosition(oldPos + data.valueLength, QTextCursor::KeepAnchor);
114 const bool html = data.elementType == ElementTypeHtml;
116 c.insertHtml(newValue);
118 c.insertText(newValue);
120 data.valueLength = c.position() - oldPos;
121 data.cursor.setPosition(oldPos);
132 if (!m_hasResizableImages && !m_usesTabPositions) {
135 QTextCursor c(m_document);
137 if (m_hasResizableImages) {
139 c.movePosition(QTextCursor::NextCharacter);
140 QTextCharFormat format = c.charFormat();
142 Q_ASSERT(format.isImageFormat());
143 QTextImageFormat imageFormat = format.toImageFormat();
144 updatePercentSize(imageFormat, size);
146 c.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor);
147 c.setCharFormat(imageFormat);
148 c.movePosition(QTextCursor::NextCharacter);
150 }
while (!c.atEnd());
153 if (m_usesTabPositions) {
154 QTextFrameFormat rootFrameFormat = m_document->rootFrame()->frameFormat();
155 const qreal rootFrameMargins = rootFrameFormat.leftMargin() + rootFrameFormat.rightMargin();
156 QTextBlock block = m_document->firstBlock();
158 QTextBlockFormat blockFormat = block.blockFormat();
161 if (!tabs.isEmpty()) {
162 for (
int i = 0; i < tabs.count(); ++i) {
163 QTextOption::Tab &tab = tabs[i];
164 if (tab.delimiter == QLatin1Char(
'P') ) {
165 if (tab.type == QTextOption::RightTab) {
167 tab.position = size.width() - rootFrameMargins;
168 }
else if (tab.type == QTextOption::CenterTab) {
169 tab.position = (size.width() - rootFrameMargins) / 2;
173 blockFormat.setTabPositions(tabs);
175 c.setPosition(block.position());
176 c.setBlockFormat(blockFormat);
178 block = block.next();
179 }
while (block.isValid());
186 if (w != m_document->textWidth()) {
188 m_document->setTextWidth(w);
189 updatePercentSizes(m_document->size());
195 if (size != m_document->pageSize()) {
197 m_document->setPageSize(size);
198 updatePercentSizes(size);
206 const qreal imageRatio = imageFormat.height() / imageFormat.width();
207 const qreal pageWidth = size.width();
208 const qreal pageHeight = size.height();
209 const qreal pageRatio = pageWidth ? pageHeight / pageWidth : 0;
210 if (prop[0] == QLatin1Char(
'T')) {
212 if (imageRatio < pageRatio) {
213 prop = QStringLiteral(
"W100");
215 prop = QStringLiteral(
"H100");
218 const qreal percent = prop.mid(1).toDouble();
219 switch (prop[0].toLatin1()) {
221 const qreal newWidth = pageWidth * percent / 100.0;
222 imageFormat.setWidth(newWidth);
223 imageFormat.setHeight(newWidth * imageRatio);
225 if (percent == 100.0)
226 imageFormat.setWidth(imageFormat.width() - 2);
229 imageFormat.setHeight(pageHeight * percent / 100.0);
233 if (percent == 100.0)
234 imageFormat.setHeight(imageFormat.height() - 10);
235 imageFormat.setWidth(imageRatio ? imageFormat.height() / imageRatio : 0);
239 qWarning(
"Unhandled image format property type - internal error");
245 m_tables.append(table);
250 QTextCursor cursor(m_document);
251 qreal currentPointSize = -1.0;
252 QTextCursor lastCursor(m_document);
254 qreal cursorFontPointSize = cursor.charFormat().fontPointSize();
256 if (cursorFontPointSize != currentPointSize) {
257 if (currentPointSize != -1.0) {
258 setFontSizeHelper(lastCursor, cursor.position() - 1, currentPointSize, factor);
259 lastCursor.setPosition(cursor.position() - 1, QTextCursor::MoveAnchor);
261 currentPointSize = cursorFontPointSize;
265 cursor.movePosition(QTextCursor::NextCharacter);
267 if (currentPointSize != -1.0) {
268 setFontSizeHelper(lastCursor, cursor.position(), currentPointSize, factor);
273 Q_FOREACH (QTextTable *table, m_tables) {
274 QTextTableFormat format = table->format();
275 format.setCellPadding(format.cellPadding() * factor);
277 QVector<QTextLength> constraints = format.columnWidthConstraints();
278 for (
int i = 0; i < constraints.size(); ++i) {
279 if (constraints[i].type() == QTextLength::FixedLength) {
280 constraints[i] = QTextLength(QTextLength::FixedLength, constraints[i].rawValue() * factor);
283 format.setColumnWidthConstraints(constraints);
285 table->setFormat(format);
289 void KDReports::TextDocumentData::setFontSizeHelper(QTextCursor &lastCursor,
int endPosition, qreal pointSize, qreal factor)
291 if (pointSize == 0) {
292 pointSize = m_document->defaultFont().pointSize();
295 QTextCharFormat newFormat;
296 newFormat.setFontPointSize(pointSize);
298 lastCursor.setPosition(endPosition, QTextCursor::KeepAnchor);
299 lastCursor.mergeCharFormat(newFormat);
305 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
306 QString htmlText = m_document->toHtml(
"utf-8");
308 QString htmlText = m_document->toHtml();
310 htmlText.remove(QLatin1String(
"margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; "));
311 htmlText.remove(QLatin1String(
"-qt-block-indent:0; "));
312 htmlText.remove(QLatin1String(
"text-indent:0px;"));
313 htmlText.remove(QLatin1String(
"style=\"\""));
314 htmlText.remove(QLatin1String(
"style=\" \""));
321 registerTable(table);
322 m_autoTables.insert(table, *element);
329 for (AutoTablesMaps::iterator it = m_autoTables.begin(); it != m_autoTables.end(); ++it)
330 lst.append(&it.value());
337 if (m_autoTables.isEmpty())
339 aboutToModifyContents(Modify);
340 QTextCursor(m_document).beginEditBlock();
342 AutoTablesMaps autoTables = m_autoTables;
343 m_autoTables.clear();
344 AutoTablesMaps::const_iterator it = autoTables.constBegin();
345 for (; it != autoTables.constEnd(); ++it) {
346 QTextTable *table = it.key();
348 regenerateOneTable(tableElement, table);
351 QTextCursor(m_document).endEditBlock();
356 aboutToModifyContents(Modify);
357 QTextCursor(m_document).beginEditBlock();
358 AutoTablesMaps::iterator it = m_autoTables.begin();
359 for (; it != m_autoTables.end(); ++it) {
362 QTextTable *table = it.key();
363 m_autoTables.erase(it);
364 regenerateOneTable(tableElement, table);
368 QTextCursor(m_document).endEditBlock();
374 QTextCursor cursor = table->firstCursorPosition();
375 cursor.beginEditBlock();
376 cursor.movePosition(QTextCursor::PreviousCharacter);
377 QTextCursor lastCurs = table->lastCursorPosition();
378 lastCurs.setPosition(lastCurs.position() + 1);
379 QTextBlockFormat blockFormat = lastCurs.blockFormat();
380 cursor.setPosition(table->lastCursorPosition().position() + 1, QTextCursor::KeepAnchor);
381 cursor.removeSelectedText();
382 cursor.setBlockFormat(QTextBlockFormat());
383 m_tables.removeAll(table);
385 ReportBuilder builder(*
this, cursor,
nullptr );
389 builder.setDefaultFont(font);
391 tableElement.
build(builder);
393 cursor.setBlockFormat(blockFormat);
394 cursor.endEditBlock();
399 Q_FOREACH (
const QString &name, m_resourceNames) {
400 const QVariant v = m_document->resource(QTextDocument::ImageResource, QUrl(name));
401 QPixmap pix = v.value<QPixmap>();
410 m_resourceNames.append(resourceName);
415 m_hasResizableImages =
true;
420 m_usesTabPositions = usesTabs;