Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets > Html делегат в QTableView


Автор: becks 4.12.2013, 13:50
Добрый день!

Задача: Нужно в ячейках таблицы QTableView показывать html текст.

Проблемы:

1) Текст не масштабируется по размерам ячейки, а располагается одной строкой. Хотелось бы, если текст не влезает в ячейку чтобы переносился.

2) Если в html есть ссылки, то при наведении на них и клике по ним нет никакой реакции. Хотелось бы в html вставлять элементы ссылок с надписью "Просмотр" и по клике на эту ссылку выполнялась некоторая Qt функция. Такое возможно?

Вот реализация:

HtmlDelegate.h
Код

#pragma once

#include <QStyledItemDelegate>

class HtmlDelegate : public QStyledItemDelegate
{
public:
    HtmlDelegate(QObject *parent=0) : QStyledItemDelegate(parent)
    {}

    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
    QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
};


HtmlDelegate.cpp
Код

#include <QPainter>
#include <QTextDocument>

#include "HTMLDelegate.h"

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

    painter->save();

    QTextDocument doc;
    QFont font = doc.defaultFont();
    font.setPixelSize(12);
    doc.setDefaultFont(font);
    doc.setHtml(options.text);


    options.text = QString();
    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());
}


Буду благодарен за любые подсказки. Спасибо.

Автор: borisbn 4.12.2013, 14:01
Цитата(becks @  4.12.2013,  13:50 Найти цитируемый пост)
Хотелось бы в html вставлять элементы ссылок с надписью "Просмотр" и по клике на эту ссылку выполнялась некоторая Qt функция. Такое возможно?

IMHO тебе нужен не QTextDocument, а QTextBrowser, у которого есть сигнал http://qt-project.org/doc/qt-5.0/qtwidgets/qtextbrowser.html#anchorClicked
А документ у него можно достать методом http://qt-project.org/doc/qt-5.0/qtwidgets/qtextedit.html#document-prop

Автор: becks 4.12.2013, 17:55
Цитата(borisbn @  4.12.2013,  14:01 Найти цитируемый пост)
IMHO тебе нужен не QTextDocument, а QTextBrowser, у которого есть сигнал anchorClicked



Переделал на QTextBrowser, кое что еще поправил, теперь лучше, но теперь текст не отображается как html, выводит и теги. Что делаю не так?

Код

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

    painter->save();

    QTextBrowser browser;

    QFont font = browser.document()->defaultFont();
    font.setPixelSize(18);
    browser.document()->setDefaultFont(font);
    browser.setHtml(options.text);

    options.text = index.model()->data(index, Qt::DisplayRole).toString();
    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());
    browser.document()->drawContents(painter, clip);
    painter->restore();
}

Автор: borisbn 4.12.2013, 18:07
поставь точку останова на строке
Код
browser.setHtml(options.text);

скопируй содержимое options.text в буфер обмена, положи на форму QTextBrowser и в конструкторе формы вызови browser.setHtml( тот, текст, который скопировал в дебаге)

Автор: becks 5.12.2013, 10:39
Цитата

скопируй содержимое options.text в буфер обмена, положи на форму QTextBrowser и в конструкторе формы вызови browser.setHtml( тот, текст, который скопировал в дебаге) 


Попробовал. Все отображается отлично. Попробовал даже с QTableWidget тоже все прекрасно отображается.

Думаю может быть мне тогда заюзать setIndexWidget( QTextBrowser ), если уж нужен только просмотр и реакция на клик по ссылке, никакого редактирования (т.е. не использовать делегат)?

Автор: borisbn 5.12.2013, 10:43
Цитата(becks @  5.12.2013,  10:39 Найти цитируемый пост)
Думаю может быть мне тогда заюзать setIndexWidget( QTextBrowser ), если уж нужен только просмотр и реакция на клик по ссылке, никакого редактирования (т.е. не использовать делегат)?

Не знаю как пацаны, а я не возражаю  smile  smile  smile 

Автор: becks 5.12.2013, 23:53
Мужики, ничего не получается с этим делегатом, чего-то затрахался уже.

И отнаследоваться от QItemDelegate пробовал переопределив createEditor, setEditorData, setModelData. Ничего не выходит, ужас какой-то.

Хотелось бы чтоб делегат был основан на QTextBrowser, поскольку anchorClicked отлично отлавливается, спасибо borisbn

Поднимаю еще раз тему, прошу помощи.

PS: Когда в QTableWidget все работает как тебе нужно, становится обидно, что столько времени потратил на MVC, не хотелось бы в итоге остановится на QTableWidget.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)