Untangle hashstring exporting into loadsave
This commit is contained in:
@@ -414,71 +414,6 @@ void LevelOnePage::loadPagePacket(QByteArray &inLine)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int LevelOnePage::controlBitsToPS() const
|
|
||||||
{
|
|
||||||
//TODO map page language for regions other than 0
|
|
||||||
int pageStatus = 0x8000 | (controlBit(PageBase::C4ErasePage) << 14) | ((m_defaultNOS & 1) << 9) | ((m_defaultNOS & 2) << 7) | ((m_defaultNOS & 4) << 5);
|
|
||||||
for (int i=C5Newsflash; i<=C11SerialMagazine; i++)
|
|
||||||
pageStatus |= controlBit(i) << (i-1);
|
|
||||||
return pageStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString LevelOnePage::exportURLHash(QString pageHash)
|
|
||||||
{
|
|
||||||
int hashDigits[1167]={0};
|
|
||||||
int totalBits, charBit;
|
|
||||||
const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
||||||
|
|
||||||
//TODO deal with "black text allowed"
|
|
||||||
pageHash.append(QString("#%1:").arg(m_defaultNOS, 1, 16));
|
|
||||||
for (int r=0; r<25; r++)
|
|
||||||
for (int c=0; c<40; c++)
|
|
||||||
for (int b=0; b<7; b++) {
|
|
||||||
totalBits = (r * 40 + c) * 7 + b;
|
|
||||||
charBit = ((m_level1Page[r][c]) >> (6 - b)) & 0x01;
|
|
||||||
hashDigits[totalBits / 6] |= charBit << (5 - (totalBits % 6));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i=0; i<1167; i++)
|
|
||||||
pageHash.append(base64[hashDigits[i]]);
|
|
||||||
|
|
||||||
if (packetNeeded(28,0) || packetNeeded(28,4)) {
|
|
||||||
QString x28StringBegin, x28StringEnd;
|
|
||||||
|
|
||||||
x28StringBegin.append(QString("00%1").arg((m_defaultCharSet << 3) | m_defaultNOS, 2, 16, QChar('0')).toUpper());
|
|
||||||
x28StringBegin.append(QString("%1").arg((m_secondCharSet << 3) | m_secondNOS, 2, 16, QChar('0')).toUpper());
|
|
||||||
x28StringBegin.append(QString("%1%2%3%4").arg(m_leftSidePanelDisplayed, 1, 10).arg(m_rightSidePanelDisplayed, 1, 10).arg(m_sidePanelStatusL25, 1, 10).arg(m_sidePanelColumns, 1, 16));
|
|
||||||
|
|
||||||
x28StringEnd = QString("%1%2%3%4").arg(m_defaultScreenColour, 2, 16, QChar('0')).arg(m_defaultRowColour, 2, 16, QChar('0')).arg(m_blackBackgroundSubst, 1, 10).arg(m_colourTableRemap, 1, 10);
|
|
||||||
|
|
||||||
if (packetNeeded(28,0)) {
|
|
||||||
pageHash.append(":X280=");
|
|
||||||
pageHash.append(x28StringBegin);
|
|
||||||
pageHash.append(colourHash(1));
|
|
||||||
pageHash.append(x28StringEnd);
|
|
||||||
}
|
|
||||||
if (packetNeeded(28,4)) {
|
|
||||||
pageHash.append(":X284=");
|
|
||||||
pageHash.append(x28StringBegin);
|
|
||||||
pageHash.append(colourHash(0));
|
|
||||||
pageHash.append(x28StringEnd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!localEnhance.isEmpty()) {
|
|
||||||
pageHash.append(":X26=");
|
|
||||||
for (int i=0; i<localEnhance.size(); i++) {
|
|
||||||
pageHash.append(base64[localEnhance.at(i).data() >> 1]);
|
|
||||||
pageHash.append(base64[localEnhance.at(i).mode() | ((localEnhance.at(i).data() & 1) << 5)]);
|
|
||||||
pageHash.append(base64[localEnhance.at(i).address()]);
|
|
||||||
}
|
|
||||||
//TODO need to add one or more terminators to X26
|
|
||||||
}
|
|
||||||
//TODO check if 0x8000 | is needed for zxnet
|
|
||||||
pageHash.append(QString(":PS=%1").arg(0x8000 | controlBitsToPS(), 0, 16, QChar('0')));
|
|
||||||
return pageHash;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* void LevelOnePage::setSubPageNumber(int newSubPageNumber) { m_subPageNumber = newSubPageNumber; } */
|
/* void LevelOnePage::setSubPageNumber(int newSubPageNumber) { m_subPageNumber = newSubPageNumber; } */
|
||||||
void LevelOnePage::setCycleValue(int newValue) { m_cycleValue = newValue; };
|
void LevelOnePage::setCycleValue(int newValue) { m_cycleValue = newValue; };
|
||||||
void LevelOnePage::setCycleType(CycleTypeEnum newType) { m_cycleType = newType; }
|
void LevelOnePage::setCycleType(CycleTypeEnum newType) { m_cycleType = newType; }
|
||||||
|
|||||||
@@ -104,9 +104,6 @@ public:
|
|||||||
QString colourHash(int);
|
QString colourHash(int);
|
||||||
QList<X26Triplet> localEnhance;
|
QList<X26Triplet> localEnhance;
|
||||||
|
|
||||||
protected:
|
|
||||||
int controlBitsToPS() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned char m_level1Page[25][40];
|
unsigned char m_level1Page[25][40];
|
||||||
/* int m_subPageNumber; */
|
/* int m_subPageNumber; */
|
||||||
|
|||||||
84
loadsave.cpp
84
loadsave.cpp
@@ -24,6 +24,7 @@
|
|||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
#include "document.h"
|
#include "document.h"
|
||||||
|
#include "levelonepage.h"
|
||||||
#include "pagebase.h"
|
#include "pagebase.h"
|
||||||
|
|
||||||
// Used by TTI and hashstring
|
// Used by TTI and hashstring
|
||||||
@@ -157,3 +158,86 @@ void saveTTI(QSaveFile &file, const TeletextDocument &document)
|
|||||||
subPageNumber++;
|
subPageNumber++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QByteArray rowPacketAlways(PageBase *subPage, int packetNumber)
|
||||||
|
{
|
||||||
|
if (subPage->packetNeeded(packetNumber))
|
||||||
|
return subPage->packet(packetNumber);
|
||||||
|
else
|
||||||
|
return QByteArray(40, ' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
QString exportHashStringPage(LevelOnePage *subPage)
|
||||||
|
{
|
||||||
|
int hashDigits[1167]={0};
|
||||||
|
int totalBits, charBit;
|
||||||
|
const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
||||||
|
QString hashString;
|
||||||
|
|
||||||
|
// TODO int editTFCharacterSet = 5;
|
||||||
|
bool blackForeground = false;
|
||||||
|
|
||||||
|
for (int r=0; r<25; r++) {
|
||||||
|
QByteArray rowPacket = rowPacketAlways(subPage, r);
|
||||||
|
for (int c=0; c<40; c++) {
|
||||||
|
if (rowPacket.at(c) == 0x00 || rowPacket.at(c) == 0x10)
|
||||||
|
blackForeground = true;
|
||||||
|
for (int b=0; b<7; b++) {
|
||||||
|
totalBits = (r * 40 + c) * 7 + b;
|
||||||
|
charBit = ((rowPacket.at(c)) >> (6 - b)) & 0x01;
|
||||||
|
hashDigits[totalBits / 6] |= charBit << (5 - (totalBits % 6));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hashString.append(QString("#%1:").arg(blackForeground ? 8 : 0, 1, 16));
|
||||||
|
|
||||||
|
for (int i=0; i<1167; i++)
|
||||||
|
hashString.append(base64[hashDigits[i]]);
|
||||||
|
|
||||||
|
return hashString;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString exportHashStringPackets(LevelOnePage *subPage)
|
||||||
|
{
|
||||||
|
auto colourToHexString=[&](int whichCLUT)
|
||||||
|
{
|
||||||
|
QString resultHexString;
|
||||||
|
|
||||||
|
for (int i=whichCLUT*8; i<whichCLUT*8+8; i++)
|
||||||
|
resultHexString.append(QString("%1").arg(subPage->CLUT(i), 3, 16, QChar('0')));
|
||||||
|
return resultHexString;
|
||||||
|
};
|
||||||
|
|
||||||
|
const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
||||||
|
QString result;
|
||||||
|
|
||||||
|
if (subPage->packetNeeded(28,0) || subPage->packetNeeded(28,4)) {
|
||||||
|
// X/28/0 and X/28/4 are duplicates apart from the CLUT definitions
|
||||||
|
// Assemble the duplicate beginning and ending of both packets
|
||||||
|
QString x28StringBegin, x28StringEnd;
|
||||||
|
|
||||||
|
x28StringBegin.append(QString("00%1").arg((subPage->defaultCharSet() << 3) | subPage->defaultNOS(), 2, 16, QChar('0')).toUpper());
|
||||||
|
x28StringBegin.append(QString("%1").arg((subPage->secondCharSet() << 3) | subPage->secondNOS(), 2, 16, QChar('0')).toUpper());
|
||||||
|
x28StringBegin.append(QString("%1%2%3%4").arg(subPage->leftSidePanelDisplayed(), 1, 10).arg(subPage->rightSidePanelDisplayed(), 1, 10).arg(subPage->sidePanelStatusL25(), 1, 10).arg(subPage->sidePanelColumns(), 1, 16));
|
||||||
|
|
||||||
|
x28StringEnd = QString("%1%2%3%4").arg(subPage->defaultScreenColour(), 2, 16, QChar('0')).arg(subPage->defaultRowColour(), 2, 16, QChar('0')).arg(subPage->blackBackgroundSubst(), 1, 10).arg(subPage->colourTableRemap(), 1, 10);
|
||||||
|
|
||||||
|
if (subPage->packetNeeded(28,0))
|
||||||
|
result.append(":X280=" + x28StringBegin + colourToHexString(2) + colourToHexString(3) + x28StringEnd);
|
||||||
|
if (subPage->packetNeeded(28,4))
|
||||||
|
result.append(":X284=" + x28StringBegin + colourToHexString(0) + colourToHexString(1) + x28StringEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!subPage->localEnhance.isEmpty()) {
|
||||||
|
result.append(":X26=");
|
||||||
|
for (int i=0; i<subPage->localEnhance.size(); i++) {
|
||||||
|
result.append(base64[subPage->localEnhance.at(i).data() >> 1]);
|
||||||
|
result.append(base64[subPage->localEnhance.at(i).mode() | ((subPage->localEnhance.at(i).data() & 1) << 5)]);
|
||||||
|
result.append(base64[subPage->localEnhance.at(i).address()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.append(QString(":PS=%1").arg(0x8000 | controlBitsToPS(subPage), 0, 16, QChar('0')));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|||||||
@@ -25,10 +25,16 @@
|
|||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
#include "document.h"
|
#include "document.h"
|
||||||
|
#include "levelonepage.h"
|
||||||
#include "pagebase.h"
|
#include "pagebase.h"
|
||||||
|
|
||||||
int controlBitsToPS(PageBase *);
|
int controlBitsToPS(PageBase *);
|
||||||
|
|
||||||
void saveTTI(QSaveFile &, const TeletextDocument &);
|
void saveTTI(QSaveFile &, const TeletextDocument &);
|
||||||
|
|
||||||
|
QByteArray rowPcketAlways(PageBase *, int);
|
||||||
|
|
||||||
|
QString exportHashStringPage(LevelOnePage *);
|
||||||
|
QString exportHashStringPackets(LevelOnePage *subPage);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -117,9 +117,14 @@ bool MainWindow::saveAs()
|
|||||||
return saveFile(fileName);
|
return saveFile(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::exportURL()
|
void MainWindow::exportZXNet()
|
||||||
{
|
{
|
||||||
QDesktopServices::openUrl(QUrl(m_textWidget->document()->currentSubPage()->exportURLHash("http://www.zxnet.co.uk/teletext/editor/")));
|
QDesktopServices::openUrl(QUrl("http://zxnet.co.uk/teletext/editor/" + exportHashStringPage(m_textWidget->document()->currentSubPage()) + exportHashStringPackets(m_textWidget->document()->currentSubPage())));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::exportEditTF()
|
||||||
|
{
|
||||||
|
QDesktopServices::openUrl(QUrl("http://edit.tf/" + exportHashStringPage(m_textWidget->document()->currentSubPage())));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::about()
|
void MainWindow::about()
|
||||||
@@ -239,9 +244,17 @@ void MainWindow::createActions()
|
|||||||
|
|
||||||
setRecentFilesVisible(MainWindow::hasRecentFiles());
|
setRecentFilesVisible(MainWindow::hasRecentFiles());
|
||||||
|
|
||||||
QAction *exportAct = fileMenu->addAction(tr("Export to zxnet.co.uk"));
|
QMenu *exportHashStringSubMenu = fileMenu->addMenu(tr("Export to online editor"));
|
||||||
exportAct->setStatusTip("Export URL to zxnet.co.uk online editor");
|
|
||||||
connect(exportAct, &QAction::triggered, this, &MainWindow::exportURL);
|
QAction *exportZXNetAct = exportHashStringSubMenu->addAction(tr("Open in zxnet.co.uk"));
|
||||||
|
exportZXNetAct->setStatusTip("Export and open page in zxnet.co.uk online editor");
|
||||||
|
connect(exportZXNetAct, &QAction::triggered, this, &MainWindow::exportZXNet);
|
||||||
|
|
||||||
|
QAction *exportEditTFAct = exportHashStringSubMenu->addAction(tr("Open in edit.tf"));
|
||||||
|
exportEditTFAct->setStatusTip("Export and open page in edit.tf online editor");
|
||||||
|
connect(exportEditTFAct, &QAction::triggered, this, &MainWindow::exportEditTF);
|
||||||
|
|
||||||
|
fileMenu->addSeparator();
|
||||||
|
|
||||||
QAction *closeAct = fileMenu->addAction(tr("&Close"), this, &QWidget::close);
|
QAction *closeAct = fileMenu->addAction(tr("&Close"), this, &QWidget::close);
|
||||||
closeAct->setShortcut(tr("Ctrl+W"));
|
closeAct->setShortcut(tr("Ctrl+W"));
|
||||||
|
|||||||
@@ -56,7 +56,8 @@ private slots:
|
|||||||
void open();
|
void open();
|
||||||
bool save();
|
bool save();
|
||||||
bool saveAs();
|
bool saveAs();
|
||||||
void exportURL();
|
void exportZXNet();
|
||||||
|
void exportEditTF();
|
||||||
void updateRecentFileActions();
|
void updateRecentFileActions();
|
||||||
void openRecentFile();
|
void openRecentFile();
|
||||||
void about();
|
void about();
|
||||||
|
|||||||
Reference in New Issue
Block a user