void HGMarkdownHighlighter::highlight()
{
    if (cached_elements == NULL) {
        qDebug() << "cached_elements is NULL";
        return;
    }

    if (highlightingStyles == NULL)
        this->setDefaultStyles();

    this->clearFormatting();

    for (int i = 0; i < highlightingStyles->size(); i++)
    {
        HighlightingStyle style = highlightingStyles->at(i);
        pmh_element *elem_cursor = cached_elements[style.type];
        while (elem_cursor != NULL)
        {
            if (elem_cursor->end <= elem_cursor->pos) {
                elem_cursor = elem_cursor->next;
                continue;
            }

            // "The QTextLayout object can only be modified from the
            // documentChanged implementation of a QAbstractTextDocumentLayout
            // subclass. Any changes applied from the outside cause undefined
            // behavior." -- we are breaking this rule here. There might be
            // a better (more correct) way to do this.

            int startBlockNum = document->findBlock(elem_cursor->pos).blockNumber();
            int endBlockNum = document->findBlock(elem_cursor->end).blockNumber();
            for (int j = startBlockNum; j <= endBlockNum; j++)
            {
                QTextBlock block = document->findBlockByNumber(j);

                QTextLayout *layout = block.layout();
                QList<QTextLayout::FormatRange> list = layout->additionalFormats();
                int blockpos = block.position();
                QTextLayout::FormatRange r;
                r.format = style.format;

                if (j == startBlockNum) {
                    r.start = elem_cursor->pos - blockpos;
                    r.length = (startBlockNum == endBlockNum)
                                ? elem_cursor->end - elem_cursor->pos
                                : block.length() - r.start;
                } else if (j == endBlockNum) {
                    r.start = 0;
                    r.length = elem_cursor->end - blockpos;
                } else {
                    r.start = 0;
                    r.length = block.length();
                }

                list.append(r);
                layout->setAdditionalFormats(list);
            }

            elem_cursor = elem_cursor->next;
        }
    }

    document->markContentsDirty(0, document->characterCount());
}
예제 #2
0
void tst_qquickstyledtext::textOutput()
{
    QFETCH(QString, input);
    QFETCH(QString, output);
    QFETCH(FormatList, formats);
    QFETCH(bool, modifiesFontSize);

    QTextLayout layout;
    QList<QQuickStyledTextImgTag*> imgTags;
    bool fontSizeModified = false;
    QQuickStyledText::parse(input, layout, imgTags, QUrl(), 0, false, &fontSizeModified);

    QCOMPARE(layout.text(), output);

    QList<QTextLayout::FormatRange> layoutFormats = layout.additionalFormats();

    QCOMPARE(layoutFormats.count(), formats.count());
    for (int i = 0; i < formats.count(); ++i) {
        QCOMPARE(layoutFormats.at(i).start, formats.at(i).start);
        QCOMPARE(layoutFormats.at(i).length, formats.at(i).length);
        if (formats.at(i).type & Format::Bold)
            QVERIFY(layoutFormats.at(i).format.fontWeight() == QFont::Bold);
        else
            QVERIFY(layoutFormats.at(i).format.fontWeight() == QFont::Normal);
        QVERIFY(layoutFormats.at(i).format.fontItalic() == bool(formats.at(i).type & Format::Italic));
        QVERIFY(layoutFormats.at(i).format.fontUnderline() == bool(formats.at(i).type & Format::Underline));
    }
    QCOMPARE(fontSizeModified, modifiesFontSize);
}
예제 #3
0
파일: qsaeditor.cpp 프로젝트: aschet/qsaqt5
void QSAEditor::clearMarkerFormat(const QTextBlock &block, int markerId)
{
    QTextLayout *layout = block.layout();
    QList<QTextLayout::FormatRange> formats = layout->additionalFormats();
    bool formatsChanged = false;
    for (int i = 0; i < formats.count(); ++i)
        if (formats.at(i).format.hasProperty(markerId)) {
            formats[i].format.clearBackground();
            formats[i].format.clearProperty(markerId);
            if (formats.at(i).format.properties().isEmpty()) {
                formats.removeAt(i);
                --i;
            }
            formatsChanged = true;
        }

    if (formatsChanged)
        layout->setAdditionalFormats(formats);
}
예제 #4
0
void tst_qquickstyledtext::anchors()
{
    QFETCH(QString, input);
    QFETCH(QString, output);
    QFETCH(FormatList, formats);

    QTextLayout layout;
    QList<QQuickStyledTextImgTag*> imgTags;
    bool fontSizeModified = false;
    QQuickStyledText::parse(input, layout, imgTags, QUrl(), 0, false, &fontSizeModified);

    QCOMPARE(layout.text(), output);

    QList<QTextLayout::FormatRange> layoutFormats = layout.additionalFormats();

    QCOMPARE(layoutFormats.count(), formats.count());
    for (int i = 0; i < formats.count(); ++i) {
        QCOMPARE(layoutFormats.at(i).start, formats.at(i).start);
        QCOMPARE(layoutFormats.at(i).length, formats.at(i).length);
        QVERIFY(layoutFormats.at(i).format.isAnchor() == bool(formats.at(i).type & Format::Anchor));
    }
}
예제 #5
0
void QSyntaxHighlighterPrivate::applyFormatChanges()
{
    QTextLayout *layout = currentBlock.layout();

    QList<QTextLayout::FormatRange> ranges = layout->additionalFormats();

    const int preeditAreaStart = layout->preeditAreaPosition();
    const int preeditAreaLength = layout->preeditAreaText().length();

    QList<QTextLayout::FormatRange>::Iterator it = ranges.begin();
    while (it != ranges.end()) {
        if (it->start >= preeditAreaStart
            && it->start + it->length <= preeditAreaStart + preeditAreaLength)
            ++it;
        else
            it = ranges.erase(it);
    }

    QTextCharFormat emptyFormat;

    QTextLayout::FormatRange r;
    r.start = r.length = -1;

    int i = 0;
    while (i < formatChanges.count()) {

        while (i < formatChanges.count() && formatChanges.at(i) == emptyFormat)
            ++i;

        if (i >= formatChanges.count())
            break;

        r.start = i;
        r.format = formatChanges.at(i);

        while (i < formatChanges.count() && formatChanges.at(i) == r.format)
            ++i;

        if (i >= formatChanges.count())
            break;

        r.length = i - r.start;

        if (r.start >= preeditAreaStart) {
            r.start += preeditAreaLength;
        } else if (r.start + r.length >= preeditAreaStart) {
            r.length += preeditAreaLength;
        }

        ranges << r;
        r.start = r.length = -1;
    }

    if (r.start != -1) {
        r.length = formatChanges.count() - r.start;

        if (r.start >= preeditAreaStart) {
            r.start += preeditAreaLength;
        } else if (r.start + r.length >= preeditAreaStart) {
            r.length += preeditAreaLength;
        }

        ranges << r;
    }

    layout->setAdditionalFormats(ranges);
}
예제 #6
0
void MarkdownHighlighter::resultReady(pmh_element **elements)
{
    QTextBlock block = document()->firstBlock();
    while (block.isValid()) {
        block.layout()->clearAdditionalFormats();
        block = block.next();
    }

    if (!elements) {
        qDebug() << "elements is null";
        return;
    }

    // QTextDocument::characterCount returns a value one higher than the
    // actual character count.
    // See: https://bugreports.qt.nokia.com//browse/QTBUG-4841
    // document->toPlainText().length() would give us the correct value
    // but it's probably too slow.
    unsigned long max_offset = document()->characterCount() - 1;

    for (int i = 0; i < highlightingStyles.size(); i++)
    {
        HighlightingStyle style = highlightingStyles.at(i);
        pmh_element *elem_cursor = elements[style.type];
        while (elem_cursor != NULL)
        {
            unsigned long pos = elem_cursor->pos;
            unsigned long end = elem_cursor->end;

            if (end <= pos || max_offset < pos)
            {
                elem_cursor = elem_cursor->next;
                continue;
            }

            if (max_offset < end)
                end = max_offset;

            // "The QTextLayout object can only be modified from the
            // documentChanged implementation of a QAbstractTextDocumentLayout
            // subclass. Any changes applied from the outside cause undefined
            // behavior." -- we are breaking this rule here. There might be
            // a better (more correct) way to do this.

            int startBlockNum = document()->findBlock(pos).blockNumber();
            int endBlockNum = document()->findBlock(end).blockNumber();
            for (int j = startBlockNum; j <= endBlockNum; j++)
            {
                QTextBlock block = document()->findBlockByNumber(j);

                QTextLayout *layout = block.layout();
                QList<QTextLayout::FormatRange> list = layout->additionalFormats();
                int blockpos = block.position();
                QTextLayout::FormatRange r;
                r.format = style.format;

                if (/*_makeLinksClickable
                    &&*/ (elem_cursor->type == pmh_LINK
                        || elem_cursor->type == pmh_AUTO_LINK_URL
                        || elem_cursor->type == pmh_AUTO_LINK_EMAIL
                        || elem_cursor->type == pmh_REFERENCE)
                    && elem_cursor->address != NULL)
                {
                    QString address(elem_cursor->address);
                    if (elem_cursor->type == pmh_AUTO_LINK_EMAIL && !address.startsWith("mailto:"))
                        address = "mailto:" + address;
                    QTextCharFormat linkFormat(r.format);
                    linkFormat.setAnchor(true);
                    linkFormat.setAnchorHref(address);
                    linkFormat.setToolTip(address);
                    r.format = linkFormat;
                }

                if (j == startBlockNum) {
                    r.start = pos - blockpos;
                    r.length = (startBlockNum == endBlockNum)
                                ? end - pos
                                : block.length() - r.start;
                } else if (j == endBlockNum) {
                    r.start = 0;
                    r.length = end - blockpos;
                } else {
                    r.start = 0;
                    r.length = block.length();
                }

                list.append(r);
                layout->setAdditionalFormats(list);
            }

            elem_cursor = elem_cursor->next;
        }
    }

    document()->markContentsDirty(0, document()->characterCount());

    pmh_free_elements(elements);
}