Example #1
0
void JSEdit::unfold(int line)
{
    QTextBlock startBlock = document()->findBlockByNumber(line - 1);
    int endPos = findClosingConstruct(startBlock);

    QTextBlock block = startBlock.next();
    while (block.isValid() && !block.isVisible()) {
        block.setVisible(true);
        block.setLineCount(block.layout()->lineCount());
        endPos = block.position() + block.length();
        block = block.next();
    }

    document()->markContentsDirty(startBlock.position(), endPos - startBlock.position() + 1);
    updateSidebar();
    update();

    JSDocLayout *layout = reinterpret_cast<JSDocLayout*>(document()->documentLayout());
    layout->forceUpdate();
}
void MgLinesNumbersExtraArea::paintEvent(QPaintEvent *e)
{
    QRect rect = e->rect();
    QPalette pal = palette();
    pal.setCurrentColorGroup(QPalette::Active);
    QPainter painter(this);
    painter.fillRect(rect, Qt::lightGray);
    const QFontMetrics fm(m_editor->fontMetrics());

    int linesNumbersAreaWidth = width();

    painter.fillRect(rect, Qt::white);//lines numbers

    painter.setPen(QPen(pal.color(QPalette::Background), 2));
    painter.drawLine(rect.x() + linesNumbersAreaWidth-1, rect.top(), rect.x() + linesNumbersAreaWidth-1, rect.bottom());

    painter.setRenderHint(QPainter::Antialiasing);

    QTextBlock block = m_editor->firstVisibleBlock();
    int blockNumber = block.blockNumber();
    qreal top = m_editor->blockBoundingGeometry(block).translated(m_editor->contentOffset()).top();
    qreal bottom = top + m_editor->blockBoundingRect(block).height();

    painter.setPen(QColor(Qt::gray));
    while (block.isValid() && top <= rect.bottom())
    {
        if (block.isVisible() && bottom >= rect.top())
        {

            int lineNumber = blockNumber + m_editor->baseLineNumber();
            QString number = QString::number(lineNumber);
            painter.drawText(rect.x() , (int)top, rect.x() + linesNumbersAreaWidth  - 4,
                             fm.height(), Qt::AlignCenter, number);
        }

        block = block.next();
        top = bottom;
        bottom = top + m_editor->blockBoundingRect(block).height();
        ++blockNumber;
    }
}
Example #3
0
QRectF TextDocumentLayout::blockBoundingRect(const QTextBlock &block) const
{
    if (!block.isValid()) { return QRectF(); }
    QTextLayout *tl = block.layout();

    if (!tl->lineCount())
        const_cast<TextDocumentLayout*>(this)->layoutBlock(block);


    QRectF br;
    if (block.isVisible()) {
        br = QRectF(QPointF(0, 0), tl->boundingRect().bottomRight());
        if (tl->lineCount() == 1)
            br.setWidth(qMax(br.width(), tl->lineAt(0).naturalTextWidth()));
        qreal margin = document()->documentMargin();
        br.adjust(0, 0, margin, 0);
        if (!block.next().isValid())
            br.adjust(0, 0, 0, margin);
    }
    return br;
}
Example #4
0
void CodeEditor::paintHandleArea(QPaintEvent *event)
{
    QPainter painter(d_numberArea);
    painter.fillRect(event->rect(), QColor(224,224,224) );

    QTextBlock block = firstVisibleBlock();
    int blockNumber = block.blockNumber();
    int top = (int) blockBoundingGeometry(block).translated(contentOffset()).top();
    int bottom = top + (int) blockBoundingRect(block).height();

    const int w = fontMetrics().width('w') + 2;
    const int h = fontMetrics().height();
    while (block.isValid() && top <= event->rect().bottom())
    {
        painter.setPen(Qt::black);
        if( d_breakPoints.contains( blockNumber ) )
        {
            const QRect r = QRect( 0, top, d_numberArea->width(), h );
            painter.fillRect( r, Qt::darkRed );
            painter.setPen(Qt::white);
        }
        if( d_showNumbers && block.isVisible() && bottom >= event->rect().top())
        {
            QString number = QString::number(blockNumber + 1);
            painter.drawText(0, top, d_numberArea->width() - 2, h, Qt::AlignRight, number);
        }
        if( blockNumber == d_curPos )
        {
            const QRect r = QRect( d_numberArea->width() - w, top, w, h );
            painter.setBrush(Qt::yellow);
            painter.setPen(Qt::black);
            painter.drawPolygon( QPolygon() << r.topLeft() << r.bottomLeft() << r.adjusted(0,0,0,-h/2).bottomRight() );
        }

        block = block.next();
        top = bottom;
        bottom = top + (int) blockBoundingRect(block).height();
        ++blockNumber;
    }
}
Example #5
0
void CodeEditor::lineNumberAreaPaintEvent(QPaintEvent *event)
 {
    QPainter painter(lineNumberArea);
    painter.fillRect(event->rect(), Qt::lightGray);
    QTextBlock block = firstVisibleBlock();
    int blockNumber = block.blockNumber();
    int top = (int) blockBoundingGeometry(block).translated(contentOffset()).top();
    int bottom = top + (int) blockBoundingRect(block).height();
    while (block.isValid() && top <= event->rect().bottom()) {
        if (block.isVisible() && bottom >= event->rect().top()) {
             QString number = QString::number(blockNumber + 1);
             painter.setPen(Qt::black);
             painter.drawText(0, top, lineNumberArea->width(), fontMetrics().height(),
                              Qt::AlignRight, number);
        }
        block = block.next();
        top = bottom;
        bottom = top + (int) blockBoundingRect(block).height();
        ++blockNumber;
    }

}
Example #6
0
void ScriptTextEdit::lineNumberAreaPaintEvent(QPaintEvent *event)
{
	int lineAreaWidth = mLineNumberArea->width();
	QPainter painter(mLineNumberArea);
	painter.fillRect(event->rect(), Qt::white);

	QPen linepen;
	linepen.setWidth(1);
	linepen.setColor( Qt::lightGray );
	painter.setPen(linepen);
	painter.drawLine(lineAreaWidth-1,0,lineAreaWidth-1,mLineNumberArea->height());


	int currentLine = textCursor().blockNumber();
	QTextBlock block = firstVisibleBlock();
	int blockNumber = block.blockNumber();
	QFont font=painter.font();
	int top = (int) blockBoundingGeometry(block).translated(contentOffset()).top();
	int bottom = top + (int) blockBoundingRect(block).height();
	while (block.isValid() && top <= event->rect().bottom())
	{
		if (block.isVisible() && bottom >= event->rect().top())
		{
			QString number = QString::number(blockNumber + 1);
			painter.setPen(Qt::darkGray);
			font.setBold(blockNumber==currentLine);
			painter.setFont( font );
			painter.drawText(-2, top, lineAreaWidth, fontMetrics().height(),
							 Qt::AlignRight | Qt::AlignVCenter, number);
		}

		block = block.next();
		top = bottom;
		bottom = top + (int) blockBoundingRect(block).height();
		++blockNumber;
	}
}
Example #7
0
void CodeEditor::lineNumberAreaPaintEvent(QPaintEvent *event)
{
    //paint on line number area
    QPainter painter(lineNumberArea);
    painter.fillRect(event->rect(), settings.value("linenumberpanelcolor", palette().color(QPalette::Window)).value<QColor>());

    QTextBlock block = firstVisibleBlock();
    int blockNumber = block.blockNumber();
    int top = (int) blockBoundingGeometry(block).translated(contentOffset()).top();
    int bottom = top + (int) blockBoundingRect(block).height();

    while (block.isValid() && top <= event->rect().bottom()) {
        if (block.isVisible() && bottom >= event->rect().top()) {
            QString number = QString::number(blockNumber + 1);
            painter.setPen(settings.value("fontcolor", palette().color(QPalette::Text)).value<QColor>());
            painter.drawText(0, top, lineNumberArea->width() - debugAreaWidth, fontMetrics().height(),
                             Qt::AlignRight, number);

            if (blockNumber + 1 == currentDebugLine)
                //blocks counting starts with 0, line number is equivalent (block number + 1)
                //if QTextOption::NoWrap is not set, lines count - visible lines, block count - lines divided by '\n'
                painter.drawPixmap(lineNumberArea->width() - debugAreaWidth + 3,
                                   top + fontMetrics().height() / 2 - debugImage.height() / 2,
                                   debugImage.width(), debugImage.height(), debugImage);
            if (breakpoints.contains(blockNumber + 1) && hasBreakpoints)
                painter.drawPixmap(lineNumberArea->width() - debugAreaWidth + 3,
                                   top + fontMetrics().height() / 2 - breakpointImage.height() / 2,
                                   breakpointImage.width(), breakpointImage.height(), breakpointImage);
        }

        block = block.next();
        top = bottom;
        bottom = top + (int) blockBoundingRect(block).height();
        ++blockNumber;
    }
}
Example #8
0
void PgxConsole::promptPaintEvent(QPaintEvent *event)
{
     QPainter painter(prompt);
     QTextBlock block = firstVisibleBlock();
     int blockNumber = block.blockNumber();
     int top = (int) blockBoundingGeometry(block).translated(contentOffset()).top();
     int bottom = top + (int) blockBoundingRect(block).height();
     while (block.isValid() && top <= event->rect().bottom()) {
        if (block.isVisible() && bottom >= event->rect().top()) {
            QString pr = QLatin1String(">");
            QString number;
            if(block.previous().isVisible() && block.previous().isValid()) {
                number = QString::number(blockNumber + 1);
                if(block.previous().text().endsWith("\\"))
                    pr = QLatin1String(" ");
                else
                    pr = QLatin1String(">");
            }

            if(block.text().endsWith("\\")) {
                if(block.previous().text().endsWith("\\"))
                    pr = QLatin1String(" ");
                else
                    pr = QLatin1String(">");
            }
            painter.setPen(Qt::lightGray);
            painter.drawText(0, top, prompt->width(), fontMetrics().height(),
                             Qt::AlignCenter, pr);
        }

        block = block.next();
        top = bottom;
        bottom = top + (int) blockBoundingRect(block).height();
        ++blockNumber;
    }
}
Example #9
0
void BaseTextDocumentLayout::FoldValidator::process(QTextBlock block)
{
    if (!m_layout)
        return;

    const QTextBlock &previous = block.previous();
    if (!previous.isValid())
        return;

    if ((BaseTextDocumentLayout::isFolded(previous)
            && !BaseTextDocumentLayout::canFold(previous))
            || (!BaseTextDocumentLayout::isFolded(previous)
                && BaseTextDocumentLayout::canFold(previous)
                && !block.isVisible())) {
        BaseTextDocumentLayout::setFolded(previous, !BaseTextDocumentLayout::isFolded(previous));
    }

    if (BaseTextDocumentLayout::isFolded(previous) && !m_insideFold)
        m_insideFold = BaseTextDocumentLayout::foldingIndent(block);

    bool toggleVisibility = false;
    if (m_insideFold) {
        if (BaseTextDocumentLayout::foldingIndent(block) >= m_insideFold) {
            if (block.isVisible())
                toggleVisibility = true;
        } else {
            m_insideFold = 0;
            if (!block.isVisible())
                toggleVisibility = true;
        }
    } else if (!block.isVisible()) {
        toggleVisibility = true;
    }

    if (toggleVisibility) {
        block.setVisible(!block.isVisible());
        block.setLineCount(block.isVisible() ? qMax(1, block.layout()->lineCount()) : 0);
        m_requestDocUpdate = true;
    }
}
Example #10
0
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);
}
Example #11
0
void QScriptEdit::extraAreaPaintEvent(QPaintEvent *e)
{
    QRect rect = e->rect();
    QPalette pal = palette();
    pal.setCurrentColorGroup(QPalette::Active);
    QPainter painter(m_extraArea);
    painter.fillRect(rect, Qt::lightGray);
    const QFontMetrics fm(fontMetrics());

    int markWidth = fm.lineSpacing();
    int extraAreaWidth = m_extraArea->width();

    QLinearGradient gradient(QPointF(extraAreaWidth - 10, 0), QPointF(extraAreaWidth, 0));
    gradient.setColorAt(0, pal.color(QPalette::Background));
    gradient.setColorAt(1, pal.color(QPalette::Base));
    painter.fillRect(rect, gradient);

    QLinearGradient gradient2(QPointF(0, 0), QPointF(markWidth, 0));
    gradient2.setColorAt(0, pal.color(QPalette::Dark));
    gradient2.setColorAt(1, pal.color(QPalette::Background));
    painter.fillRect(rect.intersected(QRect(rect.x(), rect.y(), markWidth, rect.height())), gradient2);

    painter.setPen(QPen(pal.color(QPalette::Background), 2));
    if (isLeftToRight())
        painter.drawLine(rect.x() + extraAreaWidth-1, rect.top(), rect.x() + extraAreaWidth-1, rect.bottom());
    else
        painter.drawLine(rect.x(), rect.top(), rect.x(), rect.bottom());
    painter.setRenderHint(QPainter::Antialiasing);

    QTextBlock block = firstVisibleBlock();
    int blockNumber = block.blockNumber();
    qreal top = blockBoundingGeometry(block).translated(contentOffset()).top();
    qreal bottom = top + blockBoundingRect(block).height();

    QString imagesPath = QString::fromLatin1(":/qt/scripttools/debugging/images");
    QString imageExt;
// SVGs don't work on all platforms, even when QT_NO_SVG is not defined, so disable SVG usage for now.
// #ifndef QT_NO_SVG
#if 0
    imageExt = QString::fromLatin1("svg");
#else
    imageExt = QString::fromLatin1("png");
#endif

    while (block.isValid() && top <= rect.bottom()) {
        if (block.isVisible() && bottom >= rect.top()) {

            int lineNumber = blockNumber + m_baseLineNumber;
            if (m_breakpoints.contains(lineNumber)) {
                int radius = fm.lineSpacing() - 1;
                QRect r(rect.x(), (int)top, radius, radius);
                QIcon icon(m_breakpoints[lineNumber].enabled
                           ? QString::fromLatin1("%0/breakpoint.%1").arg(imagesPath).arg(imageExt)
                           : QString::fromLatin1("%0/d_breakpoint.%1").arg(imagesPath).arg(imageExt));
                icon.paint(&painter, r, Qt::AlignCenter);
            }
            if (m_executionLineNumber == lineNumber) {
                int radius = fm.lineSpacing() - 1;
                QRect r(rect.x(), (int)top, radius, radius);
                QIcon icon(QString::fromLatin1("%0/location.%1").arg(imagesPath).arg(imageExt));
                icon.paint(&painter, r, Qt::AlignCenter);
            }

            if (!isExecutableLine(lineNumber))
                painter.setPen(pal.color(QPalette::Mid));
            else
                painter.setPen(QColor(Qt::darkCyan));
            QString number = QString::number(lineNumber);
            painter.drawText(rect.x() + markWidth, (int)top, rect.x() + extraAreaWidth - markWidth - 4,
                             fm.height(), Qt::AlignRight, number);
        }

        block = block.next();
        top = bottom;
        bottom = top + blockBoundingRect(block).height();
        ++blockNumber;
    }
}
Example #12
0
void CodeEditor::contentsChange(int pos, int, int)
{
    QTextBlock block = textCursor().block();

    // сдвиг блока клавишей Return
    // состояние предыдущего блока может быть не верным
    if (block.userState() == Empty)
        block.setUserState(block.previous().userState() | Rehighligh);

    block = document()->findBlock(pos);

    int startBlockNum = block.blockNumber();

    bool forceUnfold = false;

    while (block.isValid()) {
        int previousState = block.userState();
        int state = setBlockState(block);

        if (!(previousState & Error) && !(state & Error) &&
            previousState & Comment  && state & Comment) {

            QTextBlock next = block.next();

            int nextBlockState = next.userState();
            setBlockState(next);
            next.setUserState(nextBlockState); // в начальное состояние

            // правильное состояние комментария известно
            // только после обработки последующей строки
            state = block.userState();
        }

        if (state != previousState) {

            if (!forceUnfold) { // разворачиваем предыдущие блоки
                QTextBlock previous = block.previous();

                while (previous.isValid()) {
                    int state = previous.userState();

                    if (!(state & Error) && state & Folded)
                        previous.setUserState(state & ~Folded);

                    if (state & Error || !(state & Nested) || previous.isVisible())
                        break;

                    previous.setVisible(true);
                    previous = previous.previous();
                }
            }

            forceUnfold = true;
        } else if (block.blockNumber() > startBlockNum && // не начальный блок
                   state & Begin && !(state & Nested)) {  // (state & Begin ...) пропускаем End главного блока
          break;                                          // без state & Error, иначе срабатывает между блоками
        }                                                 // при первом обновлении

        if (forceUnfold) { // разворачиваем последующие блоки

            if (!(state & Error) && state & Folded)
                state &= ~Folded;

            block.setVisible(true);
        }

        block.setUserState(state | Rehighligh);

        block = block.next();
    }
}
Example #13
0
void CodeEditor::extraAreaPaintEvent()
{
    QTextBlock block = firstVisibleBlock();

    QPainter painter(extraArea);
    QPen 	 pen  = painter.pen();
    QFont 	 font = painter.font();
    bool 	 bold = font.bold();

    int y  = 0;
    int cx = lineNumWidth + foldBoxIndent + foldBoxWidth / 2;  // центр маркера блока по x

    do {
        if (!block.isVisible())
            continue;

        QRectF rect = blockBoundingGeometry(block);

        y = rect.translated(contentOffset()).y();

        if (block == textCursor().block()) {
            painter.setPen(Qt::yellow);
            font.setBold(!bold);
        } else {
            font.setBold(bold);
        }

        painter.setFont(font);
        painter.drawText(0, y, lineNumWidth, fontMetrics().height(), Qt::AlignRight,
                         QString::number(block.blockNumber() + 1)); // номер строки

        painter.setPen(pen);

        int state = block.userState();

        int cy    = y + fontMetrics().height() / 2; // центр маркера по Y

        if (!(state & Error) && !(state & Begin && state & End && !(state & Nested))) {

            if (state & Begin) {

                if (state & Comment)
                    painter.drawEllipse(FOLDBOXRECT(cy));
                else
                    painter.drawRoundedRect(FOLDBOXRECT(cy), 7, 3);

                if (!(!(state & Nested) && state & Folded))
                    painter.drawLine(cx, cy + foldBoxWidth / 2, cx, y + rect.height());  // края маркера вниз

                if (state & Nested)
                    painter.drawLine(cx, y, cx, cy - foldBoxWidth / 2);                  // края маркера вверх

                painter.drawLine(cx - foldBoxLength, cy, cx + foldBoxLength, cy);        // горизонтальная линия внутри маркера

                if (state & Folded)
                    painter.drawLine(cx, cy - foldBoxLength, cx, cy + foldBoxLength);    // вертикальная линия внутри маркера

            } else if (state & End) {
                painter.drawLine(cx, cy, cx + foldBoxLength, cy);                        // от центра вправо

                if (state & Nested)
                    painter.drawLine(cx, y, cx, y + rect.height());                      // вертикальная линия
                else
                    painter.drawLine(cx, y, cx, cy);                                     // от центра вверх

            } else if (state & Nested) {
                painter.drawLine(cx, y, cx, y + rect.height());                          // вертикальная линия
            }
        }

        // в paintEvent не работает
        if (state != Empty && state & Rehighligh) {
            highlighter->rehighlightBlock(block);
            block.setUserState(state & ~Rehighligh);
        }

    } while ((block = block.next()).isValid() && y < viewport()->height());
}
Example #14
0
void TextBlockUserData::doCollapse(const QTextBlock& block, bool visible)
{
    QTextBlock info = block;
    if (block.userData() && static_cast<TextBlockUserData*>(block.userData())->collapseMode() == CollapseAfter)
        ;
    else if (block.next().userData()
             && static_cast<TextBlockUserData*>(block.next().userData())->collapseMode()
             == TextBlockUserData::CollapseThis)
        info = block.next();
    else {
        if (visible && !block.next().isVisible()) {
            // no match, at least unfold!
            QTextBlock b = block.next();
            while (b.isValid() && !b.isVisible()) {
                b.setVisible(true);
                b.setLineCount(visible ? qMax(1, b.layout()->lineCount()) : 0);
                b = b.next();
            }
        }
        return;
    }
    int pos = static_cast<TextBlockUserData*>(info.userData())->collapseAtPos();
    if (pos < 0)
        return;
    QTextCursor cursor(info);
    cursor.setPosition(cursor.position() + pos);
    if (matchCursorForward(&cursor) != Match) {
        if (visible) {
            // no match, at least unfold!
            QTextBlock b = block.next();
            while (b.isValid() && !b.isVisible()) {
                b.setVisible(true);
                b.setLineCount(visible ? qMax(1, b.layout()->lineCount()) : 0);
                b = b.next();
            }
        }
        return;
    }

    QTextBlock b = block.next();
    while (b < cursor.block()) {
        b.setVisible(visible);
        b.setLineCount(visible ? qMax(1, b.layout()->lineCount()) : 0);
        if (visible) {
            TextBlockUserData *data = canCollapse(b);
            if (data && data->collapsed()) {
                QTextBlock end =  testCollapse(b);
                if (data->collapseIncludesClosure())
                    end = end.next();
                if (end.isValid()) {
                    b = end;
                    continue;
                }
            }
        }
        b = b.next();
    }

    bool collapseIncludesClosure = hasClosingCollapseAtEnd(b);
    if (collapseIncludesClosure) {
        b.setVisible(visible);
        b.setLineCount(visible ? qMax(1, b.layout()->lineCount()) : 0);
    }
    static_cast<TextBlockUserData*>(info.userData())->setCollapseIncludesClosure(collapseIncludesClosure);
    static_cast<TextBlockUserData*>(info.userData())->setCollapsed(!block.next().isVisible());

}
Example #15
0
void SourceWindow::drawLineInfoArea(QPainter* p, QPaintEvent* event)
{
    QTextBlock block = firstVisibleBlock();

    p->setFont(m_lineNoFont);

    for (; block.isValid(); block = block.next())
    {
	if (!block.isVisible())
	    continue;

	QRect r = blockBoundingGeometry(block).translated(contentOffset()).toRect();
	if (r.bottom() < event->rect().top())
	    continue; // skip blocks that are higher than the region being updated
	else if (r.top() > event->rect().bottom())
	    break;    // all the following blocks are lower then the region being updated

	int row = block.blockNumber();
	uchar item = m_lineItems[row];

	int h = r.height();
	p->save();
	p->translate(0, r.top());

	if (item & liBP) {
	    // enabled breakpoint
	    int y = (h - m_brkena.height())/2;
	    if (y < 0) y = 0;
	    p->drawPixmap(0,y,m_brkena);
	}
	if (item & liBPdisabled) {
	    // disabled breakpoint
	    int y = (h - m_brkdis.height())/2;
	    if (y < 0) y = 0;
	    p->drawPixmap(0,y,m_brkdis);
	}
	if (item & liBPtemporary) {
	    // temporary breakpoint marker
	    int y = (h - m_brktmp.height())/2;
	    if (y < 0) y = 0;
	    p->drawPixmap(0,y,m_brktmp);
	}
	if (item & liBPconditional) {
	    // conditional breakpoint marker
	    int y = (h - m_brkcond.height())/2;
	    if (y < 0) y = 0;
	    p->drawPixmap(0,y,m_brkcond);
	}
	if (item & liBPorphan) {
	    // orphaned breakpoint marker
	    int y = (h - m_brkcond.height())/2;
	    if (y < 0) y = 0;
	    p->drawPixmap(0,y,m_brkorph);
	}
	if (item & liPC) {
	    // program counter in innermost frame
	    int y = (h - m_pcinner.height())/2;
	    if (y < 0) y = 0;
	    p->drawPixmap(0,y,m_pcinner);
	}
	if (item & liPCup) {
	    // program counter somewhere up the stack
	    int y = (h - m_pcup.height())/2;
	    if (y < 0) y = 0;
	    p->drawPixmap(0,y,m_pcup);
	}
	p->translate(m_widthItems, 0);
	if (!isRowDisassCode(row) && m_sourceCode[rowToLine(row)].canDisass) {
	    int w = m_widthPlus;
	    int x = w/2;
	    int y = h/2;
	    p->drawLine(x-2, y, x+2, y);
	    if (!isRowExpanded(row)) {
		p->drawLine(x, y-2, x, y+2);
	    }
	}
	p->translate(m_widthPlus, 0);
	if (!isRowDisassCode(row)) {
	    p->drawText(0, 0, m_widthLineNo, h, Qt::AlignRight|Qt::AlignVCenter,
			QString().setNum(rowToLine(row)+1));
	}
	p->restore();
    }
}
Example #16
0
void CodeView::lineNumberAreaPaintEvent(QPaintEvent* event)
{
    QPalette pal = QApplication::palette();

#ifdef _WIN32
    QFont font(QStringLiteral("Courier"), 11);
#else
    QFont font(QStringLiteral("Courier"), 13);
#endif

    QPainter painter(m_lineNumberArea);
    painter.fillRect(event->rect(), pal.alternateBase());

    painter.setFont(font);

    QTextBlock block = firstVisibleBlock();
    int blockNumber = block.blockNumber();
    int top = (int)blockBoundingGeometry(block).translated(contentOffset()).top();
    int bottom = top + (int)blockBoundingRect(block).height();
    int width = m_lineNumberArea->width() - 4;
    int height = fontMetrics().height();

    int fontHeight = fontMetrics().height() - 2;

    while (block.isValid() && top <= event->rect().bottom()) {
        if (block.isVisible() && bottom >= event->rect().top()) {
            QString number = QString::number(blockNumber + 1);
            painter.setPen(pal.text().color());

            painter.drawText(0, top, width, height, Qt::AlignRight, number);

            if (m_breakpoints->hasBreakpointFileLine(m_sourceFile, blockNumber + 1)) {
                painter.setBrush(Qt::red);
                painter.drawEllipse(4, top, fontHeight, fontHeight);
            }

            // Draw ugly arrow!

            if ((blockNumber + 1) == m_currentSourceLine) {
                float scale = fontHeight / 2.0f;
                float pos_x = 10.0f;
                float pos_y = top + scale;

                const QPointF points[7] = {
                    QPointF((0.0f * scale) + pos_x, (-0.5f * scale) + pos_y),
                    QPointF((0.5f * scale) + pos_x, (-0.5f * scale) + pos_y),
                    QPointF((0.5f * scale) + pos_x, (-1.0f * scale) + pos_y),

                    QPointF((1.0f * scale) + pos_x, (0.0f * scale) + pos_y),

                    QPointF((0.5f * scale) + pos_x, (1.0f * scale) + pos_y),
                    QPointF((0.5f * scale) + pos_x, (0.5f * scale) + pos_y),
                    QPointF((0.0f * scale) + pos_x, (0.5f * scale) + pos_y),
                };

                painter.setPen(Qt::yellow);
                painter.setBrush(Qt::yellow);
                painter.drawConvexPolygon(points, 7);
            }
        }

        block = block.next();
        top = bottom;
        bottom = top + (int)blockBoundingRect(block).height();
        ++blockNumber;
    }
}
Example #17
0
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());
    }
}
Example #18
0
void ScCodeEditor::blinkCode( const QTextCursor & c )
{
    if( !c.document() || !c.hasSelection() ) return;

    Settings::Manager *settings = Main::settings();
    QTextCharFormat evalCodeTextFormat = settings->getThemeVal("evaluatedCode");

    QTextDocument *doc = c.document();

    int startPos = c.selectionStart();
    int endPos = c.selectionEnd();
    QTextBlock startBlock = doc->findBlock(startPos);
    QTextBlock endBlock = doc->findBlock(endPos);
    startPos -= startBlock.position();
    endPos -= endBlock.position();

    // Get the bounds of visible blocks within the cursor's selection:

    QTextBlock block = firstVisibleBlock();
    int idx = block.blockNumber();
    int sidx = startBlock.blockNumber();

    QTextBlock firstBlock, lastBlock;
    firstBlock = lastBlock = block;

    QRectF geom = blockBoundingGeometry(block).translated(contentOffset());
    qreal top = geom.top();
    qreal bottom = top;
    qreal width=0;

    while(block.isValid() && bottom < viewport()->rect().height())
    {
        if(block.isVisible())
        {
            QTextLayout *l = block.layout();
            QRectF r = l->boundingRect();
            bottom += r.height();
            if(idx < sidx) {
                // Block not within the selection. Will skip it.
                top = bottom;
            }
            else {
                // Block within the selection.
                width = qMax(width, l->maximumWidth() + r.left());
            }
        }

        if(block == endBlock) break;

        block = block.next();
        ++idx;
        if(top == bottom)
            firstBlock = block;
    }

    lastBlock = block;

    if(bottom == top) {
        //qDebug("no visible block.");
        return;
    }

    // Construct a pixmap to render the code on:

    QPixmap pix( QSize(qCeil(width), qCeil(bottom - top)) );
    pix.fill(QColor(0,0,0,0));

    // Render the visible blocks:

    QPainter painter(&pix);
    QVector<QTextLayout::FormatRange> selections;
    block = firstBlock;
    int y=0;
    while( block.isValid() )
    {
        if (block.isVisible())
        {
            QRectF blockRect = block.layout()->boundingRect();

            // Use extra char formatting to hide code outside of selection
            // and modify the appearance of selected code:

            QTextLayout::FormatRange range;
            selections.clear();

            int start = 0;
            if(block == startBlock) {
                range.start = 0;
                range.length = startPos;
                range.format.setForeground(QColor(0,0,0,0));
                range.format.setBackground(Qt::NoBrush);
                selections.append(range);
                start = startPos;
            }

            range.start = start;
            range.length = (block == endBlock ? endPos : block.length() - 1) - range.start;
            range.format = evalCodeTextFormat;
            selections.append(range);

            if(block == endBlock) {
                range.start = range.start + range.length;
                range.length = block.length() - 1 - range.start;
                range.format.setForeground(QColor(0,0,0,0));
                range.format.setBackground(Qt::NoBrush);
                selections.append(range);
            }

            block.layout()->draw(&painter, QPointF(0,y), selections);

            y += blockRect.height();
        }

        if(block == lastBlock) break;

        block = block.next();
    }

    // Create an overlay item to display the pixmap, and animate it:

    CodeFragmentOverlay *item = new CodeFragmentOverlay();
    item->setPixmap(pix);
    item->setPos(geom.left(), top);

    mOverlay->addItem(item);

    QPropertyAnimation *anim = new QPropertyAnimation(item, "opacity", item);
    anim->setDuration(mBlinkDuration);
    anim->setStartValue(1.0);
    anim->setEndValue(0.0);
    anim->setEasingCurve( QEasingCurve::InCubic );
    anim->start();

    connect(anim, SIGNAL(finished()), item, SLOT(deleteLater()));
}
void CodeFoldingPanel::paintEvent(QPaintEvent *e)
{
    QTextDocument *doc = editorWidget()->document();
    TextDocumentLayout *documentLayout = qobject_cast<TextDocumentLayout*>(doc->documentLayout());
    if(!documentLayout)
        return;

    QPalette pal = areaWidget()->palette();
    pal.setCurrentColorGroup(QPalette::Active);
    QPainter painter(this);
    const QFontMetrics fm(areaWidget()->font());

    const int collapseColumnWidth = d->m_codeFoldingVisible ? foldBoxWidth(fm): 0;
    const int extraAreaWidth = d->m_extraArea->width() - collapseColumnWidth;

    painter.fillRect(e->rect(), pal.color(QPalette::Background));

    QTextBlock block = editorWidget()->firstVisibleBlock();
    int blockNumber = block.blockNumber();
    qreal top = editorWidget()->blockBoundingGeometry(block).translated(editorWidget()->contentOffset()).top();
    qreal bottom = top;

    while (block.isValid() && top <= e->rect().bottom()) {

        top = bottom;
        const qreal height = editorWidget()->blockBoundingRect(block).height();
        bottom = top + height;
        QTextBlock nextBlock = block.next();

        QTextBlock nextVisibleBlock = nextBlock;
        int nextVisibleBlockNumber = blockNumber + 1;

        if (!nextVisibleBlock.isVisible()) {
            // invisible blocks do have zero line count
            nextVisibleBlock = doc->findBlockByLineNumber(nextVisibleBlock.firstLineNumber());
            nextVisibleBlockNumber = nextVisibleBlock.blockNumber();
        }

        if (bottom < e->rect().top()) {
            block = nextVisibleBlock;
            blockNumber = nextVisibleBlockNumber;
            continue;
        }

        painter.setPen(pal.color(QPalette::Dark));

        painter.save();
        painter.setRenderHint(QPainter::Antialiasing, false);

        int extraAreaHighlightFoldBlockNumber = -1;
        int extraAreaHighlightFoldEndBlockNumber = -1;
        bool endIsVisible = false;
        if (!d->m_highlightBlocksInfo.isEmpty()) {
            extraAreaHighlightFoldBlockNumber =  d->m_highlightBlocksInfo.open.last();
            extraAreaHighlightFoldEndBlockNumber =  d->m_highlightBlocksInfo.close.first();
            endIsVisible = doc->findBlockByNumber(extraAreaHighlightFoldEndBlockNumber).isVisible();

//                    QTextBlock before = doc->findBlockByNumber(extraAreaHighlightCollapseBlockNumber-1);
//                    if (TextBlockUserData::hasCollapseAfter(before)) {
//                        extraAreaHighlightCollapseBlockNumber--;
//                    }
        }

        TextBlockUserData *nextBlockUserData = TextDocumentLayout::testUserData(nextBlock);

        bool drawBox = nextBlockUserData
                       && TextDocumentLayout::foldingIndent(block) < nextBlockUserData->foldingIndent();



        bool active = blockNumber == extraAreaHighlightFoldBlockNumber;

        bool drawStart = active;
        bool drawEnd = blockNumber == extraAreaHighlightFoldEndBlockNumber || (drawStart && !endIsVisible);
        bool hovered = blockNumber >= extraAreaHighlightFoldBlockNumber
                       && blockNumber <= extraAreaHighlightFoldEndBlockNumber;

        int boxWidth = foldBoxWidth(fm);
        if (hovered) {
            int itop = qRound(top);
            int ibottom = qRound(bottom);
            QRect box = QRect(extraAreaWidth + 1, itop, boxWidth - 2, ibottom - itop);
            drawRectBox(&painter, box, drawStart, drawEnd, pal);
        }

        if (drawBox) {
            bool expanded = nextBlock.isVisible();
            int size = boxWidth/4;
            QRect box(extraAreaWidth + size, top + size,
                      2 * (size) + 1, 2 * (size) + 1);
            d->drawFoldingMarker(&painter, pal, box, expanded, active, hovered);
        }


        painter.restore();

        block = nextVisibleBlock;
        blockNumber = nextVisibleBlockNumber;
    }
}
QPainterPath TextEditorOverlay::createSelectionPath(const QTextCursor &begin, const QTextCursor &end,
                                                    const QRect &clip)
{
    if (begin.isNull() || end.isNull() || begin.position() > end.position())
        return QPainterPath();

    QPointF offset = m_editor->contentOffset();
    QRect viewportRect = rect();
    QTextDocument *document = m_editor->document();

    if (m_editor->blockBoundingGeometry(begin.block()).translated(offset).top() > clip.bottom() + 10
        || m_editor->blockBoundingGeometry(end.block()).translated(offset).bottom() < clip.top() - 10
        )
        return QPainterPath(); // nothing of the selection is visible


    QTextBlock block = begin.block();

    if (block.blockNumber() < m_editor->firstVisibleBlock().blockNumber() - 4)
        block = m_editor->document()->findBlockByNumber(m_editor->firstVisibleBlock().blockNumber() - 4);

    bool inSelection = false;

    QVector<QRectF> selection;

    if (begin.position() == end.position()) {
        // special case empty selections
        const QRectF blockGeometry = m_editor->blockBoundingGeometry(block);
        QTextLayout *blockLayout = block.layout();
        int pos = begin.position() - begin.block().position();
        QTextLine line = blockLayout->lineForTextPosition(pos);
        QRectF lineRect = line.naturalTextRect();
        int x = line.cursorToX(pos);
        lineRect.setLeft(x - m_borderWidth);
        lineRect.setRight(x + m_borderWidth);
        selection += lineRect.translated(blockGeometry.topLeft());
    } else {
        for (; block.isValid() && block.blockNumber() <= end.blockNumber(); block = block.next()) {
            if (! block.isVisible())
                continue;

            const QRectF blockGeometry = m_editor->blockBoundingGeometry(block);
            QTextLayout *blockLayout = block.layout();

            QTextLine line = blockLayout->lineAt(0);
            bool firstOrLastBlock = false;

            int beginChar = 0;
            if (!inSelection) {
                if (block == begin.block()) {
                    beginChar = begin.positionInBlock();
                    line = blockLayout->lineForTextPosition(beginChar);
                    firstOrLastBlock = true;
                }
                inSelection = true;
            } else {
//                while (beginChar < block.length() && document->characterAt(block.position() + beginChar).isSpace())
//                    ++beginChar;
//                if (beginChar == block.length())
//                    beginChar = 0;
            }

            int lastLine = blockLayout->lineCount()-1;
            int endChar = -1;
            if (block == end.block()) {
                endChar = end.positionInBlock();
                lastLine = blockLayout->lineForTextPosition(endChar).lineNumber();
                inSelection = false;
                firstOrLastBlock = true;
            } else {
                endChar = block.length();
                while (endChar > beginChar && document->characterAt(block.position() + endChar - 1).isSpace())
                    --endChar;
            }

            QRectF lineRect = line.naturalTextRect();
            if (beginChar < endChar) {
                lineRect.setLeft(line.cursorToX(beginChar));
                if (line.lineNumber() == lastLine)
                    lineRect.setRight(line.cursorToX(endChar));
                selection += lineRect.translated(blockGeometry.topLeft());

                for (int lineIndex = line.lineNumber()+1; lineIndex <= lastLine; ++lineIndex) {
                    line = blockLayout->lineAt(lineIndex);
                    lineRect = line.naturalTextRect();
                    if (lineIndex == lastLine)
                        lineRect.setRight(line.cursorToX(endChar));
                    selection += lineRect.translated(blockGeometry.topLeft());
                }
            } else { // empty lines
                const int emptyLineSelectionSize = 16;
                if (!firstOrLastBlock && !selection.isEmpty()) { // middle
                    lineRect.setLeft(selection.last().left());
                } else if (inSelection) { // first line
                    lineRect.setLeft(line.cursorToX(beginChar));
                } else { // last line
                    if (endChar == 0)
                        break;
                    lineRect.setLeft(line.cursorToX(endChar) - emptyLineSelectionSize);
                }
                lineRect.setRight(lineRect.left() + emptyLineSelectionSize);
                selection += lineRect.translated(blockGeometry.topLeft());
            }

            if (!inSelection)
                break;

            if (blockGeometry.translated(offset).y() > 2*viewportRect.height())
                break;
        }
    }


    if (selection.isEmpty())
        return QPainterPath();

    QVector<QPointF> points;

    const int margin = m_borderWidth/2;
    const int extra = 0;

    const QRectF &firstSelection = selection.at(0);
    points += (firstSelection.topLeft() + firstSelection.topRight()) / 2 + QPointF(0, -margin);
    points += firstSelection.topRight() + QPointF(margin+1, -margin);
    points += firstSelection.bottomRight() + QPointF(margin+1, 0);

    const int count = selection.count();
    for (int i = 1; i < count-1; ++i) {
#define MAX3(a,b,c) qMax(a, qMax(b,c))
        qreal x = MAX3(selection.at(i-1).right(),
                       selection.at(i).right(),
                       selection.at(i+1).right()) + margin;

        points += QPointF(x+1, selection.at(i).top());
        points += QPointF(x+1, selection.at(i).bottom());
    }

    const QRectF &lastSelection = selection.at(count-1);
    points += lastSelection.topRight() + QPointF(margin+1, 0);
    points += lastSelection.bottomRight() + QPointF(margin+1, margin+extra);
    points += lastSelection.bottomLeft() + QPointF(-margin, margin+extra);
    points += lastSelection.topLeft() + QPointF(-margin, 0);

    for (int i = count-2; i > 0; --i) {
#define MIN3(a,b,c) qMin(a, qMin(b,c))
        qreal x = MIN3(selection.at(i-1).left(),
                       selection.at(i).left(),
                       selection.at(i+1).left()) - margin;

        points += QPointF(x, selection.at(i).bottom()+extra);
        points += QPointF(x, selection.at(i).top());
    }

    points += firstSelection.bottomLeft() + QPointF(-margin, extra);
    points += firstSelection.topLeft() + QPointF(-margin, -margin);


    QPainterPath path;
    const int corner = 4;
    path.moveTo(points.at(0));
    points += points.at(0);
    QPointF previous = points.at(0);
    for (int i = 1; i < points.size(); ++i) {
        QPointF point = points.at(i);
        if (point.y() == previous.y() && qAbs(point.x() - previous.x()) > 2*corner) {
            QPointF tmp = QPointF(previous.x() + corner * ((point.x() > previous.x())?1:-1), previous.y());
            path.quadTo(previous, tmp);
            previous = tmp;
            i--;
            continue;
        } else if (point.x() == previous.x() && qAbs(point.y() - previous.y()) > 2*corner) {
            QPointF tmp = QPointF(previous.x(), previous.y() + corner * ((point.y() > previous.y())?1:-1));
            path.quadTo(previous, tmp);
            previous = tmp;
            i--;
            continue;
        }


        QPointF target = (previous + point) / 2;
        path.quadTo(previous, target);
        previous = points.at(i);
    }
    path.closeSubpath();
    path.translate(offset);
    return path;
}
Example #21
0
void TextContent::drawContent(QPainter * painter, const QRect & targetRect, Qt::AspectRatioMode ratio)
{
    Q_UNUSED(ratio)

    // check whether we're drawing shaped
    const bool shapedPaint = hasShape() && !m_shapeRect.isEmpty();
    QPointF shapeOffset = m_shapeRect.topLeft();

    // scale painter for adapting the Text Rect to the Contents Rect
    QRect sourceRect = shapedPaint ? m_shapeRect : m_textRect;
    painter->save();
    painter->translate(targetRect.topLeft());
    if (sourceRect.width() > 0 && sourceRect.height() > 0) {
        qreal xScale = (qreal)targetRect.width() / (qreal)sourceRect.width();
        qreal yScale = (qreal)targetRect.height() / (qreal)sourceRect.height();
        if (!qFuzzyCompare(xScale, (qreal)1.0) || !qFuzzyCompare(yScale, (qreal)1.0))
            painter->scale(xScale, yScale);
    }

    // shape
    //const bool drawHovering = RenderOpts::HQRendering ? false : isSelected();
    if (shapedPaint)
        painter->translate(-shapeOffset);
    //if (shapedPaint && drawHovering)
    //    painter->strokePath(m_shapePath, QPen(Qt::red, 0));

    // TEMP - for PDF exporting - standard rich text document drawing
    if (RenderOpts::PDFExporting) {
        if (shapedPaint)
            QMessageBox::information(0, tr("PDF Export Warning"), tr("Shaped text could not be exported in PDF"), QMessageBox::Ok);
        QAbstractTextDocumentLayout::PaintContext pCtx;
        m_text->documentLayout()->draw(painter, pCtx);
    } else {
        // manual drawing
        QPointF blockPos = shapedPaint ? QPointF(0, 0) : -m_textRect.topLeft();

        // 1. for each Text Block
        int blockRectIdx = 0;
        for (QTextBlock tb = m_text->begin(); tb.isValid(); tb = tb.next()) {
            if (!tb.isVisible() || blockRectIdx > m_blockRects.size())
                continue;

            // 1.1. compute text insertion position
            const QRect & blockRect = m_blockRects[blockRectIdx++];
            QPointF iPos = shapedPaint ? blockPos : blockPos - blockRect.topLeft();
            blockPos += QPointF(0, blockRect.height());

            qreal curLen = 8;

            // 1.2. iterate over text fragments
            for (QTextBlock::iterator tbIt = tb.begin(); !(tbIt.atEnd()); ++tbIt) {
                QTextFragment frag = tbIt.fragment();
                if (!frag.isValid())
                    continue;

                // 1.2.1. setup painter and metrics for text fragment
                QTextCharFormat format = frag.charFormat();
                QFont font = format.font();
                painter->setFont(font);
                painter->setPen(format.foreground().color());
                painter->setBrush(Qt::NoBrush);
                QFontMetrics metrics(font);

                // 1.2.2. draw each character
                QString text = frag.text();
                foreach (const QChar & textChar, text) {
                    const qreal charWidth = metrics.width(textChar);
                    if (shapedPaint) {
                        // find point on shape and angle
                        qreal t = m_shapePath.percentAtLength(curLen);
                        QPointF pt = m_shapePath.pointAtPercent(t);
                        qreal angle = -m_shapePath.angleAtPercent(t);
                        if (m_shakeRadius > 0)
                            pt += QPointF(1 + (qrand() % m_shakeRadius) - m_shakeRadius/2, 1 + (qrand() % (2*m_shakeRadius)) - m_shakeRadius);

                        // draw rotated letter
                        painter->save();
                        painter->translate(pt);
                        painter->rotate(angle);
                        painter->drawText(iPos, textChar);
                        painter->restore();

                        curLen += charWidth;
                    } else {
                        painter->drawText(iPos, textChar);
                        iPos += QPointF(charWidth, 0);
                    }
                }
            }
        }
    }

    painter->restore();
}
Example #22
0
void TextContent::updateTextConstraints()
{
    // 1. actual content stretch
    double prevXScale = 1.0;
    double prevYScale = 1.0;
   /* if (m_textRect.width() > 0 && m_textRect.height() > 0) {
        QRect cRect = contentRect();
        prevXScale = (qreal)cRect.width() / (qreal)m_textRect.width();
        prevYScale = (qreal)cRect.height() / (qreal)m_textRect.height();
    }*/

    // 2. LAYOUT TEXT. find out Block rects and Document rect
    int minCharSide = 0;
    m_blockRects.clear();
    m_textRect = QRect(0, 0, 0, 0);
    for (QTextBlock tb = m_text->begin(); tb.isValid(); tb = tb.next()) {
        if (!tb.isVisible())
            continue;

        // 2.1.A. calc the Block size uniting Fragments bounding rects
        QRect blockRect(0, 0, 0, 0);
        for (QTextBlock::iterator tbIt = tb.begin(); !(tbIt.atEnd()); ++tbIt) {
            QTextFragment frag = tbIt.fragment();
            if (!frag.isValid())
                continue;

            QString text = frag.text();
            if (text.trimmed().isEmpty())
                continue;

            QFontMetrics metrics(frag.charFormat().font());
            if (!minCharSide || metrics.height() > minCharSide)
                minCharSide = metrics.height();

            // TODO: implement superscript / subscript (it's in charFormat's alignment)
            // it must be implemented in paint too

            QRect textRect = metrics.boundingRect(text);
            if (textRect.left() > 9999)
                continue;
            if (textRect.top() < blockRect.top())
                blockRect.setTop(textRect.top());
            if (textRect.bottom() > blockRect.bottom())
                blockRect.setBottom(textRect.bottom());

            int textWidth = metrics.width(text);
            blockRect.setWidth(blockRect.width() + textWidth);
        }
        // 2.1.B. calc the Block size of blank lines
        if (tb.begin() == tb.end()) {
            QFontMetrics metrics(tb.charFormat().font());
            int textHeight = metrics.height();
            blockRect.setWidth(1);
            blockRect.setHeight(textHeight);
        }

        // 2.2. add the Block's margins
        QTextBlockFormat tbFormat = tb.blockFormat();
        blockRect.adjust(-tbFormat.leftMargin(), -tbFormat.topMargin(), tbFormat.rightMargin(), tbFormat.bottomMargin());

        // 2.3. store the original block rect
        m_blockRects.append(blockRect);

        // 2.4. enlarge the Document rect (uniting the Block rect)
        blockRect.translate(0, m_textRect.bottom() - blockRect.top() + 1);
        if (blockRect.left() < m_textRect.left())
            m_textRect.setLeft(blockRect.left());
        if (blockRect.right() > m_textRect.right())
            m_textRect.setRight(blockRect.right());
        if (blockRect.top() < m_textRect.top())
            m_textRect.setTop(blockRect.top());
        if (blockRect.bottom() > m_textRect.bottom())
            m_textRect.setBottom(blockRect.bottom());
    }
    m_textRect.adjust(-m_textMargin, -m_textMargin, m_textMargin, m_textMargin);

    // 3. use shape-based rendering
    if (hasShape()) {
#if 1
        // more precise, but too close to the path
        m_shapeRect = m_shapePath.boundingRect().toRect();
#else
        // faster, but less precise (as it uses the controls points to determine
        // the path rect, instead of the path itself)
        m_shapeRect = m_shapePath.controlPointRect().toRect();
#endif
        minCharSide = qBound(10, minCharSide, 500);
        m_shapeRect.adjust(-minCharSide, -minCharSide, minCharSide, minCharSide);

        // FIXME: layout, save layouting and calc the exact size!
        //int w = m_shapeRect.width();
        //int h = m_shapeRect.height();
        //resizeContents(QRect(-w / 2, -h / 2, w, h));
        resizeContents(m_shapeRect);

  //      moveBy(m_shapeRect.left(), m_shapeRect.top());
//        m_shapePath.translate(-m_shapeRect.left(), -m_shapeRect.top());
        //setPos(m_shapeRect.center());
        return;
    }

    // 4. resize content keeping stretch
    int w = (int)(prevXScale * (qreal)m_textRect.width());
    int h = (int)(prevYScale * (qreal)m_textRect.height());
    resizeContents(QRect(-w / 2, -h / 2, w, h));
}
Example #23
0
void GenericCodeEditor::paintLineIndicator( QPaintEvent *e )
{
    QPalette plt( mLineIndicator->palette() );
    QRect r( e->rect() );
    QPainter p( mLineIndicator );

    p.fillRect( r, plt.color( QPalette::Mid ) );

    QTextDocument *doc = QPlainTextEdit::document();
    QTextCursor cursor(textCursor());
    int selStartBlock, selEndBlock;
    if (cursor.hasSelection()) {
        selStartBlock = doc->findBlock(cursor.selectionStart()).blockNumber();
        selEndBlock = doc->findBlock(cursor.selectionEnd()).blockNumber();
    }
    else
        selStartBlock = selEndBlock = -1;

    QTextBlock block = firstVisibleBlock();
    int blockNumber = block.blockNumber();
    qreal top = blockBoundingGeometry(block).translated(contentOffset()).top();
    qreal bottom = top + blockBoundingRect(block).height();

    while (block.isValid() && top <= e->rect().bottom()) {
        if (block.isVisible() && bottom >= e->rect().top()) {
            p.save();

            QRectF numRect( 0, top, mLineIndicator->width() - 1, bottom - top );

            int num = blockNumber;
            if (num >= selStartBlock && num <= selEndBlock) {
                num -= selStartBlock;
                p.setPen(Qt::NoPen);
                p.setBrush(plt.color(QPalette::Highlight));
                p.drawRect(numRect);
                p.setPen(plt.color(QPalette::HighlightedText));
            }

            QString number = QString::number(num + 1);
            p.setPen(plt.color(QPalette::ButtonText));
            p.drawText(0, top, mLineIndicator->width() - 10, bottom - top,
                       Qt::AlignRight, number);

            p.restore();
        }

        block = block.next();
        top = bottom;
        bottom = top + blockBoundingRect(block).height();
        ++blockNumber;
    }
    
    if(!mEditorBoxIsActive) {
        QColor color = plt.color(QPalette::Mid);
        if(color.lightness() >= 128)
            color = color.darker(60);
        else
            color = color.lighter(50);
        
        color.setAlpha(inactiveFadeAlpha());
        p.fillRect( r, color );
    }
}
Example #24
0
void VMdEditor::makeBlockVisible(const QTextBlock &p_block)
{
    if (!p_block.isValid() || !p_block.isVisible()) {
        return;
    }

    QScrollBar *vbar = verticalScrollBar();
    if (!vbar || (vbar->minimum() == vbar->maximum())) {
        // No vertical scrollbar. No need to scroll.
        return;
    }

    int height = rect().height();
    QScrollBar *hbar = horizontalScrollBar();
    if (hbar && (hbar->minimum() != hbar->maximum())) {
        height -= hbar->height();
    }

    bool moved = false;

    QAbstractTextDocumentLayout *layout = document()->documentLayout();
    QRectF rect = layout->blockBoundingRect(p_block);
    int y = GETVISUALOFFSETY;
    int rectHeight = (int)rect.height();

    // Handle the case rectHeight >= height.
    if (rectHeight >= height) {
        if (y < 0) {
            // Need to scroll up.
            while (y + rectHeight < height && vbar->value() > vbar->minimum()) {
                moved = true;
                vbar->setValue(vbar->value() - vbar->singleStep());
                rect = layout->blockBoundingRect(p_block);
                rectHeight = (int)rect.height();
                y = GETVISUALOFFSETY;
            }
        } else if (y > 0) {
            // Need to scroll down.
            while (y > 0 && vbar->value() < vbar->maximum()) {
                moved = true;
                vbar->setValue(vbar->value() + vbar->singleStep());
                rect = layout->blockBoundingRect(p_block);
                rectHeight = (int)rect.height();
                y = GETVISUALOFFSETY;
            }

            if (y < 0) {
                // One step back.
                moved = true;
                vbar->setValue(vbar->value() - vbar->singleStep());
            }
        }

        if (moved) {
            qDebug() << "scroll to make huge block visible";
        }

        return;
    }

    while (y < 0 && vbar->value() > vbar->minimum()) {
        moved = true;
        vbar->setValue(vbar->value() - vbar->singleStep());
        rect = layout->blockBoundingRect(p_block);
        rectHeight = (int)rect.height();
        y = GETVISUALOFFSETY;
    }

    if (moved) {
        qDebug() << "scroll page down to make block visible";
        return;
    }

    while (y + rectHeight > height && vbar->value() < vbar->maximum()) {
        moved = true;
        vbar->setValue(vbar->value() + vbar->singleStep());
        rect = layout->blockBoundingRect(p_block);
        rectHeight = (int)rect.height();
        y = GETVISUALOFFSETY;
    }

    if (moved) {
        qDebug() << "scroll page up to make block visible";
    }
}