Как заставить представление объекта представить богатый (HTML) текст в QT

Предположим, что моя модель имеет объекты со следующей строкой для QT:: DisplayRole

<span>blah-blah <b>some text</b> other blah</span>

Я хочу, чтобы QTreeView (на самом деле, любое представление объекта) представил его как обогащенный текст. Вместо этого представления объекта представляют его как чистый текст по умолчанию. Как достигнуть желаемого рендеринга?


На самом деле это - модель результатов поиска. Пользователь вводит текст, некоторый документ ищется против того текста, и пользователю дарят результаты поиска, где искавшие слова должны быть более смелыми, чем сопроводительный текст.

48
задан Anthony Serdyukov 24 December 2009 в 03:41
поделиться

2 ответа

Предполагая, что компилятор не выходит на обед, он должен скомпилировать до двух сравнений и двух условных ходов. Это не может быть намного лучше.

Если вы разместите сборку, которую на самом деле генерирует компилятор, мы увидим, есть ли что-то ненужное, что замедляет ее.

Главное, что нужно проверить, это то, что процедура на самом деле встраивается. Компилятор не обязан делать это, и если он генерирует вызов функции, это будет очень дорого для такой простой операции.

Если вызов действительно встраивается, то разворачивание цикла может быть полезным, как сказал DigireRoss, или векторизация может быть возможна.

Edit: Если вы хотите векторизировать код и используете недавний процессор x86, вы хотите использовать инструкцию SSE4.1 pminud (intrinsic: _ mm _ min _ epu32 ), которая принимает два вектора по четыре неподписанных инта каждый и создает вектор из четырех неподписанных инт. Каждый элемент результата - это минимум соответствующих элементов на двух входах.

Также отмечу, что ваш компилятор использовал ветви вместо условных ходов; Вам, вероятно, стоит попробовать версию, в которой сначала используются условные ходы, и посмотреть, не дает ли это вам какое-либо ускорение, прежде чем вы отправитесь в гонки на векторной реализации.

-121--2141179-

Если выполняется только одно сравнение, возможно, потребуется отменить цикл вручную.

Сначала проверьте, может ли компилятор раскрутить цикл для вас, а если нет, сделайте это самостоятельно. Это по крайней мере уменьшит накладные расходы на управление контуром...

-121--2141191-

Мой ответ в основном вдохновлен @ serge _ gubenko's one. Тем не менее, было сделано несколько улучшений, чтобы код, наконец, пригодился в моем приложении.

class HtmlDelegate : public QStyledItemDelegate
{
protected:
    void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const;
    QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const;
};

void HtmlDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QStyleOptionViewItemV4 optionV4 = option;
    initStyleOption(&optionV4, index);

    QStyle *style = optionV4.widget? optionV4.widget->style() : QApplication::style();

    QTextDocument doc;
    doc.setHtml(optionV4.text);

    /// Painting item without text
    optionV4.text = QString();
    style->drawControl(QStyle::CE_ItemViewItem, &optionV4, painter);

    QAbstractTextDocumentLayout::PaintContext ctx;

    // Highlighting text if item is selected
    if (optionV4.state & QStyle::State_Selected)
        ctx.palette.setColor(QPalette::Text, optionV4.palette.color(QPalette::Active, QPalette::HighlightedText));

    QRect textRect = style->subElementRect(QStyle::SE_ItemViewItemText, &optionV4);
    painter->save();
    painter->translate(textRect.topLeft());
    painter->setClipRect(textRect.translated(-textRect.topLeft()));
    doc.documentLayout()->draw(painter, ctx);
    painter->restore();
}

QSize HtmlDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QStyleOptionViewItemV4 optionV4 = option;
    initStyleOption(&optionV4, index);

    QTextDocument doc;
    doc.setHtml(optionV4.text);
    doc.setTextWidth(optionV4.rect.width());
    return QSize(doc.idealWidth(), doc.size().height());
}
22
ответ дан 26 November 2019 в 18:53
поделиться

Я думаю, вы можете использовать метод setItemDelegate древовидной структуры для настройки пользовательского рисовальщика для ваших элементов древовидной структуры. В методе рисования делегата вы можете использовать QTextDocument для загрузки текста элемента как html и его рендеринга. Пожалуйста, проверьте, подойдет ли вам пример ниже:

Инициализация древовидной структуры:

...
    // create simple model for a tree view
    QStandardItemModel *model = new QStandardItemModel();
    QModelIndex parentItem;
    for (int i = 0; i < 4; ++i)
    {
        parentItem = model->index(0, 0, parentItem);
        model->insertRows(0, 1, parentItem);
        model->insertColumns(0, 1, parentItem);
        QModelIndex index = model->index(0, 0, parentItem);
        model->setData(index, "<span>blah-blah <b>some text</b> other blah</span>");
    }
    // create custom delegate
    HTMLDelegate* delegate = new HTMLDelegate();
    // set model and delegate to the treeview object
    ui->treeView->setModel(model);
    ui->treeView->setItemDelegate(delegate);
...

реализация настраиваемого делегата

class HTMLDelegate : public QStyledItemDelegate
{
protected:
    void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const;
    QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const;
};

void HTMLDelegate::paint(QPainter* painter, const QStyleOptionViewItem & option, const QModelIndex &index) const
{
    QStyleOptionViewItemV4 options = option;
    initStyleOption(&options, index);

    painter->save();

    QTextDocument doc;
    doc.setHtml(options.text);

    options.text = "";
    options.widget->style()->drawControl(QStyle::CE_ItemViewItem, &options, painter);

    painter->translate(options.rect.left(), options.rect.top());
    QRect clip(0, 0, options.rect.width(), options.rect.height());
    doc.drawContents(painter, clip);

    painter->restore();
}

QSize HTMLDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const
{
    QStyleOptionViewItemV4 options = option;
    initStyleOption(&options, index);

    QTextDocument doc;
    doc.setHtml(options.text);
    doc.setTextWidth(options.rect.width());
    return QSize(doc.idealWidth(), doc.size().height());
}

надеюсь, что это поможет, в отношении

update0 : изменения в HTMLDelegate, чтобы сделать значки видимыми и другой цвет пера для выбранных элементов

void HTMLDelegate::paint(QPainter* painter, const QStyleOptionViewItem & option, const QModelIndex &index) const
{
    QStyleOptionViewItemV4 options = option;
    initStyleOption(&options, index);

    painter->save();

    QTextDocument doc;
    doc.setHtml(options.text);

    options.text = "";
    options.widget->style()->drawControl(QStyle::CE_ItemViewItem, &options, painter);

    // shift text right to make icon visible
    QSize iconSize = options.icon.actualSize(options.rect.size());
    painter->translate(options.rect.left()+iconSize.width(), options.rect.top());
    QRect clip(0, 0, options.rect.width()+iconSize.width(), options.rect.height());

    //doc.drawContents(painter, clip);

    painter->setClipRect(clip);
    QAbstractTextDocumentLayout::PaintContext ctx;
    // set text color to red for selected item
    if (option.state & QStyle::State_Selected)
        ctx.palette.setColor(QPalette::Text, QColor("red"));
    ctx.clip = clip;
    doc.documentLayout()->draw(painter, ctx);

    painter->restore();
}
37
ответ дан 26 November 2019 в 18:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: