Implement draggable rectangle selection

This commit is contained in:
G.K.MacGregor
2020-10-25 11:07:04 +00:00
parent af5f0ae74c
commit 151d842bc0
4 changed files with 91 additions and 16 deletions

View File

@@ -38,6 +38,7 @@ TeletextDocument::TeletextDocument()
m_undoStack = new QUndoStack(this); m_undoStack = new QUndoStack(this);
m_cursorRow = 1; m_cursorRow = 1;
m_cursorColumn = 0; m_cursorColumn = 0;
m_selectionSubPage = nullptr;
} }
TeletextDocument::~TeletextDocument() TeletextDocument::~TeletextDocument()
@@ -285,6 +286,23 @@ void TeletextDocument::moveCursor(int newCursorRow, int newCursorColumn)
emit cursorMoved(); emit cursorMoved();
} }
void TeletextDocument::setSelection(int topRow, int leftColumn, int bottomRow, int rightColumn)
{
if (m_selectionTopRow != topRow || m_selectionBottomRow != bottomRow || m_selectionLeftColumn != leftColumn || m_selectionRightColumn != rightColumn) {
m_selectionSubPage = currentSubPage();
m_selectionTopRow = topRow;
m_selectionBottomRow = bottomRow;
m_selectionLeftColumn = leftColumn;
m_selectionRightColumn = rightColumn;
emit selectionMoved();
}
}
void TeletextDocument::cancelSelection()
{
m_selectionSubPage = nullptr;
}
OverwriteCharacterCommand::OverwriteCharacterCommand(TeletextDocument *teletextDocument, unsigned char newCharacter, QUndoCommand *parent) : QUndoCommand(parent) OverwriteCharacterCommand::OverwriteCharacterCommand(TeletextDocument *teletextDocument, unsigned char newCharacter, QUndoCommand *parent) : QUndoCommand(parent)
{ {

View File

@@ -61,9 +61,19 @@ public:
void cursorLeft(); void cursorLeft();
void cursorRight(); void cursorRight();
void moveCursor(int, int); void moveCursor(int, int);
int selectionTopRow() const { return m_selectionTopRow; }
int selectionBottomRow() const { return m_selectionBottomRow; }
int selectionLeftColumn() const { return m_selectionLeftColumn; }
int selectionRightColumn() const { return m_selectionRightColumn; }
int selectionWidth() const { return m_selectionRightColumn - m_selectionLeftColumn + 1; }
int selectionHeight() const { return m_selectionBottomRow - m_selectionTopRow + 1; }
bool selectionActive() const { return m_selectionSubPage == currentSubPage(); }
void setSelection(int, int, int, int);
void cancelSelection();
signals: signals:
void cursorMoved(); void cursorMoved();
void selectionMoved();
void colourChanged(int); void colourChanged(int);
void contentsChange(int); void contentsChange(int);
void aboutToChangeSubPage(); void aboutToChangeSubPage();
@@ -77,7 +87,8 @@ private:
int m_fastTextLink[6]; int m_fastTextLink[6];
std::vector<LevelOnePage *> m_subPages; std::vector<LevelOnePage *> m_subPages;
QUndoStack *m_undoStack; QUndoStack *m_undoStack;
int m_cursorRow, m_cursorColumn; int m_cursorRow, m_cursorColumn, m_selectionTopRow, m_selectionBottomRow, m_selectionLeftColumn, m_selectionRightColumn;
LevelOnePage *m_selectionSubPage;
}; };

View File

@@ -22,6 +22,7 @@
#include <QKeyEvent> #include <QKeyEvent>
#include <QMenu> #include <QMenu>
#include <QPainter> #include <QPainter>
#include <QPair>
#include <QUndoCommand> #include <QUndoCommand>
#include <QWidget> #include <QWidget>
#include <vector> #include <vector>
@@ -42,6 +43,7 @@ TeletextWidget::TeletextWidget(QFrame *parent) : QFrame(parent)
m_levelOnePage = m_teletextDocument->currentSubPage(); m_levelOnePage = m_teletextDocument->currentSubPage();
m_pageRender.setTeletextPage(m_levelOnePage); m_pageRender.setTeletextPage(m_levelOnePage);
m_insertMode = false; m_insertMode = false;
m_selectionInProgress = false;
m_grid = false; m_grid = false;
setFocusPolicy(Qt::StrongFocus); setFocusPolicy(Qt::StrongFocus);
m_flashTiming = m_flashPhase = 0; m_flashTiming = m_flashPhase = 0;
@@ -50,6 +52,7 @@ TeletextWidget::TeletextWidget(QFrame *parent) : QFrame(parent)
connect(m_teletextDocument, &TeletextDocument::subPageSelected, this, &TeletextWidget::subPageSelected); connect(m_teletextDocument, &TeletextDocument::subPageSelected, this, &TeletextWidget::subPageSelected);
connect(m_teletextDocument, &TeletextDocument::contentsChange, this, &TeletextWidget::refreshRow); connect(m_teletextDocument, &TeletextDocument::contentsChange, this, &TeletextWidget::refreshRow);
connect(m_teletextDocument, &TeletextDocument::refreshNeeded, this, &TeletextWidget::refreshPage); connect(m_teletextDocument, &TeletextDocument::refreshNeeded, this, &TeletextWidget::refreshPage);
connect(m_teletextDocument, &TeletextDocument::selectionMoved, this, QOverload<>::of(&TeletextWidget::update));
} }
TeletextWidget::~TeletextWidget() TeletextWidget::~TeletextWidget()
@@ -91,6 +94,11 @@ void TeletextWidget::paintEvent(QPaintEvent *event)
widgetPainter.drawPixmap(480+m_pageRender.leftSidePanelColumns()*12, 0, *m_pageRender.pagePixmap(m_flashPhase), 480, 0, m_pageRender.rightSidePanelColumns()*12, 250); widgetPainter.drawPixmap(480+m_pageRender.leftSidePanelColumns()*12, 0, *m_pageRender.pagePixmap(m_flashPhase), 480, 0, m_pageRender.rightSidePanelColumns()*12, 250);
if (this->hasFocus()) if (this->hasFocus())
widgetPainter.fillRect((m_teletextDocument->cursorColumn()+m_pageRender.leftSidePanelColumns())*12, m_teletextDocument->cursorRow()*10, 12, 10, QColor(128, 128, 128, 192)); widgetPainter.fillRect((m_teletextDocument->cursorColumn()+m_pageRender.leftSidePanelColumns())*12, m_teletextDocument->cursorRow()*10, 12, 10, QColor(128, 128, 128, 192));
if (m_teletextDocument->selectionActive()) {
widgetPainter.setPen(QPen(QColor(192, 192, 192, 224), 1, Qt::DashLine));
widgetPainter.setBrush(QBrush(QColor(255, 255, 255, 64)));
widgetPainter.drawRect((m_teletextDocument->selectionLeftColumn()+m_pageRender.leftSidePanelColumns())*12, m_teletextDocument->selectionTopRow()*10, m_teletextDocument->selectionWidth()*12-1, m_teletextDocument->selectionHeight()*10-1);
}
} }
void TeletextWidget::updateFlashTimer(int newFlashTimer) void TeletextWidget::updateFlashTimer(int newFlashTimer)
@@ -329,29 +337,64 @@ void TeletextWidget::backspaceEvent()
m_teletextDocument->undoStack()->push(backspaceCommand); m_teletextDocument->undoStack()->push(backspaceCommand);
} }
void TeletextWidget::cursorToMouse(QPoint mousePosition) QPair<int, int> TeletextWidget::mouseToRowAndColumn(const QPoint &mousePosition)
{ {
int newCursorRow = mousePosition.y() / 10; int row = mousePosition.y() / 10;
int newCursorColumn = mousePosition.x() / 12 - m_pageRender.leftSidePanelColumns(); int column = mousePosition.x() / 12 - m_pageRender.leftSidePanelColumns();
if (newCursorRow < 1) if (row < 1)
newCursorRow = 1; row = 1;
if (newCursorRow > 24) if (row > 24)
newCursorRow = 24; row = 24;
if (newCursorColumn < 0) if (column < 0)
newCursorColumn = 0; column = 0;
if (newCursorColumn > 39) if (column > 39)
newCursorColumn = 39; column = 39;
m_teletextDocument->moveCursor(newCursorRow, newCursorColumn); return qMakePair(row, column);
} }
void TeletextWidget::mousePressEvent(QMouseEvent *event) void TeletextWidget::mousePressEvent(QMouseEvent *event)
{ {
if (event->button() == Qt::LeftButton) { if (event->button() == Qt::LeftButton) {
cursorToMouse(event->pos()); m_teletextDocument->cancelSelection();
QPair<int, int> position = mouseToRowAndColumn(event->pos());
m_teletextDocument->moveCursor(position.first, position.second);
update(); update();
} }
} }
void TeletextWidget::mouseMoveEvent(QMouseEvent *event)
{
if (event->buttons() & Qt::LeftButton) {
QPair<int, int> position = mouseToRowAndColumn(event->pos());
if (m_selectionInProgress || position.first != m_teletextDocument->cursorRow() || position.second != m_teletextDocument->cursorColumn()) {
int topRow, bottomRow, leftColumn, rightColumn;
m_selectionInProgress = true;
if (m_teletextDocument->cursorRow() < position.first) {
topRow = m_teletextDocument->cursorRow();
bottomRow = position.first;
} else {
topRow = position.first;
bottomRow = m_teletextDocument->cursorRow();
}
if (m_teletextDocument->cursorColumn() < position.second) {
leftColumn = m_teletextDocument->cursorColumn();
rightColumn = position.second;
} else {
leftColumn = position.second;
rightColumn = m_teletextDocument->cursorColumn();
}
m_teletextDocument->setSelection(topRow, leftColumn, bottomRow, rightColumn);
}
}
}
void TeletextWidget::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
m_selectionInProgress = false;
}
void TeletextWidget::focusInEvent(QFocusEvent *event) void TeletextWidget::focusInEvent(QFocusEvent *event)
{ {
QFrame::focusInEvent(event); QFrame::focusInEvent(event);

View File

@@ -22,6 +22,7 @@
#include <QBasicTimer> #include <QBasicTimer>
#include <QFrame> #include <QFrame>
#include <QPair>
#include <QTextStream> #include <QTextStream>
#include <vector> #include <vector>
@@ -74,6 +75,8 @@ protected:
void paintEvent(QPaintEvent *event) override; void paintEvent(QPaintEvent *event) override;
void keyPressEvent(QKeyEvent *event) override; void keyPressEvent(QKeyEvent *event) override;
void mousePressEvent(QMouseEvent *event) override; void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void focusInEvent(QFocusEvent *event) override; void focusInEvent(QFocusEvent *event) override;
void focusOutEvent(QFocusEvent *event) override; void focusOutEvent(QFocusEvent *event) override;
@@ -82,7 +85,7 @@ protected:
private: private:
TeletextDocument* m_teletextDocument; TeletextDocument* m_teletextDocument;
LevelOnePage* m_levelOnePage; LevelOnePage* m_levelOnePage;
bool m_insertMode, m_grid; bool m_insertMode, m_grid, m_selectionInProgress;
QBasicTimer m_flashTimer; QBasicTimer m_flashTimer;
int m_flashTiming, m_flashPhase; int m_flashTiming, m_flashPhase;
@@ -90,7 +93,7 @@ private:
void calculateDimensions(); void calculateDimensions();
void cursorToMouse(QPoint mousePosition); QPair<int, int> mouseToRowAndColumn(const QPoint &);
}; };
#endif #endif