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

View File

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

View File

@ -56,7 +56,9 @@ MessageDelegate::MessageDelegate(QObject* parent):
pencilIcons(new std::map<QString, QLabel*>()),
previews(new std::map<QString, Preview*>()),
idsToKeep(new std::set<QString>()),
clearingWidgets(false)
clearingWidgets(false),
currentId(""),
selection(0, 0)
{
bodyRenderer->setDocumentMargin(0);
@ -438,6 +440,37 @@ bool MessageDelegate::isAnchorHovered(const QPoint& point, const QModelIndex& in
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)
{
bodyFont = font;
@ -664,32 +697,21 @@ int MessageDelegate::paintBody(const Models::FeedItem& data, QPainter* painter,
if (data.text.size() > 0) {
bodyRenderer->setHtml(Shared::processMessageBody(data.text));
bodyRenderer->setTextWidth(option.rect.size().width());
painter->setBackgroundMode(Qt::BGMode::OpaqueMode);
painter->save();
// QTextCursor cursor(bodyRenderer);
// cursor.setPosition(2, QTextCursor::KeepAnchor);
painter->translate(option.rect.topLeft());
// QTextFrameFormat format = bodyRenderer->rootFrame()->frameFormat();
// format.setBackground(option.palette.brush(QPalette::Active, QPalette::Highlight));
// bodyRenderer->rootFrame()->setFrameFormat(format);
if (data.id == currentId) {
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);
// 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();
QSize bodySize(std::ceil(bodyRenderer->idealWidth()), std::ceil(bodyRenderer->size().height()));

View File

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