18 #include <QAbstractTextDocumentLayout>
24 : m_usesTabPositions(false)
26 m_document.setUseDesignMetrics(
true);
30 ChartTextObject::registerChartTextObjectHandler(&m_document);
38 void KDReports::TextDocumentData::dumpTextValueCursors()
const
40 qDebug() <<
"Text value cursors: (document size=" << m_document.characterCount() <<
")";
41 QMultiMap<QString, TextValueData>::const_iterator it = m_textValueCursors.begin();
42 while (it != m_textValueCursors.end()) {
43 const TextValueData &data = *it;
44 if (data.cursor.isNull()) {
45 qDebug() << it.key() <<
"unresolved cursor at pos" << data.initialPosition;
47 qDebug() << it.key() <<
"QTextCursor currently at pos" << data.cursor.position() <<
"length" << data.valueLength;
55 resolveCursorPositions(mode);
58 void KDReports::TextDocumentData::resolveCursorPositions(ModificationMode mode)
64 auto it = m_textValueCursors.begin();
65 for (; it != m_textValueCursors.end(); ++it) {
66 TextValueData &data = *it;
67 if (data.cursor.isNull()) {
70 if (mode == Append && data.initialPosition >= m_document.characterCount() - 1) {
73 data.cursor = QTextCursor(&m_document);
74 data.cursor.setPosition(data.initialPosition);
85 val.valueLength = valueLength;
86 val.elementType = html ? ElementTypeHtml : ElementTypeText;
87 val.initialPosition = pos;
88 m_textValueCursors.insert(
id, val);
93 aboutToModifyContents(Modify);
97 QMultiMap<QString, TextValueData>::iterator it = m_textValueCursors.find(
id);
98 while (it != m_textValueCursors.end() && it.key() ==
id) {
99 TextValueData &data = *it;
102 QTextCursor c(data.cursor);
103 const int oldPos = data.cursor.position();
104 c.setPosition(oldPos + data.valueLength, QTextCursor::KeepAnchor);
105 const bool html = data.elementType == ElementTypeHtml;
107 c.insertHtml(newValue);
109 c.insertText(newValue);
111 data.valueLength = c.position() - oldPos;
112 data.cursor.setPosition(oldPos);
123 if (!m_hasResizableImages && !m_usesTabPositions) {
126 QTextCursor c(&m_document);
128 if (m_hasResizableImages) {
130 c.movePosition(QTextCursor::NextCharacter);
131 QTextCharFormat format = c.charFormat();
133 Q_ASSERT(format.isImageFormat());
134 QTextImageFormat imageFormat = format.toImageFormat();
135 updatePercentSize(imageFormat, size);
137 c.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor);
138 c.setCharFormat(imageFormat);
139 c.movePosition(QTextCursor::NextCharacter);
141 }
while (!c.atEnd());
144 if (m_usesTabPositions) {
145 QTextFrameFormat rootFrameFormat = m_document.rootFrame()->frameFormat();
146 const qreal rootFrameMargins = rootFrameFormat.leftMargin() + rootFrameFormat.rightMargin();
147 QTextBlock block = m_document.firstBlock();
149 QTextBlockFormat blockFormat = block.blockFormat();
152 if (!tabs.isEmpty()) {
153 for (QTextOption::Tab &tab : tabs) {
154 if (tab.delimiter == QLatin1Char(
'P') ) {
155 const auto availableWidth = size.width() - rootFrameMargins - block.blockFormat().leftMargin() - block.blockFormat().rightMargin();
156 if (tab.type == QTextOption::RightTab) {
158 tab.position = availableWidth;
159 }
else if (tab.type == QTextOption::CenterTab) {
160 tab.position = availableWidth / 2;
164 blockFormat.setTabPositions(tabs);
166 c.setPosition(block.position());
167 c.setBlockFormat(blockFormat);
169 block = block.next();
170 }
while (block.isValid());
177 if (w != m_document.textWidth()) {
179 m_document.setTextWidth(w);
180 updatePercentSizes(m_document.size());
186 if (size != m_document.pageSize()) {
188 m_document.setPageSize(size);
189 updatePercentSizes(size);
197 const qreal imageRatio = imageFormat.height() / imageFormat.width();
198 const qreal pageWidth = size.width();
199 const qreal pageHeight = size.height();
200 const qreal pageRatio = pageWidth ? pageHeight / pageWidth : 0;
201 if (prop[0] == QLatin1Char(
'T')) {
203 if (imageRatio < pageRatio) {
204 prop = QStringLiteral(
"W100");
206 prop = QStringLiteral(
"H100");
209 const qreal percent = prop.mid(1).toDouble();
210 switch (prop[0].toLatin1()) {
212 const qreal newWidth = pageWidth * percent / 100.0;
213 imageFormat.setWidth(newWidth);
214 imageFormat.setHeight(newWidth * imageRatio);
216 if (percent == 100.0)
217 imageFormat.setWidth(imageFormat.width() - 2);
220 imageFormat.setHeight(pageHeight * percent / 100.0);
224 if (percent == 100.0)
225 imageFormat.setHeight(imageFormat.height() - 10);
226 imageFormat.setWidth(imageRatio ? imageFormat.height() / imageRatio : 0);
230 qWarning(
"Unhandled image format property type - internal error");
236 m_tables.append(table);
241 QTextCursor cursor(&m_document);
242 qreal currentPointSize = -1.0;
243 QTextCursor lastCursor(&m_document);
246 qreal cursorFontPointSize = cursor.charFormat().fontPointSize();
248 if (cursorFontPointSize != currentPointSize) {
249 if (currentPointSize != -1.0) {
250 setFontSizeHelper(lastCursor, cursor.position() - 1, currentPointSize, factor);
251 lastCursor.setPosition(cursor.position() - 1, QTextCursor::MoveAnchor);
253 currentPointSize = cursorFontPointSize;
257 cursor.movePosition(QTextCursor::NextCharacter);
259 if (currentPointSize != -1.0) {
260 setFontSizeHelper(lastCursor, cursor.position(), currentPointSize, factor);
265 Q_FOREACH (QTextTable *table, m_tables) {
266 QTextTableFormat format = table->format();
267 format.setCellPadding(format.cellPadding() * factor);
269 QVector<QTextLength> constraints = format.columnWidthConstraints();
270 for (
int i = 0; i < constraints.size(); ++i) {
271 if (constraints[i].type() == QTextLength::FixedLength) {
272 constraints[i] = QTextLength(QTextLength::FixedLength, constraints[i].rawValue() * factor);
275 format.setColumnWidthConstraints(constraints);
277 table->setFormat(format);
281 void KDReports::TextDocumentData::setFontSizeHelper(QTextCursor &lastCursor,
int endPosition, qreal pointSize, qreal factor)
283 if (pointSize == 0) {
284 pointSize = m_document.defaultFont().pointSize();
287 QTextCharFormat newFormat;
288 newFormat.setFontPointSize(pointSize);
290 lastCursor.setPosition(endPosition, QTextCursor::KeepAnchor);
291 lastCursor.mergeCharFormat(newFormat);
297 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
298 QString htmlText = m_document.toHtml(
"utf-8");
300 QString htmlText = m_document.toHtml();
302 htmlText.remove(QLatin1String(
"margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; "));
303 htmlText.remove(QLatin1String(
"-qt-block-indent:0; "));
304 htmlText.remove(QLatin1String(
"text-indent:0px;"));
305 htmlText.remove(QLatin1String(
"style=\"\""));
306 htmlText.remove(QLatin1String(
"style=\" \""));
313 registerTable(table);
314 m_autoTables.insert(table, *element);
321 for (AutoTablesMaps::iterator it = m_autoTables.begin(); it != m_autoTables.end(); ++it)
322 lst.append(&it.value());
329 if (m_autoTables.isEmpty())
331 aboutToModifyContents(Modify);
332 QTextCursor(&m_document).beginEditBlock();
334 AutoTablesMaps autoTables = m_autoTables;
335 m_autoTables.clear();
336 AutoTablesMaps::const_iterator it = autoTables.constBegin();
337 for (; it != autoTables.constEnd(); ++it) {
338 QTextTable *table = it.key();
340 regenerateOneTable(tableElement, table);
343 QTextCursor(&m_document).endEditBlock();
348 aboutToModifyContents(Modify);
349 QTextCursor(&m_document).beginEditBlock();
350 AutoTablesMaps::iterator it = m_autoTables.begin();
351 for (; it != m_autoTables.end(); ++it) {
354 QTextTable *table = it.key();
355 m_autoTables.erase(it);
356 regenerateOneTable(tableElement, table);
360 QTextCursor(&m_document).endEditBlock();
366 QTextCursor cursor = table->firstCursorPosition();
367 cursor.beginEditBlock();
368 cursor.movePosition(QTextCursor::PreviousCharacter);
369 QTextCursor lastCurs = table->lastCursorPosition();
370 lastCurs.setPosition(lastCurs.position() + 1);
371 QTextBlockFormat blockFormat = lastCurs.blockFormat();
372 cursor.setPosition(table->lastCursorPosition().position() + 1, QTextCursor::KeepAnchor);
373 cursor.removeSelectedText();
374 cursor.setBlockFormat(QTextBlockFormat());
375 m_tables.removeAll(table);
377 ReportBuilder builder(*
this, cursor,
nullptr );
381 builder.setDefaultFont(font);
383 tableElement.
build(builder);
385 cursor.setBlockFormat(blockFormat);
386 cursor.endEditBlock();
391 Q_FOREACH (
const QString &name, m_resourceNames) {
392 const QVariant v = m_document.resource(QTextDocument::ImageResource, QUrl(name));
393 QPixmap pix = v.value<QPixmap>();
402 m_resourceNames.append(resourceName);
407 m_hasResizableImages =
true;
412 m_usesTabPositions = usesTabs;
QFont defaultFont(bool *isSet) const
QAbstractItemModel * tableModel() const
void build(ReportBuilder &) const override
static void registerHLineObjectHandler(QTextDocument *doc)
void setUsesTabPositions(bool usesTabs)
void regenerateAutoTables()
void addResourceName(const QString &resourceName)
void regenerateAutoTableForModel(QAbstractItemModel *model)
void updatePercentSizes(QSizeF size)
void aboutToModifyContents(ModificationMode mode)
void scaleFontsBy(qreal factor)
void layoutWithTextWidth(qreal w)
void registerTable(QTextTable *table)
static void updatePercentSize(QTextImageFormat &format, QSizeF size)
void registerAutoTable(QTextTable *table, const KDReports::AutoTableElement *element)
void saveResourcesToFiles()
void updateTextValue(const QString &id, const QString &newValue)
void setPageSize(QSizeF size)
void setHasResizableImages()
void setTextValueMarker(int pos, const QString &id, int valueLength, bool html)
QList< KDReports::AutoTableElement * > autoTableElements()
static const int ResizableImageProperty