diff options
-rw-r--r-- | src/quick/items/qquicktextedit.cpp | 74 | ||||
-rw-r--r-- | src/quick/items/qquicktextedit_p_p.h | 14 |
2 files changed, 46 insertions, 42 deletions
diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp index 8f3a8998f5..f8363b1e5a 100644 --- a/src/quick/items/qquicktextedit.cpp +++ b/src/quick/items/qquicktextedit.cpp @@ -1968,12 +1968,11 @@ void QQuickTextEdit::triggerPreprocess() } typedef QQuickTextEditPrivate::Node TextNode; -typedef QList<TextNode*>::iterator TextNodeIterator; +using TextNodeIterator = QQuickTextEditPrivate::TextNodeIterator; - -static bool comesBefore(TextNode* n1, TextNode* n2) +static inline bool operator<(const TextNode &n1, const TextNode &n2) { - return n1->startPos() < n2->startPos(); + return n1.startPos() < n2.startPos(); } static inline void updateNodeTransform(QQuickTextNode* node, const QPointF &topLeft) @@ -2026,13 +2025,12 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData * if (!oldNode) { // If we had any QQuickTextNode node references, they were deleted along with the root node // But here we must delete the Node structures in textNodeMap - qDeleteAll(d->textNodeMap); d->textNodeMap.clear(); } RootNode *rootNode = static_cast<RootNode *>(oldNode); TextNodeIterator nodeIterator = d->textNodeMap.begin(); - while (nodeIterator != d->textNodeMap.end() && !(*nodeIterator)->dirty()) + while (nodeIterator != d->textNodeMap.end() && !nodeIterator->dirty()) ++nodeIterator; QQuickTextNodeEngine engine; @@ -2045,13 +2043,12 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData * int firstDirtyPos = 0; if (nodeIterator != d->textNodeMap.end()) { - firstDirtyPos = (*nodeIterator)->startPos(); + firstDirtyPos = nodeIterator->startPos(); do { - rootNode->removeChildNode((*nodeIterator)->textNode()); - delete (*nodeIterator)->textNode(); - delete *nodeIterator; + rootNode->removeChildNode(nodeIterator->textNode()); + delete nodeIterator->textNode(); nodeIterator = d->textNodeMap.erase(nodeIterator); - } while (nodeIterator != d->textNodeMap.end() && (*nodeIterator)->dirty()); + } while (nodeIterator != d->textNodeMap.end() && nodeIterator->dirty()); } // FIXME: the text decorations could probably be handled separately (only updated for affected textFrames) @@ -2068,7 +2065,8 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData * rootNode->setMatrix(basePositionMatrix); QPointF nodeOffset; - TextNode *firstCleanNode = (nodeIterator != d->textNodeMap.end()) ? *nodeIterator : 0; + const TextNode firstCleanNode = (nodeIterator != d->textNodeMap.end()) ? *nodeIterator + : TextNode(); QList<QTextFrame *> frames; frames.append(d->document->rootFrame()); @@ -2078,7 +2076,8 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData * frames.append(textFrame->childFrames()); frameDecorationsEngine.addFrameDecorations(d->document, textFrame); - if (textFrame->lastPosition() < firstDirtyPos || (firstCleanNode && textFrame->firstPosition() >= firstCleanNode->startPos())) + if (textFrame->lastPosition() < firstDirtyPos + || textFrame->firstPosition() >= firstCleanNode.startPos()) continue; node = d->createTextNode(); resetEngine(&engine, d->color, d->selectedTextColor, d->selectionColor); @@ -2118,8 +2117,8 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData * engine.addTextBlock(d->document, block, -nodeOffset, d->color, QColor(), selectionStart(), selectionEnd() - 1); currentNodeSize += block.length(); - if ((it.atEnd()) || (firstCleanNode && block.next().position() >= firstCleanNode->startPos())) // last node that needed replacing or last block of the frame - break; + if ((it.atEnd()) || block.next().position() >= firstCleanNode.startPos()) + break; // last node that needed replacing or last block of the frame QList<int>::const_iterator lowerBound = std::lower_bound(frameBoundaries.constBegin(), frameBoundaries.constEnd(), block.next().position()); if (currentNodeSize > nodeBreakingSize || lowerBound == frameBoundaries.constEnd() || *lowerBound > nodeStart) { @@ -2137,16 +2136,19 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData * // Now prepend the frame decorations since we want them rendered first, with the text nodes and cursor in front. rootNode->prependChildNode(rootNode->frameDecorationsNode); - Q_ASSERT(nodeIterator == d->textNodeMap.end() || (*nodeIterator) == firstCleanNode); + Q_ASSERT(nodeIterator == d->textNodeMap.end() + || (nodeIterator->textNode() == firstCleanNode.textNode() + && nodeIterator->startPos() == firstCleanNode.startPos())); // Update the position of the subsequent text blocks. - if (firstCleanNode) { - QPointF oldOffset = firstCleanNode->textNode()->matrix().map(QPointF(0,0)); - QPointF currentOffset = d->document->documentLayout()->blockBoundingRect(d->document->findBlock(firstCleanNode->startPos())).topLeft(); + if (firstCleanNode.textNode() != nullptr) { + QPointF oldOffset = firstCleanNode.textNode()->matrix().map(QPointF(0,0)); + QPointF currentOffset = d->document->documentLayout()->blockBoundingRect( + d->document->findBlock(firstCleanNode.startPos())).topLeft(); QPointF delta = currentOffset - oldOffset; while (nodeIterator != d->textNodeMap.end()) { - QMatrix4x4 transformMatrix = (*nodeIterator)->textNode()->matrix(); + QMatrix4x4 transformMatrix = nodeIterator->textNode()->matrix(); transformMatrix.translate(delta.x(), delta.y()); - (*nodeIterator)->textNode()->setMatrix(transformMatrix); + nodeIterator->textNode()->setMatrix(transformMatrix); ++nodeIterator; } @@ -2154,7 +2156,7 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData * // Since we iterate over blocks from different text frames that are potentially not sorted // we need to ensure that our list of nodes is sorted again: - std::sort(d->textNodeMap.begin(), d->textNodeMap.end(), &comesBefore); + std::sort(d->textNodeMap.begin(), d->textNodeMap.end()); } if (d->cursorComponent == 0) { @@ -2333,22 +2335,26 @@ void QQuickTextEdit::markDirtyNodesForRange(int start, int end, int charDelta) if (start == end) return; - TextNode dummyNode(start, 0); - TextNodeIterator it = std::lower_bound(d->textNodeMap.begin(), d->textNodeMap.end(), &dummyNode, &comesBefore); + TextNode dummyNode(start); + + const TextNodeIterator textNodeMapBegin = d->textNodeMap.begin(); + const TextNodeIterator textNodeMapEnd = d->textNodeMap.end(); + + TextNodeIterator it = std::lower_bound(textNodeMapBegin, textNodeMapEnd, dummyNode); // qLowerBound gives us the first node past the start of the affected portion, rewind to the first node // that starts at the last position before the edit position. (there might be several because of images) - if (it != d->textNodeMap.begin()) { + if (it != textNodeMapBegin) { --it; - TextNode otherDummy((*it)->startPos(), 0); - it = std::lower_bound(d->textNodeMap.begin(), d->textNodeMap.end(), &otherDummy, &comesBefore); + TextNode otherDummy(it->startPos()); + it = std::lower_bound(textNodeMapBegin, textNodeMapEnd, otherDummy); } // mark the affected nodes as dirty - while (it != d->textNodeMap.end()) { - if ((*it)->startPos() <= end) - (*it)->setDirty(); + while (it != textNodeMapEnd) { + if (it->startPos() <= end) + it->setDirty(); else if (charDelta) - (*it)->moveStartPos(charDelta); + it->moveStartPos(charDelta); else return; ++it; @@ -2533,8 +2539,8 @@ void QQuickTextEdit::updateWholeDocument() { Q_D(QQuickTextEdit); if (!d->textNodeMap.isEmpty()) { - for (TextNode* node : qAsConst(d->textNodeMap)) - node->setDirty(); + for (TextNode &node : d->textNodeMap) + node.setDirty(); } polish(); @@ -2678,7 +2684,7 @@ void QQuickTextEditPrivate::handleFocusEvent(QFocusEvent *event) void QQuickTextEditPrivate::addCurrentTextNodeToRoot(QQuickTextNodeEngine *engine, QSGTransformNode *root, QQuickTextNode *node, TextNodeIterator &it, int startPos) { engine->addToSceneGraph(node, QQuickText::Normal, QColor()); - it = textNodeMap.insert(it, new TextNode(startPos, node)); + it = textNodeMap.insert(it, TextNode(startPos, node)); ++it; root->appendChildNode(node); } diff --git a/src/quick/items/qquicktextedit_p_p.h b/src/quick/items/qquicktextedit_p_p.h index 09718cb49a..ef2bdfd0ea 100644 --- a/src/quick/items/qquicktextedit_p_p.h +++ b/src/quick/items/qquicktextedit_p_p.h @@ -59,6 +59,8 @@ #include <QtCore/qlist.h> #include <private/qlazilyallocated_p.h> +#include <limits> + QT_BEGIN_NAMESPACE class QTextLayout; class QQuickTextDocumentWithImageResources; @@ -74,7 +76,8 @@ public: typedef QQuickTextEdit Public; struct Node { - explicit Node(int startPos, QQuickTextNode* node) + explicit Node(int startPos = std::numeric_limits<int>::max(), + QQuickTextNode *node = nullptr) : m_startPos(startPos), m_node(node), m_dirty(false) { } QQuickTextNode* textNode() const { return m_node; } void moveStartPos(int delta) { Q_ASSERT(m_startPos + delta > 0); m_startPos += delta; } @@ -87,7 +90,7 @@ public: QQuickTextNode* m_node; bool m_dirty; }; - typedef QList<Node*>::iterator TextNodeIterator; + typedef QList<Node>::iterator TextNodeIterator; struct ExtraData { ExtraData(); @@ -128,11 +131,6 @@ public: { } - ~QQuickTextEditPrivate() - { - qDeleteAll(textNodeMap); - } - static QQuickTextEditPrivate *get(QQuickTextEdit *item) { return static_cast<QQuickTextEditPrivate *>(QObjectPrivate::get(item)); } @@ -186,7 +184,7 @@ public: QQuickTextDocumentWithImageResources *document; QQuickTextControl *control; QQuickTextDocument *quickDocument; - QList<Node*> textNodeMap; + QList<Node> textNodeMap; int lastSelectionStart; int lastSelectionEnd; |