1
0
forked from blue/squawk

first successfull attempt to visualize selection on message body

This commit is contained in:
Blue 2022-05-01 23:19:52 +03:00
parent c3a45ec58c
commit 0340db7f2f
Signed by untrusted user: blue
GPG Key ID: 9B203B252A63EE38
4 changed files with 92 additions and 42 deletions

View File

@ -52,7 +52,10 @@ FeedView::FeedView(QWidget* parent):
dividerFont(), dividerFont(),
dividerMetrics(dividerFont), dividerMetrics(dividerFont),
mousePressed(false), mousePressed(false),
anchorHovered(false) dragging(false),
anchorHovered(false),
dragStartPoint(),
dragEndPoint()
{ {
horizontalScrollBar()->setRange(0, 0); horizontalScrollBar()->setRange(0, 0);
verticalScrollBar()->setSingleStep(approximateSingleMessageHeight); verticalScrollBar()->setSingleStep(approximateSingleMessageHeight);
@ -304,7 +307,7 @@ bool FeedView::tryToCalculateGeometriesWithNoScrollbars(const QStyleOptionViewIt
void FeedView::paintEvent(QPaintEvent* event) void FeedView::paintEvent(QPaintEvent* event)
{ {
//qDebug() << "paint" << event->rect(); qDebug() << "paint" << event->rect();
const QAbstractItemModel* m = model(); const QAbstractItemModel* m = model();
QWidget* vp = viewport(); QWidget* vp = viewport();
QRect zone = event->rect().translated(0, -vo); QRect zone = event->rect().translated(0, -vo);
@ -427,19 +430,31 @@ void FeedView::mouseMoveEvent(QMouseEvent* event)
return; return;
} }
mousePressed = false; dragEndPoint = event->localPos().toPoint();
//qDebug() << event; if (mousePressed) {
QPoint distance = dragStartPoint - dragEndPoint;
if (distance.manhattanLength() > 5) {
dragging = true;
}
}
QAbstractItemView::mouseMoveEvent(event); QAbstractItemView::mouseMoveEvent(event);
if (specialDelegate) { if (specialDelegate) {
QPoint point = event->localPos().toPoint(); QModelIndex index = indexAt(dragEndPoint);
QModelIndex index = indexAt(point);
if (index.isValid()) { if (index.isValid()) {
QRect rect = visualRect(index); QRect rect = visualRect(index);
MessageDelegate* del = static_cast<MessageDelegate*>(itemDelegate()); if (rect.contains(dragEndPoint)) {
if (rect.contains(point)) { MessageDelegate* del = static_cast<MessageDelegate*>(itemDelegate());
setAnchorHovered(del->isAnchorHovered(point, index, rect)); if (dragging) {
setAnchorHovered(false);
if (del->mouseDrag(dragStartPoint, dragEndPoint, index, rect)) {
qDebug() << "asking to repaint" << rect;
setDirtyRegion(rect);
}
} else {
setAnchorHovered(del->isAnchorHovered(dragEndPoint, index, rect));
}
} else { } else {
setAnchorHovered(false); setAnchorHovered(false);
} }
@ -453,22 +468,29 @@ void FeedView::mousePressEvent(QMouseEvent* event)
{ {
QAbstractItemView::mousePressEvent(event); QAbstractItemView::mousePressEvent(event);
mousePressed = event->button() == Qt::LeftButton; mousePressed = event->button() == Qt::LeftButton;
if (mousePressed) {
dragStartPoint = event->localPos().toPoint();
}
} }
void FeedView::mouseReleaseEvent(QMouseEvent* event) void FeedView::mouseReleaseEvent(QMouseEvent* event)
{ {
QAbstractItemView::mouseReleaseEvent(event); QAbstractItemView::mouseReleaseEvent(event);
if (mousePressed && specialDelegate) { if (mousePressed) {
QPoint point = event->localPos().toPoint(); if (!dragging && specialDelegate) {
QModelIndex index = indexAt(point); QPoint point = event->localPos().toPoint();
if (index.isValid()) { QModelIndex index = indexAt(point);
QRect rect = visualRect(index); if (index.isValid()) {
MessageDelegate* del = static_cast<MessageDelegate*>(itemDelegate()); QRect rect = visualRect(index);
if (rect.contains(point)) { MessageDelegate* del = static_cast<MessageDelegate*>(itemDelegate());
del->leftClick(point, index, rect); if (rect.contains(point)) {
del->leftClick(point, index, rect);
}
} }
} }
dragging = false;
mousePressed = false;
} }
} }

View File

@ -99,7 +99,10 @@ private:
QFont dividerFont; QFont dividerFont;
QFontMetrics dividerMetrics; QFontMetrics dividerMetrics;
bool mousePressed; bool mousePressed;
bool dragging;
bool anchorHovered; bool anchorHovered;
QPoint dragStartPoint;
QPoint dragEndPoint;
static const std::set<int> geometryChangingRoles; static const std::set<int> geometryChangingRoles;

View File

@ -56,7 +56,9 @@ MessageDelegate::MessageDelegate(QObject* parent):
pencilIcons(new std::map<QString, QLabel*>()), pencilIcons(new std::map<QString, QLabel*>()),
previews(new std::map<QString, Preview*>()), previews(new std::map<QString, Preview*>()),
idsToKeep(new std::set<QString>()), idsToKeep(new std::set<QString>()),
clearingWidgets(false) clearingWidgets(false),
currentId(""),
selection(0, 0)
{ {
bodyRenderer->setDocumentMargin(0); bodyRenderer->setDocumentMargin(0);
@ -438,6 +440,37 @@ bool MessageDelegate::isAnchorHovered(const QPoint& point, const QModelIndex& in
return anchor.size() > 0; return anchor.size() > 0;
} }
bool MessageDelegate::mouseDrag(const QPoint& start, const QPoint& end, const QModelIndex& index, const QRect& sizeHint)
{
QVariant vi = index.data(Models::MessageFeed::Bulk);
Models::FeedItem data = qvariant_cast<Models::FeedItem>(vi);
if (data.text.size() > 0) {
QRect localHint = getHoveredMessageBodyRect(index, data, sizeHint);
if (localHint.contains(start)) {
QPoint translated = start - localHint.topLeft();
bodyRenderer->setHtml(Shared::processMessageBody(data.text));
bodyRenderer->setTextWidth(localHint.size().width());
selection.first = bodyRenderer->documentLayout()->hitTest(translated, Qt::HitTestAccuracy::FuzzyHit);
selection.second = bodyRenderer->documentLayout()->hitTest(end - localHint.topLeft(), Qt::HitTestAccuracy::FuzzyHit);
currentId = data.id;
return true;
}
}
return false;
}
QString MessageDelegate::clearSelection()
{
QString lastSelectedId = currentId;
currentId = "";
selection = std::pair(0, 0);
return lastSelectedId;
}
void MessageDelegate::initializeFonts(const QFont& font) void MessageDelegate::initializeFonts(const QFont& font)
{ {
bodyFont = font; bodyFont = font;
@ -664,32 +697,21 @@ int MessageDelegate::paintBody(const Models::FeedItem& data, QPainter* painter,
if (data.text.size() > 0) { if (data.text.size() > 0) {
bodyRenderer->setHtml(Shared::processMessageBody(data.text)); bodyRenderer->setHtml(Shared::processMessageBody(data.text));
bodyRenderer->setTextWidth(option.rect.size().width()); bodyRenderer->setTextWidth(option.rect.size().width());
painter->setBackgroundMode(Qt::BGMode::OpaqueMode);
painter->save(); painter->save();
// QTextCursor cursor(bodyRenderer);
// cursor.setPosition(2, QTextCursor::KeepAnchor);
painter->translate(option.rect.topLeft()); painter->translate(option.rect.topLeft());
// QTextFrameFormat format = bodyRenderer->rootFrame()->frameFormat();
// format.setBackground(option.palette.brush(QPalette::Active, QPalette::Highlight)); if (data.id == currentId) {
// bodyRenderer->rootFrame()->setFrameFormat(format); QTextCursor cursor(bodyRenderer);
cursor.setPosition(selection.first, QTextCursor::MoveAnchor);
cursor.setPosition(selection.second, QTextCursor::KeepAnchor);
QTextCharFormat format = cursor.charFormat();
format.setBackground(option.palette.color(QPalette::Active, QPalette::Highlight));
format.setForeground(option.palette.color(QPalette::Active, QPalette::HighlightedText));
cursor.setCharFormat(format);
}
bodyRenderer->drawContents(painter); bodyRenderer->drawContents(painter);
// QColor c = option.palette.color(QPalette::Active, QPalette::Highlight);
// QTextBlock b = bodyRenderer->begin();
// QTextBlockFormat format = b.blockFormat();
// format.setBackground(option.palette.brush(QPalette::Active, QPalette::Highlight));
// format.setProperty(QTextFormat::BackgroundBrush, option.palette.brush(QPalette::Active, QPalette::Highlight));
// QTextCursor cursor(bodyRenderer);
// cursor.setBlockFormat(format);
// b = bodyRenderer->begin();
// while (b.isValid() > 0) {
// QTextLayout* lay = b.layout();
// QTextLayout::FormatRange range;
// range.format = b.charFormat();
// range.start = 0;
// range.length = 2;
// lay->draw(painter, option.rect.topLeft(), {range});
// b = b.next();
// }
painter->restore(); painter->restore();
QSize bodySize(std::ceil(bodyRenderer->idealWidth()), std::ceil(bodyRenderer->size().height())); QSize bodySize(std::ceil(bodyRenderer->idealWidth()), std::ceil(bodyRenderer->size().height()));

View File

@ -59,6 +59,8 @@ public:
void beginClearWidgets(); void beginClearWidgets();
void leftClick(const QPoint& point, const QModelIndex& index, const QRect& sizeHint) const; void leftClick(const QPoint& point, const QModelIndex& index, const QRect& sizeHint) const;
bool isAnchorHovered(const QPoint& point, const QModelIndex& index, const QRect& sizeHint) const; bool isAnchorHovered(const QPoint& point, const QModelIndex& index, const QRect& sizeHint) const;
bool mouseDrag(const QPoint& start, const QPoint& end, const QModelIndex& index, const QRect& sizeHint);
QString clearSelection();
static int avatarHeight; static int avatarHeight;
static int margin; static int margin;
@ -116,7 +118,8 @@ private:
std::map<QString, Preview*>* previews; std::map<QString, Preview*>* previews;
std::set<QString>* idsToKeep; std::set<QString>* idsToKeep;
bool clearingWidgets; bool clearingWidgets;
QString currentId;
std::pair<int, int> selection;
}; };
#endif // MESSAGEDELEGATE_H #endif // MESSAGEDELEGATE_H