📄 qtextdocumentlayout.cpp
字号:
selectedTableCells[i * 4 + 3] = num_cols; } if (td->rowPageBreaks.isEmpty()) { drawFrameDecoration(painter, frame, fd, context.clip, frameRect); } else { Q_ASSERT(td->rowPageBreaks.first() > 0); QRectF rect = frameRect; const qreal extraTableHeight = td->padding + td->border + td->cellSpacing // inter cell spacing + td->margin + td->border + td->padding; // effective table margin int lastVisibleRow = td->rowPageBreaks.first() - 1; rect.setHeight(td->rowPositions.at(lastVisibleRow) + td->heights.at(lastVisibleRow) + extraTableHeight); drawFrameDecoration(painter, frame, fd, context.clip, rect); for (int i = 0; i < td->rowPageBreaks.count(); ++i) { const int firstVisibleRow = td->rowPageBreaks.at(i); if (i < td->rowPageBreaks.count() - 1) lastVisibleRow = td->rowPageBreaks.at(i + 1) - 1; else lastVisibleRow = rows - 1; rect.setTop(off.y() + td->rowPositions.at(firstVisibleRow) - extraTableHeight); rect.setBottom(off.y() + td->rowPositions.at(lastVisibleRow) + td->heights.at(lastVisibleRow) + extraTableHeight); drawFrameDecoration(painter, frame, fd, context.clip, rect); } } int firstRow = 0; int lastRow = rows; if (context.clip.isValid()) { QVector<qreal>::ConstIterator rowIt = qLowerBound(td->rowPositions.begin(), td->rowPositions.end(), context.clip.top() - off.y()); if (rowIt != td->rowPositions.end() && rowIt != td->rowPositions.begin()) { --rowIt; firstRow = rowIt - td->rowPositions.begin(); } rowIt = qUpperBound(td->rowPositions.begin(), td->rowPositions.end(), context.clip.bottom() - off.y()); if (rowIt != td->rowPositions.end()) { ++rowIt; lastRow = rowIt - td->rowPositions.begin(); } } for (int c = 0; c < columns; ++c) { QTextTableCell cell = table->cellAt(firstRow, c); firstRow = qMin(firstRow, cell.row()); } for (int r = firstRow; r < lastRow; ++r) { for (int c = 0; c < columns; ++c) { QTextTableCell cell = table->cellAt(r, c); int rspan = cell.rowSpan(); int cspan = cell.columnSpan(); if (rspan != 1) { int cr = cell.row(); if (cr != r) continue; } if (cspan != 1) { int cc = cell.column(); if (cc != c) continue; } QRectF cellRect = td->cellRect(cell); cellRect.translate(off); // we draw the right/bottom border at left() + width(), so for the clipping test // we have to enlarge the cell rect by one pixel in both directions if (context.clip.isValid() && !cellRect.adjusted(0, 0, 1, 1).intersects(context.clip)) continue; if (fd->border) { const QBrush oldBrush = painter->brush(); const QPen oldPen = painter->pen(); painter->setBrush(Qt::darkGray); painter->setPen(Qt::NoPen); // top border painter->drawRect(QRectF(cellRect.left(), cellRect.top() - fd->border, cellRect.width() + fd->border, fd->border)); // left border painter->drawRect(QRectF(cellRect.left() - fd->border, cellRect.top() - fd->border, fd->border, cellRect.height() + 2 * fd->border)); painter->setBrush(Qt::lightGray); // bottom border painter->drawRect(QRectF(cellRect.left(), cellRect.top() + cellRect.height(), cellRect.width() + fd->border, fd->border)); // right border painter->drawRect(QRectF(cellRect.left() + cellRect.width(), cellRect.top(), fd->border, cellRect.height())); painter->setBrush(oldBrush); painter->setPen(oldPen); } { const QBrush bg = cell.format().background(); if (bg != Qt::NoBrush) painter->fillRect(cellRect, bg); } QAbstractTextDocumentLayout::PaintContext cell_context = context; for (int i = 0; i < context.selections.size(); ++i) { int row_start = selectedTableCells[i * 4]; int col_start = selectedTableCells[i * 4 + 1]; int num_rows = selectedTableCells[i * 4 + 2]; int num_cols = selectedTableCells[i * 4 + 3]; if (row_start != -1) { if (r >= row_start && r < row_start + num_rows && c >= col_start && c < col_start + num_cols) { cell_context.selections[i].cursor.setPosition(cell.firstPosition()); cell_context.selections[i].cursor.setPosition(cell.lastPosition(), QTextCursor::KeepAnchor); } else { cell_context.selections[i].cursor.clearSelection(); } } } const QPointF cellPos = off + td->cellPosition(r, c); QTextBlock repaintBlock; drawFlow(cellPos, painter, cell_context, cell.begin(), &repaintBlock); if (repaintBlock.isValid()) { cursorBlockNeedingRepaint = repaintBlock; offsetOfRepaintedCursorBlock = cellPos; } } } } else { drawFrameDecoration(painter, frame, fd, context.clip, frameRect); QTextFrame::Iterator it = frame->begin(); if (frame == q->document()->rootFrame()) it = iteratorForYPosition(context.clip.top()); drawFlow(off, painter, context, it, &cursorBlockNeedingRepaint); } if (cursorBlockNeedingRepaint.isValid()) { const QPen oldPen = painter->pen(); painter->setPen(context.palette.color(QPalette::Text)); const int cursorPos = context.cursorPosition - cursorBlockNeedingRepaint.position(); cursorBlockNeedingRepaint.layout()->drawCursor(painter, offsetOfRepaintedCursorBlock, cursorPos); painter->setPen(oldPen); }// DEC_INDENT; return;}void QTextDocumentLayoutPrivate::drawFlow(const QPointF &offset, QPainter *painter, const QAbstractTextDocumentLayout::PaintContext &context, QTextFrame::Iterator it, QTextBlock *cursorBlockNeedingRepaint) const{ const bool inRootFrame = (!it.atEnd() && it.parentFrame() && it.parentFrame()->parentFrame() == 0); QVector<QCheckPoint>::ConstIterator lastVisibleCheckPoint = checkPoints.end(); if (inRootFrame && context.clip.isValid()) { lastVisibleCheckPoint = qLowerBound(checkPoints.begin(), checkPoints.end(), qreal(context.clip.bottom())); } QTextBlock lastBlock; for (; !it.atEnd(); ++it) { QTextFrame *c = it.currentFrame(); if (inRootFrame && !checkPoints.isEmpty()) { int currentPosInDoc; if (c) currentPosInDoc = c->firstPosition(); else currentPosInDoc = it.currentBlock().position(); // if we're past what is already layouted then we're better off // not trying to draw things that may not be positioned correctly yet if (currentPosInDoc >= checkPoints.last().positionInFrame) break; if (lastVisibleCheckPoint != checkPoints.end() && context.clip.isValid() && currentPosInDoc >= lastVisibleCheckPoint->positionInFrame ) break; } if (c) drawFrame(offset, painter, context, c); else drawBlock(offset, painter, context, it.currentBlock()); // when entering a table and the previous block is empty // then layoutFlow 'hides' the block that just causes a // new line by positioning it /on/ the table border. as we // draw that block before the table itself the decoration // 'overpaints' the cursor and we need to paint it afterwards // again if (isEmptyBlockBeforeTable(lastBlock, it) && lastBlock.contains(context.cursorPosition) ) { *cursorBlockNeedingRepaint = lastBlock; } lastBlock = it.currentBlock(); }}void QTextDocumentLayoutPrivate::drawBlock(const QPointF &offset, QPainter *painter, const QAbstractTextDocumentLayout::PaintContext &context, QTextBlock bl) const{ Q_Q(const QTextDocumentLayout); const QTextLayout *tl = bl.layout(); QRectF r = tl->boundingRect(); r.translate(offset + tl->position()); if (context.clip.isValid() && !r.intersects(context.clip)) return;// LDEBUG << debug_indent << "drawBlock" << bl.position() << "at" << offset << "br" << tl->boundingRect(); QTextBlockFormat blockFormat = bl.blockFormat(); QBrush bg = blockFormat.background(); if (bg != Qt::NoBrush) { // don't paint into the left margin. Right margin is already excluded by the line breaking QRectF contentsRect = r; contentsRect.setLeft(contentsRect.left() + bl.blockFormat().leftMargin()); painter->fillRect(contentsRect, bg); } QVector<QTextLayout::FormatRange> selections; int blpos = bl.position(); int bllen = bl.length(); const QTextCharFormat *selFormat = 0; for (int i = 0; i < context.selections.size(); ++i) { const QAbstractTextDocumentLayout::Selection &range = context.selections.at(i); const int selStart = range.cursor.selectionStart() - blpos; const int selEnd = range.cursor.selectionEnd() - blpos; if (selStart < bllen && selEnd > 0) { QTextLayout::FormatRange o; o.start = selStart; o.length = selEnd - selStart; o.format = range.format; selections.append(o); } if (selStart <= 0 && selEnd >= 1) selFormat = &range.format; } QTextObject *object = q->document()->objectForFormat(bl.blockFormat()); if (object && object->format().toListFormat().style() != QTextListFormat::ListStyleUndefined) drawListItem(offset, painter, context, bl, selFormat); QPen oldPen = painter->pen(); painter->setPen(context.palette.color(QPalette::Text)); tl->draw(painter, offset, selections, context.clip); if ((context.cursorPosition >= blpos && context.cursorPosition < blpos + bllen) || (context.cursorPosition < -1 && !tl->preeditAreaText().isEmpty())) { int cpos = context.cursorPosition; if (cpos < -1) cpos = tl->preeditAreaPosition() - (cpos + 2); else cpos -= blpos; tl->drawCursor(painter, offset, cpos); } if (blockFormat.hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth)) { const qreal width = blockFormat.lengthProperty(QTextFormat::BlockTrailingHorizontalRulerWidth).value(r.width()); painter->setPen(context.palette.color(QPalette::Dark)); qreal y = r.bottom(); if (bl.length() == 1) y = r.top() + r.height() / 2; const qreal middleX = r.left() + r.width() / 2; painter->drawLine(QLineF(middleX - width / 2, y, middleX + width / 2, y)); } painter->setPen(oldPen);}void QTextDocumentLayoutPrivate::drawListItem(const QPointF &offset, QPainter *painter, const QAbstractTextDocumentLayout::PaintContext &context, QTextBlock bl, const QTextCharFormat *selectionFormat) const{ Q_Q(const QTextDocumentLayout); const QTextBlockFormat blockFormat = bl.blockFormat(); const QTextCharFormat charFormat = bl.charFormat(); QFont font(charFormat.font()); if (q->paintDevice()) font = QFont(font, q->paintDevice()); const QFontMetrics fontMetrics(font); QTextObject * const object = q->document()->objectForFormat(blockFormat); const QTextListFormat lf = object->format().toListFormat(); const int style = lf.style(); QString itemText; QSizeF size; QTextLayout *layout = bl.layout(); if (layout->lineCount() == 0) return; QTextLine firstLine = layout->lineAt(0); Q_ASSERT(firstLine.isValid()); QPointF pos = (offset + layout->boundingRect().topLeft() + layout->position()).toPoint(); Qt::LayoutDirection dir = blockFormat.layoutDirection(); { QRectF textRect = firstLine.naturalTextRect(); pos += textRect.topLeft().toPoint(); if (dir == Qt::RightToLeft) pos.rx() += textRect.width(); } switch (style) { case QTextListFormat::ListDecimal: case QTextListFormat::ListLowerAlpha: case QTextListFormat::ListUpperAlpha: itemText = static_cast<QTextList *>(object)->itemText(bl); size.setWidth(fontMetrics.width(itemText)); size.setHeight(fontMetrics.height()); break; case QTextListFormat::ListSquare: case QTextListFormat::ListCircle: case QTextListFormat::ListDisc: size.setWidth(fontMetrics.lineSpacing() / 3); size.setHeight(size.width()); break; case QTextListFormat::ListStyleUndefined: return; default: return; } QRectF r(pos, size); qreal xoff = fontMetrics.width(QLatin1Char(' ')); if (dir == Qt::LeftToRight) xoff = -xoff - size.width(); r.translate( xoff, (fontMetrics.height() / 2 - size.height() / 2)); painter->save();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -