From 151d842bc04ac743db2f2045b253db67d38afced Mon Sep 17 00:00:00 2001 From: "G.K.MacGregor" Date: Sun, 25 Oct 2020 11:07:04 +0000 Subject: [PATCH] Implement draggable rectangle selection --- document.cpp | 18 +++++++++++++ document.h | 13 +++++++++- mainwidget.cpp | 69 ++++++++++++++++++++++++++++++++++++++++---------- mainwidget.h | 7 +++-- 4 files changed, 91 insertions(+), 16 deletions(-) diff --git a/document.cpp b/document.cpp index b4562b5..176df4d 100644 --- a/document.cpp +++ b/document.cpp @@ -38,6 +38,7 @@ TeletextDocument::TeletextDocument() m_undoStack = new QUndoStack(this); m_cursorRow = 1; m_cursorColumn = 0; + m_selectionSubPage = nullptr; } TeletextDocument::~TeletextDocument() @@ -285,6 +286,23 @@ void TeletextDocument::moveCursor(int newCursorRow, int newCursorColumn) 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) { diff --git a/document.h b/document.h index 0332522..9eacb4f 100644 --- a/document.h +++ b/document.h @@ -61,9 +61,19 @@ public: void cursorLeft(); void cursorRight(); 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: void cursorMoved(); + void selectionMoved(); void colourChanged(int); void contentsChange(int); void aboutToChangeSubPage(); @@ -77,7 +87,8 @@ private: int m_fastTextLink[6]; std::vector m_subPages; QUndoStack *m_undoStack; - int m_cursorRow, m_cursorColumn; + int m_cursorRow, m_cursorColumn, m_selectionTopRow, m_selectionBottomRow, m_selectionLeftColumn, m_selectionRightColumn; + LevelOnePage *m_selectionSubPage; }; diff --git a/mainwidget.cpp b/mainwidget.cpp index 1a722bf..0d84355 100644 --- a/mainwidget.cpp +++ b/mainwidget.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -42,6 +43,7 @@ TeletextWidget::TeletextWidget(QFrame *parent) : QFrame(parent) m_levelOnePage = m_teletextDocument->currentSubPage(); m_pageRender.setTeletextPage(m_levelOnePage); m_insertMode = false; + m_selectionInProgress = false; m_grid = false; setFocusPolicy(Qt::StrongFocus); 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::contentsChange, this, &TeletextWidget::refreshRow); connect(m_teletextDocument, &TeletextDocument::refreshNeeded, this, &TeletextWidget::refreshPage); + connect(m_teletextDocument, &TeletextDocument::selectionMoved, this, QOverload<>::of(&TeletextWidget::update)); } 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); if (this->hasFocus()) 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) @@ -329,29 +337,64 @@ void TeletextWidget::backspaceEvent() m_teletextDocument->undoStack()->push(backspaceCommand); } -void TeletextWidget::cursorToMouse(QPoint mousePosition) +QPair TeletextWidget::mouseToRowAndColumn(const QPoint &mousePosition) { - int newCursorRow = mousePosition.y() / 10; - int newCursorColumn = mousePosition.x() / 12 - m_pageRender.leftSidePanelColumns(); - if (newCursorRow < 1) - newCursorRow = 1; - if (newCursorRow > 24) - newCursorRow = 24; - if (newCursorColumn < 0) - newCursorColumn = 0; - if (newCursorColumn > 39) - newCursorColumn = 39; - m_teletextDocument->moveCursor(newCursorRow, newCursorColumn); + int row = mousePosition.y() / 10; + int column = mousePosition.x() / 12 - m_pageRender.leftSidePanelColumns(); + if (row < 1) + row = 1; + if (row > 24) + row = 24; + if (column < 0) + column = 0; + if (column > 39) + column = 39; + return qMakePair(row, column); } void TeletextWidget::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { - cursorToMouse(event->pos()); + m_teletextDocument->cancelSelection(); + QPair position = mouseToRowAndColumn(event->pos()); + m_teletextDocument->moveCursor(position.first, position.second); update(); } } +void TeletextWidget::mouseMoveEvent(QMouseEvent *event) +{ + if (event->buttons() & Qt::LeftButton) { + QPair 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) { QFrame::focusInEvent(event); diff --git a/mainwidget.h b/mainwidget.h index 48dba8d..e857490 100644 --- a/mainwidget.h +++ b/mainwidget.h @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -74,6 +75,8 @@ protected: void paintEvent(QPaintEvent *event) override; void keyPressEvent(QKeyEvent *event) override; void mousePressEvent(QMouseEvent *event) override; + void mouseMoveEvent(QMouseEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; void focusInEvent(QFocusEvent *event) override; void focusOutEvent(QFocusEvent *event) override; @@ -82,7 +85,7 @@ protected: private: TeletextDocument* m_teletextDocument; LevelOnePage* m_levelOnePage; - bool m_insertMode, m_grid; + bool m_insertMode, m_grid, m_selectionInProgress; QBasicTimer m_flashTimer; int m_flashTiming, m_flashPhase; @@ -90,7 +93,7 @@ private: void calculateDimensions(); - void cursorToMouse(QPoint mousePosition); + QPair mouseToRowAndColumn(const QPoint &); }; #endif