diff --git a/src/qteletextmaker/levelonecommands.cpp b/src/qteletextmaker/levelonecommands.cpp index 9936605..d9fc834 100644 --- a/src/qteletextmaker/levelonecommands.cpp +++ b/src/qteletextmaker/levelonecommands.cpp @@ -457,6 +457,49 @@ ShiftMosaicsRightCommand::ShiftMosaicsRightCommand(TeletextDocument *teletextDoc setText(QObject::tr("shift mosaics right")); } +FillMosaicsCommand::FillMosaicsCommand(TeletextDocument *teletextDocument, const QSet> &mosaicList, QUndoCommand *parent) : ShiftMosaicsCommand(teletextDocument, mosaicList, parent) +{ + for (const auto &m : m_mosaicList) + m_newCharacters[m.first - m_selectionTopRow][m.second - m_selectionLeftColumn] = 0x7f; + + setText(QObject::tr("fill mosaics")); +} + +ClearMosaicsCommand::ClearMosaicsCommand(TeletextDocument *teletextDocument, const QSet> &mosaicList, QUndoCommand *parent) : ShiftMosaicsCommand(teletextDocument, mosaicList, parent) +{ + for (const auto &m : m_mosaicList) + m_newCharacters[m.first - m_selectionTopRow][m.second - m_selectionLeftColumn] = 0x20; + + setText(QObject::tr("clear mosaics")); +} + +InvertMosaicsCommand::InvertMosaicsCommand(TeletextDocument *teletextDocument, const QSet> &mosaicList, QUndoCommand *parent) : ShiftMosaicsCommand(teletextDocument, mosaicList, parent) +{ + for (const auto &m : m_mosaicList) + m_newCharacters[m.first - m_selectionTopRow][m.second - m_selectionLeftColumn] ^= 0x5f; + + setText(QObject::tr("reverse mosaics")); +} + +bool InvertMosaicsCommand::mergeWith(const QUndoCommand *command) +{ + const InvertMosaicsCommand *newerCommand = static_cast(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; + + setObsolete(true); + return true; +} + +DitherMosaicsCommand::DitherMosaicsCommand(TeletextDocument *teletextDocument, const QSet> &mosaicList, QUndoCommand *parent) : ShiftMosaicsCommand(teletextDocument, mosaicList, parent) +{ + for (const auto &m : m_mosaicList) + m_newCharacters[m.first - m_selectionTopRow][m.second - m_selectionLeftColumn] = (m.first & 1) ? 0x66 : 0x39; + + setText(QObject::tr("dither mosaics")); +} + InsertRowCommand::InsertRowCommand(TeletextDocument *teletextDocument, bool copyRow, QUndoCommand *parent) : LevelOneCommand(teletextDocument, parent) { diff --git a/src/qteletextmaker/levelonecommands.h b/src/qteletextmaker/levelonecommands.h index cf2e1ac..e0dbc65 100644 --- a/src/qteletextmaker/levelonecommands.h +++ b/src/qteletextmaker/levelonecommands.h @@ -164,6 +164,47 @@ public: int id() const override { return Id; } }; +class FillMosaicsCommand : public ShiftMosaicsCommand +{ +public: + enum { Id = 120 }; + + FillMosaicsCommand(TeletextDocument *teletextDocument, const QSet> &mosaicList, QUndoCommand *parent = 0); + + int id() const override { return Id; } +}; + +class ClearMosaicsCommand : public ShiftMosaicsCommand +{ +public: + enum { Id = 121 }; + + ClearMosaicsCommand(TeletextDocument *teletextDocument, const QSet> &mosaicList, QUndoCommand *parent = 0); + + int id() const override { return Id; } +}; + +class InvertMosaicsCommand : public ShiftMosaicsCommand +{ +public: + enum { Id = 122 }; + + InvertMosaicsCommand(TeletextDocument *teletextDocument, const QSet> &mosaicList, QUndoCommand *parent = 0); + + bool mergeWith(const QUndoCommand *command) override; + int id() const override { return Id; } +}; + +class DitherMosaicsCommand : public ShiftMosaicsCommand +{ +public: + enum { Id = 123 }; + + DitherMosaicsCommand(TeletextDocument *teletextDocument, const QSet> &mosaicList, QUndoCommand *parent = 0); + + int id() const override { return Id; } +}; + class InsertSubPageCommand : public LevelOneCommand { public: diff --git a/src/qteletextmaker/mainwidget.cpp b/src/qteletextmaker/mainwidget.cpp index 0d4eb6a..23f4269 100644 --- a/src/qteletextmaker/mainwidget.cpp +++ b/src/qteletextmaker/mainwidget.cpp @@ -228,8 +228,9 @@ void TeletextWidget::keyPressEvent(QKeyEvent *event) // Map it to block character so it doesn't need to be inserted-between later on if (mappedKeyPress & 0x80) mappedKeyPress = 0x7f; - if (m_pageDecode.level1MosaicAttr(m_teletextDocument->cursorRow(), m_teletextDocument->cursorColumn()) && (mappedKeyPress < 0x40 || mappedKeyPress > 0x5f)) { - // We're on a mosaic and a blast-through character was NOT pressed + if ((m_pageDecode.level1MosaicAttr(m_teletextDocument->cursorRow(), m_teletextDocument->cursorColumn()) || m_teletextDocument->selectionActive()) && (mappedKeyPress < 0x40 || mappedKeyPress > 0x5f)) { + // A blast-through character was NOT pressed + // and we're either on a mosaic or a selection is active if (event->key() >= Qt::Key_0 && event->key() <= Qt::Key_9 && event->modifiers() & Qt::KeypadModifier) { switch (event->key()) { case Qt::Key_7: @@ -388,7 +389,27 @@ void TeletextWidget::setCharacter(unsigned char newCharacter) void TeletextWidget::toggleCharacterBit(unsigned char bitToToggle) { - m_teletextDocument->undoStack()->push(new ToggleMosaicBitCommand(m_teletextDocument, bitToToggle)); + if (!m_teletextDocument->selectionActive()) + m_teletextDocument->undoStack()->push(new ToggleMosaicBitCommand(m_teletextDocument, bitToToggle)); + else { + const QSet> mosaicList = findMosaics(); + + if (!mosaicList.isEmpty()) + switch (bitToToggle) { + case 0x7f: + m_teletextDocument->undoStack()->push(new FillMosaicsCommand(m_teletextDocument, mosaicList)); + break; + case 0x20: + m_teletextDocument->undoStack()->push(new ClearMosaicsCommand(m_teletextDocument, mosaicList)); + break; + case 0x5f: + m_teletextDocument->undoStack()->push(new InvertMosaicsCommand(m_teletextDocument, mosaicList)); + break; + case 0x66: + m_teletextDocument->undoStack()->push(new DitherMosaicsCommand(m_teletextDocument, mosaicList)); + break; + } + } } QSet> TeletextWidget::findMosaics()