encrypted messages now are displayed in the feed

This commit is contained in:
Blue 2023-11-06 20:57:08 -03:00
parent 637eb702a8
commit 0a530bfa93
Signed by untrusted user: blue
GPG key ID: 9B203B252A63EE38
34 changed files with 439 additions and 245 deletions

View file

@ -47,22 +47,23 @@ MessageDelegate::MessageDelegate(QObject* parent):
dateFont(Shared::Global::getInstance()->smallFont),
nickMetrics(Shared::Global::getInstance()->headerFontMetrics),
dateMetrics(Shared::Global::getInstance()->smallFontMetrics),
bodyRenderer(new QTextDocument()),
bodyRenderer(),
buttonHeight(0),
buttonWidth(0),
barHeight(0),
buttons(new std::map<QString, FeedButton*>()),
bars(new std::map<QString, QProgressBar*>()),
statusIcons(new std::map<QString, QLabel*>()),
pencilIcons(new std::map<QString, QLabel*>()),
previews(new std::map<QString, Preview*>()),
idsToKeep(new std::set<QString>()),
buttons(),
bars(),
statusIcons(),
pencilIcons(),
encryptionIcons(),
previews(),
idsToKeep(),
clearingWidgets(false),
currentId(""),
selection(0, 0)
{
bodyRenderer->setDocumentMargin(0);
bodyRenderer->setDefaultFont(bodyFont);
bodyRenderer.setDocumentMargin(0);
bodyRenderer.setDefaultFont(bodyFont);
QPushButton btn(QCoreApplication::translate("MessageLine", "Download"));
buttonHeight = btn.sizeHint().height();
@ -73,28 +74,23 @@ MessageDelegate::MessageDelegate(QObject* parent):
}
MessageDelegate::~MessageDelegate() {
for (const std::pair<const QString, FeedButton*>& pair: *buttons)
for (const std::pair<const QString, FeedButton*>& pair: buttons)
delete pair.second;
for (const std::pair<const QString, QProgressBar*>& pair: *bars)
for (const std::pair<const QString, QProgressBar*>& pair: bars)
delete pair.second;
for (const std::pair<const QString, QLabel*>& pair: *statusIcons)
for (const std::pair<const QString, QLabel*>& pair: statusIcons)
delete pair.second;
for (const std::pair<const QString, QLabel*>& pair: *pencilIcons)
for (const std::pair<const QString, QLabel*>& pair: pencilIcons)
delete pair.second;
for (const std::pair<const QString, QLabel*>& pair: encryptionIcons)
delete pair.second;
for (const std::pair<const QString, Preview*>& pair: *previews)
for (const std::pair<const QString, Preview*>& pair: previews)
delete pair.second;
delete statusIcons;
delete pencilIcons;
delete idsToKeep;
delete buttons;
delete bars;
delete previews;
delete bodyRenderer;
}
void MessageDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const {
@ -168,6 +164,7 @@ void MessageDelegate::paint(QPainter* painter, const QStyleOptionViewItem& optio
painter->setPen(q);
painter->drawText(opt.rect, opt.displayAlignment, dateString, &rect);
int currentY = opt.rect.y();
int statusOffset = statusIconSize;
if (data.sentByMe) {
QLabel* statusIcon = getStatusIcon(data);
@ -176,30 +173,43 @@ void MessageDelegate::paint(QPainter* painter, const QStyleOptionViewItem& optio
statusIcon->show();
opt.rect.adjust(0, statusIconSize + textMargin, 0, 0);
statusOffset = statusIconSize + margin;
}
if (data.correction.corrected) {
QLabel* pencilIcon = getPencilIcon(data);
pencilIcon->setParent(vp);
if (data.sentByMe)
pencilIcon->move(opt.rect.left() + statusIconSize + margin, currentY);
pencilIcon->move(opt.rect.left() + statusOffset, currentY);
else
pencilIcon->move(opt.rect.right() - statusIconSize - margin, currentY);
pencilIcon->move(opt.rect.right() - statusOffset, currentY);
pencilIcon->show();
statusOffset += statusIconSize + margin;
} else {
std::map<QString, QLabel*>::const_iterator itr = pencilIcons->find(data.id);
if (itr != pencilIcons->end()) {
std::map<QString, QLabel*>::const_iterator itr = pencilIcons.find(data.id);
if (itr != pencilIcons.end()) {
delete itr->second;
pencilIcons->erase(itr);
pencilIcons.erase(itr);
}
}
if (data.encryption != Shared::EncryptionProtocol::none) {
QLabel* shieldIcon = getEncryptionIcon(data);
shieldIcon->setParent(vp);
if (data.sentByMe)
shieldIcon->move(opt.rect.left() + statusOffset, currentY);
else
shieldIcon->move(opt.rect.right() - statusOffset, currentY);
shieldIcon->show();
statusOffset += statusIconSize + margin;
}
painter->restore();
if (clearingWidgets)
idsToKeep->insert(data.id);
idsToKeep.insert(data.id);
}
void MessageDelegate::paintBubble(const Models::FeedItem& data, QPainter* painter, const QStyleOptionViewItem& option) const {
@ -281,11 +291,11 @@ 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) {
bodyRenderer->setPlainText(data.text);
bodyRenderer->setTextWidth(messageRect.size().width());
bodyRenderer.setPlainText(data.text);
bodyRenderer.setTextWidth(messageRect.size().width());
QSizeF size = bodyRenderer->size();
size.setWidth(bodyRenderer->idealWidth());
QSizeF size = bodyRenderer.size();
size.setWidth(bodyRenderer.idealWidth());
messageSize = QSize(std::ceil(size.width()), std::ceil(size.height()));
messageSize.rheight() += textMargin;
}
@ -338,9 +348,12 @@ QSize MessageDelegate::sizeHint(const QStyleOptionViewItem& option, const QModel
messageSize.rheight() += dateSize.height() > statusIconSize ? dateSize.height() : statusIconSize;
int statusWidth = dateSize.width() + statusIconSize + margin;
if (data.correction.corrected) {
if (data.correction.corrected)
statusWidth += statusIconSize + margin;
}
if (data.encryption != Shared::EncryptionProtocol::none)
statusWidth += statusIconSize + margin;
messageSize.setWidth(std::max(statusWidth, messageSize.width()));
messageSize.rwidth() += 2 * bubbleMargin;
@ -399,10 +412,10 @@ QString MessageDelegate::getAnchor(const QPoint& point, const QModelIndex& index
if (localHint.contains(point)) {
QPoint translated = point - localHint.topLeft();
bodyRenderer->setHtml(Shared::processMessageBody(data.text));
bodyRenderer->setTextWidth(localHint.size().width());
bodyRenderer.setHtml(Shared::processMessageBody(data.text));
bodyRenderer.setTextWidth(localHint.size().width());
return bodyRenderer->documentLayout()->anchorAt(translated);
return bodyRenderer.documentLayout()->anchorAt(translated);
}
}
@ -424,13 +437,13 @@ QString MessageDelegate::leftDoubleClick(const QPoint& point, const QModelIndex&
if (localHint.contains(point)) {
QPoint translated = point - localHint.topLeft();
bodyRenderer->setHtml(Shared::processMessageBody(data.text));
bodyRenderer->setTextWidth(localHint.size().width());
bodyRenderer.setHtml(Shared::processMessageBody(data.text));
bodyRenderer.setTextWidth(localHint.size().width());
QAbstractTextDocumentLayout* lay = bodyRenderer->documentLayout();
QAbstractTextDocumentLayout* lay = bodyRenderer.documentLayout();
int position = lay->hitTest(translated, Qt::HitTestAccuracy::FuzzyHit);
QTextCursor cursor(bodyRenderer);
QTextCursor cursor(&bodyRenderer);
cursor.setPosition(position, QTextCursor::MoveAnchor);
cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::MoveAnchor);
cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
@ -456,10 +469,10 @@ Shared::Hover MessageDelegate::hoverType(const QPoint& point, const QModelIndex&
if (localHint.contains(point)) {
QPoint translated = point - localHint.topLeft();
bodyRenderer->setHtml(Shared::processMessageBody(data.text));
bodyRenderer->setTextWidth(localHint.size().width());
bodyRenderer.setHtml(Shared::processMessageBody(data.text));
bodyRenderer.setTextWidth(localHint.size().width());
QAbstractTextDocumentLayout* lay = bodyRenderer->documentLayout();
QAbstractTextDocumentLayout* lay = bodyRenderer.documentLayout();
QString anchor = lay->anchorAt(translated);
if (anchor.size() > 0) {
@ -489,15 +502,15 @@ QString MessageDelegate::mouseDrag(const QPoint& start, const QPoint& end, const
last.setY(std::max(last.y(), 0));
last.setY(std::min(last.y(), localHint.height()));
bodyRenderer->setHtml(Shared::processMessageBody(data.text));
bodyRenderer->setTextWidth(localHint.size().width());
selection.first = bodyRenderer->documentLayout()->hitTest(first, Qt::HitTestAccuracy::FuzzyHit);
selection.second = bodyRenderer->documentLayout()->hitTest(last, Qt::HitTestAccuracy::FuzzyHit);
bodyRenderer.setHtml(Shared::processMessageBody(data.text));
bodyRenderer.setTextWidth(localHint.size().width());
selection.first = bodyRenderer.documentLayout()->hitTest(first, Qt::HitTestAccuracy::FuzzyHit);
selection.second = bodyRenderer.documentLayout()->hitTest(last, Qt::HitTestAccuracy::FuzzyHit);
currentId = data.id;
if (selection.first != selection.second) {
QTextCursor cursor(bodyRenderer);
QTextCursor cursor(&bodyRenderer);
cursor.setPosition(selection.first, QTextCursor::MoveAnchor);
cursor.setPosition(selection.second, QTextCursor::KeepAnchor);
return cursor.selectedText();
@ -562,17 +575,17 @@ int MessageDelegate::paintBar(QProgressBar* bar, QPainter* painter, bool sentByM
int MessageDelegate::paintPreview(const Models::FeedItem& data, QPainter* painter, QStyleOptionViewItem& option) const {
Preview* preview = 0;
std::map<QString, Preview*>::iterator itr = previews->find(data.id);
std::map<QString, Preview*>::iterator itr = previews.find(data.id);
QSize size = option.rect.size();
QString path = Shared::resolvePath(data.attach.localPath);
if (itr != previews->end()) {
if (itr != previews.end()) {
preview = itr->second;
preview->actualize(path, size, option.rect.topLeft());
} else {
QWidget* vp = static_cast<QWidget*>(painter->device());
preview = new Preview(path, size, option.rect.topLeft(), vp);
previews->insert(std::make_pair(data.id, preview));
previews.insert(std::make_pair(data.id, preview));
}
if (!preview->isFileReachable()) //this is the situation when the file preview couldn't be painted because the file was moved
@ -585,15 +598,15 @@ int MessageDelegate::paintPreview(const Models::FeedItem& data, QPainter* painte
}
QPushButton * MessageDelegate::getButton(const Models::FeedItem& data) const {
std::map<QString, FeedButton*>::const_iterator itr = buttons->find(data.id);
std::map<QString, FeedButton*>::const_iterator itr = buttons.find(data.id);
FeedButton* result = 0;
if (itr != buttons->end()) {
if (itr != buttons.end()) {
result = itr->second;
} else {
std::map<QString, QProgressBar*>::const_iterator barItr = bars->find(data.id);
if (barItr != bars->end()) {
std::map<QString, QProgressBar*>::const_iterator barItr = bars.find(data.id);
if (barItr != bars.end()) {
delete barItr->second;
bars->erase(barItr);
bars.erase(barItr);
}
}
@ -601,7 +614,7 @@ QPushButton * MessageDelegate::getButton(const Models::FeedItem& data) const {
result = new FeedButton();
result->messageId = data.id;
result->setText(QCoreApplication::translate("MessageLine", "Download"));
buttons->insert(std::make_pair(data.id, result));
buttons.insert(std::make_pair(data.id, result));
connect(result, &QPushButton::clicked, this, &MessageDelegate::onButtonPushed);
}
@ -609,22 +622,22 @@ QPushButton * MessageDelegate::getButton(const Models::FeedItem& data) const {
}
QProgressBar * MessageDelegate::getBar(const Models::FeedItem& data) const {
std::map<QString, QProgressBar*>::const_iterator barItr = bars->find(data.id);
std::map<QString, QProgressBar*>::const_iterator barItr = bars.find(data.id);
QProgressBar* result = 0;
if (barItr != bars->end()) {
if (barItr != bars.end()) {
result = barItr->second;
} else {
std::map<QString, FeedButton*>::const_iterator itr = buttons->find(data.id);
if (itr != buttons->end()) {
std::map<QString, FeedButton*>::const_iterator itr = buttons.find(data.id);
if (itr != buttons.end()) {
delete itr->second;
buttons->erase(itr);
buttons.erase(itr);
}
}
if (result == 0) {
result = new QProgressBar();
result->setRange(0, 100);
bars->insert(std::make_pair(data.id, result));
bars.insert(std::make_pair(data.id, result));
}
result->setValue(data.attach.progress * 100);
@ -633,14 +646,14 @@ QProgressBar * MessageDelegate::getBar(const Models::FeedItem& data) const {
}
QLabel * MessageDelegate::getStatusIcon(const Models::FeedItem& data) const {
std::map<QString, QLabel*>::const_iterator itr = statusIcons->find(data.id);
std::map<QString, QLabel*>::const_iterator itr = statusIcons.find(data.id);
QLabel* result = 0;
if (itr != statusIcons->end()) {
if (itr != statusIcons.end()) {
result = itr->second;
} else {
result = new QLabel();
statusIcons->insert(std::make_pair(data.id, result));
statusIcons.insert(std::make_pair(data.id, result));
}
QIcon q(Shared::icon(Shared::messageStateThemeIcons[static_cast<uint8_t>(data.state)]));
@ -657,17 +670,17 @@ QLabel * MessageDelegate::getStatusIcon(const Models::FeedItem& data) const {
return result;
}
QLabel * MessageDelegate::getPencilIcon(const Models::FeedItem& data) const {
std::map<QString, QLabel*>::const_iterator itr = pencilIcons->find(data.id);
QLabel* MessageDelegate::getPencilIcon(const Models::FeedItem& data) const {
std::map<QString, QLabel*>::const_iterator itr = pencilIcons.find(data.id);
QLabel* result = 0;
if (itr != pencilIcons->end()) {
if (itr != pencilIcons.end()) {
result = itr->second;
} else {
result = new QLabel();
QIcon icon = Shared::icon("edit-rename");
result->setPixmap(icon.pixmap(statusIconSize));
pencilIcons->insert(std::make_pair(data.id, result));
pencilIcons.insert(std::make_pair(data.id, result));
}
result->setToolTip("Last time edited: " + data.correction.lastCorrection.toLocalTime().toString()
@ -676,30 +689,46 @@ QLabel * MessageDelegate::getPencilIcon(const Models::FeedItem& data) const {
return result;
}
QLabel* MessageDelegate::getEncryptionIcon(const Models::FeedItem& data) const {
std::map<QString, QLabel*>::const_iterator itr = encryptionIcons.find(data.id);
QLabel* result = 0;
if (itr != encryptionIcons.end()) {
result = itr->second;
} else {
result = new QLabel();
QIcon icon = Shared::icon("secure");
result->setPixmap(icon.pixmap(statusIconSize));
encryptionIcons.insert(std::make_pair(data.id, result));
result->setToolTip("Encrypted: " + Shared::Global::getName(data.encryption));
}
return result;
}
template <typename T>
void removeElements(std::map<QString, T*>* elements, std::set<QString>* idsToKeep) {
void removeElements(std::map<QString, T*>& elements, std::set<QString>& idsToKeep) {
std::set<QString> toRemove;
for (const std::pair<const QString, T*>& pair: *elements) {
if (idsToKeep->find(pair.first) == idsToKeep->end()) {
for (const std::pair<const QString, T*>& pair: elements) {
if (idsToKeep.find(pair.first) == idsToKeep.end()) {
delete pair.second;
toRemove.insert(pair.first);
}
}
for (const QString& key : toRemove) {
elements->erase(key);
}
for (const QString& key : toRemove)
elements.erase(key);
}
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());
bodyRenderer.setHtml(Shared::processMessageBody(data.text));
bodyRenderer.setTextWidth(option.rect.size().width());
painter->save();
painter->translate(option.rect.topLeft());
if (data.id == currentId) {
QTextCursor cursor(bodyRenderer);
QTextCursor cursor(&bodyRenderer);
cursor.setPosition(selection.first, QTextCursor::MoveAnchor);
cursor.setPosition(selection.second, QTextCursor::KeepAnchor);
QTextCharFormat format = cursor.charFormat();
@ -708,10 +737,10 @@ int MessageDelegate::paintBody(const Models::FeedItem& data, QPainter* painter,
cursor.setCharFormat(format);
}
bodyRenderer->drawContents(painter);
bodyRenderer.drawContents(painter);
painter->restore();
QSize bodySize(std::ceil(bodyRenderer->idealWidth()), std::ceil(bodyRenderer->size().height()));
QSize bodySize(std::ceil(bodyRenderer.idealWidth()), std::ceil(bodyRenderer.size().height()));
option.rect.adjust(0, bodySize.height() + textMargin, 0, 0);
return bodySize.width();
@ -720,7 +749,7 @@ int MessageDelegate::paintBody(const Models::FeedItem& data, QPainter* painter,
}
void MessageDelegate::beginClearWidgets() {
idsToKeep->clear();
idsToKeep.clear();
clearingWidgets = true;
}
@ -730,9 +759,10 @@ void MessageDelegate::endClearWidgets() {
removeElements(bars, idsToKeep);
removeElements(statusIcons, idsToKeep);
removeElements(pencilIcons, idsToKeep);
removeElements(encryptionIcons, idsToKeep);
removeElements(previews, idsToKeep);
idsToKeep->clear();
idsToKeep.clear();
clearingWidgets = false;
}
}
@ -743,15 +773,15 @@ void MessageDelegate::onButtonPushed() const {
}
void MessageDelegate::clearHelperWidget(const Models::FeedItem& data) const {
std::map<QString, FeedButton*>::const_iterator itr = buttons->find(data.id);
if (itr != buttons->end()) {
std::map<QString, FeedButton*>::const_iterator itr = buttons.find(data.id);
if (itr != buttons.end()) {
delete itr->second;
buttons->erase(itr);
buttons.erase(itr);
} else {
std::map<QString, QProgressBar*>::const_iterator barItr = bars->find(data.id);
if (barItr != bars->end()) {
std::map<QString, QProgressBar*>::const_iterator barItr = bars.find(data.id);
if (barItr != bars.end()) {
delete barItr->second;
bars->erase(barItr);
bars.erase(barItr);
}
}
}