void KTextDocumentLayout::Private::adjustSize() { if (parent->resizeMethod() == KTextDocument::NoResize) return; if (parent->shapes().isEmpty()) return; // Limit auto-resizing to the first shape only (there won't be more // with auto-resizing turned on, unless specifically set) KShape *shape = parent->shapes().first(); // Determine the maximum width of all text lines qreal width = 0; for (QTextBlock block = parent->document()->begin(); block.isValid(); block = block.next()) { // The block layout's wrap mode must be QTextOption::NoWrap, thus the line count // of a valid block must be 1 (otherwise this resizing scheme wouldn't work) Q_ASSERT(block.layout()->lineCount() == 1); QTextLine line = block.layout()->lineAt(0); width = qMax(width, line.naturalTextWidth()); } // Use position and height of last text line to calculate height QTextLine line = parent->document()->lastBlock().layout()->lineAt(0); qreal height = line.position().y() + line.height(); shape->setSize(QSizeF(width, height)); }
static void calculateBoundingRect( QTextDocument *document, int startPosition, int endPosition, QRectF &rect ) { const QTextBlock startBlock = document->findBlock( startPosition ); const QRectF startBoundingRect = document->documentLayout()->blockBoundingRect( startBlock ); const QTextBlock endBlock = document->findBlock( endPosition ); const QRectF endBoundingRect = document->documentLayout()->blockBoundingRect( endBlock ); QTextLayout *startLayout = startBlock.layout(); QTextLayout *endLayout = endBlock.layout(); int startPos = startPosition - startBlock.position(); int endPos = endPosition - endBlock.position(); const QTextLine startLine = startLayout->lineForTextPosition( startPos ); const QTextLine endLine = endLayout->lineForTextPosition( endPos ); double x = startBoundingRect.x() + startLine.cursorToX( startPos ); double y = startBoundingRect.y() + startLine.y(); double r = endBoundingRect.x() + endLine.cursorToX( endPos ); double b = endBoundingRect.y() + endLine.y() + endLine.height(); const QSizeF size = document->size(); rect = QRectF( x / size.width(), y / size.height(), (r - x) / size.width(), (b - y) / size.height() ); }
void TestDocumentLayout::testCenteredItems() { initForNewTest("ListItem\nListItem\nListItem"); KoListStyle listStyle; KoListLevelProperties llp; llp.setStyle(KoListStyle::DecimalItem); listStyle.setLevelProperties(llp); QTextBlock block = m_doc->begin(); // normal block QVERIFY(block.isValid()); listStyle.applyStyle(block); block = block.next(); // centered block QVERIFY(block.isValid()); listStyle.applyStyle(block); QTextBlockFormat fmt; fmt.setAlignment(Qt::AlignHCenter); QTextCursor cursor(block); cursor.mergeBlockFormat(fmt); block = block.next(); // centered RTL text. listStyle.applyStyle(block); cursor = QTextCursor(block); fmt.setProperty(KoParagraphStyle::TextProgressionDirection, KoText::RightLeftTopBottom); cursor.mergeBlockFormat(fmt); m_layout->layout(); block = m_doc->begin(); QTextLayout *layout = block.layout(); QTextLine line1 = layout->lineAt(0); KoTextBlockData *data1 = dynamic_cast<KoTextBlockData *>(block.userData()); QVERIFY(line1.isValid()); QVERIFY(line1.width() < 200); // the counter takes some space. block = block.next(); layout = block.layout(); QTextLine line2 = layout->lineAt(0); KoTextBlockData *data2 = dynamic_cast<KoTextBlockData *>(block.userData()); QVERIFY(line2.isValid()); QVERIFY(line2.width() < 200); // the counter takes some space. QCOMPARE(line1.width(), line2.width()); const qreal width1 = line1.naturalTextWidth() + data1->counterWidth() + data1->counterSpacing(); const qreal width2 = line2.naturalTextWidth() + data2->counterWidth() + data2->counterSpacing(); QCOMPARE(width1, width2); QVERIFY(data1->counterPosition().x() < data2->counterPosition().x()); const qreal padding = (200 - width2) / 2; QVERIFY(padding > 0);// not really a layout test, but the rest will be bogus otherwise. QCOMPARE(data2->counterPosition().x(), padding); // close to the centered text. // right to left parag places the counter on the right. Its centered, so not the far right. block = block.next(); layout = block.layout(); QTextLine line = layout->lineAt(0); KoTextBlockData *data = dynamic_cast<KoTextBlockData *>(block.userData()); QCOMPARE(data->counterPosition().x(), 200 - padding - data->counterWidth()); }
void KPrAttributeHeight::updateCache(KPrAnimationCache *cache, KPrShapeAnimation *shapeAnimation, qreal value) { qreal tx = 0.0, ty = 0.0; KoShape * shape = shapeAnimation->shape(); KoTextBlockData * textBlockData = shapeAnimation->textBlockData(); QTransform transform; if (textBlockData) { if (KoTextShapeData *textShapeData = dynamic_cast<KoTextShapeData*>(shape->userData())) { QTextDocument *textDocument = textShapeData->document(); for (int i = 0; i < textDocument->blockCount(); i++) { QTextBlock textBlock = textDocument->findBlockByNumber(i); if (textBlock.userData() == textBlockData) { QTextLayout *layout = textBlock.layout(); value = value * cache->pageSize().height() / layout->boundingRect().height(); tx = layout->minimumWidth() * cache->zoom() / 2; ty = layout->boundingRect().height() * cache->zoom() / 2; } } } } else { value = value * cache->pageSize().height() / shape->size().height(); tx = shape->size().width() * cache->zoom() / 2; ty = shape->size().height() * cache->zoom() / 2; } transform.translate(tx, ty).scale(1, value).translate(-tx, -ty); cache->update(shape, shapeAnimation->textBlockData(), "transform", transform); }
void tst_QTextFormat::testTabsUsed() { QTextDocument doc; QTextCursor cursor(&doc); QList<QTextOption::Tab> tabs; QTextBlockFormat format; QTextOption::Tab tab; tab.position = 100; tabs.append(tab); format.setTabPositions(tabs); cursor.mergeBlockFormat(format); cursor.insertText("foo\tbar"); //doc.setPageSize(QSizeF(200, 200)); doc.documentLayout()->pageCount(); // force layout; QTextBlock block = doc.begin(); QTextLayout *layout = block.layout(); QVERIFY(layout); QCOMPARE(layout->lineCount(), 1); QTextLine line = layout->lineAt(0); QCOMPARE(line.cursorToX(4), 100.); QTextOption option = layout->textOption(); QCOMPARE(option.tabs().count(), tabs.count()); }
void TestDocumentLayout::testRightToLeftList() { initForNewTest("a\nb\nc"); KoParagraphStyle h1; h1.setTextProgressionDirection(KoText::RightLeftTopBottom); m_styleManager->add(&h1); KoListStyle listStyle; KoListLevelProperties llp = listStyle.levelProperties(1); llp.setStyle(KoListStyle::DecimalItem); listStyle.setLevelProperties(llp); h1.setListStyle(&listStyle); QTextBlock block = m_doc->begin(); h1.applyStyle(block); block = block.next(); h1.applyStyle(block); block = block.next(); h1.applyStyle(block); block = block.next(); m_layout->layout(); block = m_doc->begin(); while (block.isValid()) { KoTextBlockData *data = dynamic_cast<KoTextBlockData *>(block.userData()); QVERIFY(data); QVERIFY(data->counterWidth() > 2); QVERIFY(data->counterPosition().x() > 100); QTextLine line = block.layout()->lineAt(0); QVERIFY(line.isValid()); QCOMPARE(line.x(), (qreal)0); QCOMPARE(line.width() + data->counterWidth() + data->counterSpacing(), (qreal)200); block = block.next(); } }
void TestDocumentLayout::initForNewTest(const QString &initText) { // this leaks memory like mad, but who cares ;) frameSet = new KWTextFrameSet(0); shape1 = new MockTextShape(); shape1->setSize(QSizeF(200, 1000)); new KWTextFrame(shape1, frameSet); doc = frameSet->document(); Q_ASSERT(doc); layout = dynamic_cast<KWTextDocumentLayout*>(doc->documentLayout()); Q_ASSERT(layout); styleManager = new KStyleManager(); KTextDocument(doc).setStyleManager(styleManager); QTextBlock block = doc->begin(); if (initText.length() > 0) { QTextCursor cursor(doc); cursor.insertText(initText); KParagraphStyle style; style.setStyleId(101); // needed to do manually since we don't use the stylemanager QTextBlock b2 = doc->begin(); while (b2.isValid()) { style.applyStyle(b2); b2 = b2.next(); } } blockLayout = block.layout(); }
void TextDocumentModel::fillBlock(const QTextBlock &block, QStandardItem *parent) { for (auto it = block.begin(); it != block.end(); ++it) { QStandardItem *item = new QStandardItem(tr("Fragment: %1").arg(it.fragment().text())); const QRectF b = m_document->documentLayout()->blockBoundingRect(block); appendRow(parent, item, it.fragment().charFormat(), b); if (!block.layout()) continue; #if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) foreach (const auto &range, block.layout()->formats()) { const auto start = std::max(range.start, it.fragment().position() - block.position()); const auto end = std::min(range.start + range.length, it.fragment().position() + it.fragment().length() - block.position()); if (start >= end) continue; auto child = new QStandardItem(tr("Layout Range: %1").arg(it.fragment().text().mid(start, end -start))); appendRow(item, child, range.format, QRectF()); } #endif } }
void KPrAttributeHeight::initCache(KPrAnimationCache *animationCache, int step, KPrShapeAnimation * shapeAnimation, qreal startValue, qreal endValue) { qreal v1 = 0.0, v2 = 0.0, tx = 0.0, ty = 0.0; KoShape * shape = shapeAnimation->shape(); KoTextBlockData * textBlockData = shapeAnimation->textBlockData(); if (textBlockData) { if (KoTextShapeData *textShapeData = dynamic_cast<KoTextShapeData*>(shape->userData())) { QTextDocument *textDocument = textShapeData->document(); for (int i = 0; i < textDocument->blockCount(); i++) { QTextBlock textBlock = textDocument->findBlockByNumber(i); if (textBlock.userData() == textBlockData) { QTextLayout *layout = textBlock.layout(); v1 = startValue * animationCache->pageSize().height() / layout->boundingRect().height(); v2 = endValue * animationCache->pageSize().height() / layout->boundingRect().height(); tx = layout->minimumWidth() * animationCache->zoom() / 2; ty = layout->boundingRect().height() * animationCache->zoom() / 2; } } } } else { v1 = startValue * animationCache->pageSize().height() / shape->size().height(); v2 = endValue * animationCache->pageSize().height() / shape->size().height(); tx = shape->size().width() * animationCache->zoom() / 2; ty = shape->size().height() * animationCache->zoom() / 2; } animationCache->init(step, shape, textBlockData, "transform", QTransform().translate(tx, ty).scale(1, v1).translate(-tx, -ty)); animationCache->init(step + 1, shape, textBlockData, "transform", QTransform().translate(tx, ty).scale(1, v2).translate(-tx, -ty)); }
void CodeHighlighter::updateFormatting(QTextDocument* _document, CodeHighlighterSettings const& _settings) { QTextBlock block = _document->firstBlock(); QList<QTextLayout::FormatRange> ranges; Formats::const_iterator format = m_formats.begin(); while (true) { while ((format == m_formats.end() || (block.position() + block.length() <= format->start)) && block.isValid()) { auto layout = block.layout(); layout->clearAdditionalFormats(); layout->setAdditionalFormats(ranges); _document->markContentsDirty(block.position(), block.length()); block = block.next(); ranges.clear(); } if (!block.isValid()) break; int intersectionStart = std::max(format->start, block.position()); int intersectionLength = std::min(format->start + format->length, block.position() + block.length()) - intersectionStart; if (intersectionLength > 0) { QTextLayout::FormatRange range; range.format = _settings.formats[format->token]; range.start = format->start - block.position(); range.length = format->length; ranges.append(range); } ++format; } }
/*! \fn QString QAbstractTextDocumentLayout::anchorAt(const QPointF &position) const Returns the reference of the anchor the given \a position, or an empty string if no anchor exists at that point. */ QString QAbstractTextDocumentLayout::anchorAt(const QPointF& pos) const { int cursorPos = hitTest(pos, Qt::ExactHit); if (cursorPos == -1) return QString(); // compensate for preedit in the hit text block QTextBlock block = document()->firstBlock(); while (block.isValid()) { QRectF blockBr = blockBoundingRect(block); if (blockBr.contains(pos)) { QTextLayout *layout = block.layout(); int relativeCursorPos = cursorPos - block.position(); const int preeditLength = layout ? layout->preeditAreaText().length() : 0; if (preeditLength > 0 && relativeCursorPos > layout->preeditAreaPosition()) cursorPos -= qMin(cursorPos - layout->preeditAreaPosition(), preeditLength); break; } block = block.next(); } QTextDocumentPrivate *pieceTable = qobject_cast<const QTextDocument *>(parent())->docHandle(); QTextDocumentPrivate::FragmentIterator it = pieceTable->find(cursorPos); QTextCharFormat fmt = pieceTable->formatCollection()->charFormat(it->format); return fmt.anchorHref(); }
void HGMarkdownHighlighter::clearFormatting() { QTextBlock block = document->firstBlock(); while (block.isValid()) { block.layout()->clearAdditionalFormats(); block = block.next(); } }
void TestDocumentLayout::testBasicList() { initForNewTest("Base\nListItem\nListItem2: The quick brown fox jums over the lazy dog.\nNormal\nNormal"); KoParagraphStyle style; QTextBlock block = m_doc->begin(); style.applyStyle(block); block = block.next(); QVERIFY(block.isValid()); KoListStyle listStyle; KoListLevelProperties level1; level1.setStyle(KoListStyle::Bullet); listStyle.setLevelProperties(level1); style.setListStyle(&listStyle); style.applyStyle(block); // make this a listStyle QVERIFY(block.textList()); QCOMPARE(block.textList()->format().intProperty(QTextListFormat::ListStyle), (int) KoListStyle::Bullet); block = block.next(); QVERIFY(block.isValid()); style.applyStyle(block); // make this a listStyle m_layout->layout(); QTextLayout *blockLayout = m_block.layout(); QCOMPARE(blockLayout->lineAt(0).x(), 0.0); block = m_doc->begin().next(); QVERIFY(block.isValid()); blockLayout = block.layout(); // parag 2 KoTextBlockData *data = dynamic_cast<KoTextBlockData *>(block.userData()); QVERIFY(data); qreal counterSpacing = data->counterSpacing(); QVERIFY(counterSpacing > 0.); // 12 is hardcoded to be the width of a discitem (taken from the default font): QCOMPARE(blockLayout->lineAt(0).x(), 12.0 + counterSpacing); block = block.next(); QVERIFY(block.isValid()); blockLayout = block.layout(); // parag 3 QCOMPARE(blockLayout->lineAt(0).x(), 12.0 + counterSpacing); QVERIFY(blockLayout->lineCount() > 1); QCOMPARE(blockLayout->lineAt(1).x(), 12.0 + counterSpacing); // make sure not only the first line is indented block = block.next(); QVERIFY(block.isValid()); blockLayout = block.layout(); // parag 4 QCOMPARE(blockLayout->lineAt(0).x(), 0.0); }
///Indique si on est à la dernière ligne bool RzxTextEdit::atEnd() const { QTextBlock block = textCursor().block(); if(block.next().isValid()) return false; QTextLine line = currentTextLine(); return line.isValid() && line.lineNumber() == block.layout()->lineCount() - 1; }
void DevLineNumber::paintEvent(QPaintEvent *e) { const QPixmap pm[] ={ QPixmap(":/break.png"), QPixmap(":/error.png") }; int n = 1, contentsY = editor->verticalScrollBar()->value(); qreal pageBottom = contentsY + editor->viewport()->height(); const QFontMetrics fm( editor->document()->defaultFont() ); QPainter p(this); for (QTextBlock block = editor->document()->begin(); block.isValid(); block = block.next(), ++n ) { QTextLayout *layout = block.layout(); const QRectF boundingRect = layout->boundingRect(); QPointF position = layout->position(); if (position.y() + boundingRect.height() < contentsY) continue; if (position.y() > pageBottom) break; int posY = qRound(position.y()); BlockData *dat = BlockData::data(block); const QString txt = QString::number(n); p.drawText( 0, posY - contentsY, width(), fm.lineSpacing(), Qt::AlignRight | Qt::AlignVCenter, txt); if ( !dat ) continue; int x = 0; if ( dat->s & BlockData::BreakPoint ) p.drawPixmap( 15*(x++), posY - contentsY +(fm.lineSpacing() - (*pm).height())/2, (*pm).width(), (*pm).height(), *pm); if ( dat->s & BlockData::Error ) p.drawPixmap( 15*(x++), posY - contentsY +(fm.lineSpacing() - pm[1].height())/2, pm[1].width(), pm[1].height(), pm[1]); } }
void MibEditor::ExecuteGotoLine(void) { QTextBlock currentBlock = s->MainUI()->MIBFile->document()->begin(); QTextBlock foundBlock; int l = 1; int found = 0; int line = goto_uid.spinLine->value(); // Loop through the blocks while(currentBlock.isValid()) { if (l == line) { found = 1; foundBlock = currentBlock; break; } currentBlock = currentBlock.next(); l++; }; if (found) { // Change scrollbar to put the marker visible in the middle of the editor int halfViewPortHeight = s->MainUI()->MIBFile->maximumViewportSize().height()/2; int yCoord = (int)foundBlock.layout()->position().y(); int yAdjust = (yCoord < halfViewPortHeight)?yCoord : halfViewPortHeight; int halfLineHeight = (int)foundBlock.layout()->boundingRect().height()/2; s->MainUI()->MIBFile->verticalScrollBar()->setValue(yCoord - yAdjust); // Set the cursor position to the marker line QPoint cursorPos(0, yAdjust+halfLineHeight); QTextCursor tc = s->MainUI()->MIBFile->cursorForPosition(cursorPos); s->MainUI()->MIBFile->setTextCursor(tc); // Finally, set the focus to the editor s->MainUI()->MIBFile->setFocus(Qt::OtherFocusReason); } }
int KTextDocumentLayout::hitTestIterated(QTextFrame::iterator begin, QTextFrame::iterator end, const QPointF &point, Qt::HitTestAccuracy accuracy) const { int position = -1; QTextFrame::iterator it = begin; for (it = begin; it != end; ++it) { QTextBlock block = it.currentBlock(); QTextTable *table = qobject_cast<QTextTable*>(it.currentFrame()); QTextFrame *subFrame = it.currentFrame(); if (table) { QTextTableCell cell = m_state->hitTestTable(table, point); if (cell.isValid()) { position = hitTestIterated(cell.begin(), cell.end(), point, accuracy); if (position == -1) position = cell.lastPosition(); return position; } continue; } else if (subFrame) { position = hitTestIterated(subFrame->begin(), subFrame->end(), point, accuracy); if (position != -1) return position; continue; } else { if (!block.isValid()) continue; } // kDebug(32500) <<"hitTest[" << point.x() <<"," << point.y() <<"]"; QTextLayout *layout = block.layout(); if (point.y() > layout->boundingRect().bottom()) { // just skip this block. position = block.position() + block.length() - 1; continue; } for (int i = 0; i < layout->lineCount(); i++) { QTextLine line = layout->lineAt(i); // kDebug(32500) <<" + line[" << line.textStart() <<"]:" << line.y() <<"-" << line.height(); if (point.y() > line.y() + line.height()) { position = line.textStart() + line.textLength(); continue; } if (accuracy == Qt::ExactHit && point.y() < line.y()) // between lines return -1; if (accuracy == Qt::ExactHit && // left or right of line (point.x() < line.x() || point.x() > line.x() + line.width())) return -1; if (point.x() > line.width() && layout->textOption().textDirection() == Qt::RightToLeft) { // totally right of RTL text means the position is the start of the text. return block.position() + line.textStart(); } return block.position() + line.xToCursor(point.x()); } } return -1; }
qreal Text::baseLine() const { if (styled()) return SimpleText::baseLine(); for (QTextBlock tb = _doc->begin(); tb.isValid(); tb = tb.next()) { const QTextLayout* tl = tb.layout(); if (tl->lineCount()) return (tl->lineAt(0).ascent() + tl->position().y()); } return 0.0; }
qreal TextDocumentLayout::blockWidth(const QTextBlock &block) { QTextLayout *layout = block.layout(); if (!layout->lineCount()) return 0; // only for layouted blocks qreal blockWidth = 0; for (int i = 0; i < layout->lineCount(); ++i) { QTextLine line = layout->lineAt(i); blockWidth = qMax(line.naturalTextWidth() + 8, blockWidth); } return blockWidth; }
int QTextDocumentPrivate::previousCursorPosition(int position, QTextLayout::CursorMode mode) const { if (position == 0) return position; QTextBlock it = blocksFind(position); int start = it.position(); if (position == start) return start - 1; return it.layout()->previousCursorPosition(position-start, mode) + start; }
///Retourne un QTextLine indiquant la position du curseur QTextLine RzxTextEdit::currentTextLine() const { const QTextBlock block = textCursor().block(); if (!block.isValid()) return QTextLine(); const QTextLayout *layout = block.layout(); if (!layout) return QTextLine(); const int relativePos = textCursor().position() - block.position(); return layout->lineForTextPosition(relativePos); }
int CodeEditor::getTokenTypeAtCursor() const { const QTextCursor cur = textCursor(); const QTextBlock block = cur.block(); const int pos = cur.selectionStart() - block.position(); QList<QTextLayout::FormatRange> fmts = block.layout()->additionalFormats(); foreach( const QTextLayout::FormatRange& f, fmts ) { if( pos >= f.start && pos < f.start + f.length ) return f.format.intProperty(SyntaxHighlighter::TokenProp); } return 0; }
QTextLine TabTerminal::_currentTextLine(const QTextCursor & cursor) { const QTextBlock block = cursor.block(); if (!block.isValid()) return QTextLine(); const QTextLayout *layout = block.layout(); if (!layout) return QTextLine(); const int relativePos = cursor.position() - block.position(); return layout->lineForTextPosition(relativePos); }
/*! Installs the syntax highlighter on the given QTextDocument \a doc. A QSyntaxHighlighter can only be used with one document at a time. */ void QSyntaxHighlighter::setDocument(QTextDocument *doc) { Q_D(QSyntaxHighlighter); if (d->doc) { disconnect(d->doc, SIGNAL(contentsChange(int,int,int)), this, SLOT(_q_reformatBlocks(int,int,int))); QTextCursor cursor(d->doc); cursor.beginEditBlock(); for (QTextBlock blk = d->doc->begin(); blk.isValid(); blk = blk.next()) blk.layout()->clearAdditionalFormats(); cursor.endEditBlock(); }
int QTextDocumentPrivate::nextCursorPosition(int position, QTextLayout::CursorMode mode) const { if (position == length()-1) return position; QTextBlock it = blocksFind(position); int start = it.position(); int end = start + it.length() - 1; if (position == end) return end + 1; return it.layout()->nextCursorPosition(position-start, mode) + start; }
void LineNumberWidget::paintEvent( QPaintEvent* /*e*/ ) { int max=0; int l=0; QPainter painter( this ); painter.setFont(numfont); const QFontMetrics fm(numfont); int yOffset = m_editor->verticalScrollBar()->value(); QTextDocument *doc = m_editor->document(); int i = 1; QTextBlock p = doc->begin(); QString numtext; const QBrush oldbrush=painter.brush(); QPen oldpen(QColor("#136872")); oldpen.setStyle(Qt::SolidLine); painter.setPen(oldpen); painter.drawLine(width()-2,0,width()-2,height()); while ( p.isValid() ) { QPointF point = p.layout()->position(); if ( point.y() + 20 - yOffset < 0 ) { i++; p = p.next(); continue; } if ( (int)(point.y()) - yOffset > height() ) break; for (int j = 0; j < 3; ++j) { if (m_editor->UserBookmark[j]==i) { const QBrush brush(QColor("#1B8EA6")); painter.fillRect(2, (int)(point.y()) - yOffset,fm.width("0")+6,fm.lineSpacing(), brush); const QPen pen(QColor("#FFFFFF")); painter.setPen(pen); painter.drawText(4, (int)(point.y()) - yOffset,width()-4,fm.lineSpacing(),Qt::AlignLeft | Qt::AlignTop,QString::number(j+1)); } } painter.setPen(oldpen); numtext=QString::number(i); painter.drawText(0, (int)(point.y()) - yOffset,width()-4,fm.lineSpacing(),Qt::AlignRight | Qt::AlignTop,numtext); l= fm.width(numtext)+18+fm.width("0"); if (l>max) max=l; i++; p = p.next(); } if (i>=10000) setFixedWidth(max); painter.end(); }
void QQuickTextNode::addTextDocument(const QPointF &position, QTextDocument *textDocument, const QColor &textColor, QQuickText::TextStyle style, const QColor &styleColor, const QColor &anchorColor, const QColor &selectionColor, const QColor &selectedTextColor, int selectionStart, int selectionEnd) { QQuickTextNodeEngine engine; engine.setTextColor(textColor); engine.setSelectedTextColor(selectedTextColor); engine.setSelectionColor(selectionColor); engine.setAnchorColor(anchorColor); engine.setPosition(position); QList<QTextFrame *> frames; frames.append(textDocument->rootFrame()); while (!frames.isEmpty()) { QTextFrame *textFrame = frames.takeFirst(); frames.append(textFrame->childFrames()); engine.addFrameDecorations(textDocument, textFrame); if (textFrame->firstPosition() > textFrame->lastPosition() && textFrame->frameFormat().position() != QTextFrameFormat::InFlow) { const int pos = textFrame->firstPosition() - 1; ProtectedLayoutAccessor *a = static_cast<ProtectedLayoutAccessor *>(textDocument->documentLayout()); QTextCharFormat format = a->formatAccessor(pos); QRectF rect = a->frameBoundingRect(textFrame); QTextBlock block = textFrame->firstCursorPosition().block(); engine.setCurrentLine(block.layout()->lineForTextPosition(pos - block.position())); engine.addTextObject(rect.topLeft(), format, QQuickTextNodeEngine::Unselected, textDocument, pos, textFrame->frameFormat().position()); } else { QTextFrame::iterator it = textFrame->begin(); while (!it.atEnd()) { Q_ASSERT(!engine.currentLine().isValid()); QTextBlock block = it.currentBlock(); engine.addTextBlock(textDocument, block, position, textColor, anchorColor, selectionStart, selectionEnd); ++it; } } } engine.addToSceneGraph(this, style, styleColor); }
QPainterPath Text::shape() const { QPainterPath pp; #if 0 for (QTextBlock tb = doc()->begin(); tb.isValid(); tb = tb.next()) { QTextLayout* tl = tb.layout(); int n = tl->lineCount(); for (int i = 0; i < n; ++i) { QTextLine l = tl->lineAt(i); QRectF r(l.naturalTextRect().translated(tl->position())); r.adjust(-l.position().x(), 0.0, 0.0, 0.0); pp.addRect(r); } } #endif return pp; }
void CodeEditor::paintEvent(QPaintEvent* event) { QPlainTextEdit::paintEvent(event); QPainter painter(viewport()); painter.setPen(Qt::darkGray); QTextBlock block = firstVisibleBlock(); QRectF rect; do { if (!block.isVisible()) continue; rect = blockBoundingGeometry(block).translated(contentOffset()); QTextLine line = block.layout()->lineAt(0); if (config->whitespaces) { QString txt = block.text(); for (int i = 0; i < txt.length(); i++) { // rect.x() <- учитывая горизонтальный скролинг QPoint point(rect.x() + line.cursorToX(i), rect.y() + line.ascent()); if (txt[i] == ' ') painter.drawText(point, QChar(0x00b7)); else if (txt[i] == '\t') painter.drawText(point, QChar(0x21b9)); } } int state = block.userState(); if (!(state & Error) && state & Folded) { QRect collapseRect(rect.x() + line.rect().x() + line.naturalTextWidth() + FONTWIDTH * 2, rect.y() + 2, FONTWIDTH * 6, line.height() - 4); painter.drawText(collapseRect, Qt::AlignCenter, state & Comment ? "...;" : "...)"); painter.drawRoundedRect(collapseRect, 4, 6); } } while ((block = block.next()).isValid() && rect.y() < viewport()->height()); }
void TailView::scrollToIfNecessary(const YFileCursor & ycursor) { QTextBlock cursorBlock = m_document->lineAddresses().findContainingBlock(ycursor.lineAddress()); int cursorLineNumber = m_document->blockLayoutLines().at(cursorBlock.blockNumber()); int blockLine = cursorBlock.layout()->lineForTextPosition(ycursor.charPos()).lineNumber(); cursorLineNumber += blockLine; int topScreenLine = m_layoutStrategy->topScreenLine(); int numReadableLines = numLinesOnScreen(); if(topScreenLine <= cursorLineNumber && cursorLineNumber < topScreenLine + numReadableLines) { // No scrolling needed -- return return; } int newTopLine = cursorLineNumber - numReadableLines / 2; m_layoutStrategy->scrollTo(newTopLine); }