Implement mosaic shifting
When a selection box is dragged, holding Ctrl while pressing the arrow keys will shift the mosaics one sixel at a time. If a shifting sixel encounters a non-mosaic cell it will pass through to the other side of it.
This commit is contained in:
@@ -24,6 +24,7 @@
|
|||||||
#include <QImage>
|
#include <QImage>
|
||||||
#include <QMimeData>
|
#include <QMimeData>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
#include <QSet>
|
||||||
|
|
||||||
#include "levelonecommands.h"
|
#include "levelonecommands.h"
|
||||||
|
|
||||||
@@ -318,6 +319,145 @@ bool DeleteKeyCommand::mergeWith(const QUndoCommand *command)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ShiftMosaicsCommand::ShiftMosaicsCommand(TeletextDocument *teletextDocument, const QSet<QPair<int, int>> &mosaicList, QUndoCommand *parent) : LevelOneCommand(teletextDocument, parent)
|
||||||
|
{
|
||||||
|
m_selectionTopRow = m_teletextDocument->selectionTopRow();
|
||||||
|
m_selectionLeftColumn = m_teletextDocument->selectionLeftColumn();
|
||||||
|
m_selectionBottomRow = m_teletextDocument->selectionBottomRow();
|
||||||
|
m_selectionRightColumn = m_teletextDocument->selectionRightColumn();
|
||||||
|
|
||||||
|
m_selectionCornerRow = m_teletextDocument->selectionCornerRow();
|
||||||
|
m_selectionCornerColumn = m_teletextDocument->selectionCornerColumn();
|
||||||
|
|
||||||
|
m_mosaicList = mosaicList;
|
||||||
|
|
||||||
|
m_oldCharacters = storeCharacters(m_selectionTopRow, m_selectionLeftColumn, m_selectionBottomRow, m_selectionRightColumn);
|
||||||
|
m_newCharacters = m_oldCharacters;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShiftMosaicsCommand::redo()
|
||||||
|
{
|
||||||
|
m_teletextDocument->selectSubPageIndex(m_subPageIndex);
|
||||||
|
retrieveCharacters(m_selectionTopRow, m_selectionLeftColumn, m_newCharacters);
|
||||||
|
|
||||||
|
emit m_teletextDocument->contentsChanged();
|
||||||
|
|
||||||
|
m_teletextDocument->setSelectionCorner(m_selectionCornerRow, m_selectionCornerColumn);
|
||||||
|
m_teletextDocument->moveCursor(m_row, m_column, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShiftMosaicsCommand::undo()
|
||||||
|
{
|
||||||
|
m_teletextDocument->selectSubPageIndex(m_subPageIndex);
|
||||||
|
retrieveCharacters(m_selectionTopRow, m_selectionLeftColumn, m_oldCharacters);
|
||||||
|
|
||||||
|
emit m_teletextDocument->contentsChanged();
|
||||||
|
|
||||||
|
m_teletextDocument->setSelectionCorner(m_selectionCornerRow, m_selectionCornerColumn);
|
||||||
|
m_teletextDocument->moveCursor(m_row, m_column, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ShiftMosaicsCommand::mergeWith(const QUndoCommand *command)
|
||||||
|
{
|
||||||
|
const ShiftMosaicsCommand *newerCommand = static_cast<const ShiftMosaicsCommand *>(command);
|
||||||
|
|
||||||
|
if (m_subPageIndex != newerCommand->m_subPageIndex || m_selectionTopRow != newerCommand->m_selectionTopRow || m_selectionLeftColumn != newerCommand->m_selectionLeftColumn || m_selectionBottomRow != newerCommand->m_selectionBottomRow || m_selectionRightColumn != newerCommand->m_selectionRightColumn)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_newCharacters = newerCommand->m_newCharacters;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShiftMosaicsUpCommand::ShiftMosaicsUpCommand(TeletextDocument *teletextDocument, const QSet<QPair<int, int>> &mosaicList, QUndoCommand *parent) : ShiftMosaicsCommand(teletextDocument, mosaicList, parent)
|
||||||
|
{
|
||||||
|
for (int r=m_selectionTopRow; r<=m_selectionBottomRow; r++)
|
||||||
|
for (int c=m_selectionLeftColumn; c<=m_selectionRightColumn; c++)
|
||||||
|
if (m_mosaicList.contains(qMakePair(r, c))) {
|
||||||
|
const int lr = r - m_selectionTopRow;
|
||||||
|
const int lc = c - m_selectionLeftColumn;
|
||||||
|
unsigned char mosaicWrap = 0x00;
|
||||||
|
|
||||||
|
for (int sr=r+1; sr<=m_selectionBottomRow; sr++)
|
||||||
|
if (m_mosaicList.contains(qMakePair(sr, c))) {
|
||||||
|
mosaicWrap = m_newCharacters[sr - m_selectionTopRow][lc];
|
||||||
|
mosaicWrap = ((mosaicWrap & 0x01) << 4) | ((mosaicWrap & 0x02) << 5);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_newCharacters[lr][lc] = ((m_newCharacters[lr][lc] >> 2) & 0x07) | ((m_newCharacters[lr][lc] & 0x40) >> 3) | mosaicWrap | 0x20;
|
||||||
|
}
|
||||||
|
|
||||||
|
setText(QObject::tr("shift mosaics up"));
|
||||||
|
}
|
||||||
|
|
||||||
|
ShiftMosaicsDownCommand::ShiftMosaicsDownCommand(TeletextDocument *teletextDocument, const QSet<QPair<int, int>> &mosaicList, QUndoCommand *parent) : ShiftMosaicsCommand(teletextDocument, mosaicList, parent)
|
||||||
|
{
|
||||||
|
for (int r=m_selectionBottomRow; r>=m_selectionTopRow; r--)
|
||||||
|
for (int c=m_selectionLeftColumn; c<=m_selectionRightColumn; c++)
|
||||||
|
if (m_mosaicList.contains(qMakePair(r, c))) {
|
||||||
|
const int lr = r - m_selectionTopRow;
|
||||||
|
const int lc = c - m_selectionLeftColumn;
|
||||||
|
unsigned char mosaicWrap = 0x00;
|
||||||
|
|
||||||
|
for (int sr=r-1; sr>=m_selectionTopRow; sr--)
|
||||||
|
if (m_mosaicList.contains(qMakePair(sr, c))) {
|
||||||
|
mosaicWrap = m_newCharacters[sr - m_selectionTopRow][lc];
|
||||||
|
mosaicWrap = ((mosaicWrap & 0x10) >> 4) | ((mosaicWrap & 0x40) >> 5);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_newCharacters[lr][lc] = ((m_newCharacters[lr][lc] & 0x07) << 2) | ((m_newCharacters[lr][lc] & 0x08) << 3) | mosaicWrap | 0x20;
|
||||||
|
}
|
||||||
|
|
||||||
|
setText(QObject::tr("shift mosaics down"));
|
||||||
|
}
|
||||||
|
|
||||||
|
ShiftMosaicsLeftCommand::ShiftMosaicsLeftCommand(TeletextDocument *teletextDocument, const QSet<QPair<int, int>> &mosaicList, QUndoCommand *parent) : ShiftMosaicsCommand(teletextDocument, mosaicList, parent)
|
||||||
|
{
|
||||||
|
for (int c=m_selectionLeftColumn; c<=m_selectionRightColumn; c++)
|
||||||
|
for (int r=m_selectionTopRow; r<=m_selectionBottomRow; r++)
|
||||||
|
if (m_mosaicList.contains(qMakePair(r, c))) {
|
||||||
|
const int lr = r - m_selectionTopRow;
|
||||||
|
const int lc = c - m_selectionLeftColumn;
|
||||||
|
unsigned char mosaicWrap = 0x00;
|
||||||
|
|
||||||
|
for (int sc=c+1; sc<=m_selectionRightColumn; sc++)
|
||||||
|
if (m_mosaicList.contains(qMakePair(r, sc))) {
|
||||||
|
mosaicWrap = m_newCharacters[lr][sc - m_selectionLeftColumn];
|
||||||
|
mosaicWrap = ((mosaicWrap & 0x05) << 1) | ((mosaicWrap & 0x10) << 2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_newCharacters[lr][lc] = ((m_newCharacters[lr][lc] & 0x0a) >> 1) | ((m_newCharacters[lr][lc] & 0x40) >> 2) | mosaicWrap | 0x20;
|
||||||
|
}
|
||||||
|
|
||||||
|
setText(QObject::tr("shift mosaics left"));
|
||||||
|
}
|
||||||
|
|
||||||
|
ShiftMosaicsRightCommand::ShiftMosaicsRightCommand(TeletextDocument *teletextDocument, const QSet<QPair<int, int>> &mosaicList, QUndoCommand *parent) : ShiftMosaicsCommand(teletextDocument, mosaicList, parent)
|
||||||
|
{
|
||||||
|
for (int c=m_selectionRightColumn; c>=m_selectionLeftColumn; c--)
|
||||||
|
for (int r=m_selectionTopRow; r<=m_selectionBottomRow; r++)
|
||||||
|
if (m_mosaicList.contains(qMakePair(r, c))) {
|
||||||
|
const int lr = r - m_selectionTopRow;
|
||||||
|
const int lc = c - m_selectionLeftColumn;
|
||||||
|
unsigned char mosaicWrap = 0x00;
|
||||||
|
|
||||||
|
for (int sc=c-1; sc>=m_selectionLeftColumn; sc--)
|
||||||
|
if (m_mosaicList.contains(qMakePair(r, sc))) {
|
||||||
|
mosaicWrap = m_newCharacters[lr][sc - m_selectionLeftColumn];
|
||||||
|
mosaicWrap = ((mosaicWrap & 0x0a) >> 1) | ((mosaicWrap & 0x40) >> 2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_newCharacters[lr][lc] = ((m_newCharacters[lr][lc] & 0x05) << 1) | ((m_newCharacters[lr][lc] & 0x10) << 2) | mosaicWrap | 0x20;
|
||||||
|
}
|
||||||
|
|
||||||
|
setText(QObject::tr("shift mosaics right"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
InsertRowCommand::InsertRowCommand(TeletextDocument *teletextDocument, bool copyRow, QUndoCommand *parent) : LevelOneCommand(teletextDocument, parent)
|
InsertRowCommand::InsertRowCommand(TeletextDocument *teletextDocument, bool copyRow, QUndoCommand *parent) : LevelOneCommand(teletextDocument, parent)
|
||||||
{
|
{
|
||||||
m_copyRow = copyRow;
|
m_copyRow = copyRow;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#define LEVELONECOMMANDS_H
|
#define LEVELONECOMMANDS_H
|
||||||
|
|
||||||
#include <QByteArrayList>
|
#include <QByteArrayList>
|
||||||
|
#include <QSet>
|
||||||
#include <QUndoCommand>
|
#include <QUndoCommand>
|
||||||
|
|
||||||
#include "document.h"
|
#include "document.h"
|
||||||
@@ -107,6 +108,62 @@ private:
|
|||||||
unsigned char m_oldRowContents[40], m_newRowContents[40];
|
unsigned char m_oldRowContents[40], m_newRowContents[40];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ShiftMosaicsCommand : public LevelOneCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ShiftMosaicsCommand(TeletextDocument *teletextDocument, const QSet<QPair<int, int>> &mosaicList, QUndoCommand *parent = 0);
|
||||||
|
|
||||||
|
void redo() override;
|
||||||
|
void undo() override;
|
||||||
|
bool mergeWith(const QUndoCommand *command) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QByteArrayList m_oldCharacters, m_newCharacters;
|
||||||
|
QSet<QPair<int, int>> m_mosaicList;
|
||||||
|
int m_selectionTopRow, m_selectionBottomRow, m_selectionLeftColumn, m_selectionRightColumn;
|
||||||
|
int m_selectionCornerRow, m_selectionCornerColumn;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ShiftMosaicsUpCommand : public ShiftMosaicsCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum { Id = 110 };
|
||||||
|
|
||||||
|
ShiftMosaicsUpCommand(TeletextDocument *teletextDocument, const QSet<QPair<int, int>> &mosaicList, QUndoCommand *parent = 0);
|
||||||
|
|
||||||
|
int id() const override { return Id; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class ShiftMosaicsDownCommand : public ShiftMosaicsCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum { Id = 111 };
|
||||||
|
|
||||||
|
ShiftMosaicsDownCommand(TeletextDocument *teletextDocument, const QSet<QPair<int, int>> &mosaicList, QUndoCommand *parent = 0);
|
||||||
|
|
||||||
|
int id() const override { return Id; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class ShiftMosaicsLeftCommand : public ShiftMosaicsCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum { Id = 112 };
|
||||||
|
|
||||||
|
ShiftMosaicsLeftCommand(TeletextDocument *teletextDocument, const QSet<QPair<int, int>> &mosaicList, QUndoCommand *parent = 0);
|
||||||
|
|
||||||
|
int id() const override { return Id; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class ShiftMosaicsRightCommand : public ShiftMosaicsCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum { Id = 113 };
|
||||||
|
|
||||||
|
ShiftMosaicsRightCommand(TeletextDocument *teletextDocument, const QSet<QPair<int, int>> &mosaicList, QUndoCommand *parent = 0);
|
||||||
|
|
||||||
|
int id() const override { return Id; }
|
||||||
|
};
|
||||||
|
|
||||||
class InsertSubPageCommand : public LevelOneCommand
|
class InsertSubPageCommand : public LevelOneCommand
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
#include <QMimeData>
|
#include <QMimeData>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QPair>
|
#include <QPair>
|
||||||
|
#include <QSet>
|
||||||
#include <QUndoCommand>
|
#include <QUndoCommand>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -318,6 +319,7 @@ void TeletextWidget::keyPressEvent(QKeyEvent *event)
|
|||||||
setCharacter(mappedKeyPress);
|
setCharacter(mappedKeyPress);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (event->key()) {
|
switch (event->key()) {
|
||||||
case Qt::Key_Backspace:
|
case Qt::Key_Backspace:
|
||||||
m_teletextDocument->undoStack()->push(new BackspaceKeyCommand(m_teletextDocument, m_insertMode));
|
m_teletextDocument->undoStack()->push(new BackspaceKeyCommand(m_teletextDocument, m_insertMode));
|
||||||
@@ -333,15 +335,27 @@ void TeletextWidget::keyPressEvent(QKeyEvent *event)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case Qt::Key_Up:
|
case Qt::Key_Up:
|
||||||
|
if (event->modifiers() & Qt::ControlModifier)
|
||||||
|
shiftMosaics(event->key());
|
||||||
|
else
|
||||||
m_teletextDocument->cursorUp(event->modifiers() & Qt::ShiftModifier);
|
m_teletextDocument->cursorUp(event->modifiers() & Qt::ShiftModifier);
|
||||||
break;
|
break;
|
||||||
case Qt::Key_Down:
|
case Qt::Key_Down:
|
||||||
|
if (event->modifiers() & Qt::ControlModifier)
|
||||||
|
shiftMosaics(event->key());
|
||||||
|
else
|
||||||
m_teletextDocument->cursorDown(event->modifiers() & Qt::ShiftModifier);
|
m_teletextDocument->cursorDown(event->modifiers() & Qt::ShiftModifier);
|
||||||
break;
|
break;
|
||||||
case Qt::Key_Left:
|
case Qt::Key_Left:
|
||||||
|
if (event->modifiers() & Qt::ControlModifier)
|
||||||
|
shiftMosaics(event->key());
|
||||||
|
else
|
||||||
m_teletextDocument->cursorLeft(event->modifiers() & Qt::ShiftModifier);
|
m_teletextDocument->cursorLeft(event->modifiers() & Qt::ShiftModifier);
|
||||||
break;
|
break;
|
||||||
case Qt::Key_Right:
|
case Qt::Key_Right:
|
||||||
|
if (event->modifiers() & Qt::ControlModifier)
|
||||||
|
shiftMosaics(event->key());
|
||||||
|
else
|
||||||
m_teletextDocument->cursorRight(event->modifiers() & Qt::ShiftModifier);
|
m_teletextDocument->cursorRight(event->modifiers() & Qt::ShiftModifier);
|
||||||
break;
|
break;
|
||||||
case Qt::Key_Return:
|
case Qt::Key_Return:
|
||||||
@@ -377,6 +391,35 @@ void TeletextWidget::toggleCharacterBit(unsigned char bitToToggle)
|
|||||||
m_teletextDocument->undoStack()->push(new ToggleMosaicBitCommand(m_teletextDocument, bitToToggle));
|
m_teletextDocument->undoStack()->push(new ToggleMosaicBitCommand(m_teletextDocument, bitToToggle));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TeletextWidget::shiftMosaics(int key)
|
||||||
|
{
|
||||||
|
if (!m_teletextDocument->selectionActive())
|
||||||
|
return;
|
||||||
|
|
||||||
|
QSet<QPair<int, int>> mosaicList;
|
||||||
|
|
||||||
|
for (int r=m_teletextDocument->selectionTopRow(); r<=m_teletextDocument->selectionBottomRow(); r++)
|
||||||
|
for (int c=m_teletextDocument->selectionLeftColumn(); c<=m_teletextDocument->selectionRightColumn(); c++)
|
||||||
|
if (m_pageDecode.level1MosaicChar(r, c))
|
||||||
|
mosaicList.insert(qMakePair(r, c));
|
||||||
|
|
||||||
|
if (!mosaicList.isEmpty())
|
||||||
|
switch (key) {
|
||||||
|
case Qt::Key_Up:
|
||||||
|
m_teletextDocument->undoStack()->push(new ShiftMosaicsUpCommand(m_teletextDocument, mosaicList));
|
||||||
|
break;
|
||||||
|
case Qt::Key_Down:
|
||||||
|
m_teletextDocument->undoStack()->push(new ShiftMosaicsDownCommand(m_teletextDocument, mosaicList));
|
||||||
|
break;
|
||||||
|
case Qt::Key_Left:
|
||||||
|
m_teletextDocument->undoStack()->push(new ShiftMosaicsLeftCommand(m_teletextDocument, mosaicList));
|
||||||
|
break;
|
||||||
|
case Qt::Key_Right:
|
||||||
|
m_teletextDocument->undoStack()->push(new ShiftMosaicsRightCommand(m_teletextDocument, mosaicList));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TeletextWidget::selectionToClipboard()
|
void TeletextWidget::selectionToClipboard()
|
||||||
{
|
{
|
||||||
QByteArray nativeData;
|
QByteArray nativeData;
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ private:
|
|||||||
int m_flashTiming, m_flashPhase;
|
int m_flashTiming, m_flashPhase;
|
||||||
|
|
||||||
void timerEvent(QTimerEvent *event) override;
|
void timerEvent(QTimerEvent *event) override;
|
||||||
|
void shiftMosaics(int key);
|
||||||
void selectionToClipboard();
|
void selectionToClipboard();
|
||||||
|
|
||||||
QPair<int, int> mouseToRowAndColumn(const QPoint &mousePosition);
|
QPair<int, int> mouseToRowAndColumn(const QPoint &mousePosition);
|
||||||
|
|||||||
Reference in New Issue
Block a user