1
0
mirror of https://github.com/qTox/qTox.git synced 2024-03-22 14:00:36 +08:00

revisited selection

This commit is contained in:
krepa098 2014-12-09 13:17:08 +01:00
parent c91b7cb03c
commit 661a8c4da4
4 changed files with 96 additions and 65 deletions

View File

@ -84,3 +84,8 @@ void ChatLineContent::visibilityChanged(bool)
{ {
} }
QString ChatLineContent::getText() const
{
return QString();
}

View File

@ -44,6 +44,8 @@ public:
virtual bool isOverSelection(QPointF scenePos) const; virtual bool isOverSelection(QPointF scenePos) const;
virtual QString getSelectedText() const; virtual QString getSelectedText() const;
virtual QString getText() const;
virtual qreal firstLineVOffset() const; virtual qreal firstLineVOffset() const;
virtual QRectF boundingSceneRect() const = 0; virtual QRectF boundingSceneRect() const = 0;

View File

@ -57,6 +57,12 @@ ChatLog::ChatLog(QWidget* parent)
setViewportUpdateMode(SmartViewportUpdate); setViewportUpdateMode(SmartViewportUpdate);
//setRenderHint(QPainter::TextAntialiasing); //setRenderHint(QPainter::TextAntialiasing);
selGraphItem = new QGraphicsRectItem();
selGraphItem->setZValue(-10.0); //behind all items
selGraphItem->setBrush(QBrush(QColor(166,225,255)));
scene->addItem(selGraphItem);
// copy action // copy action
copyAction = new QAction(this); copyAction = new QAction(this);
copyAction->setShortcut(QKeySequence::Copy); copyAction->setShortcut(QKeySequence::Copy);
@ -116,14 +122,17 @@ ChatMessage *ChatLog::addFileTransferMessage(const QString &sender, const ToxFil
void ChatLog::clearSelection() void ChatLog::clearSelection()
{ {
if(selStartRow >= 0) for(int i=selFirstRow; i<=selLastRow && i<lines.size() && i >= 0; ++i)
for(int r = qMin(selStartRow, selLastRow); r <= qMax(selLastRow, selStartRow) && r < lines.size(); ++r) lines[i]->selectionCleared();
lines[r]->selectionCleared();
selStartRow = -1; selGraphItem->hide();
selStartCol = -1;
selFirstRow = -1;
selLastRow = -1; selLastRow = -1;
selLastCol = -1; selClickedCol = -1;
selClickedRow = -1;
selectionMode = None;
} }
QRect ChatLog::getVisibleRect() const QRect ChatLog::getVisibleRect() const
@ -229,9 +238,6 @@ void ChatLog::mousePressEvent(QMouseEvent* ev)
void ChatLog::mouseReleaseEvent(QMouseEvent* ev) void ChatLog::mouseReleaseEvent(QMouseEvent* ev)
{ {
QGraphicsView::mouseReleaseEvent(ev); QGraphicsView::mouseReleaseEvent(ev);
if(ev->button() == Qt::LeftButton)
selecting = false;
} }
void ChatLog::mouseMoveEvent(QMouseEvent* ev) void ChatLog::mouseMoveEvent(QMouseEvent* ev)
@ -242,21 +248,21 @@ void ChatLog::mouseMoveEvent(QMouseEvent* ev)
if(ev->buttons() & Qt::LeftButton) if(ev->buttons() & Qt::LeftButton)
{ {
if(!selecting && (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());
ChatLineContent* content = getContentFromPos(sceneClickPos); ChatLineContent* content = getContentFromPos(sceneClickPos);
if(content) if(content)
{ {
selStartRow = content->getRow(); selClickedRow = content->getRow();
selStartCol = content->getColumn(); selClickedCol = content->getColumn();
selLastRow = selStartRow; selFirstRow = content->getRow();
selLastCol = selStartCol; selLastRow = content->getRow();
content->selectionStarted(sceneClickPos); content->selectionStarted(sceneClickPos);
selecting = true; selectionMode = Precise;
// ungrab mouse grabber // ungrab mouse grabber
if(scene->mouseGrabberItem()) if(scene->mouseGrabberItem())
@ -265,7 +271,7 @@ void ChatLog::mouseMoveEvent(QMouseEvent* ev)
} }
} }
if(selecting && ev->pos() != lastPos) if(selectionMode != None && ev->pos() != lastPos)
{ {
lastPos = ev->pos(); lastPos = ev->pos();
@ -273,47 +279,35 @@ void ChatLog::mouseMoveEvent(QMouseEvent* ev)
if(content) if(content)
{ {
// TODO: turn this into a sane algo.
int row = content->getRow(); int row = content->getRow();
int col = content->getColumn(); int col = content->getColumn();
int firstRow = selStartRow;
// selection if(row >= selClickedRow)
for(int r = qMin(firstRow, row + 1); r < qMax(row, firstRow); r++) selLastRow = row;
lines[r]->selectAll();
if(row != selStartRow) if(row <= selClickedRow)
for(int c = 0; c < col; c++) selFirstRow = row;
lines[selStartRow]->selectAll();
if(row == selClickedRow && col == selClickedCol)
{
selectionMode = Precise;
if(row == selStartRow)
content->selectionMouseMove(scenePos); content->selectionMouseMove(scenePos);
selGraphItem->hide();
}
else else
{ {
lines[row]->selectAll(); selectionMode = Multi;
selStartCol = 0;
selLastCol = lines[row]->getColumnCount(); lines[selClickedRow]->selectionCleared();
QRectF selBBox;
selBBox = selBBox.united(lines[selFirstRow]->boundingSceneRect());
selBBox = selBBox.united(lines[selLastRow]->boundingSceneRect());
selGraphItem->setRect(selBBox);
selGraphItem->show();
} }
// de-selection
if(row < selStartRow)
selLastRow = qMin(row, selLastRow);
else
selLastRow = qMax(row, selLastRow);
if(col < selStartCol)
selLastCol = qMin(col, selLastCol);
else
selLastCol = qMax(col, selLastCol);
for(int r = qMin(row, selLastRow); r < qMax(row, selLastRow + 1) && r < lines.size(); ++r)
if(r != row)
lines[r]->selectionCleared();
if(row == selStartRow)
for(int c = col + 1; c < lines[row]->getColumnCount() && c < selLastCol; ++c)
lines[row]->selectionCleared(c);
} }
} }
} }
@ -330,17 +324,25 @@ ChatLineContent* ChatLog::getContentFromPos(QPointF scenePos) const
bool ChatLog::isOverSelection(QPointF scenePos) bool ChatLog::isOverSelection(QPointF scenePos)
{ {
ChatLineContent* content = getContentFromPos(scenePos); if(selectionMode == Precise)
{
ChatLineContent* content = getContentFromPos(scenePos);
if(content) if(content)
return content->isOverSelection(scenePos); return content->isOverSelection(scenePos);
}
else if(selectionMode == Multi)
{
if(selGraphItem->rect().contains(scenePos))
return true;
}
return false; return false;
} }
int ChatLog::useableWidth() int ChatLog::useableWidth()
{ {
return width() - verticalScrollBar()->sizeHint().width(); return width() - verticalScrollBar()->sizeHint().width() - 10.0;
} }
void ChatLog::reposition(int start, int end) void ChatLog::reposition(int start, int end)
@ -411,19 +413,33 @@ void ChatLog::scrollToBottom()
QString ChatLog::getSelectedText() const QString ChatLog::getSelectedText() const
{ {
QString ret; if(selectionMode == Precise)
{
return lines[selClickedRow]->content[selClickedCol]->getSelectedText();
}
else if(selectionMode == Multi)
{
// build a nicely formatted message
QString out;
const int rowStart = qMin(selStartRow, selLastRow); QString lastSender;
const int rowLast = qMax(selStartRow, selLastRow); for(int i=selFirstRow; i<=selLastRow && i>=0 && i<lines.size(); ++i)
{
if(lastSender != lines[i]->content[0]->getText() && !lines[i]->content[0]->getText().isEmpty())
{
//author changed
out += lines[i]->content[0]->getText() + ":\n";
lastSender = lines[i]->content[0]->getText();
}
const int colStart = qMin(selStartCol, selLastCol); out += lines[i]->content[1]->getText();
const int colLast = qMax(selStartCol, selLastCol); out += "\n\n";
}
for(int r = rowStart; r <= rowLast && r < lines.size(); ++r) return out;
for(int c = colStart; c <= colLast && c < lines[r]->getColumnCount(); ++c) }
ret.append(lines[r]->content[c]->getSelectedText() + '\n');
return ret; return QString();
} }
void ChatLog::showContextMenu(const QPoint& globalPos, const QPointF& scenePos) void ChatLog::showContextMenu(const QPoint& globalPos, const QPointF& scenePos)

View File

@ -21,6 +21,7 @@
#include <QDateTime> #include <QDateTime>
class QGraphicsScene; class QGraphicsScene;
class QGraphicsRectItem;
class ChatLine; class ChatLine;
class ChatLineContent; class ChatLineContent;
class ChatMessage; class ChatMessage;
@ -72,6 +73,12 @@ protected:
virtual void resizeEvent(QResizeEvent *ev); virtual void resizeEvent(QResizeEvent *ev);
private: private:
enum SelectionMode {
None,
Precise,
Multi,
};
QGraphicsScene* scene = nullptr; QGraphicsScene* scene = nullptr;
QList<ChatLine*> lines; QList<ChatLine*> lines;
QList<ChatLine*> visibleLines; QList<ChatLine*> visibleLines;
@ -81,13 +88,14 @@ private:
int insertStartIndex = -1; int insertStartIndex = -1;
// selection // selection
int selStartRow = -1; int selClickedRow = -1;
int selStartCol = -1; int selClickedCol = -1;
int selFirstRow = -1;
int selLastRow = -1; int selLastRow = -1;
int selLastCol = -1; SelectionMode selectionMode = None;
bool selecting = false;
QPointF clickPos; QPointF clickPos;
QPointF lastPos; QPointF lastPos;
QGraphicsRectItem* selGraphItem = nullptr;
// actions // actions
QAction* copyAction = nullptr; QAction* copyAction = nullptr;