Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
72dbe94dc2 | ||
|
|
8d415f1a0f | ||
|
|
2c04c898ab | ||
|
|
a66474b7cf | ||
|
|
3906bfde80 | ||
|
|
19f74a1761 | ||
|
|
8903703064 | ||
|
|
56e7b0500c | ||
|
|
9fa86f8c4c | ||
|
|
551172aed3 | ||
|
|
7a0dbcca2b | ||
|
|
1a7e5aff5f | ||
|
|
c24a6b1fa1 | ||
|
|
4387e9ffbd | ||
|
|
f258c6e095 | ||
|
|
5739474957 | ||
|
|
8bc0c2c886 | ||
|
|
4584ba668d | ||
|
|
d3607f5b00 | ||
|
|
2ad5d45153 | ||
|
|
690f340922 | ||
|
|
dc93fe856d |
90
document.cpp
90
document.cpp
@@ -34,6 +34,7 @@ TeletextDocument::TeletextDocument()
|
||||
m_undoStack = new QUndoStack(this);
|
||||
m_cursorRow = 1;
|
||||
m_cursorColumn = 0;
|
||||
m_selectionCornerRow = m_selectionCornerColumn = -1;
|
||||
m_selectionSubPage = nullptr;
|
||||
}
|
||||
|
||||
@@ -73,6 +74,7 @@ void TeletextDocument::selectSubPageIndex(int newSubPageIndex, bool forceRefresh
|
||||
emit aboutToChangeSubPage();
|
||||
m_currentSubPageIndex = newSubPageIndex;
|
||||
emit subPageSelected();
|
||||
emit selectionMoved();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -83,6 +85,7 @@ void TeletextDocument::selectSubPageNext()
|
||||
emit aboutToChangeSubPage();
|
||||
m_currentSubPageIndex++;
|
||||
emit subPageSelected();
|
||||
emit selectionMoved();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,6 +95,7 @@ void TeletextDocument::selectSubPagePrevious()
|
||||
emit aboutToChangeSubPage();
|
||||
m_currentSubPageIndex--;
|
||||
emit subPageSelected();
|
||||
emit selectionMoved();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,62 +172,124 @@ void TeletextDocument::setFastTextLinkPageNumberOnAllSubPages(int linkNumber, in
|
||||
subPage->setFastTextLinkPageNumber(linkNumber, pageNumber);
|
||||
}
|
||||
|
||||
void TeletextDocument::cursorUp()
|
||||
void TeletextDocument::cursorUp(bool shiftKey)
|
||||
{
|
||||
if (shiftKey && !selectionActive())
|
||||
setSelectionCorner(m_cursorRow, m_cursorColumn);
|
||||
|
||||
if (--m_cursorRow == 0)
|
||||
m_cursorRow = 24;
|
||||
|
||||
if (shiftKey)
|
||||
emit selectionMoved();
|
||||
else
|
||||
cancelSelection();
|
||||
|
||||
emit cursorMoved();
|
||||
}
|
||||
|
||||
void TeletextDocument::cursorDown()
|
||||
void TeletextDocument::cursorDown(bool shiftKey)
|
||||
{
|
||||
if (shiftKey && !selectionActive())
|
||||
setSelectionCorner(m_cursorRow, m_cursorColumn);
|
||||
|
||||
if (++m_cursorRow == 25)
|
||||
m_cursorRow = 1;
|
||||
|
||||
if (shiftKey)
|
||||
emit selectionMoved();
|
||||
else
|
||||
cancelSelection();
|
||||
|
||||
emit cursorMoved();
|
||||
}
|
||||
|
||||
void TeletextDocument::cursorLeft()
|
||||
void TeletextDocument::cursorLeft(bool shiftKey)
|
||||
{
|
||||
if (shiftKey && !selectionActive())
|
||||
setSelectionCorner(m_cursorRow, m_cursorColumn);
|
||||
|
||||
if (--m_cursorColumn == -1) {
|
||||
m_cursorColumn = 39;
|
||||
cursorUp();
|
||||
cursorUp(shiftKey);
|
||||
}
|
||||
|
||||
if (shiftKey)
|
||||
emit selectionMoved();
|
||||
else
|
||||
cancelSelection();
|
||||
|
||||
emit cursorMoved();
|
||||
}
|
||||
|
||||
void TeletextDocument::cursorRight()
|
||||
void TeletextDocument::cursorRight(bool shiftKey)
|
||||
{
|
||||
if (shiftKey && !selectionActive())
|
||||
setSelectionCorner(m_cursorRow, m_cursorColumn);
|
||||
|
||||
if (++m_cursorColumn == 40) {
|
||||
m_cursorColumn = 0;
|
||||
cursorDown();
|
||||
cursorDown(shiftKey);
|
||||
}
|
||||
|
||||
if (shiftKey)
|
||||
emit selectionMoved();
|
||||
else
|
||||
cancelSelection();
|
||||
|
||||
emit cursorMoved();
|
||||
}
|
||||
|
||||
void TeletextDocument::moveCursor(int cursorRow, int cursorColumn)
|
||||
void TeletextDocument::moveCursor(int cursorRow, int cursorColumn, bool selectionInProgress)
|
||||
{
|
||||
if (selectionInProgress && !selectionActive())
|
||||
setSelectionCorner(m_cursorRow, m_cursorColumn);
|
||||
|
||||
if (cursorRow != -1)
|
||||
m_cursorRow = cursorRow;
|
||||
if (cursorColumn != -1)
|
||||
m_cursorColumn = cursorColumn;
|
||||
|
||||
if (selectionInProgress)
|
||||
emit selectionMoved();
|
||||
else
|
||||
cancelSelection();
|
||||
|
||||
emit cursorMoved();
|
||||
}
|
||||
|
||||
void TeletextDocument::setSelectionCorner(int row, int column)
|
||||
{
|
||||
if (m_selectionCornerRow != row || m_selectionCornerColumn != column) {
|
||||
m_selectionSubPage = currentSubPage();
|
||||
m_selectionCornerRow = row;
|
||||
m_selectionCornerColumn = column;
|
||||
|
||||
// emit selectionMoved();
|
||||
}
|
||||
}
|
||||
|
||||
void TeletextDocument::setSelection(int topRow, int leftColumn, int bottomRow, int rightColumn)
|
||||
{
|
||||
if (m_selectionTopRow != topRow || m_selectionBottomRow != bottomRow || m_selectionLeftColumn != leftColumn || m_selectionRightColumn != rightColumn) {
|
||||
if (selectionTopRow() != topRow || selectionBottomRow() != bottomRow || selectionLeftColumn() != leftColumn || selectionRightColumn() != rightColumn) {
|
||||
m_selectionSubPage = currentSubPage();
|
||||
m_selectionTopRow = topRow;
|
||||
m_selectionBottomRow = bottomRow;
|
||||
m_selectionLeftColumn = leftColumn;
|
||||
m_selectionRightColumn = rightColumn;
|
||||
m_selectionCornerRow = topRow;
|
||||
m_cursorRow = bottomRow;
|
||||
m_selectionCornerColumn = leftColumn;
|
||||
m_cursorColumn = rightColumn;
|
||||
|
||||
emit selectionMoved();
|
||||
emit cursorMoved();
|
||||
}
|
||||
}
|
||||
|
||||
void TeletextDocument::cancelSelection()
|
||||
{
|
||||
if (m_selectionSubPage != nullptr) {
|
||||
m_selectionSubPage = nullptr;
|
||||
emit selectionMoved();
|
||||
m_selectionCornerRow = m_selectionCornerColumn = -1;
|
||||
}
|
||||
}
|
||||
|
||||
int TeletextDocument::levelRequired() const
|
||||
|
||||
27
document.h
27
document.h
@@ -64,18 +64,21 @@ public:
|
||||
QUndoStack *undoStack() const { return m_undoStack; }
|
||||
int cursorRow() const { return m_cursorRow; }
|
||||
int cursorColumn() const { return m_cursorColumn; }
|
||||
void cursorUp();
|
||||
void cursorDown();
|
||||
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; }
|
||||
void cursorUp(bool shiftKey=false);
|
||||
void cursorDown(bool shiftKey=false);
|
||||
void cursorLeft(bool shiftKey=false);
|
||||
void cursorRight(bool shiftKey=false);
|
||||
void moveCursor(int, int, bool selectionInProgress=false);
|
||||
int selectionTopRow() const { return m_selectionCornerRow == -1 ? m_cursorRow : qMin(m_selectionCornerRow, m_cursorRow); }
|
||||
int selectionBottomRow() const { return qMax(m_selectionCornerRow, m_cursorRow); }
|
||||
int selectionLeftColumn() const { return m_selectionCornerColumn == -1 ? m_cursorColumn : qMin(m_selectionCornerColumn, m_cursorColumn); }
|
||||
int selectionRightColumn() const { return qMax(m_selectionCornerColumn, m_cursorColumn); }
|
||||
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();
|
||||
int levelRequired() const;
|
||||
@@ -99,7 +102,7 @@ private:
|
||||
std::vector<LevelOnePage *> m_subPages;
|
||||
std::vector<LevelOnePage *> m_recycleSubPages;
|
||||
QUndoStack *m_undoStack;
|
||||
int m_cursorRow, m_cursorColumn, m_selectionTopRow, m_selectionBottomRow, m_selectionLeftColumn, m_selectionRightColumn;
|
||||
int m_cursorRow, m_cursorColumn, m_selectionCornerRow, m_selectionCornerColumn;
|
||||
LevelOnePage *m_selectionSubPage;
|
||||
};
|
||||
|
||||
|
||||
23
examples/Level1p5-Defcon.tti
Normal file
23
examples/Level1p5-Defcon.tti
Normal file
@@ -0,0 +1,23 @@
|
||||
PN,11600
|
||||
SC,0000
|
||||
PS,8000
|
||||
CT,8,T
|
||||
OL,26,@lD@Ib\UbTXb\ZbT]b\`B]mD@HB{VBsWB{[Bs\B{
|
||||
OL,26,AaBRnD@`BraB]oD@HBXVBPWBX[BP\BX`B}pD@Iby
|
||||
OL,26,BUbqXbyZbq]byaBruD@KBYLBSRbTVb\ZbT^b\cbY
|
||||
OL,26,CdBSvD@JBYKBSLBywD@Fb\JBTKByLBsVB^ZbX[bU
|
||||
OL,26,D\bS^bxxD@[bx\bu]bsyD@BbqFbyRbqVbyCC
|
||||
OL,3,W <,,,,,,,,,,,,,,,,,,,,,,,,,,,,,l
|
||||
OL,4,W 5t xt xt 5 j
|
||||
OL,5,W 5 " !"/ !" j
|
||||
OL,6,W 5 j5j
|
||||
OL,7,W 5 ` 0`| 0` j
|
||||
OL,8,W 5' +' +' jj
|
||||
OL,9,W -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.
|
||||
OL,12,V<,,,,,lR<,,,,,lS<,,,,,lQ<,,,,,lW<,,,,,l
|
||||
OL,13,V5jR5 `5jS5xtjQ5xtjW5 `~5 j
|
||||
OL,14,V55 jR5 ~75jS5/% jjQ5/% jjW5 #5 j
|
||||
OL,15,V5tjR5z? 5jS5 j5jQ5`x~/jW5 5 j
|
||||
OL,16,V5|4 jjR5jS5|4 jjQ5?# jW5 5 j
|
||||
OL,17,V5+'jR5 5jS5+'jQ5jW5 5 j
|
||||
OL,18,V-,,,,,.R-,,,,,.S-,,,,,.Q-,,,,,.W-,,,,,.
|
||||
33
examples/SidePanels-PriceChop.tti
Normal file
33
examples/SidePanels-PriceChop.tti
Normal file
@@ -0,0 +1,33 @@
|
||||
PN,13200
|
||||
SC,0000
|
||||
PS,8000
|
||||
CT,8,T
|
||||
OL,28,@@@|H@p_@|wsA@@AfUrLs_w}ww]_}_wM@p
|
||||
OL,26,@rD@Ab|BBpKBxLbtsD@BB{CbqJbyKBstD@Db|EBp
|
||||
OL,26,AHBxIbtuD@EB{FbqGbyHBswD@AbqLbyxD@Bb|CBp
|
||||
OL,26,BJBxKbtyD@CB{DbqIbyJBszD@Eb|FBpGBxHbt{D@
|
||||
OL,26,CFB{GBs}aJ@cJhPThr]hP`hre~aI@cI_Cxv]@It
|
||||
OL,26,DAipBitCIwGi\iD@@@H@irAiyBIzCirDIyxve@Iy
|
||||
OL,26,EAIqCiqDItEipFitGIwiD@@@HAisBIvCipDiyEis
|
||||
OL,26,FFiwGi{BBBBBBBBBBB
|
||||
OL,1, calls cost #5 WZ`p0ppb`p0pp `p0up`p0pp
|
||||
OL,2, 0909 879 0100 WZjp55"jj 1=.(j 15jj 5uz
|
||||
OL,3, GB #9.99 p&p WZ* ! ""#!## "#!!""#!%
|
||||
OL,4, W Zn,h h
|
||||
OL,5,C]Dstart #89 \ W Zjp"d&
|
||||
OL,6,S############
|
||||
OL,7, LIVE
|
||||
OL,8,E]G now at \
|
||||
OL,9,Ussssssssssss
|
||||
OL,10,U+'
|
||||
OL,11,U^"o]G#3U?\!
|
||||
OL,12,U +'
|
||||
OL,13,U "o?!
|
||||
OL,14,Spppppppppppp
|
||||
OL,15,S+]D^leftS\'
|
||||
OL,16,S^"o]D24S?\!
|
||||
OL,17,S +'
|
||||
OL,18,S "o?!
|
||||
OL,19,S
|
||||
OL,21,E]G9ct gold curb chain 9ct gold curb c
|
||||
OL,22,C]DNEW BUYER JOHN london JANET manch
|
||||
@@ -17,16 +17,29 @@
|
||||
* along with QTeletextMaker. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <QApplication>
|
||||
#include <QByteArray>
|
||||
#include <QByteArrayList>
|
||||
#include <QClipboard>
|
||||
#include <QMimeData>
|
||||
|
||||
#include "levelonecommands.h"
|
||||
|
||||
#include "document.h"
|
||||
#include "keymap.h"
|
||||
|
||||
TypeCharacterCommand::TypeCharacterCommand(TeletextDocument *teletextDocument, unsigned char newCharacter, bool insertMode, QUndoCommand *parent) : QUndoCommand(parent)
|
||||
LevelOneCommand::LevelOneCommand(TeletextDocument *teletextDocument, QUndoCommand *parent) : QUndoCommand(parent)
|
||||
{
|
||||
m_teletextDocument = teletextDocument;
|
||||
m_subPageIndex = teletextDocument->currentSubPageIndex();
|
||||
m_row = teletextDocument->cursorRow();
|
||||
m_columnStart = m_columnEnd = teletextDocument->cursorColumn();
|
||||
m_column = teletextDocument->cursorColumn();
|
||||
m_firstDo = true;
|
||||
}
|
||||
|
||||
TypeCharacterCommand::TypeCharacterCommand(TeletextDocument *teletextDocument, unsigned char newCharacter, bool insertMode, QUndoCommand *parent) : LevelOneCommand(teletextDocument, parent)
|
||||
{
|
||||
m_columnStart = m_columnEnd = m_column;
|
||||
m_newCharacter = newCharacter;
|
||||
m_insertMode = insertMode;
|
||||
|
||||
@@ -37,7 +50,6 @@ TypeCharacterCommand::TypeCharacterCommand(TeletextDocument *teletextDocument, u
|
||||
setText(QObject::tr("insert character"));
|
||||
else
|
||||
setText(QObject::tr("overwrite character"));
|
||||
m_firstDo = true;
|
||||
}
|
||||
|
||||
void TypeCharacterCommand::redo()
|
||||
@@ -89,12 +101,8 @@ bool TypeCharacterCommand::mergeWith(const QUndoCommand *command)
|
||||
}
|
||||
|
||||
|
||||
ToggleMosaicBitCommand::ToggleMosaicBitCommand(TeletextDocument *teletextDocument, unsigned char bitToToggle, QUndoCommand *parent) : QUndoCommand(parent)
|
||||
ToggleMosaicBitCommand::ToggleMosaicBitCommand(TeletextDocument *teletextDocument, unsigned char bitToToggle, QUndoCommand *parent) : LevelOneCommand(teletextDocument, parent)
|
||||
{
|
||||
m_teletextDocument = teletextDocument;
|
||||
m_subPageIndex = teletextDocument->currentSubPageIndex();
|
||||
m_row = teletextDocument->cursorRow();
|
||||
m_column = teletextDocument->cursorColumn();
|
||||
m_oldCharacter = teletextDocument->currentSubPage()->character(m_row, m_column);
|
||||
if (bitToToggle == 0x20 || bitToToggle == 0x7f)
|
||||
m_newCharacter = bitToToggle;
|
||||
@@ -134,12 +142,10 @@ bool ToggleMosaicBitCommand::mergeWith(const QUndoCommand *command)
|
||||
}
|
||||
|
||||
|
||||
BackspaceKeyCommand::BackspaceKeyCommand(TeletextDocument *teletextDocument, bool insertMode, QUndoCommand *parent) : QUndoCommand(parent)
|
||||
BackspaceKeyCommand::BackspaceKeyCommand(TeletextDocument *teletextDocument, bool insertMode, QUndoCommand *parent) : LevelOneCommand(teletextDocument, parent)
|
||||
{
|
||||
m_teletextDocument = teletextDocument;
|
||||
m_subPageIndex = teletextDocument->currentSubPageIndex();
|
||||
m_row = teletextDocument->cursorRow();
|
||||
m_columnStart = teletextDocument->cursorColumn()-1;
|
||||
m_columnStart = m_column - 1;
|
||||
|
||||
if (m_columnStart == -1) {
|
||||
m_columnStart = 39;
|
||||
if (--m_row == 0)
|
||||
@@ -152,7 +158,6 @@ BackspaceKeyCommand::BackspaceKeyCommand(TeletextDocument *teletextDocument, boo
|
||||
m_oldRowContents[c] = m_newRowContents[c] = m_teletextDocument->currentSubPage()->character(m_row, c);
|
||||
|
||||
setText(QObject::tr("backspace"));
|
||||
m_firstDo = true;
|
||||
}
|
||||
|
||||
void BackspaceKeyCommand::redo()
|
||||
@@ -208,13 +213,8 @@ bool BackspaceKeyCommand::mergeWith(const QUndoCommand *command)
|
||||
}
|
||||
|
||||
|
||||
DeleteKeyCommand::DeleteKeyCommand(TeletextDocument *teletextDocument, QUndoCommand *parent) : QUndoCommand(parent)
|
||||
DeleteKeyCommand::DeleteKeyCommand(TeletextDocument *teletextDocument, QUndoCommand *parent) : LevelOneCommand(teletextDocument, parent)
|
||||
{
|
||||
m_teletextDocument = teletextDocument;
|
||||
m_subPageIndex = teletextDocument->currentSubPageIndex();
|
||||
m_row = teletextDocument->cursorRow();
|
||||
m_column = teletextDocument->cursorColumn();
|
||||
|
||||
for (int c=0; c<40; c++)
|
||||
m_oldRowContents[c] = m_newRowContents[c] = m_teletextDocument->currentSubPage()->character(m_row, c);
|
||||
|
||||
@@ -262,11 +262,8 @@ bool DeleteKeyCommand::mergeWith(const QUndoCommand *command)
|
||||
}
|
||||
|
||||
|
||||
InsertRowCommand::InsertRowCommand(TeletextDocument *teletextDocument, bool copyRow, QUndoCommand *parent) : QUndoCommand(parent)
|
||||
InsertRowCommand::InsertRowCommand(TeletextDocument *teletextDocument, bool copyRow, QUndoCommand *parent) : LevelOneCommand(teletextDocument, parent)
|
||||
{
|
||||
m_teletextDocument = teletextDocument;
|
||||
m_subPageIndex = teletextDocument->currentSubPageIndex();
|
||||
m_row = teletextDocument->cursorRow();
|
||||
m_copyRow = copyRow;
|
||||
|
||||
if (m_copyRow)
|
||||
@@ -310,12 +307,8 @@ void InsertRowCommand::undo()
|
||||
}
|
||||
|
||||
|
||||
DeleteRowCommand::DeleteRowCommand(TeletextDocument *teletextDocument, QUndoCommand *parent) : QUndoCommand(parent)
|
||||
DeleteRowCommand::DeleteRowCommand(TeletextDocument *teletextDocument, QUndoCommand *parent) : LevelOneCommand(teletextDocument, parent)
|
||||
{
|
||||
m_teletextDocument = teletextDocument;
|
||||
m_subPageIndex = teletextDocument->currentSubPageIndex();
|
||||
m_row = teletextDocument->cursorRow();
|
||||
|
||||
setText(QObject::tr("delete row"));
|
||||
}
|
||||
|
||||
@@ -354,10 +347,233 @@ void DeleteRowCommand::undo()
|
||||
}
|
||||
|
||||
|
||||
InsertSubPageCommand::InsertSubPageCommand(TeletextDocument *teletextDocument, bool afterCurrentSubPage, bool copySubPage, QUndoCommand *parent) : QUndoCommand(parent)
|
||||
#ifndef QT_NO_CLIPBOARD
|
||||
CutCommand::CutCommand(TeletextDocument *teletextDocument, QUndoCommand *parent) : LevelOneCommand(teletextDocument, parent)
|
||||
{
|
||||
m_teletextDocument = teletextDocument;
|
||||
m_newSubPageIndex = teletextDocument->currentSubPageIndex()+afterCurrentSubPage;
|
||||
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, int pageCharSet, 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
|
||||
// FIXME is this a correct "custom" mime type? Or should we use vnd?
|
||||
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; r<m_clipboardDataHeight; r++)
|
||||
m_pastingCharacters.append(nativeData.mid(2 + r * m_clipboardDataWidth, m_clipboardDataWidth));
|
||||
else
|
||||
// Invalidate
|
||||
m_clipboardDataHeight = m_clipboardDataWidth = 0;
|
||||
} else if (mimeData->hasText()) {
|
||||
// Plain text
|
||||
QStringList plainTextData = mimeData->text().split(QRegExp("\n|\r\n|\r"));
|
||||
|
||||
m_clipboardDataHeight = plainTextData.size();
|
||||
m_clipboardDataWidth = 0;
|
||||
|
||||
for (int r=0; r<m_clipboardDataHeight; r++) {
|
||||
m_pastingCharacters.append(QByteArray());
|
||||
for (int c=0; c<plainTextData.at(r).size(); c++) {
|
||||
// Try to map the unicode character to the current Level 1 character set of this page
|
||||
|
||||
char convertedChar;
|
||||
const QChar charToConvert = plainTextData.at(r).at(c);
|
||||
|
||||
if (keymapping[pageCharSet].contains(charToConvert))
|
||||
// Remapped character or non-Latin character converted successfully
|
||||
convertedChar = keymapping[pageCharSet].value(charToConvert);
|
||||
else {
|
||||
// Either a Latin character or non-Latin character that can't be converted
|
||||
// See if it's a Latin character
|
||||
convertedChar = charToConvert.toLatin1();
|
||||
if (convertedChar == 0)
|
||||
// Couldn't convert - make it a block character so it doesn't need to be inserted-between later on
|
||||
convertedChar = 0x7f;
|
||||
}
|
||||
|
||||
m_pastingCharacters[r].append(convertedChar);
|
||||
}
|
||||
m_clipboardDataWidth = qMax(m_pastingCharacters.at(r).size(), m_clipboardDataWidth);
|
||||
}
|
||||
// Pad short lines with spaces to make a box
|
||||
for (int r=0; r<m_clipboardDataHeight; r++)
|
||||
m_pastingCharacters[r] = m_pastingCharacters.at(r).leftJustified(m_clipboardDataWidth);
|
||||
}
|
||||
|
||||
if (m_clipboardDataWidth == 0 || m_clipboardDataHeight == 0)
|
||||
return;
|
||||
|
||||
if (m_selectionActive) {
|
||||
m_pasteTopRow = m_teletextDocument->selectionTopRow();
|
||||
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 || m_clipboardDataHeight == 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, qMin(m_column+m_clipboardDataWidth-1, 39));
|
||||
m_teletextDocument->cursorRight();
|
||||
}
|
||||
}
|
||||
|
||||
void PasteCommand::undo()
|
||||
{
|
||||
if (m_clipboardDataWidth == 0 || m_clipboardDataHeight == 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++;
|
||||
}
|
||||
|
||||
if (!m_selectionActive)
|
||||
m_teletextDocument->moveCursor(m_row, m_column);
|
||||
}
|
||||
#endif // !QT_NO_CLIPBOARD
|
||||
|
||||
|
||||
InsertSubPageCommand::InsertSubPageCommand(TeletextDocument *teletextDocument, bool afterCurrentSubPage, bool copySubPage, QUndoCommand *parent) : LevelOneCommand(teletextDocument, parent)
|
||||
{
|
||||
m_newSubPageIndex = m_subPageIndex + afterCurrentSubPage;
|
||||
m_copySubPage = copySubPage;
|
||||
|
||||
setText(QObject::tr("insert subpage"));
|
||||
@@ -380,30 +596,26 @@ void InsertSubPageCommand::undo()
|
||||
}
|
||||
|
||||
|
||||
DeleteSubPageCommand::DeleteSubPageCommand(TeletextDocument *teletextDocument, QUndoCommand *parent) : QUndoCommand(parent)
|
||||
DeleteSubPageCommand::DeleteSubPageCommand(TeletextDocument *teletextDocument, QUndoCommand *parent) : LevelOneCommand(teletextDocument, parent)
|
||||
{
|
||||
m_teletextDocument = teletextDocument;
|
||||
m_subPageToDelete = teletextDocument->currentSubPageIndex();
|
||||
setText(QObject::tr("delete subpage"));
|
||||
}
|
||||
|
||||
void DeleteSubPageCommand::redo()
|
||||
{
|
||||
m_teletextDocument->deleteSubPageToRecycle(m_subPageToDelete);
|
||||
m_teletextDocument->selectSubPageIndex(qMin(m_subPageToDelete, m_teletextDocument->numberOfSubPages()-1), true);
|
||||
m_teletextDocument->deleteSubPageToRecycle(m_subPageIndex);
|
||||
m_teletextDocument->selectSubPageIndex(qMin(m_subPageIndex, m_teletextDocument->numberOfSubPages()-1), true);
|
||||
}
|
||||
|
||||
void DeleteSubPageCommand::undo()
|
||||
{
|
||||
m_teletextDocument->unDeleteSubPageFromRecycle(m_subPageToDelete);
|
||||
m_teletextDocument->selectSubPageIndex(m_subPageToDelete, true);
|
||||
m_teletextDocument->unDeleteSubPageFromRecycle(m_subPageIndex);
|
||||
m_teletextDocument->selectSubPageIndex(m_subPageIndex, true);
|
||||
}
|
||||
|
||||
|
||||
SetColourCommand::SetColourCommand(TeletextDocument *teletextDocument, int colourIndex, int newColour, QUndoCommand *parent) : QUndoCommand(parent)
|
||||
SetColourCommand::SetColourCommand(TeletextDocument *teletextDocument, int colourIndex, int newColour, QUndoCommand *parent) : LevelOneCommand(teletextDocument, parent)
|
||||
{
|
||||
m_teletextDocument = teletextDocument;
|
||||
m_subPageIndex = teletextDocument->currentSubPageIndex();
|
||||
m_colourIndex = colourIndex;
|
||||
m_oldColour = teletextDocument->currentSubPage()->CLUT(colourIndex);
|
||||
m_newColour = newColour;
|
||||
@@ -431,10 +643,8 @@ void SetColourCommand::undo()
|
||||
}
|
||||
|
||||
|
||||
ResetCLUTCommand::ResetCLUTCommand(TeletextDocument *teletextDocument, int colourTable, QUndoCommand *parent) : QUndoCommand(parent)
|
||||
ResetCLUTCommand::ResetCLUTCommand(TeletextDocument *teletextDocument, int colourTable, QUndoCommand *parent) : LevelOneCommand(teletextDocument, parent)
|
||||
{
|
||||
m_teletextDocument = teletextDocument;
|
||||
m_subPageIndex = teletextDocument->currentSubPageIndex();
|
||||
m_colourTable = colourTable;
|
||||
for (int i=m_colourTable*8; i<m_colourTable*8+8; i++)
|
||||
m_oldColourEntry[i&7] = teletextDocument->currentSubPage()->CLUT(i);
|
||||
|
||||
@@ -20,11 +20,23 @@
|
||||
#ifndef LEVELONECOMMANDS_H
|
||||
#define LEVELONECOMMANDS_H
|
||||
|
||||
#include <QByteArrayList>
|
||||
#include <QUndoCommand>
|
||||
|
||||
#include "document.h"
|
||||
|
||||
class TypeCharacterCommand : public QUndoCommand
|
||||
class LevelOneCommand : public QUndoCommand
|
||||
{
|
||||
public:
|
||||
LevelOneCommand(TeletextDocument *, QUndoCommand *parent = 0);
|
||||
|
||||
protected:
|
||||
TeletextDocument *m_teletextDocument;
|
||||
int m_subPageIndex, m_row, m_column;
|
||||
bool m_firstDo;
|
||||
};
|
||||
|
||||
class TypeCharacterCommand : public LevelOneCommand
|
||||
{
|
||||
public:
|
||||
enum { Id = 101 };
|
||||
@@ -37,13 +49,12 @@ public:
|
||||
int id() const override { return Id; }
|
||||
|
||||
private:
|
||||
TeletextDocument *m_teletextDocument;
|
||||
unsigned char m_newCharacter, m_oldRowContents[40], m_newRowContents[40];
|
||||
int m_subPageIndex, m_row, m_columnStart, m_columnEnd;
|
||||
bool m_firstDo, m_insertMode;
|
||||
int m_columnStart, m_columnEnd;
|
||||
bool m_insertMode;
|
||||
};
|
||||
|
||||
class ToggleMosaicBitCommand : public QUndoCommand
|
||||
class ToggleMosaicBitCommand : public LevelOneCommand
|
||||
{
|
||||
public:
|
||||
enum { Id = 102 };
|
||||
@@ -56,12 +67,10 @@ public:
|
||||
int id() const override { return Id; }
|
||||
|
||||
private:
|
||||
TeletextDocument *m_teletextDocument;
|
||||
unsigned char m_oldCharacter, m_newCharacter;
|
||||
int m_subPageIndex, m_row, m_column;
|
||||
};
|
||||
|
||||
class BackspaceKeyCommand : public QUndoCommand
|
||||
class BackspaceKeyCommand : public LevelOneCommand
|
||||
{
|
||||
public:
|
||||
enum { Id = 103 };
|
||||
@@ -74,13 +83,12 @@ public:
|
||||
int id() const override { return Id; }
|
||||
|
||||
private:
|
||||
TeletextDocument *m_teletextDocument;
|
||||
unsigned char m_oldRowContents[40], m_newRowContents[40];
|
||||
int m_subPageIndex, m_row, m_columnStart, m_columnEnd;
|
||||
bool m_firstDo, m_insertMode;
|
||||
int m_columnStart, m_columnEnd;
|
||||
bool m_insertMode;
|
||||
};
|
||||
|
||||
class DeleteKeyCommand : public QUndoCommand
|
||||
class DeleteKeyCommand : public LevelOneCommand
|
||||
{
|
||||
public:
|
||||
enum { Id = 104 };
|
||||
@@ -93,12 +101,10 @@ public:
|
||||
int id() const override { return Id; }
|
||||
|
||||
private:
|
||||
TeletextDocument *m_teletextDocument;
|
||||
unsigned char m_oldRowContents[40], m_newRowContents[40];
|
||||
int m_subPageIndex, m_row, m_column;
|
||||
};
|
||||
|
||||
class InsertSubPageCommand : public QUndoCommand
|
||||
class InsertSubPageCommand : public LevelOneCommand
|
||||
{
|
||||
public:
|
||||
InsertSubPageCommand(TeletextDocument *, bool, bool, QUndoCommand *parent = 0);
|
||||
@@ -107,25 +113,20 @@ public:
|
||||
void undo() override;
|
||||
|
||||
private:
|
||||
TeletextDocument *m_teletextDocument;
|
||||
int m_newSubPageIndex;
|
||||
bool m_copySubPage;
|
||||
};
|
||||
|
||||
class DeleteSubPageCommand : public QUndoCommand
|
||||
class DeleteSubPageCommand : public LevelOneCommand
|
||||
{
|
||||
public:
|
||||
DeleteSubPageCommand(TeletextDocument *, QUndoCommand *parent = 0);
|
||||
|
||||
void redo() override;
|
||||
void undo() override;
|
||||
|
||||
private:
|
||||
TeletextDocument *m_teletextDocument;
|
||||
int m_subPageToDelete;
|
||||
};
|
||||
|
||||
class InsertRowCommand : public QUndoCommand
|
||||
class InsertRowCommand : public LevelOneCommand
|
||||
{
|
||||
public:
|
||||
InsertRowCommand(TeletextDocument *, bool, QUndoCommand *parent = 0);
|
||||
@@ -134,13 +135,11 @@ public:
|
||||
void undo() override;
|
||||
|
||||
private:
|
||||
TeletextDocument *m_teletextDocument;
|
||||
int m_subPageIndex, m_row;
|
||||
bool m_copyRow;
|
||||
unsigned char m_deletedBottomRow[40];
|
||||
};
|
||||
|
||||
class DeleteRowCommand : public QUndoCommand
|
||||
class DeleteRowCommand : public LevelOneCommand
|
||||
{
|
||||
public:
|
||||
DeleteRowCommand(TeletextDocument *, QUndoCommand *parent = 0);
|
||||
@@ -149,12 +148,42 @@ public:
|
||||
void undo() override;
|
||||
|
||||
private:
|
||||
TeletextDocument *m_teletextDocument;
|
||||
int m_subPageIndex, m_row;
|
||||
unsigned char m_deletedRow[40];
|
||||
};
|
||||
|
||||
class SetColourCommand : public QUndoCommand
|
||||
#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 *, int, 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:
|
||||
SetColourCommand(TeletextDocument *, int, int, QUndoCommand *parent = 0);
|
||||
@@ -163,11 +192,10 @@ public:
|
||||
void undo() override;
|
||||
|
||||
private:
|
||||
TeletextDocument *m_teletextDocument;
|
||||
int m_subPageIndex, m_colourIndex, m_oldColour, m_newColour;
|
||||
int m_colourIndex, m_oldColour, m_newColour;
|
||||
};
|
||||
|
||||
class ResetCLUTCommand : public QUndoCommand
|
||||
class ResetCLUTCommand : public LevelOneCommand
|
||||
{
|
||||
public:
|
||||
ResetCLUTCommand(TeletextDocument *, int, QUndoCommand *parent = 0);
|
||||
@@ -176,8 +204,7 @@ public:
|
||||
void undo() override;
|
||||
|
||||
private:
|
||||
TeletextDocument *m_teletextDocument;
|
||||
int m_subPageIndex, m_colourTable;
|
||||
int m_colourTable;
|
||||
int m_oldColourEntry[8];
|
||||
};
|
||||
|
||||
|
||||
@@ -27,13 +27,13 @@
|
||||
|
||||
LevelOnePage::LevelOnePage()
|
||||
{
|
||||
m_enhancements.reserve(208);
|
||||
m_enhancements.reserve(maxEnhancements());
|
||||
clearPage();
|
||||
}
|
||||
|
||||
LevelOnePage::LevelOnePage(const PageBase &other)
|
||||
{
|
||||
m_enhancements.reserve(208);
|
||||
m_enhancements.reserve(maxEnhancements());
|
||||
clearPage();
|
||||
|
||||
for (int i=0; i<26; i++)
|
||||
|
||||
@@ -52,6 +52,8 @@ public:
|
||||
|
||||
void clearPage();
|
||||
|
||||
int maxEnhancements() const { return 208; };
|
||||
|
||||
/* void setSubPageNumber(int); */
|
||||
int cycleValue() const { return m_cycleValue; };
|
||||
void setCycleValue(int);
|
||||
|
||||
55
loadsave.cpp
55
loadsave.cpp
@@ -193,7 +193,11 @@ void saveTTI(QSaveFile &file, const TeletextDocument &document)
|
||||
outLine.insert(c, 0x1b);
|
||||
c++;
|
||||
}
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
||||
outStream << outLine << Qt::endl;
|
||||
#else
|
||||
outStream << outLine << endl;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
@@ -207,14 +211,22 @@ void saveTTI(QSaveFile &file, const TeletextDocument &document)
|
||||
outLine[0] = designationCode | 0x40;
|
||||
for (int c=1; c<outLine.size(); c++)
|
||||
outLine[c] = outLine.at(c) | 0x40;
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
||||
outStream << outLine << Qt::endl;
|
||||
#else
|
||||
outStream << outLine << endl;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
outStream.setCodec("ISO-8859-1");
|
||||
|
||||
if (!document.description().isEmpty())
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
||||
outStream << "DE," << document.description() << Qt::endl;
|
||||
#else
|
||||
outStream << "DE," << document.description() << endl;
|
||||
#endif
|
||||
|
||||
// TODO DS and SP commands
|
||||
|
||||
@@ -224,21 +236,48 @@ void saveTTI(QSaveFile &file, const TeletextDocument &document)
|
||||
|
||||
for (p=0; p<document.numberOfSubPages(); p++) {
|
||||
|
||||
outStream << QString("PN,%1%2").arg(document.pageNumber(), 3, 16, QChar('0')).arg(subPageNumber & 0xff, 2, 16, QChar('0')) << Qt::endl;
|
||||
// Page number
|
||||
outStream << QString("PN,%1%2").arg(document.pageNumber(), 3, 16, QChar('0')).arg(subPageNumber & 0xff, 2, 16, QChar('0'));
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
||||
outStream << Qt::endl;
|
||||
#else
|
||||
outStream << endl;
|
||||
#endif
|
||||
|
||||
// Subpage
|
||||
// Magazine Organisation Table and Magazine Inventory Page don't have subpages
|
||||
if (document.pageFunction() != TeletextDocument::PFMOT && document.pageFunction() != TeletextDocument::PFMIP)
|
||||
outStream << QString("SC,%1").arg(subPageNumber, 4, 16, QChar('0')) << Qt::endl;
|
||||
if (document.pageFunction() != TeletextDocument::PFMOT && document.pageFunction() != TeletextDocument::PFMIP) {
|
||||
outStream << QString("SC,%1").arg(subPageNumber, 4, 16, QChar('0'));
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
||||
outStream << Qt::endl;
|
||||
#else
|
||||
outStream << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
outStream << QString("PS,%1").arg(0x8000 | controlBitsToPS(document.subPage(p)), 4, 16, QChar('0')) << Qt::endl;
|
||||
// Status bits
|
||||
outStream << QString("PS,%1").arg(0x8000 | controlBitsToPS(document.subPage(p)), 4, 16, QChar('0'));
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
||||
outStream << Qt::endl;
|
||||
#else
|
||||
outStream << endl;
|
||||
#endif
|
||||
|
||||
// Cycle time
|
||||
if (document.pageFunction() == TeletextDocument::PFLevelOnePage)
|
||||
// Assume that only Level One Pages have configurable cycle times
|
||||
outStream << QString("CT,%1,%2").arg(document.subPage(p)->cycleValue()).arg(document.subPage(p)->cycleType()==LevelOnePage::CTcycles ? 'C' : 'T') << Qt::endl;
|
||||
outStream << QString("CT,%1,%2").arg(document.subPage(p)->cycleValue()).arg(document.subPage(p)->cycleType()==LevelOnePage::CTcycles ? 'C' : 'T');
|
||||
else
|
||||
// X/28/0 specifies page function and coding but the PF command
|
||||
// should make it obvious to a human that this isn't a Level One Page
|
||||
outStream << QString("PF,%1,%2").arg(document.pageFunction()).arg(document.packetCoding()) << Qt::endl;
|
||||
outStream << QString("PF,%1,%2").arg(document.pageFunction()).arg(document.packetCoding());
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
||||
outStream << Qt::endl;
|
||||
#else
|
||||
outStream << endl;
|
||||
#endif
|
||||
|
||||
// FastText links
|
||||
bool writeFLCommand = false;
|
||||
if (document.pageFunction() == TeletextDocument::PFLevelOnePage && document.subPage(p)->packetNeeded(27,0)) {
|
||||
// Subpage has FastText links - if any link to a specific subpage, we need to write X/27/0 as raw
|
||||
@@ -285,7 +324,11 @@ void saveTTI(QSaveFile &file, const TeletextDocument &document)
|
||||
if (i<5)
|
||||
outStream << ',';
|
||||
}
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
||||
outStream << Qt::endl;
|
||||
#else
|
||||
outStream << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
subPageNumber++;
|
||||
|
||||
2
main.cpp
2
main.cpp
@@ -30,7 +30,7 @@ int main(int argc, char *argv[])
|
||||
QApplication::setApplicationDisplayName(QApplication::applicationName());
|
||||
QApplication::setOrganizationName("gkmac.co.uk");
|
||||
QApplication::setOrganizationDomain("gkmac.co.uk");
|
||||
QApplication::setApplicationVersion("0.1-alpha");
|
||||
QApplication::setApplicationVersion("0.2-alpha");
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription(QApplication::applicationName());
|
||||
parser.addHelpOption();
|
||||
|
||||
247
mainwidget.cpp
247
mainwidget.cpp
@@ -17,13 +17,18 @@
|
||||
* along with QTeletextMaker. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <QApplication>
|
||||
#include <QBitmap>
|
||||
#include <QClipboard>
|
||||
#include <QFrame>
|
||||
#include <QGraphicsItem>
|
||||
#include <QGraphicsItemGroup>
|
||||
#include <QGraphicsProxyWidget>
|
||||
#include <QGraphicsScene>
|
||||
#include <QGraphicsSceneEvent>
|
||||
#include <QKeyEvent>
|
||||
#include <QMenu>
|
||||
#include <QMimeData>
|
||||
#include <QPainter>
|
||||
#include <QPair>
|
||||
#include <QUndoCommand>
|
||||
@@ -50,7 +55,6 @@ TeletextWidget::TeletextWidget(QFrame *parent) : QFrame(parent)
|
||||
m_pageRender.setTeletextPage(m_levelOnePage);
|
||||
m_insertMode = false;
|
||||
m_selectionInProgress = false;
|
||||
m_grid = false;
|
||||
setFocusPolicy(Qt::StrongFocus);
|
||||
m_flashTiming = m_flashPhase = 0;
|
||||
connect(&m_pageRender, &TeletextPageRender::flashChanged, this, &TeletextWidget::updateFlashTimer);
|
||||
@@ -58,7 +62,6 @@ 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()
|
||||
@@ -109,13 +112,6 @@ void TeletextWidget::paintEvent(QPaintEvent *event)
|
||||
widgetPainter.drawPixmap(0, 0, *m_pageRender.pagePixmap(m_flashPhase), 864-m_pageRender.leftSidePanelColumns()*12, 0, m_pageRender.leftSidePanelColumns()*12, 250);
|
||||
if (m_pageRender.rightSidePanelColumns())
|
||||
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)
|
||||
@@ -161,14 +157,6 @@ void TeletextWidget::toggleMix(bool mixOn)
|
||||
update();
|
||||
}
|
||||
|
||||
void TeletextWidget::toggleGrid(bool gridOn)
|
||||
{
|
||||
m_grid = gridOn;
|
||||
m_pageRender.setGrid(gridOn);
|
||||
m_pageRender.renderPage();
|
||||
update();
|
||||
}
|
||||
|
||||
void TeletextWidget::setControlBit(int bitNumber, bool active)
|
||||
{
|
||||
m_levelOnePage->setControlBit(bitNumber, active);
|
||||
@@ -354,32 +342,27 @@ void TeletextWidget::keyPressEvent(QKeyEvent *event)
|
||||
break;
|
||||
|
||||
case Qt::Key_Up:
|
||||
m_teletextDocument->cursorUp();
|
||||
update();
|
||||
m_teletextDocument->cursorUp(event->modifiers() & Qt::ShiftModifier);
|
||||
break;
|
||||
case Qt::Key_Down:
|
||||
m_teletextDocument->cursorDown();
|
||||
update();
|
||||
m_teletextDocument->cursorDown(event->modifiers() & Qt::ShiftModifier);
|
||||
break;
|
||||
case Qt::Key_Left:
|
||||
m_teletextDocument->cursorLeft();
|
||||
update();
|
||||
m_teletextDocument->cursorLeft(event->modifiers() & Qt::ShiftModifier);
|
||||
break;
|
||||
case Qt::Key_Right:
|
||||
m_teletextDocument->cursorRight();
|
||||
update();
|
||||
m_teletextDocument->cursorRight(event->modifiers() & Qt::ShiftModifier);
|
||||
break;
|
||||
case Qt::Key_Return:
|
||||
case Qt::Key_Enter:
|
||||
m_teletextDocument->cursorDown();
|
||||
// fall through
|
||||
case Qt::Key_Home:
|
||||
m_teletextDocument->moveCursor(m_teletextDocument->cursorRow(), 0);
|
||||
update();
|
||||
break;
|
||||
case Qt::Key_Home:
|
||||
m_teletextDocument->moveCursor(m_teletextDocument->cursorRow(), 0, event->modifiers() & Qt::ShiftModifier);
|
||||
break;
|
||||
case Qt::Key_End:
|
||||
m_teletextDocument->moveCursor(m_teletextDocument->cursorRow(), 39);
|
||||
update();
|
||||
m_teletextDocument->moveCursor(m_teletextDocument->cursorRow(), 39, event->modifiers() & Qt::ShiftModifier);
|
||||
break;
|
||||
|
||||
case Qt::Key_PageUp:
|
||||
@@ -405,8 +388,62 @@ void TeletextWidget::setCharacter(unsigned char newCharacter)
|
||||
|
||||
void TeletextWidget::toggleCharacterBit(unsigned char bitToToggle)
|
||||
{
|
||||
QUndoCommand *toggleMosaicBitCommand = new ToggleMosaicBitCommand(m_teletextDocument, bitToToggle);
|
||||
m_teletextDocument->undoStack()->push(toggleMosaicBitCommand);
|
||||
m_teletextDocument->undoStack()->push(new ToggleMosaicBitCommand(m_teletextDocument, bitToToggle));
|
||||
}
|
||||
|
||||
void TeletextWidget::selectionToClipboard()
|
||||
{
|
||||
QByteArray nativeData;
|
||||
QString plainTextData;
|
||||
QClipboard *clipboard = QApplication::clipboard();
|
||||
|
||||
nativeData.resize(2 + m_teletextDocument->selectionWidth() * m_teletextDocument->selectionHeight());
|
||||
nativeData[0] = m_teletextDocument->selectionHeight();
|
||||
nativeData[1] = m_teletextDocument->selectionWidth();
|
||||
|
||||
plainTextData.reserve((m_teletextDocument->selectionWidth()+1) * m_teletextDocument->selectionHeight() - 1);
|
||||
|
||||
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);
|
||||
|
||||
if (m_teletextDocument->currentSubPage()->character(r, c) >= 0x20)
|
||||
plainTextData.append(keymapping[m_pageRender.level1CharSet(r, c)].key(m_teletextDocument->currentSubPage()->character(r, c), m_teletextDocument->currentSubPage()->character(r, c)));
|
||||
else
|
||||
plainTextData.append(' ');
|
||||
}
|
||||
|
||||
plainTextData.append('\n');
|
||||
}
|
||||
|
||||
QMimeData *mimeData = new QMimeData();
|
||||
mimeData->setData("application/x-teletext", nativeData);
|
||||
mimeData->setText(plainTextData);
|
||||
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, m_pageRender.level1CharSet(m_teletextDocument->cursorRow(), m_teletextDocument->cursorColumn())));
|
||||
}
|
||||
|
||||
QPair<int, int> TeletextWidget::mouseToRowAndColumn(const QPoint &mousePosition)
|
||||
@@ -438,25 +475,12 @@ 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;
|
||||
|
||||
if (position.first != m_teletextDocument->cursorRow() || position.second != m_teletextDocument->cursorColumn()) {
|
||||
if (!m_selectionInProgress) {
|
||||
m_selectionInProgress = true;
|
||||
if (m_teletextDocument->cursorRow() < position.first) {
|
||||
topRow = m_teletextDocument->cursorRow();
|
||||
bottomRow = position.first;
|
||||
} else {
|
||||
topRow = position.first;
|
||||
bottomRow = m_teletextDocument->cursorRow();
|
||||
m_teletextDocument->setSelectionCorner(m_teletextDocument->cursorRow(), m_teletextDocument->cursorColumn());
|
||||
}
|
||||
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);
|
||||
m_teletextDocument->moveCursor(position.first, position.second, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -480,7 +504,12 @@ void TeletextWidget::focusOutEvent(QFocusEvent *event)
|
||||
|
||||
LevelOneScene::LevelOneScene(QWidget *levelOneWidget, QObject *parent) : QGraphicsScene(parent)
|
||||
{
|
||||
m_grid = false;
|
||||
|
||||
// These dimensions are scratch, setBorderDimensions will get called straight away to adjust them
|
||||
setSceneRect(0, 0, 600, 288);
|
||||
|
||||
// Full screen colours
|
||||
m_fullScreenTopRectItem = new QGraphicsRectItem(0, 0, 600, 19);
|
||||
m_fullScreenTopRectItem->setPen(Qt::NoPen);
|
||||
m_fullScreenTopRectItem->setBrush(QBrush(QColor(0, 0, 0)));
|
||||
@@ -490,6 +519,7 @@ LevelOneScene::LevelOneScene(QWidget *levelOneWidget, QObject *parent) : QGraphi
|
||||
m_fullScreenBottomRectItem->setBrush(QBrush(QColor(0, 0, 0)));
|
||||
addItem(m_fullScreenBottomRectItem);
|
||||
|
||||
// Full row colours
|
||||
for (int r=0; r<25; r++) {
|
||||
m_fullRowLeftRectItem[r] = new QGraphicsRectItem(0, 19+r*10, 60, 10);
|
||||
m_fullRowLeftRectItem[r]->setPen(Qt::NoPen);
|
||||
@@ -501,16 +531,59 @@ LevelOneScene::LevelOneScene(QWidget *levelOneWidget, QObject *parent) : QGraphi
|
||||
addItem(m_fullRowRightRectItem[r]);
|
||||
}
|
||||
|
||||
// Main text widget
|
||||
m_levelOneProxyWidget = addWidget(levelOneWidget);
|
||||
m_levelOneProxyWidget->setPos(60, 19);
|
||||
m_levelOneProxyWidget->setAutoFillBackground(false);
|
||||
m_levelOneProxyWidget->setFocus();
|
||||
|
||||
// Selection
|
||||
m_selectionRectItem = new QGraphicsRectItem(0, 0, 12, 10);
|
||||
m_selectionRectItem->setVisible(false);
|
||||
m_selectionRectItem->setPen(QPen(QColor(192, 192, 192), 1, Qt::DashLine));
|
||||
m_selectionRectItem->setBrush(QBrush(QColor(255, 255, 255, 64)));
|
||||
addItem(m_selectionRectItem);
|
||||
|
||||
// Cursor
|
||||
m_cursorRectItem = new QGraphicsRectItem(0, 0, 12, 10);
|
||||
m_cursorRectItem->setPen(Qt::NoPen);
|
||||
m_cursorRectItem->setBrush(QBrush(QColor(128, 128, 128, 192)));
|
||||
addItem(m_cursorRectItem);
|
||||
|
||||
// Optional grid overlay for text widget
|
||||
m_mainGridItemGroup = new QGraphicsItemGroup;
|
||||
m_mainGridItemGroup->setVisible(false);
|
||||
addItem(m_mainGridItemGroup);
|
||||
// Additional vertical pieces of grid for side panels
|
||||
for (int i=0; i<32; i++) {
|
||||
m_sidePanelGridNeeded[i] = false;
|
||||
m_sidePanelGridItemGroup[i] = new QGraphicsItemGroup;
|
||||
m_sidePanelGridItemGroup[i]->setVisible(false);
|
||||
addItem(m_sidePanelGridItemGroup[i]);
|
||||
}
|
||||
for (int r=1; r<25; r++) {
|
||||
for (int c=0; c<40; c++) {
|
||||
QGraphicsRectItem *gridPiece = new QGraphicsRectItem(c*12, r*10, 12, 10);
|
||||
gridPiece->setPen(QPen(QBrush(QColor(128, 128, 128, r<24 ? 192 : 128)), 0));
|
||||
m_mainGridItemGroup->addToGroup(gridPiece);
|
||||
}
|
||||
|
||||
if (r < 24)
|
||||
for (int c=0; c<32; c++) {
|
||||
QGraphicsRectItem *gridPiece = new QGraphicsRectItem(0, r*10, 12, 10);
|
||||
gridPiece->setPen(QPen(QBrush(QColor(128, 128, 128, 64)), 0));
|
||||
m_sidePanelGridItemGroup[c]->addToGroup(gridPiece);
|
||||
}
|
||||
}
|
||||
|
||||
installEventFilter(this);
|
||||
}
|
||||
|
||||
void LevelOneScene::setDimensions(int sceneWidth, int sceneHeight, int widgetWidth)
|
||||
void LevelOneScene::setBorderDimensions(int sceneWidth, int sceneHeight, int widgetWidth, int leftSidePanelColumns, int rightSidePanelColumns)
|
||||
{
|
||||
setSceneRect(0, 0, sceneWidth, sceneHeight);
|
||||
|
||||
// Assume widget height is always 250
|
||||
// Assume text widget height is always 250
|
||||
int topBottomBorders = (sceneHeight-250) / 2;
|
||||
// Ideally we'd use m_levelOneProxyWidget->size() to discover the widget width ourselves
|
||||
// but this causes a stubborn segfault, so we have to receive the widgetWidth as a parameter
|
||||
@@ -518,15 +591,85 @@ void LevelOneScene::setDimensions(int sceneWidth, int sceneHeight, int widgetWid
|
||||
|
||||
m_levelOneProxyWidget->setPos(leftRightBorders, topBottomBorders);
|
||||
|
||||
// Position grid to cover central 40 columns
|
||||
m_mainGridItemGroup->setPos(leftRightBorders + leftSidePanelColumns*12, topBottomBorders);
|
||||
|
||||
updateCursor();
|
||||
updateSelection();
|
||||
|
||||
// Grid for right side panel
|
||||
for (int c=0; c<16; c++)
|
||||
if (rightSidePanelColumns > c) {
|
||||
m_sidePanelGridItemGroup[c]->setPos(leftRightBorders + leftSidePanelColumns*12 + 480 + c*12, topBottomBorders);
|
||||
m_sidePanelGridItemGroup[c]->setVisible(m_grid);
|
||||
m_sidePanelGridNeeded[c] = true;
|
||||
} else {
|
||||
m_sidePanelGridItemGroup[c]->setVisible(false);
|
||||
m_sidePanelGridNeeded[c] = false;
|
||||
}
|
||||
// Grid for left side panel
|
||||
for (int c=0; c<16; c++)
|
||||
if (c < leftSidePanelColumns) {
|
||||
m_sidePanelGridItemGroup[31-c]->setPos(leftRightBorders + (leftSidePanelColumns-c-1)*12, topBottomBorders);
|
||||
m_sidePanelGridItemGroup[31-c]->setVisible(m_grid);
|
||||
m_sidePanelGridNeeded[31-c] = true;
|
||||
} else {
|
||||
m_sidePanelGridItemGroup[31-c]->setVisible(false);
|
||||
m_sidePanelGridNeeded[31-c] = false;
|
||||
}
|
||||
|
||||
// Full screen colours
|
||||
m_fullScreenTopRectItem->setRect(0, 0, sceneWidth, topBottomBorders);
|
||||
m_fullScreenBottomRectItem->setRect(0, 250+topBottomBorders, sceneWidth, topBottomBorders);
|
||||
|
||||
// Full row colours
|
||||
for (int r=0; r<25; r++) {
|
||||
m_fullRowLeftRectItem[r]->setRect(0, topBottomBorders+r*10, leftRightBorders+1, 10);
|
||||
m_fullRowRightRectItem[r]->setRect(sceneWidth-leftRightBorders-1, topBottomBorders+r*10, leftRightBorders+1, 10);
|
||||
}
|
||||
}
|
||||
|
||||
void LevelOneScene::updateCursor()
|
||||
{
|
||||
m_cursorRectItem->setPos(m_mainGridItemGroup->pos().x() + static_cast<TeletextWidget *>(m_levelOneProxyWidget->widget())->document()->cursorColumn()*12, m_mainGridItemGroup->pos().y() + static_cast<TeletextWidget *>(m_levelOneProxyWidget->widget())->document()->cursorRow()*10);
|
||||
}
|
||||
|
||||
void LevelOneScene::updateSelection()
|
||||
{
|
||||
if (!static_cast<TeletextWidget *>(m_levelOneProxyWidget->widget())->document()->selectionActive()) {
|
||||
m_selectionRectItem->setVisible(false);
|
||||
return;
|
||||
}
|
||||
|
||||
m_selectionRectItem->setRect(m_mainGridItemGroup->pos().x() + static_cast<TeletextWidget *>(m_levelOneProxyWidget->widget())->document()->selectionLeftColumn()*12, m_mainGridItemGroup->pos().y() + static_cast<TeletextWidget *>(m_levelOneProxyWidget->widget())->document()->selectionTopRow()*10, static_cast<TeletextWidget *>(m_levelOneProxyWidget->widget())->document()->selectionWidth()*12-1, static_cast<TeletextWidget *>(m_levelOneProxyWidget->widget())->document()->selectionHeight()*10-1);
|
||||
|
||||
m_selectionRectItem->setVisible(true);
|
||||
}
|
||||
|
||||
void LevelOneScene::toggleGrid(bool gridOn)
|
||||
{
|
||||
m_grid = gridOn;
|
||||
m_mainGridItemGroup->setVisible(gridOn);
|
||||
for (int i=0; i<32; i++)
|
||||
if (m_sidePanelGridNeeded[i])
|
||||
m_sidePanelGridItemGroup[i]->setVisible(gridOn);
|
||||
}
|
||||
|
||||
bool LevelOneScene::eventFilter(QObject *object, QEvent *event)
|
||||
{
|
||||
Q_UNUSED(object);
|
||||
|
||||
if (event->type() == QEvent::GraphicsSceneWheel && static_cast<QGraphicsSceneWheelEvent *>(event)->modifiers() == Qt::ControlModifier) {
|
||||
if (static_cast<QGraphicsSceneWheelEvent *>(event)->delta() > 0)
|
||||
emit mouseZoomIn();
|
||||
else if (static_cast<QGraphicsSceneWheelEvent *>(event)->delta() < 0)
|
||||
emit mouseZoomOut();
|
||||
|
||||
event->accept();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void LevelOneScene::setFullScreenColour(const QColor &newColor)
|
||||
{
|
||||
m_fullScreenTopRectItem->setBrush(QBrush(newColor));
|
||||
|
||||
27
mainwidget.h
27
mainwidget.h
@@ -22,6 +22,7 @@
|
||||
|
||||
#include <QBasicTimer>
|
||||
#include <QFrame>
|
||||
#include <QGraphicsItemGroup>
|
||||
#include <QGraphicsProxyWidget>
|
||||
#include <QGraphicsScene>
|
||||
#include <QPair>
|
||||
@@ -62,7 +63,6 @@ public slots:
|
||||
void refreshPage();
|
||||
void toggleReveal(bool);
|
||||
void toggleMix(bool);
|
||||
void toggleGrid(bool);
|
||||
void updateFlashTimer(int);
|
||||
void refreshRow(int);
|
||||
|
||||
@@ -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:
|
||||
@@ -91,13 +96,12 @@ protected:
|
||||
private:
|
||||
TeletextDocument* m_teletextDocument;
|
||||
LevelOnePage* m_levelOnePage;
|
||||
bool m_insertMode, m_grid, m_selectionInProgress;
|
||||
bool m_insertMode, m_selectionInProgress;
|
||||
QBasicTimer m_flashTimer;
|
||||
int m_flashTiming, m_flashPhase;
|
||||
|
||||
void timerEvent(QTimerEvent *event) override;
|
||||
|
||||
void calculateDimensions();
|
||||
void selectionToClipboard();
|
||||
|
||||
QPair<int, int> mouseToRowAndColumn(const QPoint &);
|
||||
};
|
||||
@@ -108,16 +112,29 @@ class LevelOneScene : public QGraphicsScene
|
||||
|
||||
public:
|
||||
LevelOneScene(QWidget *, QObject *parent = nullptr);
|
||||
void setDimensions(int, int, int);
|
||||
void setBorderDimensions(int, int, int, int, int);
|
||||
QGraphicsRectItem *cursorRectItem() const { return m_cursorRectItem; }
|
||||
|
||||
public slots:
|
||||
void updateCursor();
|
||||
void updateSelection();
|
||||
void toggleGrid(bool);
|
||||
void setFullScreenColour(const QColor &);
|
||||
void setFullRowColour(int, const QColor &);
|
||||
|
||||
signals:
|
||||
void mouseZoomIn();
|
||||
void mouseZoomOut();
|
||||
|
||||
private:
|
||||
bool eventFilter(QObject *, QEvent *);
|
||||
|
||||
QGraphicsRectItem *m_fullScreenTopRectItem, *m_fullScreenBottomRectItem;
|
||||
QGraphicsRectItem *m_fullRowLeftRectItem[25], *m_fullRowRightRectItem[25];
|
||||
QGraphicsProxyWidget *m_levelOneProxyWidget;
|
||||
QGraphicsRectItem *m_cursorRectItem, *m_selectionRectItem;
|
||||
QGraphicsItemGroup *m_mainGridItemGroup, *m_sidePanelGridItemGroup[32];
|
||||
bool m_grid, m_sidePanelGridNeeded[32];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -132,12 +132,12 @@ void MainWindow::exportEditTF()
|
||||
|
||||
void MainWindow::about()
|
||||
{
|
||||
QMessageBox::about(this, tr("About QTeletextMaker"), tr("<b>QTeletextMaker</b><br>"
|
||||
QMessageBox::about(this, tr("About"), QString("<b>%1</b><br>"
|
||||
"An open source Level 2.5 teletext page editor.<br>"
|
||||
"<i>Version 0.1-alpha</i><br><br>"
|
||||
"<i>Version %2</i><br><br>"
|
||||
"Copyright (C) 2020, 2021 Gavin MacGregor<br><br>"
|
||||
"Released under the GNU General Public License version 3<br>"
|
||||
"<a href=\"https://github.com/gkthemac/qteletextmaker\">https://github.com/gkthemac/qteletextmaker</a>"));
|
||||
"<a href=\"https://github.com/gkthemac/qteletextmaker\">https://github.com/gkthemac/qteletextmaker</a>").arg(QApplication::applicationDisplayName()).arg(QApplication::applicationVersion()));
|
||||
}
|
||||
|
||||
void MainWindow::init()
|
||||
@@ -157,13 +157,13 @@ void MainWindow::init()
|
||||
m_paletteDockWidget = new PaletteDockWidget(m_textWidget);
|
||||
addDockWidget(Qt::RightDockWidgetArea, m_paletteDockWidget);
|
||||
|
||||
m_textScene = new LevelOneScene(m_textWidget, this);
|
||||
|
||||
createActions();
|
||||
createStatusBar();
|
||||
|
||||
readSettings();
|
||||
|
||||
m_textScene = new LevelOneScene(m_textWidget, this);
|
||||
|
||||
m_textView = new QGraphicsView(this);
|
||||
m_textView->setScene(m_textScene);
|
||||
m_textView->setRenderHints(QPainter::SmoothPixmapTransform);
|
||||
@@ -172,6 +172,7 @@ void MainWindow::init()
|
||||
setCentralWidget(m_textView);
|
||||
|
||||
connect(m_textWidget->document(), &TeletextDocument::cursorMoved, this, &MainWindow::updateCursorPosition);
|
||||
connect(m_textWidget->document(), &TeletextDocument::selectionMoved, m_textScene, &LevelOneScene::updateSelection);
|
||||
connect(m_textWidget->document()->undoStack(), &QUndoStack::cleanChanged, this, [=]() { setWindowModified(!m_textWidget->document()->undoStack()->isClean()); } );
|
||||
connect(m_textWidget->document(), &TeletextDocument::aboutToChangeSubPage, m_x26DockWidget, &X26DockWidget::unloadX26List);
|
||||
connect(m_textWidget->document(), &TeletextDocument::subPageSelected, this, &MainWindow::updatePageWidgets);
|
||||
@@ -180,12 +181,17 @@ void MainWindow::init()
|
||||
connect(m_textWidget->pageRender(), &TeletextPageRender::fullRowColourChanged, m_textScene, &LevelOneScene::setFullRowColour);
|
||||
connect(m_textWidget, &TeletextWidget::insertKeyPressed, this, &MainWindow::toggleInsertMode);
|
||||
|
||||
connect(m_textScene, &LevelOneScene::mouseZoomIn, this, &MainWindow::zoomIn);
|
||||
connect(m_textScene, &LevelOneScene::mouseZoomOut, this, &MainWindow::zoomOut);
|
||||
|
||||
QShortcut *blockShortCut = new QShortcut(QKeySequence(Qt::Key_Escape, Qt::Key_J), m_textView);
|
||||
connect(blockShortCut, &QShortcut::activated, [=]() { m_textWidget->setCharacter(0x7f); });
|
||||
|
||||
setUnifiedTitleAndToolBarOnMac(true);
|
||||
|
||||
updatePageWidgets();
|
||||
|
||||
m_textView->setFocus();
|
||||
}
|
||||
|
||||
void MainWindow::tile(const QMainWindow *previous)
|
||||
@@ -291,36 +297,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"));
|
||||
@@ -374,7 +377,7 @@ void MainWindow::createActions()
|
||||
gridAct->setCheckable(true);
|
||||
gridAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_G));
|
||||
gridAct->setStatusTip(tr("Toggle the text grid"));
|
||||
connect(gridAct, &QAction::toggled, m_textWidget, &TeletextWidget::toggleGrid);
|
||||
connect(gridAct, &QAction::toggled, m_textScene, &LevelOneScene::toggleGrid);
|
||||
|
||||
QAction *showCodesAct = viewMenu->addAction(tr("Show codes"));
|
||||
showCodesAct->setCheckable(true);
|
||||
@@ -568,7 +571,7 @@ void MainWindow::setSceneDimensions()
|
||||
else
|
||||
newSceneWidth = m_textWidget->width() + leftRightBorders[m_viewBorder]*2;
|
||||
|
||||
m_textScene->setDimensions(newSceneWidth, 250+topBottomBorders[m_viewBorder]*2, m_textWidget->width());
|
||||
m_textScene->setBorderDimensions(newSceneWidth, 250+topBottomBorders[m_viewBorder]*2, m_textWidget->width(), m_textWidget->pageRender()->leftSidePanelColumns(), m_textWidget->pageRender()->rightSidePanelColumns());
|
||||
m_textView->setTransform(QTransform((1+(float)m_viewZoom/2)*aspectRatioHorizontalScaling[m_viewAspectRatio], 0, 0, 1+(float)m_viewZoom/2, 0, 0));
|
||||
}
|
||||
|
||||
@@ -576,20 +579,17 @@ void MainWindow::insertRow(bool copyRow)
|
||||
{
|
||||
if (m_textWidget->document()->cursorRow() == 24)
|
||||
return;
|
||||
QUndoCommand *insertRowCommand = new InsertRowCommand(m_textWidget->document(), copyRow);
|
||||
m_textWidget->document()->undoStack()->push(insertRowCommand);
|
||||
m_textWidget->document()->undoStack()->push(new InsertRowCommand(m_textWidget->document(), copyRow));
|
||||
}
|
||||
|
||||
void MainWindow::deleteRow()
|
||||
{
|
||||
QUndoCommand *deleteRowCommand = new DeleteRowCommand(m_textWidget->document());
|
||||
m_textWidget->document()->undoStack()->push(deleteRowCommand);
|
||||
m_textWidget->document()->undoStack()->push(new DeleteRowCommand(m_textWidget->document()));
|
||||
}
|
||||
|
||||
void MainWindow::insertSubPage(bool afterCurrentSubPage, bool copyCurrentSubPage)
|
||||
{
|
||||
QUndoCommand *insertSubPageCommand = new InsertSubPageCommand(m_textWidget->document(), afterCurrentSubPage, copyCurrentSubPage);
|
||||
m_textWidget->document()->undoStack()->push(insertSubPageCommand);
|
||||
m_textWidget->document()->undoStack()->push(new InsertSubPageCommand(m_textWidget->document(), afterCurrentSubPage, copyCurrentSubPage));
|
||||
}
|
||||
|
||||
void MainWindow::deleteSubPage()
|
||||
@@ -926,6 +926,8 @@ MainWindow *MainWindow::findMainWindow(const QString &fileName) const
|
||||
void MainWindow::updateCursorPosition()
|
||||
{
|
||||
m_cursorPositionLabel->setText(QString("Row %1 Column %2").arg(m_textWidget->document()->cursorRow()).arg(m_textWidget->document()->cursorColumn()));
|
||||
m_textScene->updateCursor();
|
||||
m_textView->ensureVisible(m_textScene->cursorRectItem(), 16, 24);
|
||||
}
|
||||
|
||||
void MainWindow::updatePageWidgets()
|
||||
|
||||
@@ -32,6 +32,7 @@ class PageX26Base : public PageBase //: public QObject
|
||||
|
||||
public:
|
||||
QList<X26Triplet> *enhancements() { return &m_enhancements; };
|
||||
virtual int maxEnhancements() const =0;
|
||||
|
||||
protected:
|
||||
QByteArray packetFromEnhancementList(int) const;
|
||||
|
||||
@@ -108,14 +108,11 @@ void PaletteDockWidget::selectColour(int colourIndex)
|
||||
{
|
||||
const QColor newColour = QColorDialog::getColor(m_parentMainWidget->document()->currentSubPage()->CLUTtoQColor(colourIndex), this, "Select Colour");
|
||||
|
||||
if (newColour.isValid()) {
|
||||
QUndoCommand *setColourCommand = new SetColourCommand(m_parentMainWidget->document(), colourIndex, ((newColour.red() & 0xf0) << 4) | (newColour.green() & 0xf0) | ((newColour.blue() & 0xf0) >> 4));
|
||||
m_parentMainWidget->document()->undoStack()->push(setColourCommand);
|
||||
}
|
||||
if (newColour.isValid())
|
||||
m_parentMainWidget->document()->undoStack()->push(new SetColourCommand(m_parentMainWidget->document(), colourIndex, ((newColour.red() & 0xf0) << 4) | (newColour.green() & 0xf0) | ((newColour.blue() & 0xf0) >> 4)));
|
||||
}
|
||||
|
||||
void PaletteDockWidget::resetCLUT(int colourTable)
|
||||
{
|
||||
QUndoCommand *resetCLUTCommand = new ResetCLUTCommand(m_parentMainWidget->document(), colourTable);
|
||||
m_parentMainWidget->document()->undoStack()->push(resetCLUTCommand);
|
||||
m_parentMainWidget->document()->undoStack()->push(new ResetCLUTCommand(m_parentMainWidget->document(), colourTable));
|
||||
}
|
||||
|
||||
18
render.cpp
18
render.cpp
@@ -34,7 +34,7 @@ TeletextPageRender::TeletextPageRender()
|
||||
for (int i=0; i<6; i++)
|
||||
m_pagePixmap[i] = new QPixmap(864, 250);
|
||||
m_pagePixmap[0]->fill(Qt::transparent);
|
||||
m_grid = m_mix = m_reveal = m_showCodes = false;
|
||||
m_mix = m_reveal = m_showCodes = false;
|
||||
m_renderLevel = 0;
|
||||
m_flashRequired = 0;
|
||||
m_finalFullScreenColour = 0;
|
||||
@@ -92,7 +92,6 @@ void TeletextPageRender::setRenderLevel(int newRenderLevel)
|
||||
renderPage();
|
||||
}
|
||||
|
||||
void TeletextPageRender::setGrid(bool newGrid) { m_grid = newGrid; }
|
||||
void TeletextPageRender::setShowCodes(bool newShowCodes)
|
||||
{
|
||||
m_showCodes = newShowCodes;
|
||||
@@ -164,7 +163,7 @@ void TeletextPageRender::buildEnhanceMap(TextLayer *enhanceLayer, int tripletNum
|
||||
if ((x26Triplet->address() & 0x18) == 0x08) {
|
||||
// Local Object
|
||||
// Check if the pointer in the Invocation triplet is valid
|
||||
// Can't point to triplets 13-15; only 12 triplets per packet
|
||||
// Can't point to triplets 13-15; only triplets 0-12 per packet
|
||||
if ((x26Triplet->data() & 0x0f) > 12)
|
||||
break;
|
||||
int tripletPointer = ((x26Triplet->data() >> 4) | ((x26Triplet->address() & 1) << 3)) * 13 + (x26Triplet->data() & 0x0f);
|
||||
@@ -174,12 +173,15 @@ void TeletextPageRender::buildEnhanceMap(TextLayer *enhanceLayer, int tripletNum
|
||||
// Check if we're pointing to an actual Object Definition of the same type
|
||||
if ((x26Triplet->mode() | 0x04) != m_levelOnePage->enhancements()->at(tripletPointer).mode())
|
||||
break;
|
||||
// The Object Definition can't declare it's at triplet 13-15; only 12 triplets per packet
|
||||
// The Object Definition can't declare it's at triplet 13-15; only triplets 0-12 per packet
|
||||
if ((m_levelOnePage->enhancements()->at(tripletPointer).data() & 0x0f) > 12)
|
||||
break;
|
||||
// Check if the Object Definition triplet is where it declares it is
|
||||
if ((((m_levelOnePage->enhancements()->at(tripletPointer).data() >> 4) | ((m_levelOnePage->enhancements()->at(tripletPointer).address() & 1) << 3)) * 13 + (m_levelOnePage->enhancements()->at(tripletPointer).data() & 0x0f)) != tripletPointer)
|
||||
break;
|
||||
// Check if (sub)Object type can be invoked by Object type we're within
|
||||
if (enhanceLayer->objectType() >= (x26Triplet->mode() & 0x03))
|
||||
break;
|
||||
// Is the object required at the current presentation Level?
|
||||
if (m_renderLevel == 2 && (m_levelOnePage->enhancements()->at(tripletPointer).address() & 0x08) == 0x00)
|
||||
break;
|
||||
@@ -188,7 +190,7 @@ void TeletextPageRender::buildEnhanceMap(TextLayer *enhanceLayer, int tripletNum
|
||||
EnhanceLayer *newLayer = new EnhanceLayer;
|
||||
m_textLayer.push_back(newLayer);
|
||||
newLayer->setObjectType(x26Triplet->mode() & 0x03);
|
||||
newLayer->setOrigin(activePosition.row()+originModifierR, activePosition.column()+originModifierC);
|
||||
newLayer->setOrigin(enhanceLayer->originR() + activePosition.row() + originModifierR, enhanceLayer->originC() + activePosition.column() + originModifierC);
|
||||
buildEnhanceMap(newLayer, tripletPointer+1);
|
||||
} else
|
||||
qDebug("POP or GPOP");
|
||||
@@ -360,12 +362,6 @@ void TeletextPageRender::renderPage(int r)
|
||||
else
|
||||
pixmapPainter.drawRect(c*12, r*10+18, charWidth-1, 1);
|
||||
}
|
||||
|
||||
if (m_grid) {
|
||||
pixmapPainter.setPen(QColor(128, 128, 128, (c <= 39) ? 192 : 64));
|
||||
pixmapPainter.drawRect(c*12, r*10, 11, 9);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
pixmapPainter.begin(m_pagePixmap[0]);
|
||||
|
||||
7
render.h
7
render.h
@@ -107,6 +107,8 @@ public:
|
||||
virtual int fullRowColour(int) const =0;
|
||||
virtual bool fullRowDownwards(int) const =0;
|
||||
virtual int objectType() const =0;
|
||||
virtual int originR() const { return 0; };
|
||||
virtual int originC() const { return 0; };
|
||||
void setFullScreenColour(int);
|
||||
void setFullRowColour(int, int, bool);
|
||||
|
||||
@@ -131,6 +133,8 @@ public:
|
||||
int fullRowColour(int r) const { return m_layerFullRowColour[r]; };
|
||||
bool fullRowDownwards(int r) const { return m_layerFullRowDownwards[r]; };
|
||||
int objectType() const { return m_objectType; };
|
||||
int originR() const { return m_originR; };
|
||||
int originC() const { return m_originC; };
|
||||
void setObjectType(int);
|
||||
void setOrigin(int, int);
|
||||
|
||||
@@ -193,7 +197,6 @@ public:
|
||||
int level1CharSet(int r, int c) const { return m_cell[r][c].level1CharSet; };
|
||||
int leftSidePanelColumns() const { return m_leftSidePanelColumns; };
|
||||
int rightSidePanelColumns() const { return m_rightSidePanelColumns; };
|
||||
void setGrid(bool);
|
||||
|
||||
public slots:
|
||||
void setReveal(bool);
|
||||
@@ -217,7 +220,7 @@ protected:
|
||||
int m_finalFullScreenColour, m_renderLevel;
|
||||
QColor m_finalFullScreenQColor;
|
||||
int m_leftSidePanelColumns, m_rightSidePanelColumns;
|
||||
bool m_reveal, m_mix, m_grid, m_showCodes;
|
||||
bool m_reveal, m_mix, m_showCodes;
|
||||
Level1Layer m_level1Layer;
|
||||
std::vector<TextLayer *> m_textLayer;
|
||||
const int m_foregroundRemap[8] = { 0, 0, 0, 8, 8, 16, 16, 16 };
|
||||
|
||||
@@ -799,6 +799,9 @@ bool X26Model::insertRows(int row, int count, const QModelIndex &parent)
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
|
||||
if (m_parentMainWidget->document()->currentSubPage()->enhancements()->size() + count > m_parentMainWidget->document()->currentSubPage()->maxEnhancements())
|
||||
return false;
|
||||
|
||||
m_parentMainWidget->document()->undoStack()->push(new InsertTripletCommand(m_parentMainWidget->document(), this, row, count, m_parentMainWidget->document()->currentSubPage()->enhancements()->at(row)));
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user