forked from blue/squawk
an attempt to display text in a better way with QTextDocument + QTextBrowser
This commit is contained in:
parent
51ac1ac709
commit
d86e2c28a0
7 changed files with 88 additions and 338 deletions
|
@ -343,6 +343,7 @@ void FeedView::paintEvent(QPaintEvent* event)
|
|||
|
||||
QDateTime lastDate;
|
||||
bool first = true;
|
||||
QRect viewportRect = vp->rect();
|
||||
for (const QModelIndex& index : toRener) {
|
||||
QDateTime currentDate = index.data(Models::MessageFeed::Date).toDateTime();
|
||||
option.rect = visualRect(index);
|
||||
|
@ -356,7 +357,10 @@ void FeedView::paintEvent(QPaintEvent* event)
|
|||
}
|
||||
first = false;
|
||||
}
|
||||
bool mouseOver = option.rect.contains(cursor) && vp->rect().contains(cursor);
|
||||
QRect stripe = option.rect;
|
||||
stripe.setLeft(0);
|
||||
stripe.setWidth(viewportRect.width());
|
||||
bool mouseOver = stripe.contains(cursor) && viewportRect.contains(cursor);
|
||||
option.state.setFlag(QStyle::State_MouseOver, mouseOver);
|
||||
itemDelegate(index)->paint(&painter, option, index);
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <QApplication>
|
||||
#include <QMouseEvent>
|
||||
#include <QAbstractItemView>
|
||||
#include <QtMath>
|
||||
|
||||
#include "messagedelegate.h"
|
||||
#include "messagefeed.h"
|
||||
|
@ -42,7 +43,7 @@ MessageDelegate::MessageDelegate(QObject* parent):
|
|||
nickFont(),
|
||||
dateFont(),
|
||||
bodyMetrics(bodyFont),
|
||||
bodyMeter(),
|
||||
bodyRenderer(new QTextDocument()),
|
||||
nickMetrics(nickFont),
|
||||
dateMetrics(dateFont),
|
||||
buttonHeight(0),
|
||||
|
@ -52,11 +53,13 @@ MessageDelegate::MessageDelegate(QObject* parent):
|
|||
bars(new std::map<QString, QProgressBar*>()),
|
||||
statusIcons(new std::map<QString, QLabel*>()),
|
||||
pencilIcons(new std::map<QString, QLabel*>()),
|
||||
bodies(new std::map<QString, QLabel*>()),
|
||||
bodies(new std::map<QString, QTextBrowser*>()),
|
||||
previews(new std::map<QString, Preview*>()),
|
||||
idsToKeep(new std::set<QString>()),
|
||||
clearingWidgets(false)
|
||||
{
|
||||
bodyRenderer->setDocumentMargin(0);
|
||||
|
||||
QPushButton btn(QCoreApplication::translate("MessageLine", "Download"));
|
||||
buttonHeight = btn.sizeHint().height();
|
||||
buttonWidth = btn.sizeHint().width();
|
||||
|
@ -83,7 +86,7 @@ MessageDelegate::~MessageDelegate()
|
|||
delete pair.second;
|
||||
}
|
||||
|
||||
for (const std::pair<const QString, QLabel*>& pair: *bodies){
|
||||
for (const std::pair<const QString, QTextBrowser*>& pair: *bodies){
|
||||
delete pair.second;
|
||||
}
|
||||
|
||||
|
@ -98,6 +101,7 @@ MessageDelegate::~MessageDelegate()
|
|||
delete bars;
|
||||
delete bodies;
|
||||
delete previews;
|
||||
delete bodyRenderer;
|
||||
}
|
||||
|
||||
void MessageDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
|
@ -124,8 +128,6 @@ void MessageDelegate::paint(QPainter* painter, const QStyleOptionViewItem& optio
|
|||
opt.displayAlignment = Qt::AlignRight | Qt::AlignTop;
|
||||
}
|
||||
|
||||
QSize bodySize = bodyMeter.boundingSize(data.text, opt.rect.size());
|
||||
|
||||
QRect rect;
|
||||
if (ntds) {
|
||||
painter->setFont(nickFont);
|
||||
|
@ -168,15 +170,7 @@ void MessageDelegate::paint(QPainter* painter, const QStyleOptionViewItem& optio
|
|||
painter->restore();
|
||||
|
||||
QWidget* vp = static_cast<QWidget*>(painter->device());
|
||||
if (data.text.size() > 0) {
|
||||
QLabel* body = getBody(data);
|
||||
body->setParent(vp);
|
||||
body->setMinimumSize(bodySize);
|
||||
body->setMaximumSize(bodySize);
|
||||
body->move(opt.rect.left(), opt.rect.y());
|
||||
body->show();
|
||||
opt.rect.adjust(0, bodySize.height() + textMargin, 0, 0);
|
||||
}
|
||||
paintBody(data, painter, opt);
|
||||
painter->setFont(dateFont);
|
||||
QColor q = painter->pen().color();
|
||||
QString dateString = data.date.toLocalTime().toString("hh:mm");
|
||||
|
@ -304,7 +298,12 @@ QSize MessageDelegate::sizeHint(const QStyleOptionViewItem& option, const QModel
|
|||
Models::FeedItem data = qvariant_cast<Models::FeedItem>(vi);
|
||||
QSize messageSize(0, 0);
|
||||
if (data.text.size() > 0) {
|
||||
messageSize = bodyMeter.boundingSize(data.text, messageRect.size());
|
||||
bodyRenderer->setPlainText(data.text);
|
||||
bodyRenderer->setTextWidth(messageRect.size().width());
|
||||
|
||||
QSizeF size = bodyRenderer->size();
|
||||
size.setWidth(bodyRenderer->idealWidth());
|
||||
messageSize = QSize(qCeil(size.width()), qCeil(size.height()));
|
||||
messageSize.rheight() += textMargin;
|
||||
}
|
||||
|
||||
|
@ -393,7 +392,7 @@ void MessageDelegate::initializeFonts(const QFont& font)
|
|||
nickMetrics = QFontMetrics(nickFont);
|
||||
dateMetrics = QFontMetrics(dateFont);
|
||||
|
||||
bodyMeter.initializeFonts(bodyFont);
|
||||
bodyRenderer->setDefaultFont(bodyFont);
|
||||
|
||||
Preview::initializeFont(bodyFont);
|
||||
}
|
||||
|
@ -573,34 +572,36 @@ QLabel * MessageDelegate::getPencilIcon(const Models::FeedItem& data) const
|
|||
return result;
|
||||
}
|
||||
|
||||
QLabel * MessageDelegate::getBody(const Models::FeedItem& data) const
|
||||
QTextBrowser * MessageDelegate::getBody(const Models::FeedItem& data) const
|
||||
{
|
||||
std::map<QString, QLabel*>::const_iterator itr = bodies->find(data.id);
|
||||
QLabel* result = 0;
|
||||
std::map<QString, QTextBrowser*>::const_iterator itr = bodies->find(data.id);
|
||||
QTextBrowser* result = 0;
|
||||
|
||||
if (itr != bodies->end()) {
|
||||
result = itr->second;
|
||||
} else {
|
||||
result = new QLabel();
|
||||
result = new QTextBrowser();
|
||||
result->setFont(bodyFont);
|
||||
result->setContextMenuPolicy(Qt::NoContextMenu);
|
||||
result->setWordWrap(true);
|
||||
result->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
result->setContentsMargins(0, 0, 0, 0);
|
||||
//result->viewport()->setAutoFillBackground(false);
|
||||
result->document()->setDocumentMargin(0);
|
||||
result->setFrameStyle(0);
|
||||
result->setLineWidth(0);
|
||||
//result->setAutoFillBackground(false);
|
||||
//->setWordWrap(true);
|
||||
result->setOpenExternalLinks(true);
|
||||
//result->setTextInteractionFlags(result->textInteractionFlags() | Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse);
|
||||
result->setOpenExternalLinks(true);
|
||||
result->setTextInteractionFlags(result->textInteractionFlags() | Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse);
|
||||
bodies->insert(std::make_pair(data.id, result));
|
||||
}
|
||||
|
||||
result->setText(Shared::processMessageBody(data.text));
|
||||
result->setHtml(Shared::processMessageBody(data.text));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void MessageDelegate::beginClearWidgets()
|
||||
{
|
||||
idsToKeep->clear();
|
||||
clearingWidgets = true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void removeElements(std::map<QString, T*>* elements, std::set<QString>* idsToKeep) {
|
||||
std::set<QString> toRemove;
|
||||
|
@ -615,6 +616,51 @@ void removeElements(std::map<QString, T*>* elements, std::set<QString>* idsToKee
|
|||
}
|
||||
}
|
||||
|
||||
int MessageDelegate::paintBody(const Models::FeedItem& data, QPainter* painter, QStyleOptionViewItem& option) const
|
||||
{
|
||||
if (data.text.size() > 0) {
|
||||
bodyRenderer->setHtml(Shared::processMessageBody(data.text));
|
||||
bodyRenderer->setTextWidth(option.rect.size().width());
|
||||
painter->save();
|
||||
painter->translate(option.rect.topLeft());
|
||||
bodyRenderer->drawContents(painter);
|
||||
painter->restore();
|
||||
QSize bodySize(qCeil(bodyRenderer->idealWidth()), qCeil(bodyRenderer->size().height()));
|
||||
|
||||
|
||||
QTextBrowser* editor = nullptr;
|
||||
if (option.state.testFlag(QStyle::State_MouseOver)) {
|
||||
std::set<QString> ids({data.id});
|
||||
removeElements(bodies, &ids);
|
||||
editor = getBody(data);
|
||||
editor->setParent(static_cast<QWidget*>(painter->device()));
|
||||
} else {
|
||||
std::map<QString, QTextBrowser*>::const_iterator itr = bodies->find(data.id);
|
||||
if (itr != bodies->end()) {
|
||||
editor = itr->second;
|
||||
}
|
||||
}
|
||||
if (editor != nullptr) {
|
||||
editor->setMinimumSize(bodySize);
|
||||
editor->setMaximumSize(bodySize);
|
||||
editor->move(option.rect.left(), option.rect.y());
|
||||
editor->show();
|
||||
}
|
||||
|
||||
option.rect.adjust(0, bodySize.height() + textMargin, 0, 0);
|
||||
return bodySize.width();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MessageDelegate::beginClearWidgets()
|
||||
{
|
||||
idsToKeep->clear();
|
||||
clearingWidgets = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void MessageDelegate::endClearWidgets()
|
||||
{
|
||||
if (clearingWidgets) {
|
||||
|
|
|
@ -29,12 +29,13 @@
|
|||
#include <QPushButton>
|
||||
#include <QProgressBar>
|
||||
#include <QLabel>
|
||||
#include <QTextEdit>
|
||||
#include <QTextBrowser>
|
||||
|
||||
#include "shared/icons.h"
|
||||
#include "shared/global.h"
|
||||
#include "shared/utils.h"
|
||||
#include "shared/pathcheck.h"
|
||||
#include "ui/utils/textmeter.h"
|
||||
|
||||
#include "preview.h"
|
||||
|
||||
|
@ -70,13 +71,15 @@ protected:
|
|||
int paintBar(QProgressBar* bar, QPainter* painter, bool sentByMe, QStyleOptionViewItem& option) const;
|
||||
int paintPreview(const Models::FeedItem& data, QPainter* painter, QStyleOptionViewItem& option) const;
|
||||
int paintComment(const Models::FeedItem& data, QPainter* painter, QStyleOptionViewItem& option) const;
|
||||
int paintBody(const Models::FeedItem& data, QPainter* painter, QStyleOptionViewItem& option) const;
|
||||
void paintAvatar(const Models::FeedItem& data, const QModelIndex& index, const QStyleOptionViewItem& option, QPainter* painter) const;
|
||||
void paintBubble(const Models::FeedItem& data, QPainter* painter, const QStyleOptionViewItem& option) const;
|
||||
|
||||
QPushButton* getButton(const Models::FeedItem& data) const;
|
||||
QProgressBar* getBar(const Models::FeedItem& data) const;
|
||||
QLabel* getStatusIcon(const Models::FeedItem& data) const;
|
||||
QLabel* getPencilIcon(const Models::FeedItem& data) const;
|
||||
QLabel* getBody(const Models::FeedItem& data) const;
|
||||
QTextBrowser* getBody(const Models::FeedItem& data) const;
|
||||
void clearHelperWidget(const Models::FeedItem& data) const;
|
||||
|
||||
bool needToDrawAvatar(const QModelIndex& index, const Models::FeedItem& data, const QStyleOptionViewItem& option) const;
|
||||
|
@ -95,7 +98,7 @@ private:
|
|||
QFont nickFont;
|
||||
QFont dateFont;
|
||||
QFontMetrics bodyMetrics;
|
||||
TextMeter bodyMeter;
|
||||
QTextDocument* bodyRenderer;
|
||||
QFontMetrics nickMetrics;
|
||||
QFontMetrics dateMetrics;
|
||||
|
||||
|
@ -107,7 +110,7 @@ private:
|
|||
std::map<QString, QProgressBar*>* bars;
|
||||
std::map<QString, QLabel*>* statusIcons;
|
||||
std::map<QString, QLabel*>* pencilIcons;
|
||||
std::map<QString, QLabel*>* bodies;
|
||||
std::map<QString, QTextBrowser*>* bodies;
|
||||
std::map<QString, Preview*>* previews;
|
||||
std::set<QString>* idsToKeep;
|
||||
bool clearingWidgets;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue