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; }
void FileMetaDataToolTip::setName(const QString& name) { QTextOption textOption; textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); const QString processedName = Qt::mightBeRichText(name) ? name : KStringHandler::preProcessWrap(name); QTextLayout textLayout(processedName); textLayout.setFont(m_name->font()); textLayout.setTextOption(textOption); QString wrappedText; wrappedText.reserve(processedName.length()); // wrap the text to fit into the maximum width of m_name textLayout.beginLayout(); QTextLine line = textLayout.createLine(); while (line.isValid()) { line.setLineWidth(m_name->maximumWidth()); wrappedText += processedName.midRef(line.textStart(), line.textLength()); line = textLayout.createLine(); if (line.isValid()) { wrappedText += QChar::LineSeparator; } } textLayout.endLayout(); m_name->setText(wrappedText); }
void YTDelegate::layoutText(QTextLayout& textLayout, QString text, QSize constraint) const { QTextOption textOption(Qt::AlignJustify); textLayout.setTextOption(textOption); textLayout.setText(text); textLayout.beginLayout(); int lHeight = 0; while(true){ QTextLine line = textLayout.createLine(); if(!line.isValid()) break; line.setLineWidth(constraint.width()); line.setPosition(QPointF(0, lHeight)); if(lHeight + line.height() > constraint.height()) { QTextLine lastLine = textLayout.lineAt(textLayout.lineCount() - 2); QString lastString = text.mid(lastLine.textStart()); QFontMetrics fm(textLayout.font()); text.chop(lastString.length()); text += fm.elidedText(lastString, Qt::ElideRight, constraint.width()-1); textLayout.endLayout(); layoutText(textLayout, text, constraint); return; } lHeight += line.height(); lHeight += line.leading(); } textLayout.endLayout(); }
int cursorPosition() const { if (!m_currentBlock.isValid()) return 0; int answer = m_currentBlock.position(); if (m_currentBlock.layout()->lineCount()) { QTextLine tl = m_currentBlock.layout()->lineAt(m_currentBlock.layout()->lineCount() - 1); answer += tl.textStart() + tl.textLength(); } return answer; }
QStringList StatusEventItemDelegate::layoutText(const QString &text, const QFont &font, int maxLineWidth, int maxLines, int *textHeight) { QTextLayout textLayout(text, font); QFontMetrics fontMetrics(font); QStringList lines; qreal height = 0.0; textLayout.beginLayout(); while (lines.size() < maxLines) { QTextLine line = textLayout.createLine(); if (! line.isValid()) break; if (maxLines <= 0 || lines.size() < maxLines-1) { // Wrap the current line at or below the maximum line width line.setLineWidth(maxLineWidth); lines.append(text.mid(line.textStart(), line.textLength())); } else { // Set the line width beyond the max line width, and then elide it // so the user has a visible indication that the full message is // longer than what is visible. line.setLineWidth(2 * maxLineWidth); lines.append(fontMetrics.elidedText(text.mid(line.textStart()), Qt::ElideRight, maxLineWidth)); } height += fontMetrics.leading() + line.height(); } textLayout.endLayout(); if (textHeight) *textHeight = qRound(height); return lines; }
void QQuickTextNode::addTextLayout(const QPointF &position, QTextLayout *textLayout, const QColor &color, QQuickText::TextStyle style, const QColor &styleColor, const QColor &anchorColor, const QColor &selectionColor, const QColor &selectedTextColor, int selectionStart, int selectionEnd, int lineStart, int lineCount) { QQuickTextNodeEngine engine; engine.setTextColor(color); engine.setSelectedTextColor(selectedTextColor); engine.setSelectionColor(selectionColor); engine.setAnchorColor(anchorColor); engine.setPosition(position); #if QT_CONFIG(im) int preeditLength = textLayout->preeditAreaText().length(); int preeditPosition = textLayout->preeditAreaPosition(); #endif QVarLengthArray<QTextLayout::FormatRange> colorChanges; engine.mergeFormats(textLayout, &colorChanges); lineCount = lineCount >= 0 ? qMin(lineStart + lineCount, textLayout->lineCount()) : textLayout->lineCount(); for (int i=lineStart; i<lineCount; ++i) { QTextLine line = textLayout->lineAt(i); int start = line.textStart(); int length = line.textLength(); int end = start + length; #if QT_CONFIG(im) if (preeditPosition >= 0 && preeditPosition >= start && preeditPosition < end) { end += preeditLength; } #endif engine.setCurrentLine(line); engine.addGlyphsForRanges(colorChanges, start, end, selectionStart, selectionEnd); } engine.addToSceneGraph(this, style, styleColor); }
//! [2] void ElidedLabel::paintEvent(QPaintEvent *event) { QFrame::paintEvent(event); QPainter painter(this); QFontMetrics fontMetrics = painter.fontMetrics(); bool didElide = false; int lineSpacing = fontMetrics.lineSpacing(); int y = 0; QTextLayout textLayout(content, painter.font()); textLayout.beginLayout(); forever { QTextLine line = textLayout.createLine(); if (!line.isValid()) break; line.setLineWidth(width()); int nextLineY = y + lineSpacing; if (height() >= nextLineY + lineSpacing) { line.draw(&painter, QPoint(0, y)); y = nextLineY; //! [2] //! [3] } else { QString lastLine = content.mid(line.textStart()); QString elidedLastLine = fontMetrics.elidedText(lastLine, Qt::ElideRight, width()); painter.drawText(QPoint(0, y + fontMetrics.ascent()), elidedLastLine); line = textLayout.createLine(); didElide = line.isValid(); break; } } textLayout.endLayout(); //! [3] //! [4] if (didElide != elided) { elided = didElide; emit elisionChanged(didElide); } }
void ElidedLabel::paintEvent(QPaintEvent *event) { QLabel::paintEvent(event); QPainter painter(this); QFontMetrics fontMetrics = painter.fontMetrics(); QRect cr = contentsRect(); cr.adjust(margin(), margin(), -margin(), -margin()); bool didElide = false; int lineSpacing = fontMetrics.lineSpacing(); int x, y = x =cr.top()+(cr.height()-lineSpacing)/2; QTextLayout textLayout(mContent, painter.font()); textLayout.beginLayout(); forever { QTextLine line = textLayout.createLine(); if (!line.isValid()) break; line.setLineWidth(cr.width()+2*x); int nextLineY = y + lineSpacing; if (cr.height() >= nextLineY + lineSpacing) { line.draw(&painter, QPoint(x, y)); y = nextLineY; } else { QString lastLine = mContent.mid(line.textStart()); QString elidedLastLine = fontMetrics.elidedText(lastLine, Qt::ElideRight, cr.width()); painter.drawText(QPoint(x, y + fontMetrics.ascent()), elidedLastLine); line = textLayout.createLine(); didElide = line.isValid(); break; } } textLayout.endLayout(); if (didElide != mElided) { mElided = didElide; emit elisionChanged(didElide); } }
int QQuickTextNodeEngine::addText(const QTextBlock &block, const QTextCharFormat &charFormat, const QColor &textColor, const QVarLengthArray<QTextLayout::FormatRange> &colorChanges, int textPos, int fragmentEnd, int selectionStart, int selectionEnd) { if (charFormat.foreground().style() != Qt::NoBrush) setTextColor(charFormat.foreground().color()); else setTextColor(textColor); while (textPos < fragmentEnd) { int blockRelativePosition = textPos - block.position(); QTextLine line = block.layout()->lineForTextPosition(blockRelativePosition); if (!currentLine().isValid() || line.lineNumber() != currentLine().lineNumber()) { setCurrentLine(line); } Q_ASSERT(line.textLength() > 0); int lineEnd = line.textStart() + block.position() + line.textLength(); int len = qMin(lineEnd - textPos, fragmentEnd - textPos); Q_ASSERT(len > 0); int currentStepEnd = textPos + len; addGlyphsForRanges(colorChanges, textPos - block.position(), currentStepEnd - block.position(), selectionStart - block.position(), selectionEnd - block.position()); textPos = currentStepEnd; } return textPos; }
// FIXME: we need to figure out a way to derive from Fm::FolderItemDelegate to avoid code duplication. void DesktopItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { Q_ASSERT(index.isValid()); QStyleOptionViewItemV4 opt = option; initStyleOption(&opt, index); painter->save(); painter->setClipRect(option.rect); opt.decorationAlignment = Qt::AlignHCenter | Qt::AlignTop; opt.displayAlignment = Qt::AlignTop | Qt::AlignHCenter; // draw the icon QIcon::Mode iconMode; if(opt.state & QStyle::State_Enabled) { if(opt.state & QStyle::State_Selected) iconMode = QIcon::Selected; else { iconMode = QIcon::Normal; } } else iconMode = QIcon::Disabled; QPoint iconPos(opt.rect.x() + (opt.rect.width() - opt.decorationSize.width()) / 2, opt.rect.y()); QPixmap pixmap = opt.icon.pixmap(opt.decorationSize, iconMode); painter->drawPixmap(iconPos, pixmap); // draw some emblems for the item if needed // we only support symlink emblem at the moment FmFileInfo* file = static_cast<FmFileInfo*>(index.data(Fm::FolderModel::FileInfoRole).value<void*>()); if(file) { if(fm_file_info_is_symlink(file)) { painter->drawPixmap(iconPos, symlinkIcon_.pixmap(opt.decorationSize / 2, iconMode)); } } // draw text QRectF textRect(opt.rect.x(), opt.rect.y() + opt.decorationSize.height(), opt.rect.width(), opt.rect.height() - opt.decorationSize.height()); QTextLayout layout(opt.text, opt.font); QTextOption textOption; textOption.setAlignment(opt.displayAlignment); textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); textOption.setTextDirection(opt.direction); layout.setTextOption(textOption); qreal height = 0; qreal width = 0; int visibleLines = 0; layout.beginLayout(); QString elidedText; for(;;) { QTextLine line = layout.createLine(); if(!line.isValid()) break; line.setLineWidth(textRect.width()); height += opt.fontMetrics.leading(); line.setPosition(QPointF(0, height)); if((height + line.height() + textRect.y()) > textRect.bottom()) { // if part of this line falls outside the textRect, ignore it and quit. QTextLine lastLine = layout.lineAt(visibleLines - 1); elidedText = opt.text.mid(lastLine.textStart()); elidedText = opt.fontMetrics.elidedText(elidedText, opt.textElideMode, textRect.width()); break; } height += line.height(); width = qMax(width, line.naturalTextWidth()); ++ visibleLines; } layout.endLayout(); QRectF boundRect = layout.boundingRect(); boundRect.setWidth(width); boundRect.moveTo(textRect.x() + (textRect.width() - width)/2, textRect.y()); if((opt.state & QStyle::State_Selected) && opt.widget) { QPalette palette = opt.widget->palette(); // qDebug("w: %f, h:%f, m:%f", boundRect.width(), boundRect.height(), layout.minimumWidth()); painter->fillRect(boundRect, palette.highlight()); } else { // only draw shadow for non-selected items // draw shadow, FIXME: is it possible to use QGraphicsDropShadowEffect here? QPen prevPen = painter->pen(); painter->setPen(QPen(shadowColor_)); for(int i = 0; i < visibleLines; ++i) { QTextLine line = layout.lineAt(i); if(i == (visibleLines - 1) && !elidedText.isEmpty()) { // the last line, draw elided text QPointF pos(textRect.x() + line.position().x() + 1, textRect.y() + line.y() + line.ascent() + 1); painter->drawText(pos, elidedText); } else { line.draw(painter, textRect.topLeft() + QPointF(1, 1)); } } painter->setPen(prevPen); } // draw text for(int i = 0; i < visibleLines; ++i) { QTextLine line = layout.lineAt(i); if(i == (visibleLines - 1) && !elidedText.isEmpty()) { // the last line, draw elided text QPointF pos(textRect.x() + line.position().x(), textRect.y() + line.y() + line.ascent()); painter->drawText(pos, elidedText); } else { line.draw(painter, textRect.topLeft()); } } if(opt.state & QStyle::State_HasFocus) { // FIXME: draw focus rect } painter->restore(); }
void KStandardItemListWidget::updateIconsLayoutTextCache() { // +------+ // | Icon | // +------+ // // Name role that // might get wrapped above // several lines. // Additional role 1 // Additional role 2 const QHash<QByteArray, QVariant> values = data(); const KItemListStyleOption& option = styleOption(); const qreal padding = option.padding; const qreal maxWidth = size().width() - 2 * padding; const qreal widgetHeight = size().height(); const qreal lineSpacing = m_customizedFontMetrics.lineSpacing(); // Initialize properties for the "text" role. It will be used as anchor // for initializing the position of the other roles. TextInfo* nameTextInfo = m_textInfo.value("text"); const QString nameText = KStringHandler::preProcessWrap(values["text"].toString()); nameTextInfo->staticText.setText(nameText); // Calculate the number of lines required for the name and the required width qreal nameWidth = 0; qreal nameHeight = 0; QTextLine line; const int additionalRolesCount = qMax(visibleRoles().count() - 1, 0); const int maxNameLines = (option.maxTextSize.height() / int(lineSpacing)) - additionalRolesCount; QTextLayout layout(nameTextInfo->staticText.text(), m_customizedFont); layout.setTextOption(nameTextInfo->staticText.textOption()); layout.beginLayout(); int nameLineIndex = 0; while ((line = layout.createLine()).isValid()) { line.setLineWidth(maxWidth); nameWidth = qMax(nameWidth, line.naturalTextWidth()); nameHeight += line.height(); ++nameLineIndex; if (nameLineIndex == maxNameLines) { // The maximum number of textlines has been reached. If this is // the case provide an elided text if necessary. const int textLength = line.textStart() + line.textLength(); if (textLength < nameText.length()) { // Elide the last line of the text QString lastTextLine = nameText.mid(line.textStart(), line.textLength()); lastTextLine = m_customizedFontMetrics.elidedText(lastTextLine, Qt::ElideRight, line.naturalTextWidth() - 1); const QString elidedText = nameText.left(line.textStart()) + lastTextLine; nameTextInfo->staticText.setText(elidedText); } break; } } layout.endLayout(); // Use one line for each additional information nameTextInfo->staticText.setTextWidth(maxWidth); nameTextInfo->pos = QPointF(padding, widgetHeight - nameHeight - additionalRolesCount * lineSpacing - padding); m_textRect = QRectF(padding + (maxWidth - nameWidth) / 2, nameTextInfo->pos.y(), nameWidth, nameHeight); // Calculate the position for each additional information qreal y = nameTextInfo->pos.y() + nameHeight; foreach (const QByteArray& role, m_sortedVisibleRoles) { if (role == "text") { continue; } const QString text = roleText(role, values); TextInfo* textInfo = m_textInfo.value(role); textInfo->staticText.setText(text); qreal requiredWidth = 0; QTextLayout layout(text, m_customizedFont); QTextOption textOption; textOption.setWrapMode(QTextOption::NoWrap); layout.setTextOption(textOption); layout.beginLayout(); QTextLine textLine = layout.createLine(); if (textLine.isValid()) { textLine.setLineWidth(maxWidth); requiredWidth = textLine.naturalTextWidth(); if (requiredWidth > maxWidth) { const QString elidedText = m_customizedFontMetrics.elidedText(text, Qt::ElideRight, maxWidth); textInfo->staticText.setText(elidedText); requiredWidth = m_customizedFontMetrics.width(elidedText); } else if (role == "rating") { // Use the width of the rating pixmap, because the rating text is empty. requiredWidth = m_rating.width(); } } layout.endLayout(); textInfo->pos = QPointF(padding, y); textInfo->staticText.setTextWidth(maxWidth); const QRectF textRect(padding + (maxWidth - requiredWidth) / 2, y, requiredWidth, lineSpacing); m_textRect |= textRect; y += lineSpacing; } // Add a padding to the text rectangle m_textRect.adjust(-padding, -padding, padding, padding); }
// if painter is nullptr, the method calculate the bounding rectangle of the text and save it to textRect void FolderItemDelegate::drawText(QPainter* painter, QStyleOptionViewItemV4& opt, QRectF& textRect) const { QTextLayout layout(opt.text, opt.font); QTextOption textOption; textOption.setAlignment(opt.displayAlignment); textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); textOption.setTextDirection(opt.direction); layout.setTextOption(textOption); qreal height = 0; qreal width = 0; int visibleLines = 0; layout.beginLayout(); QString elidedText; for(;;) { QTextLine line = layout.createLine(); if(!line.isValid()) break; line.setLineWidth(textRect.width()); height += opt.fontMetrics.leading(); line.setPosition(QPointF(0, height)); if((height + line.height() + textRect.y()) > textRect.bottom()) { // if part of this line falls outside the textRect, ignore it and quit. QTextLine lastLine = layout.lineAt(visibleLines - 1); elidedText = opt.text.mid(lastLine.textStart()); elidedText = opt.fontMetrics.elidedText(elidedText, opt.textElideMode, textRect.width()); if(visibleLines == 1) // this is the only visible line width = textRect.width(); break; } height += line.height(); width = qMax(width, line.naturalTextWidth()); ++ visibleLines; } layout.endLayout(); // draw background for selected item QRectF boundRect = layout.boundingRect(); //qDebug() << "bound rect: " << boundRect << "width: " << width; boundRect.setWidth(width); boundRect.moveTo(textRect.x() + (textRect.width() - width)/2, textRect.y()); if(!painter) { // no painter, calculate the bounding rect only textRect = boundRect; return; } QPalette::ColorGroup cg = opt.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled; if(opt.state & QStyle::State_Selected) { painter->fillRect(boundRect, opt.palette.highlight()); painter->setPen(opt.palette.color(cg, QPalette::HighlightedText)); } else painter->setPen(opt.palette.color(cg, QPalette::Text)); // draw text for(int i = 0; i < visibleLines; ++i) { QTextLine line = layout.lineAt(i); if(i == (visibleLines - 1) && !elidedText.isEmpty()) { // the last line, draw elided text QPointF pos(textRect.x() + line.position().x(), textRect.y() + line.y() + line.ascent()); painter->drawText(pos, elidedText); } else { line.draw(painter, textRect.topLeft()); } } if(opt.state & QStyle::State_HasFocus) { // draw focus rect QStyleOptionFocusRect o; o.QStyleOption::operator=(opt); o.rect = boundRect.toRect(); // subElementRect(SE_ItemViewItemFocusRect, vopt, widget); o.state |= QStyle::State_KeyboardFocusChange; o.state |= QStyle::State_Item; QPalette::ColorGroup cg = (opt.state & QStyle::State_Enabled) ? QPalette::Normal : QPalette::Disabled; o.backgroundColor = opt.palette.color(cg, (opt.state & QStyle::State_Selected) ? QPalette::Highlight : QPalette::Window); if (const QWidget* widget = opt.widget) { QStyle* style = widget->style() ? widget->style() : qApp->style(); style->drawPrimitive(QStyle::PE_FrameFocusRect, &o, painter, widget); } } }
ReportItem::PrintResult ReportItemPara::printMetaPaintChildren(ReportItemMetaPaint *out, const ReportItem::Rect &bounding_rect) { qfLogFuncFrame() << this << bounding_rect.toString(); PrintResult res = PR_PrintedOk; if(m_indexToPrint == 0) { printedText = paraText(); } //qfInfo() << printedText; QString text = printedText.mid(m_indexToPrint); int initial_index_to_print = m_indexToPrint; QString sql_id = sqlId(); /// tiskne se prazdny text bool omit_empty_text = isOmitEmptyText(); if(text.isEmpty() && omit_empty_text) { } else { QString text_to_layout = text; //qfWarning() << "length: " << text.length() << " text: [" << text << "]\n" << text.toUtf8().toHex(); bool text_item_should_be_created = true; style::CompiledTextStyle style; style::Text *p_text_style = effectiveTextStyle(); if(p_text_style) { style = p_text_style->textStyle(); } QFontMetricsF font_metrics = processor()->fontMetrics(style.font()); QTextOption text_option; { if(isTextWrap()) text_option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); //alignment_flags |= Qt::TextWordWrap; int al = textHAlign() | textVAlign(); Qt::Alignment alignment_flags = (Qt::Alignment)al; text_option.setAlignment(alignment_flags); } Rect rendered_bounding_rect; /// velikost boundingRect je v mm, tak to prepocitej na body vystupniho zarizeni rendered_bounding_rect = qmlwidgets::graphics::mm2device(bounding_rect, processor()->paintDevice()); bool render_check_mark = false; QRegExp rx = ReportItemMetaPaint::checkReportSubstitutionRegExp; if(rx.exactMatch(text_to_layout)) { //bool check_on = rx.capturedTexts().value(1) == "1"; rendered_bounding_rect = font_metrics.boundingRect('X'); render_check_mark = true; m_indexToPrint += text_to_layout.length(); } else { if(text_to_layout.isEmpty()) { /// neni omitEmptyString, takze i prazdnej text vyrendruj alespon jako mezeru aby se na to dalo treba kliknout text_to_layout = ' '; } //text.replace(ReportItemMetaPaint::checkOnReportSubstitution, "X"); //text.replace(ReportItemMetaPaint::checkOffReportSubstitution, "X"); //qfInfo().noSpace().color(QFLog::Green) << "index to print: " << indexToPrint << " text: '" << text << "'"; //qfInfo() << "bounding rect:" << bounding_rect.toString(); //qfWarning() << "device physical DPI:" << processor()->paintDevice()->physicalDpiX() << processor()->paintDevice()->physicalDpiY(); //qfWarning().noSpace() << "'" << text << "' font metrics: " << br.toString(); //QString text = element.text().simplified().replace("\\n", "\n"); //qfInfo() << "br:" << br.toString(); //Rect br_debug = br; //bool splitted = false; /// do layout { qreal leading = font_metrics.leading(); qreal height = 0; qreal width = 0; textLayout.setFont(style.font()); textLayout.setTextOption(text_option); textLayout.setText(text_to_layout); textLayout.beginLayout(); bool finished = false; while (!finished) { QTextLine line = textLayout.createLine(); finished = !line.isValid(); if(!finished) { line.setLineWidth(rendered_bounding_rect.width()); /// setWidth() nastavi spravne line.height(), proto musi byt pred merenim popsane vysky. if((line.textLength() == 0) && (line.textStart() + line.textLength() == text_to_layout.length())) { /// nevim kde je chyba, pri vicerakovych textech mi to pridava jeden prazdnej radek na konec, takhle se tomu snazim zabranit (Qt 4.6.3) finished = true; } else { qreal interline_space = (height > 0)? leading: 0; if(height + interline_space + line.height() > rendered_bounding_rect.height()) { res = PR_PrintAgainOnNextPage; if(height == 0) { /// nevejde se ani jeden radek text_item_should_be_created = false; break; } else { /// neco se preci jenom veslo int pos = line.textStart(); m_indexToPrint += pos; break; } } height += interline_space; line.setPosition(QPointF(0., height)); height += line.height(); width = qMax(width, line.naturalTextWidth()); } } if(finished) { m_indexToPrint = printedText.length(); } } textLayout.endLayout(); rendered_bounding_rect.setWidth(width); rendered_bounding_rect.setHeight(height); } } /// velikost boundingRect je v bodech vystupniho zarizeni, tak to prepocitej na mm rendered_bounding_rect = qmlwidgets::graphics::device2mm(rendered_bounding_rect, processor()->paintDevice()); /// rendered rect is left aligned, if text is reight aligned or centered, the ReportItemMetaPaintText::paint() does it if(text_item_should_be_created ) { ReportItemMetaPaintText *mt; if(render_check_mark ) mt = new ReportItemMetaPaintCheck(out, this); else { mt = new ReportItemMetaPaintText(out, this); mt->sqlId = sql_id; //--mt->editGrants = elementAttribute("editGrants"); } //qfInfo() << "creating item:" << mt; mt->pen = style.pen(); mt->font = style.font(); mt->text = text.mid(0, m_indexToPrint - initial_index_to_print); //qfWarning() << "text:" << text; mt->textOption = text_option; mt->renderedRect = rendered_bounding_rect; mt->renderedRect.flags = designedRect.flags; } //qfDebug().color(QFLog::Green, QFLog::Red) << "\tleading:" << processor()->fontMetrics(style.font).leading() << "\theight:" << processor()->fontMetrics(style.font).height(); qfDebug() << "\tchild rendered rect:" << rendered_bounding_rect.toString(); } qfDebug() << "\t<<< CHILDREN paraText return:" << res.toString(); return res; }
void BaseEditor::paintEvent(QPaintEvent *e) { //copy from QPlainTextEditor QPainter painter(viewport()); Q_ASSERT(qobject_cast<QPlainTextDocumentLayout*>(document()->documentLayout())); QPointF offset(contentOffset()); QRect er = e->rect(); QRect viewportRect = viewport()->rect(); bool editable = !isReadOnly(); QTextBlock block = firstVisibleBlock(); qreal maximumWidth = document()->documentLayout()->documentSize().width(); //margin qreal lineX = 0; if (conf->isDisplayRightColumnMargin()) { // Don't use QFontMetricsF::averageCharWidth here, due to it returning // a fractional size even when this is not supported by the platform. lineX = QFontMetricsF(document()->defaultFont()).width(QLatin1Char('X')) * conf->getRightMarginColumn() + offset.x() + 4; if (lineX < viewportRect.width()) { const QBrush background = QBrush(QColor(239, 239, 239)); painter.fillRect(QRectF(lineX, er.top(), viewportRect.width() - lineX, er.height()), background); const QColor col = (palette().base().color().value() > 128) ? Qt::black : Qt::white; const QPen pen = painter.pen(); painter.setPen(blendColors(background.isOpaque() ? background.color() : palette().base().color(), col, 32)); painter.drawLine(QPointF(lineX, er.top()), QPointF(lineX, er.bottom())); painter.setPen(pen); } } // Set a brush origin so that the WaveUnderline knows where the wave started painter.setBrushOrigin(offset); // keep right margin clean from full-width selection int maxX = offset.x() + qMax((qreal)viewportRect.width(), maximumWidth) - document()->documentMargin(); er.setRight(qMin(er.right(), maxX)); painter.setClipRect(er); QAbstractTextDocumentLayout::PaintContext context = getPaintContext(); while (block.isValid()) { QRectF r = blockBoundingRect(block).translated(offset); QTextLayout *layout = block.layout(); if (!block.isVisible()) { offset.ry() += r.height(); block = block.next(); continue; } if (r.bottom() >= er.top() && r.top() <= er.bottom()) { QTextBlockFormat blockFormat = block.blockFormat(); QBrush bg = blockFormat.background(); if (bg != Qt::NoBrush) { QRectF contentsRect = r; contentsRect.setWidth(qMax(r.width(), maximumWidth)); fillBackground(&painter, contentsRect, bg); } QVector<QTextLayout::FormatRange> selections; int blpos = block.position(); int bllen = block.length(); 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 && selEnd > selStart) { QTextLayout::FormatRange o; o.start = selStart; o.length = selEnd - selStart; o.format = range.format; selections.append(o); } else if (!range.cursor.hasSelection() && range.format.hasProperty(QTextFormat::FullWidthSelection) && block.contains(range.cursor.position())) { // for full width selections we don't require an actual selection, just // a position to specify the line. that's more convenience in usage. QTextLayout::FormatRange o; QTextLine l = layout->lineForTextPosition(range.cursor.position() - blpos); o.start = l.textStart(); o.length = l.textLength(); if (o.start + o.length == bllen - 1) ++o.length; // include newline o.format = range.format; selections.append(o); } } bool drawCursor = ((editable || (textInteractionFlags() & Qt::TextSelectableByKeyboard)) && context.cursorPosition >= blpos && context.cursorPosition < blpos + bllen); bool drawCursorAsBlock = drawCursor && overwriteMode() ; if (drawCursorAsBlock) { if (context.cursorPosition == blpos + bllen - 1) { drawCursorAsBlock = false; } else { QTextLayout::FormatRange o; o.start = context.cursorPosition - blpos; o.length = 1; o.format.setForeground(palette().base()); o.format.setBackground(palette().text()); selections.append(o); } } layout->draw(&painter, offset, selections, er); if ((drawCursor && !drawCursorAsBlock) || (editable && context.cursorPosition < -1 && !layout->preeditAreaText().isEmpty())) { int cpos = context.cursorPosition; if (cpos < -1) cpos = layout->preeditAreaPosition() - (cpos + 2); else cpos -= blpos; layout->drawCursor(&painter, offset, cpos, cursorWidth()); } } offset.ry() += r.height(); if (offset.y() > viewportRect.height()) break; block = block.next(); } if (backgroundVisible() && !block.isValid() && offset.y() <= er.bottom() && (centerOnScroll() || verticalScrollBar()->maximum() == verticalScrollBar()->minimum())) { painter.fillRect(QRect(QPoint((int)er.left(), (int)offset.y()), er.bottomRight()), palette().background()); } }