forked from blue/squawk
link clicking and hovering in message body now works!
This commit is contained in:
parent
eac87e713f
commit
7ba94e9deb
4 changed files with 105 additions and 120 deletions
|
@ -44,7 +44,6 @@ MessageDelegate::MessageDelegate(QObject* parent):
|
|||
bodyFont(),
|
||||
nickFont(),
|
||||
dateFont(),
|
||||
bodyMetrics(bodyFont),
|
||||
bodyRenderer(new QTextDocument()),
|
||||
nickMetrics(nickFont),
|
||||
dateMetrics(dateFont),
|
||||
|
@ -55,7 +54,6 @@ 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, QTextBrowser*>()),
|
||||
previews(new std::map<QString, Preview*>()),
|
||||
idsToKeep(new std::set<QString>()),
|
||||
clearingWidgets(false)
|
||||
|
@ -88,10 +86,6 @@ MessageDelegate::~MessageDelegate()
|
|||
delete pair.second;
|
||||
}
|
||||
|
||||
for (const std::pair<const QString, QTextBrowser*>& pair: *bodies){
|
||||
delete pair.second;
|
||||
}
|
||||
|
||||
for (const std::pair<const QString, Preview*>& pair: *previews){
|
||||
delete pair.second;
|
||||
}
|
||||
|
@ -101,7 +95,6 @@ MessageDelegate::~MessageDelegate()
|
|||
delete idsToKeep;
|
||||
delete buttons;
|
||||
delete bars;
|
||||
delete bodies;
|
||||
delete previews;
|
||||
delete bodyRenderer;
|
||||
}
|
||||
|
@ -366,66 +359,83 @@ QSize MessageDelegate::sizeHint(const QStyleOptionViewItem& option, const QModel
|
|||
return messageSize;
|
||||
}
|
||||
|
||||
void MessageDelegate::leftClick(const QPoint& point, const QModelIndex& index, const QRect& sizeHint) const
|
||||
QRect MessageDelegate::getHoveredMessageBodyRect(const QModelIndex& index, const Models::FeedItem& data, const QRect& sizeHint) const
|
||||
{
|
||||
QRect localHint = sizeHint.adjusted(bubbleMargin, bubbleMargin + margin, -bubbleMargin, -bubbleMargin / 2);
|
||||
if (needToDrawSender(index, data)) {
|
||||
localHint.adjust(0, nickMetrics.lineSpacing() + textMargin, 0, 0);
|
||||
}
|
||||
|
||||
int attachHeight = 0;
|
||||
switch (data.attach.state) {
|
||||
case Models::none:
|
||||
break;
|
||||
case Models::uploading:
|
||||
attachHeight += Preview::calculateAttachSize(Shared::resolvePath(data.attach.localPath), localHint).height() + textMargin;
|
||||
[[fallthrough]];
|
||||
case Models::downloading:
|
||||
attachHeight += barHeight + textMargin;
|
||||
break;
|
||||
case Models::remote:
|
||||
attachHeight += buttonHeight + textMargin;
|
||||
break;
|
||||
case Models::ready:
|
||||
case Models::local: {
|
||||
QSize aSize = Preview::calculateAttachSize(Shared::resolvePath(data.attach.localPath), localHint);
|
||||
attachHeight += aSize.height() + textMargin;
|
||||
}
|
||||
break;
|
||||
case Models::errorDownload: {
|
||||
QSize commentSize = dateMetrics.boundingRect(localHint, Qt::TextWordWrap, data.attach.error).size();
|
||||
attachHeight += commentSize.height() + buttonHeight + textMargin * 2;
|
||||
}
|
||||
break;
|
||||
case Models::errorUpload: {
|
||||
QSize aSize = Preview::calculateAttachSize(Shared::resolvePath(data.attach.localPath), localHint);
|
||||
QSize commentSize = dateMetrics.boundingRect(localHint, Qt::TextWordWrap, data.attach.error).size();
|
||||
attachHeight += aSize.height() + commentSize.height() + textMargin * 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
int bottomSize = std::max(dateMetrics.lineSpacing(), statusIconSize);
|
||||
localHint.adjust(0, attachHeight, 0, -(bottomSize + textMargin));
|
||||
|
||||
return localHint;
|
||||
}
|
||||
|
||||
QString MessageDelegate::getAnchor(const QPoint& point, const QModelIndex& index, const QRect& sizeHint) const
|
||||
{
|
||||
QVariant vi = index.data(Models::MessageFeed::Bulk);
|
||||
Models::FeedItem data = qvariant_cast<Models::FeedItem>(vi);
|
||||
if (data.text.size() > 0) {
|
||||
QRect localHint = sizeHint.adjusted(bubbleMargin, bubbleMargin + margin, -bubbleMargin, -bubbleMargin / 2);
|
||||
if (needToDrawSender(index, data)) {
|
||||
localHint.adjust(0, nickMetrics.lineSpacing() + textMargin, 0, 0);
|
||||
}
|
||||
|
||||
int attachHeight = 0;
|
||||
switch (data.attach.state) {
|
||||
case Models::none:
|
||||
break;
|
||||
case Models::uploading:
|
||||
attachHeight += Preview::calculateAttachSize(Shared::resolvePath(data.attach.localPath), localHint).height() + textMargin;
|
||||
[[fallthrough]];
|
||||
case Models::downloading:
|
||||
attachHeight += barHeight + textMargin;
|
||||
break;
|
||||
case Models::remote:
|
||||
attachHeight += buttonHeight + textMargin;
|
||||
break;
|
||||
case Models::ready:
|
||||
case Models::local: {
|
||||
QSize aSize = Preview::calculateAttachSize(Shared::resolvePath(data.attach.localPath), localHint);
|
||||
attachHeight += aSize.height() + textMargin;
|
||||
}
|
||||
break;
|
||||
case Models::errorDownload: {
|
||||
QSize commentSize = dateMetrics.boundingRect(localHint, Qt::TextWordWrap, data.attach.error).size();
|
||||
attachHeight += commentSize.height() + buttonHeight + textMargin * 2;
|
||||
}
|
||||
break;
|
||||
case Models::errorUpload: {
|
||||
QSize aSize = Preview::calculateAttachSize(Shared::resolvePath(data.attach.localPath), localHint);
|
||||
QSize commentSize = dateMetrics.boundingRect(localHint, Qt::TextWordWrap, data.attach.error).size();
|
||||
attachHeight += aSize.height() + commentSize.height() + textMargin * 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
int bottomSize = std::max(dateMetrics.lineSpacing(), statusIconSize);
|
||||
localHint.adjust(0, attachHeight, 0, -(bottomSize + textMargin));
|
||||
QRect localHint = getHoveredMessageBodyRect(index, data, sizeHint);
|
||||
|
||||
if (localHint.contains(point)) {
|
||||
qDebug() << "MESSAGE CLICKED";
|
||||
QPoint translated = point - localHint.topLeft();
|
||||
|
||||
bodyRenderer->setPlainText(data.text);
|
||||
bodyRenderer->setHtml(Shared::processMessageBody(data.text));
|
||||
bodyRenderer->setTextWidth(localHint.size().width());
|
||||
|
||||
int pos = bodyRenderer->documentLayout()->hitTest(translated, Qt::FuzzyHit);
|
||||
QTextBlock block = bodyRenderer->findBlock(pos);
|
||||
QString text = block.text();
|
||||
if (text.size() > 0) {
|
||||
qDebug() << text;
|
||||
}
|
||||
return bodyRenderer->documentLayout()->anchorAt(translated);
|
||||
}
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
void MessageDelegate::leftClick(const QPoint& point, const QModelIndex& index, const QRect& sizeHint) const
|
||||
{
|
||||
QString anchor = getAnchor(point, index, sizeHint);
|
||||
if (anchor.size() > 0) {
|
||||
emit openLink(anchor);
|
||||
}
|
||||
}
|
||||
|
||||
bool MessageDelegate::isAnchorHovered(const QPoint& point, const QModelIndex& index, const QRect& sizeHint) const
|
||||
{
|
||||
QString anchor = getAnchor(point, index, sizeHint);
|
||||
return anchor.size() > 0;
|
||||
}
|
||||
|
||||
void MessageDelegate::initializeFonts(const QFont& font)
|
||||
|
@ -452,7 +462,6 @@ void MessageDelegate::initializeFonts(const QFont& font)
|
|||
}
|
||||
|
||||
bodyFont.setKerning(false);
|
||||
bodyMetrics = QFontMetrics(bodyFont);
|
||||
nickMetrics = QFontMetrics(nickFont);
|
||||
dateMetrics = QFontMetrics(dateFont);
|
||||
|
||||
|
@ -636,36 +645,6 @@ QLabel * MessageDelegate::getPencilIcon(const Models::FeedItem& data) const
|
|||
return result;
|
||||
}
|
||||
|
||||
QTextBrowser * MessageDelegate::getBody(const Models::FeedItem& data) const
|
||||
{
|
||||
std::map<QString, QTextBrowser*>::const_iterator itr = bodies->find(data.id);
|
||||
QTextBrowser* result = 0;
|
||||
|
||||
if (itr != bodies->end()) {
|
||||
result = itr->second;
|
||||
} else {
|
||||
result = new QTextBrowser();
|
||||
result->setFont(bodyFont);
|
||||
result->setContextMenuPolicy(Qt::NoContextMenu);
|
||||
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);
|
||||
bodies->insert(std::make_pair(data.id, result));
|
||||
}
|
||||
|
||||
result->setHtml(Shared::processMessageBody(data.text));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void removeElements(std::map<QString, T*>* elements, std::set<QString>* idsToKeep) {
|
||||
std::set<QString> toRemove;
|
||||
|
@ -691,26 +670,6 @@ int MessageDelegate::paintBody(const Models::FeedItem& data, QPainter* painter,
|
|||
painter->restore();
|
||||
QSize bodySize(std::ceil(bodyRenderer->idealWidth()), std::ceil(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();
|
||||
}
|
||||
|
@ -723,8 +682,6 @@ void MessageDelegate::beginClearWidgets()
|
|||
clearingWidgets = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void MessageDelegate::endClearWidgets()
|
||||
{
|
||||
if (clearingWidgets) {
|
||||
|
@ -732,7 +689,6 @@ void MessageDelegate::endClearWidgets()
|
|||
removeElements(bars, idsToKeep);
|
||||
removeElements(statusIcons, idsToKeep);
|
||||
removeElements(pencilIcons, idsToKeep);
|
||||
removeElements(bodies, idsToKeep);
|
||||
removeElements(previews, idsToKeep);
|
||||
|
||||
idsToKeep->clear();
|
||||
|
@ -760,8 +716,3 @@ void MessageDelegate::clearHelperWidget(const Models::FeedItem& data) const
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// void MessageDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const
|
||||
// {
|
||||
//
|
||||
// }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue