/*! * Returns the rectangle for the cursor including the predictive text area. * HbAbstractEditPrivate::ensurePositionVisible() uses the same algorithm. */ QRectF NmEditorTextEdit::rectForCursorPosition() const { NM_FUNCTION; int cursorPos = cursorPosition(); QRectF rect = rectForPosition(cursorPos); QTextDocument *doc = document(); if (doc) { rect.adjust(0, -doc->documentMargin(), 0, doc->documentMargin()); const QTextBlock block = doc->findBlock(cursorPos); QTextLayout *blockLayout = block.layout(); if (block.isValid() && blockLayout) { if (blockLayout->preeditAreaText().length()) { // Adjust cursor rect so that predictive text will be also visible rect.adjust(0, 0, boundingRect().width() / 2, 0); } } } return rect; }
QSize CustomLabel::sizeHint() const { #ifdef DEBUG_CUSTOMLABEL QSize sh = QLabel::sizeHint(); //sh.setWidth(sh.width() + 1); //sh.setHeight(sh.height() + 4); qDebug() << "for text:" << text(); qDebug() << " size hint:" << sh; QTextDocument *doc = textDocument(); sh = doc->documentLayout()->documentSize().toSize(); qDebug() << " doc size:" << sh; sh += QSize(doc->documentMargin(), doc->documentMargin()); qDebug() << " doc size with margin:" << sh; return sh; #else return QLabel::sizeHint(); #endif }
void TextDocumentLayout::layoutBlock(const QTextBlock &block) { QTextDocument *doc = document(); qreal margin = doc->documentMargin(); qreal blockMaximumWidth = 0; qreal height = 0; QTextLayout *tl = block.layout(); QTextOption option = doc->defaultTextOption(); tl->setTextOption(option); int extraMargin = 0; if (option.flags() & QTextOption::AddSpaceForLineAndParagraphSeparators) { QFontMetrics fm(block.charFormat().font()); extraMargin += fm.width(QChar(0x21B5)); } tl->beginLayout(); qreal availableWidth = d->width; if (availableWidth <= 0) { availableWidth = qreal(INT_MAX); // similar to text edit with pageSize.width == 0 } availableWidth -= 2*margin + extraMargin; qreal indentMargin = 0; while (1) { QTextLine line = tl->createLine(); if (!line.isValid()) break; line.setLeadingIncluded(true); line.setLineWidth(availableWidth - indentMargin); line.setPosition(QPointF(margin + indentMargin, height)); if(!height) //enter only in the first iteration { indentMargin = indentWidth(block); } height += line.height(); blockMaximumWidth = qMax(blockMaximumWidth, line.naturalTextWidth() + 2*margin); } tl->endLayout(); int previousLineCount = doc->lineCount(); const_cast<QTextBlock&>(block).setLineCount(block.isVisible() ? tl->lineCount() : 0); int lineCount = doc->lineCount(); bool emitDocumentSizeChanged = previousLineCount != lineCount; if (blockMaximumWidth > d->maximumWidth) { // new longest line d->maximumWidth = blockMaximumWidth; d->maximumWidthBlockNumber = block.blockNumber(); emitDocumentSizeChanged = true; } else if (block.blockNumber() == d->maximumWidthBlockNumber && blockMaximumWidth < d->maximumWidth) { // longest line shrinking QTextBlock b = doc->firstBlock(); d->maximumWidth = 0; QTextBlock maximumBlock; while (b.isValid()) { qreal blockMaximumWidth = blockWidth(b); if (blockMaximumWidth > d->maximumWidth) { d->maximumWidth = blockMaximumWidth; maximumBlock = b; } b = b.next(); } if (maximumBlock.isValid()) { d->maximumWidthBlockNumber = maximumBlock.blockNumber(); emitDocumentSizeChanged = true; } } if (emitDocumentSizeChanged)// && !d->blockDocumentSizeChanged) emit documentSizeChanged(documentSize()); emit updateBlock(block); }
/*! \reimp */ void TextDocumentLayout::documentChanged(int from, int /*charsRemoved*/, int charsAdded) { QTextDocument *doc = document(); int newBlockCount = doc->blockCount(); QTextBlock changeStartBlock = doc->findBlock(from); QTextBlock changeEndBlock = doc->findBlock(qMax(0, from + charsAdded - 1)); if (changeStartBlock == changeEndBlock && newBlockCount == d->blockCount) { QTextBlock block = changeStartBlock; if (block.isValid() && block.layout()->lineCount()) { QRectF oldBr = blockBoundingRect(block); layoutBlock(block); QRectF newBr = blockBoundingRect(block); if (newBr.height() == oldBr.height()) { if (!d->blockUpdate) emit updateBlock(block); return; } } } else { QTextBlock block = changeStartBlock; do { block.clearLayout(); if (block == changeEndBlock) break; block = block.next(); } while(block.isValid()); } if (newBlockCount != d->blockCount) { int changeEnd = changeEndBlock.blockNumber(); int blockDiff = newBlockCount - d->blockCount; int oldChangeEnd = changeEnd - blockDiff; if (d->maximumWidthBlockNumber > oldChangeEnd) d->maximumWidthBlockNumber += blockDiff; d->blockCount = newBlockCount; if (d->blockCount == 1) d->maximumWidth = blockWidth(doc->firstBlock()); if (!d->blockDocumentSizeChanged) emit documentSizeChanged(documentSize()); if (blockDiff == 1 && changeEnd == newBlockCount -1 ) { if (!d->blockUpdate) { QTextBlock b = changeStartBlock; for(;;) { emit updateBlock(b); if (b == changeEndBlock) break; b = b.next(); } } return; } } if (!d->blockUpdate) emit update(QRectF(0., -doc->documentMargin(), 1000000000., 1000000000.)); // optimization potential }
void AATextItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){ if (hasFocus()){ QGraphicsTextItem::paint(painter, option, widget); return; } painter->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing); QPainterPath path; QString s = toPlainText(); QTextDocument *doc = document(); qreal margin = doc->documentMargin(); QStringList lines = s.split("\n", QString::SkipEmptyParts); QFont f = font(); f.setStyleHint(QFont::AnyStyle, QFont::PreferAntialias); QFontMetrics fm(f); QFont f_bold = f; f_bold.setBold(true); QFontMetrics fm_bold(f_bold); int line = 0; for (int i = 0; i < lines.length(); i++){ QString thisline = lines[i]; QStringList s1 = thisline.split(']', QString::SkipEmptyParts); QStringList s_non_bold, s_bold; foreach(QString s, s1){ if (!s.contains('[')){ s_non_bold << s; s_bold << QString(); } else if (!s.startsWith('[')){ QStringList s2 = s.split('[', QString::SkipEmptyParts); s_non_bold << s2.first(); s_bold << s2.last(); } else { s = s.mid(1); s_non_bold << QString(); s_bold << s; } } int width = 0; for (int j = 0; j < s_non_bold.length(); j++){ QString non_bold = s_non_bold[j]; for (int k = 0; k < non_bold.length(); k++){ QChar c = non_bold[k]; QString str = c; int width_c = fm.width(str); if (width + width_c > doc->size().width()){ ++line; width = 0; } path.addText(margin + width, fm.height() * (line + 1), f, str); width += width_c; } QString bold = s_bold[j]; for (int k = 0; k < bold.length(); k++){ QChar c = bold[k]; QString str = c; int width_c = fm_bold.width(str); if (width + width_c > doc->size().width()){ ++line; width = 0; } path.addText(margin + width, fm.height() * (line + 1), f_bold, str); //use fm.height not fm_bold.height, for sometimes the bold characters are not as high as the non-bold ones width += width_c; } } ++line; } painter->fillPath(path, defaultTextColor()); }