|
|
@ -35,16 +35,6 @@ T clamp(T x, T min, T max) |
|
|
|
return x; |
|
|
|
return x; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
auto compareSmaller = [](const ChatLine::Ptr lhs, const qreal rhs) -> bool |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return lhs->boundingSceneRect().top() < rhs; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
auto compareGreater = [](const qreal lhs, const ChatLine::Ptr rhs) -> bool |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return lhs < rhs->boundingSceneRect().bottom(); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ChatLog::ChatLog(QWidget* parent) |
|
|
|
ChatLog::ChatLog(QWidget* parent) |
|
|
|
: QGraphicsView(parent) |
|
|
|
: QGraphicsView(parent) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -71,7 +61,7 @@ ChatLog::ChatLog(QWidget* parent) |
|
|
|
copyAction = new QAction(this); |
|
|
|
copyAction = new QAction(this); |
|
|
|
copyAction->setShortcut(QKeySequence::Copy); |
|
|
|
copyAction->setShortcut(QKeySequence::Copy); |
|
|
|
addAction(copyAction); |
|
|
|
addAction(copyAction); |
|
|
|
connect(copyAction, &QAction::triggered, this, [ = ](bool) |
|
|
|
connect(copyAction, &QAction::triggered, this, [this](bool) |
|
|
|
{ |
|
|
|
{ |
|
|
|
copySelectedText(); |
|
|
|
copySelectedText(); |
|
|
|
}); |
|
|
|
}); |
|
|
@ -148,7 +138,7 @@ void ChatLog::clearSelection() |
|
|
|
|
|
|
|
|
|
|
|
QRect ChatLog::getVisibleRect() const |
|
|
|
QRect ChatLog::getVisibleRect() const |
|
|
|
{ |
|
|
|
{ |
|
|
|
return mapToScene(calculateSceneRect().toRect()).boundingRect().toRect(); |
|
|
|
return mapToScene(viewport()->rect()).boundingRect().toRect(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void ChatLog::updateSceneRect() |
|
|
|
void ChatLog::updateSceneRect() |
|
|
@ -282,7 +272,7 @@ void ChatLog::mouseMoveEvent(QMouseEvent* ev) |
|
|
|
if(selectionMode == None && (clickPos - ev->pos()).manhattanLength() > QApplication::startDragDistance()) |
|
|
|
if(selectionMode == None && (clickPos - ev->pos()).manhattanLength() > QApplication::startDragDistance()) |
|
|
|
{ |
|
|
|
{ |
|
|
|
QPointF sceneClickPos = mapToScene(clickPos.toPoint()); |
|
|
|
QPointF sceneClickPos = mapToScene(clickPos.toPoint()); |
|
|
|
ChatLine::Ptr line = findLineByYPos(scenePos.y()); |
|
|
|
ChatLine::Ptr line = findLineByPosY(scenePos.y()); |
|
|
|
|
|
|
|
|
|
|
|
ChatLineContent* content = getContentFromPos(sceneClickPos); |
|
|
|
ChatLineContent* content = getContentFromPos(sceneClickPos); |
|
|
|
if(content) |
|
|
|
if(content) |
|
|
@ -313,7 +303,7 @@ void ChatLog::mouseMoveEvent(QMouseEvent* ev) |
|
|
|
if(selectionMode != None) |
|
|
|
if(selectionMode != None) |
|
|
|
{ |
|
|
|
{ |
|
|
|
ChatLineContent* content = getContentFromPos(scenePos); |
|
|
|
ChatLineContent* content = getContentFromPos(scenePos); |
|
|
|
ChatLine::Ptr line = findLineByYPos(scenePos.y()); |
|
|
|
ChatLine::Ptr line = findLineByPosY(scenePos.y()); |
|
|
|
|
|
|
|
|
|
|
|
if(!content && !line.get()) |
|
|
|
if(!content && !line.get()) |
|
|
|
return; |
|
|
|
return; |
|
|
@ -369,18 +359,11 @@ ChatLineContent* ChatLog::getContentFromPos(QPointF scenePos) const |
|
|
|
if(lines.empty()) |
|
|
|
if(lines.empty()) |
|
|
|
return nullptr; |
|
|
|
return nullptr; |
|
|
|
|
|
|
|
|
|
|
|
//the first visible line
|
|
|
|
auto itr = std::lower_bound(lines.cbegin(), lines.cend(), scenePos.y(), ChatLine::lessThanBSRectBottom); |
|
|
|
auto lowerBound = std::upper_bound(lines.cbegin(), lines.cend(), scenePos.y(), compareGreater); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//the last visible line
|
|
|
|
|
|
|
|
auto upperBound = std::lower_bound(lines.cbegin(), lines.cend(), scenePos.y(), compareSmaller); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//find content
|
|
|
|
//find content
|
|
|
|
for(auto itr = lowerBound; itr != upperBound; ++itr) |
|
|
|
if(itr != lines.cend() && (*itr)->boundingSceneRect().contains(scenePos)) |
|
|
|
{ |
|
|
|
return (*itr)->getContent(scenePos); |
|
|
|
if((*itr)->boundingSceneRect().contains(scenePos)) |
|
|
|
|
|
|
|
return (*itr)->getContent(scenePos); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return nullptr; |
|
|
|
return nullptr; |
|
|
|
} |
|
|
|
} |
|
|
@ -620,10 +603,10 @@ void ChatLog::checkVisibility() |
|
|
|
return; |
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
// find first visible line
|
|
|
|
// find first visible line
|
|
|
|
auto lowerBound = std::upper_bound(lines.cbegin(), lines.cend(), getVisibleRect().top(), compareGreater); |
|
|
|
auto lowerBound = std::lower_bound(lines.cbegin(), lines.cend(), getVisibleRect().top(), ChatLine::lessThanBSRectBottom); |
|
|
|
|
|
|
|
|
|
|
|
// find last visible line
|
|
|
|
// find last visible line
|
|
|
|
auto upperBound = std::lower_bound(lines.cbegin(), lines.cend(), getVisibleRect().bottom(), compareSmaller); |
|
|
|
auto upperBound = std::lower_bound(lines.cbegin(), lines.cend(), getVisibleRect().bottom(), ChatLine::lessThanBSRectTop); |
|
|
|
|
|
|
|
|
|
|
|
// set visibilty
|
|
|
|
// set visibilty
|
|
|
|
QList<ChatLine::Ptr> newVisibleLines; |
|
|
|
QList<ChatLine::Ptr> newVisibleLines; |
|
|
@ -644,13 +627,10 @@ void ChatLog::checkVisibility() |
|
|
|
visibleLines = newVisibleLines; |
|
|
|
visibleLines = newVisibleLines; |
|
|
|
|
|
|
|
|
|
|
|
// enforce order
|
|
|
|
// enforce order
|
|
|
|
std::sort(visibleLines.begin(), visibleLines.end(), [](const ChatLine::Ptr lhs, const ChatLine::Ptr rhs) |
|
|
|
std::sort(visibleLines.begin(), visibleLines.end(), ChatLine::lessThanRowIndex); |
|
|
|
{ |
|
|
|
|
|
|
|
return lhs->getRowIndex() < rhs->getRowIndex(); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//if(!visibleLines.empty())
|
|
|
|
//if(!visibleLines.empty())
|
|
|
|
// qDebug() << "visible from " << visibleLines.first()->getRowIndex() << "to " << visibleLines.last()->getRowIndex() << " total " << visibleLines.size();
|
|
|
|
// qDebug() << "visible from " << visibleLines.first()->getRowIndex() << "to " << visibleLines.last()->getRowIndex() << " total " << visibleLines.size();
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void ChatLog::scrollContentsBy(int dx, int dy) |
|
|
|
void ChatLog::scrollContentsBy(int dx, int dy) |
|
|
@ -710,12 +690,12 @@ void ChatLog::updateTypingNotification() |
|
|
|
notification->layout(useableWidth(), QPointF(0.0, posY)); |
|
|
|
notification->layout(useableWidth(), QPointF(0.0, posY)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
ChatLine::Ptr ChatLog::findLineByYPos(qreal yPos) const |
|
|
|
ChatLine::Ptr ChatLog::findLineByPosY(qreal yPos) const |
|
|
|
{ |
|
|
|
{ |
|
|
|
auto lowerBound = std::upper_bound(lines.cbegin(), lines.cend(), yPos, compareGreater); |
|
|
|
auto itr = std::lower_bound(lines.cbegin(), lines.cend(), yPos, ChatLine::lessThanBSRectBottom); |
|
|
|
|
|
|
|
|
|
|
|
if(lowerBound != lines.cend()) |
|
|
|
if(itr != lines.cend()) |
|
|
|
return *lowerBound; |
|
|
|
return *itr; |
|
|
|
|
|
|
|
|
|
|
|
return ChatLine::Ptr(); |
|
|
|
return ChatLine::Ptr(); |
|
|
|
} |
|
|
|
} |
|
|
|