diff --git a/document.h b/document.h
index f542827..c22df18 100644
--- a/document.h
+++ b/document.h
@@ -76,6 +76,8 @@ public:
int selectionWidth() const { return m_selectionCornerColumn == -1 ? 1 : selectionRightColumn() - selectionLeftColumn() + 1; }
int selectionHeight() const { return m_selectionCornerRow == -1 ? 1 : selectionBottomRow() - selectionTopRow() + 1; }
bool selectionActive() const { return m_selectionSubPage == currentSubPage(); }
+ int selectionCornerRow() const { return m_selectionCornerRow == -1 ? m_cursorRow : m_selectionCornerRow; }
+ int selectionCornerColumn() const { return m_selectionCornerColumn == -1 ? m_cursorColumn : m_selectionCornerColumn; }
void setSelectionCorner(int, int);
void setSelection(int, int, int, int);
void cancelSelection();
diff --git a/levelonecommands.cpp b/levelonecommands.cpp
index 4905b92..85b1603 100644
--- a/levelonecommands.cpp
+++ b/levelonecommands.cpp
@@ -17,6 +17,12 @@
* along with QTeletextMaker. If not, see .
*/
+#include
+#include
+#include
+#include
+#include
+
#include "levelonecommands.h"
#include "document.h"
@@ -340,6 +346,192 @@ void DeleteRowCommand::undo()
}
+#ifndef QT_NO_CLIPBOARD
+CutCommand::CutCommand(TeletextDocument *teletextDocument, QUndoCommand *parent) : LevelOneCommand(teletextDocument, parent)
+{
+ m_selectionTopRow = m_teletextDocument->selectionTopRow();
+ m_selectionBottomRow = m_teletextDocument->selectionBottomRow();
+ m_selectionLeftColumn = m_teletextDocument->selectionLeftColumn();
+ m_selectionRightColumn = m_teletextDocument->selectionRightColumn();
+
+ m_selectionCornerRow = m_teletextDocument->selectionCornerRow();
+ m_selectionCornerColumn = m_teletextDocument->selectionCornerColumn();
+
+ // Store copy of the characters that we're about to blank
+ for (int r=m_selectionTopRow; r<=m_selectionBottomRow; r++) {
+ QByteArray rowArray;
+
+ for (int c=m_selectionLeftColumn; c<=m_selectionRightColumn; c++)
+ rowArray.append(m_teletextDocument->currentSubPage()->character(r, c));
+
+ m_deletedCharacters.append(rowArray);
+ }
+
+ setText(QObject::tr("cut"));
+}
+
+void CutCommand::redo()
+{
+ m_teletextDocument->selectSubPageIndex(m_subPageIndex);
+
+ for (int r=m_selectionTopRow; r<=m_selectionBottomRow; r++) {
+ for (int c=m_selectionLeftColumn; c<=m_selectionRightColumn; c++)
+ m_teletextDocument->currentSubPage()->setCharacter(r, c, 0x20);
+ emit m_teletextDocument->contentsChange(r);
+ }
+}
+
+void CutCommand::undo()
+{
+ m_teletextDocument->selectSubPageIndex(m_subPageIndex);
+
+ int arrayR = 0;
+ int arrayC;
+
+ for (int r=m_selectionTopRow; r<=m_selectionBottomRow; r++) {
+ arrayC = 0;
+ for (int c=m_selectionLeftColumn; c<=m_selectionRightColumn; c++)
+ m_teletextDocument->currentSubPage()->setCharacter(r, c, m_deletedCharacters[arrayR].at(arrayC++));
+
+ emit m_teletextDocument->contentsChange(r);
+ arrayR++;
+ }
+
+ m_teletextDocument->setSelectionCorner(m_selectionCornerRow, m_selectionCornerColumn);
+ m_teletextDocument->moveCursor(m_row, m_column, true);
+}
+
+
+PasteCommand::PasteCommand(TeletextDocument *teletextDocument, QUndoCommand *parent) : LevelOneCommand(teletextDocument, parent)
+{
+ const QClipboard *clipboard = QApplication::clipboard();
+ const QMimeData *mimeData = clipboard->mimeData();
+ QByteArray nativeData;
+
+ m_selectionActive = m_teletextDocument->selectionActive();
+ if (m_selectionActive) {
+ m_selectionCornerRow = m_teletextDocument->selectionCornerRow();
+ m_selectionCornerColumn = m_teletextDocument->selectionCornerColumn();
+ }
+
+ m_clipboardDataHeight = m_clipboardDataWidth = 0;
+
+ // Try to get something from the clipboard
+ nativeData = mimeData->data("application/x-teletext");
+ if (nativeData.size() > 2) {
+ // Native clipboard data: we put it there ourselves
+ m_clipboardDataHeight = nativeData.at(0);
+ m_clipboardDataWidth = nativeData.at(1);
+
+ // Guard against invalid dimensions or total size not matching stated dimensions
+ if (m_clipboardDataHeight > 0 && m_clipboardDataWidth > 0 && m_clipboardDataHeight <= 25 && m_clipboardDataWidth <= 40 && nativeData.size() == m_clipboardDataHeight * m_clipboardDataWidth + 2)
+ for (int r=0; rselectionTopRow();
+ m_pasteBottomRow = m_teletextDocument->selectionBottomRow();
+ m_pasteLeftColumn = m_teletextDocument->selectionLeftColumn();
+ m_pasteRightColumn = m_teletextDocument->selectionRightColumn();
+ } else {
+ m_pasteTopRow = m_row;
+ m_pasteBottomRow = m_row + m_clipboardDataHeight - 1;
+ m_pasteLeftColumn = m_column;
+ m_pasteRightColumn = m_column + m_clipboardDataWidth - 1;
+ }
+
+ // Store copy of the characters that we're about to overwrite
+ for (int r=m_pasteTopRow; r<=m_pasteBottomRow; r++) {
+ QByteArray rowArray;
+
+ for (int c=m_pasteLeftColumn; c<=m_pasteRightColumn; c++)
+ // Guard against size of pasted block going beyond last line or column
+ if (r < 25 && c < 40)
+ rowArray.append(m_teletextDocument->currentSubPage()->character(r, c));
+ else
+ // Gone beyond last line or column - store a filler character which we won't see
+ // Not sure if this is really necessary as out-of-bounds access might not occur?
+ rowArray.append(0x7f);
+
+ m_deletedCharacters.append(rowArray);
+ }
+
+ setText(QObject::tr("paste"));
+}
+
+void PasteCommand::redo()
+{
+ if (m_clipboardDataWidth == 0)
+ return;
+
+ m_teletextDocument->selectSubPageIndex(m_subPageIndex);
+
+ int arrayR = 0;
+ int arrayC;
+
+ for (int r=m_pasteTopRow; r<=m_pasteBottomRow; r++) {
+ arrayC = 0;
+ for (int c=m_pasteLeftColumn; c<=m_pasteRightColumn; c++)
+ // Guard against size of pasted block going beyond last line or column
+ if (r < 25 && c < 40) {
+ m_teletextDocument->currentSubPage()->setCharacter(r, c, m_pastingCharacters[arrayR].at(arrayC++));
+
+ // If paste area is wider than clipboard data, repeat the pattern
+ if (arrayC == m_clipboardDataWidth)
+ arrayC = 0;
+ }
+
+ if (r < 25)
+ emit m_teletextDocument->contentsChange(r);
+
+ arrayR++;
+ // If paste area is taller than clipboard data, repeat the pattern
+ if (arrayR == m_clipboardDataHeight)
+ arrayR = 0;
+ }
+
+ if (m_selectionActive) {
+ m_teletextDocument->setSelectionCorner(m_selectionCornerRow, m_selectionCornerColumn);
+ m_teletextDocument->moveCursor(m_row, m_column, true);
+ } else {
+ m_teletextDocument->moveCursor(m_row, m_column+m_clipboardDataWidth-1);
+ m_teletextDocument->cursorRight();
+ }
+}
+
+void PasteCommand::undo()
+{
+ if (m_clipboardDataWidth == 0)
+ return;
+
+ m_teletextDocument->selectSubPageIndex(m_subPageIndex);
+
+ int arrayR = 0;
+ int arrayC;
+
+ for (int r=m_pasteTopRow; r<=m_pasteBottomRow; r++) {
+ arrayC = 0;
+ for (int c=m_pasteLeftColumn; c<=m_pasteRightColumn; c++)
+ // Guard against size of pasted block going beyond last line or column
+ if (r < 25 && c < 40)
+ m_teletextDocument->currentSubPage()->setCharacter(r, c, m_deletedCharacters[arrayR].at(arrayC++));
+
+ if (r < 25)
+ emit m_teletextDocument->contentsChange(r);
+
+ arrayR++;
+ }
+}
+#endif // !QT_NO_CLIPBOARD
+
+
InsertSubPageCommand::InsertSubPageCommand(TeletextDocument *teletextDocument, bool afterCurrentSubPage, bool copySubPage, QUndoCommand *parent) : LevelOneCommand(teletextDocument, parent)
{
m_newSubPageIndex = m_subPageIndex + afterCurrentSubPage;
diff --git a/levelonecommands.h b/levelonecommands.h
index 9c0f32e..30e13d5 100644
--- a/levelonecommands.h
+++ b/levelonecommands.h
@@ -20,6 +20,7 @@
#ifndef LEVELONECOMMANDS_H
#define LEVELONECOMMANDS_H
+#include
#include
#include "document.h"
@@ -150,6 +151,38 @@ private:
unsigned char m_deletedRow[40];
};
+#ifndef QT_NO_CLIPBOARD
+class CutCommand : public LevelOneCommand
+{
+public:
+ CutCommand(TeletextDocument *, QUndoCommand *parent = 0);
+
+ void redo() override;
+ void undo() override;
+
+private:
+ QByteArrayList m_deletedCharacters;
+ int m_selectionTopRow, m_selectionBottomRow, m_selectionLeftColumn, m_selectionRightColumn;
+ int m_selectionCornerRow, m_selectionCornerColumn;
+};
+
+class PasteCommand : public LevelOneCommand
+{
+public:
+ PasteCommand(TeletextDocument *, QUndoCommand *parent = 0);
+
+ void redo() override;
+ void undo() override;
+
+private:
+ QByteArrayList m_deletedCharacters, m_pastingCharacters;
+ int m_pasteTopRow, m_pasteBottomRow, m_pasteLeftColumn, m_pasteRightColumn;
+ int m_clipboardDataHeight, m_clipboardDataWidth;
+ int m_selectionCornerRow, m_selectionCornerColumn;
+ bool m_selectionActive;
+};
+#endif // !QT_NO_CLIPBOARD
+
class SetColourCommand : public LevelOneCommand
{
public:
diff --git a/mainwidget.cpp b/mainwidget.cpp
index ed91490..8cae394 100644
--- a/mainwidget.cpp
+++ b/mainwidget.cpp
@@ -17,7 +17,9 @@
* along with QTeletextMaker. If not, see .
*/
+#include
#include
+#include
#include
#include
#include
@@ -25,6 +27,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -387,6 +390,48 @@ void TeletextWidget::toggleCharacterBit(unsigned char bitToToggle)
m_teletextDocument->undoStack()->push(new ToggleMosaicBitCommand(m_teletextDocument, bitToToggle));
}
+void TeletextWidget::selectionToClipboard()
+{
+ QByteArray nativeData;
+ QClipboard *clipboard = QApplication::clipboard();
+
+ nativeData.resize(2 + m_teletextDocument->selectionWidth() * m_teletextDocument->selectionHeight());
+ nativeData[0] = m_teletextDocument->selectionHeight();
+ nativeData[1] = m_teletextDocument->selectionWidth();
+
+ int i=2;
+
+ for (int r=m_teletextDocument->selectionTopRow(); r<=m_teletextDocument->selectionBottomRow(); r++)
+ for (int c=m_teletextDocument->selectionLeftColumn(); c<=m_teletextDocument->selectionRightColumn(); c++)
+ nativeData[i++] = m_teletextDocument->currentSubPage()->character(r, c);
+
+ QMimeData *mimeData = new QMimeData();
+ mimeData->setData("application/x-teletext", nativeData);
+ clipboard->setMimeData(mimeData);
+}
+
+void TeletextWidget::cut()
+{
+ if (!m_teletextDocument->selectionActive())
+ return;
+
+ selectionToClipboard();
+ m_teletextDocument->undoStack()->push(new CutCommand(m_teletextDocument));
+}
+
+void TeletextWidget::copy()
+{
+ if (!m_teletextDocument->selectionActive())
+ return;
+
+ selectionToClipboard();
+}
+
+void TeletextWidget::paste()
+{
+ m_teletextDocument->undoStack()->push(new PasteCommand(m_teletextDocument));
+}
+
QPair TeletextWidget::mouseToRowAndColumn(const QPoint &mousePosition)
{
int row = mousePosition.y() / 10;
diff --git a/mainwidget.h b/mainwidget.h
index b4b1316..2971534 100644
--- a/mainwidget.h
+++ b/mainwidget.h
@@ -75,6 +75,11 @@ public slots:
void setBlackBackgroundSubst(bool);
void setSidePanelWidths(int, int);
void setSidePanelAtL35Only(bool);
+
+ void cut();
+ void copy();
+ void paste();
+
void changeSize();
protected:
@@ -96,6 +101,7 @@ private:
int m_flashTiming, m_flashPhase;
void timerEvent(QTimerEvent *event) override;
+ void selectionToClipboard();
QPair mouseToRowAndColumn(const QPoint &);
};
diff --git a/mainwindow.cpp b/mainwindow.cpp
index 83f816a..cdd32cc 100644
--- a/mainwindow.cpp
+++ b/mainwindow.cpp
@@ -292,36 +292,33 @@ void MainWindow::createActions()
redoAction->setShortcuts(QKeySequence::Redo);
editMenu->addSeparator();
+
#ifndef QT_NO_CLIPBOARD
-/* const QIcon cutIcon = QIcon::fromTheme("edit-cut", QIcon(":/images/cut.png"));
+ const QIcon cutIcon = QIcon::fromTheme("edit-cut", QIcon(":/images/cut.png"));
QAction *cutAct = new QAction(cutIcon, tr("Cu&t"), this);
cutAct->setShortcuts(QKeySequence::Cut);
- cutAct->setStatusTip(tr("Cut the current selection's contents to the "
- "clipboard"));
- connect(cutAct, &QAction::triggered, textWidget, &QTextEdit::cut);
+ cutAct->setStatusTip(tr("Cut the current selection's contents to the clipboard"));
+ connect(cutAct, &QAction::triggered, m_textWidget, &TeletextWidget::cut);
editMenu->addAction(cutAct);
editToolBar->addAction(cutAct);
const QIcon copyIcon = QIcon::fromTheme("edit-copy", QIcon(":/images/copy.png"));
QAction *copyAct = new QAction(copyIcon, tr("&Copy"), this);
copyAct->setShortcuts(QKeySequence::Copy);
- copyAct->setStatusTip(tr("Copy the current selection's contents to the "
- "clipboard"));
- connect(copyAct, &QAction::triggered, textWidget, &QTextEdit::copy);
+ copyAct->setStatusTip(tr("Copy the current selection's contents to the clipboard"));
+ connect(copyAct, &QAction::triggered, m_textWidget, &TeletextWidget::copy);
editMenu->addAction(copyAct);
editToolBar->addAction(copyAct);
const QIcon pasteIcon = QIcon::fromTheme("edit-paste", QIcon(":/images/paste.png"));
QAction *pasteAct = new QAction(pasteIcon, tr("&Paste"), this);
pasteAct->setShortcuts(QKeySequence::Paste);
- pasteAct->setStatusTip(tr("Paste the clipboard's contents into the current "
- "selection"));
- connect(pasteAct, &QAction::triggered, textWidget, &QTextEdit::paste);
+ pasteAct->setStatusTip(tr("Paste the clipboard's contents into the current selection"));
+ connect(pasteAct, &QAction::triggered, m_textWidget, &TeletextWidget::paste);
editMenu->addAction(pasteAct);
editToolBar->addAction(pasteAct);
editMenu->addSeparator();
-*/
#endif // !QT_NO_CLIPBOARD
QAction *insertBlankRowAct = editMenu->addAction(tr("Insert blank row"));