From 8675cef6c54836d1a9ccadec5d3e167e268c3e37 Mon Sep 17 00:00:00 2001 From: Gavin MacGregor Date: Tue, 27 May 2025 17:34:18 +0100 Subject: [PATCH] Load files into QList of PageBase objects A document is first loaded as a generic PageBase before being converted to level one pages afterwards. This is preparation for loading pages of other types such as DRCS and Public Object Pages. The latter will need further work as the non-TTI file loaders blindly assume X/1 to X/25 are 7-bit odd parity coded. This also reverts 0a1c018 putting back the copy constructor that allows a PageBase to be converted to a LevelOnePage. --- src/qteletextdecoder/levelonepage.cpp | 18 +++++++++ src/qteletextdecoder/levelonepage.h | 1 + src/qteletextmaker/document.cpp | 8 ++++ src/qteletextmaker/document.h | 1 + src/qteletextmaker/loadformats.cpp | 55 ++++++++++++++++----------- src/qteletextmaker/loadformats.h | 12 +++--- src/qteletextmaker/mainwindow.cpp | 4 +- 7 files changed, 69 insertions(+), 30 deletions(-) diff --git a/src/qteletextdecoder/levelonepage.cpp b/src/qteletextdecoder/levelonepage.cpp index 64ae634..a27d63a 100644 --- a/src/qteletextdecoder/levelonepage.cpp +++ b/src/qteletextdecoder/levelonepage.cpp @@ -33,6 +33,24 @@ LevelOnePage::LevelOnePage() clearPage(); } +LevelOnePage::LevelOnePage(const PageBase &other) +{ + m_enhancements.reserve(maxEnhancements()); + clearPage(); + + for (int y=0; y<26; y++) + if (other.packetExists(y)) + setPacket(y, other.packet(y)); + + for (int y=26; y<29; y++) + for (int d=0; d<16; d++) + if (other.packetExists(y, d)) + setPacket(y, d, other.packet(y, d)); + + for (int b=PageBase::C4ErasePage; b<=PageBase::C14NOS; b++) + setControlBit(b, other.controlBit(b)); +} + // So far we only call clearPage() once, within the constructor void LevelOnePage::clearPage() { diff --git a/src/qteletextdecoder/levelonepage.h b/src/qteletextdecoder/levelonepage.h index 67cc7f5..fddc04d 100644 --- a/src/qteletextdecoder/levelonepage.h +++ b/src/qteletextdecoder/levelonepage.h @@ -40,6 +40,7 @@ public: enum CycleTypeEnum { CTcycles, CTseconds }; LevelOnePage(); + LevelOnePage(const PageBase &other); PageFunctionEnum pageFunction() const override { return PFLevelOnePage; } PacketCodingEnum packetCoding() const override { return Coding7bit; } diff --git a/src/qteletextmaker/document.cpp b/src/qteletextmaker/document.cpp index 756b55f..f8865e7 100644 --- a/src/qteletextmaker/document.cpp +++ b/src/qteletextmaker/document.cpp @@ -187,6 +187,14 @@ void TeletextDocument::unDeleteSubPageFromRecycle(int subPage) m_recycleSubPages.removeLast(); } +void TeletextDocument::loadFromList(QList const &subPageList) +{ + *m_subPages[0] = subPageList.at(0); + + for (int i=1; i const &subPageList); void loadMetaData(QVariantHash const &metadata); int pageNumber() const { return m_pageNumber; } void setPageNumber(int pageNumber); diff --git a/src/qteletextmaker/loadformats.cpp b/src/qteletextmaker/loadformats.cpp index 43aea13..11f8e20 100644 --- a/src/qteletextmaker/loadformats.cpp +++ b/src/qteletextmaker/loadformats.cpp @@ -22,16 +22,16 @@ #include #include #include +#include #include #include #include -#include "document.h" #include "hamming.h" #include "levelonepage.h" #include "pagebase.h" -bool LoadTTIFormat::load(QFile *inFile, TeletextDocument *document, QVariantHash *metadata) +bool LoadTTIFormat::load(QFile *inFile, QList& subPages, QVariantHash *metadata) { m_warnings.clear(); m_error.clear(); @@ -42,7 +42,10 @@ bool LoadTTIFormat::load(QFile *inFile, TeletextDocument *document, QVariantHash bool firstSubPageAlreadyFound = false; bool pageBodyPacketsFound = false; - LevelOnePage* loadingPage = document->subPage(0); +// subPages.clear(); + subPages.append(PageBase { } ); + + PageBase* loadingPage = &subPages[0]; for (;;) { inLine = inFile->readLine(160).trimmed(); @@ -67,8 +70,8 @@ bool LoadTTIFormat::load(QFile *inFile, TeletextDocument *document, QVariantHash } else { // Subsequent PN command found; this assumes that PN is the first command of a new subpage currentSubPageNum++; - document->insertSubPage(document->numberOfSubPages(), false); - loadingPage = document->subPage(document->numberOfSubPages()-1); + subPages.append(PageBase { } ); + loadingPage = &subPages[subPages.size()-1]; } } /* if (lineType == "SC,") { @@ -208,7 +211,7 @@ bool LoadT42Format::readPacket() return m_inFile->read((char *)m_inLine, 42) == 42; } -bool LoadT42Format::load(QFile *inFile, TeletextDocument *document, QVariantHash *metadata) +bool LoadT42Format::load(QFile *inFile, QList& subPages, QVariantHash *metadata) { int readMagazineNumber, readPacketNumber; int foundMagazineNumber = -1; @@ -222,6 +225,11 @@ bool LoadT42Format::load(QFile *inFile, TeletextDocument *document, QVariantHash m_error.clear(); m_reExportWarning = false; +// subPages.clear(); + subPages.append(PageBase { }); + + PageBase* loadingPage = &subPages[0]; + for (;;) { if (!readPacket()) // Reached end of .t42 file, or less than 42 bytes left @@ -280,15 +288,15 @@ bool LoadT42Format::load(QFile *inFile, TeletextDocument *document, QVariantHash metadata->insert("pageNumber", (foundMagazineNumber << 8) | foundPageNumber); } - document->subPage(0)->setControlBit(PageBase::C4ErasePage, m_inLine[5] & 0x08); - document->subPage(0)->setControlBit(PageBase::C5Newsflash, m_inLine[7] & 0x04); - document->subPage(0)->setControlBit(PageBase::C6Subtitle, m_inLine[7] & 0x08); + loadingPage->setControlBit(PageBase::C4ErasePage, m_inLine[5] & 0x08); + loadingPage->setControlBit(PageBase::C5Newsflash, m_inLine[7] & 0x04); + loadingPage->setControlBit(PageBase::C6Subtitle, m_inLine[7] & 0x08); for (int i=0; i<4; i++) - document->subPage(0)->setControlBit(PageBase::C7SuppressHeader+i, m_inLine[8] & (1 << i)); - document->subPage(0)->setControlBit(PageBase::C11SerialMagazine, m_inLine[9] & 0x01); - document->subPage(0)->setControlBit(PageBase::C12NOS, m_inLine[9] & 0x08); - document->subPage(0)->setControlBit(PageBase::C13NOS, m_inLine[9] & 0x04); - document->subPage(0)->setControlBit(PageBase::C14NOS, m_inLine[9] & 0x02); + loadingPage->setControlBit(PageBase::C7SuppressHeader+i, m_inLine[8] & (1 << i)); + loadingPage->setControlBit(PageBase::C11SerialMagazine, m_inLine[9] & 0x01); + loadingPage->setControlBit(PageBase::C12NOS, m_inLine[9] & 0x08); + loadingPage->setControlBit(PageBase::C13NOS, m_inLine[9] & 0x04); + loadingPage->setControlBit(PageBase::C14NOS, m_inLine[9] & 0x02); // See if there's text in the header row bool headerText = false; @@ -304,7 +312,7 @@ bool LoadT42Format::load(QFile *inFile, TeletextDocument *document, QVariantHash for (int i=0; i<10; i++) m_inLine[i] = 0x20; - document->subPage(0)->setPacket(0, QByteArray((const char *)&m_inLine[2], 40)); + loadingPage->setPacket(0, QByteArray((const char *)&m_inLine[2], 40)); } continue; } @@ -327,7 +335,7 @@ bool LoadT42Format::load(QFile *inFile, TeletextDocument *document, QVariantHash for (int i=2; i<42; i++) // TODO - obey odd parity? m_inLine[i] &= 0x7f; - document->subPage(0)->setPacket(readPacketNumber, QByteArray((const char *)&m_inLine[2], 40)); + loadingPage->setPacket(readPacketNumber, QByteArray((const char *)&m_inLine[2], 40)); continue; } @@ -365,7 +373,7 @@ bool LoadT42Format::load(QFile *inFile, TeletextDocument *document, QVariantHash m_inLine[b+5] = 0x3; } } - document->subPage(0)->setPacket(readPacketNumber, readDesignationCode, QByteArray((const char *)&m_inLine[2], 40)); + loadingPage->setPacket(readPacketNumber, readDesignationCode, QByteArray((const char *)&m_inLine[2], 40)); continue; } @@ -415,7 +423,7 @@ bool LoadT42Format::load(QFile *inFile, TeletextDocument *document, QVariantHash m_inLine[b+2] = d >> 12; } } - document->subPage(0)->setPacket(readPacketNumber, readDesignationCode, QByteArray((const char *)&m_inLine[2], 40)); + loadingPage->setPacket(readPacketNumber, readDesignationCode, QByteArray((const char *)&m_inLine[2], 40)); } if (!firstPacket0Found) { @@ -451,7 +459,7 @@ bool LoadHTTFormat::readPacket() } -bool LoadEP1Format::load(QFile *inFile, TeletextDocument *document, QVariantHash *metadata) +bool LoadEP1Format::load(QFile *inFile, QList& subPages, QVariantHash *metadata) { m_warnings.clear(); m_error.clear(); @@ -460,7 +468,10 @@ bool LoadEP1Format::load(QFile *inFile, TeletextDocument *document, QVariantHash unsigned char inLine[42]; unsigned char numOfSubPages = 1; - LevelOnePage* loadingPage = document->subPage(0); +// subPages.clear(); + subPages.append(PageBase { } ); + + PageBase* loadingPage = &subPages[0]; for (;;) { // Read six bytes, will either be a header for a (sub)page @@ -564,8 +575,8 @@ bool LoadEP1Format::load(QFile *inFile, TeletextDocument *document, QVariantHash if (inFile->read((char *)inLine, 42) != 42) return false; - document->insertSubPage(document->numberOfSubPages(), false); - loadingPage = document->subPage(document->numberOfSubPages()-1); + subPages.append(PageBase { } ); + loadingPage = &subPages[subPages.size()-1]; } return true; } diff --git a/src/qteletextmaker/loadformats.h b/src/qteletextmaker/loadformats.h index 0bb2a62..dfad9cb 100644 --- a/src/qteletextmaker/loadformats.h +++ b/src/qteletextmaker/loadformats.h @@ -23,12 +23,11 @@ #include #include #include +#include #include #include #include -#include "document.h" -#include "levelonepage.h" #include "pagebase.h" class LoadFormat @@ -36,7 +35,7 @@ class LoadFormat public: virtual ~LoadFormat() {}; - virtual bool load(QFile *inFile, TeletextDocument *document, QVariantHash *metadata = nullptr) =0; + virtual bool load(QFile *inFile, QList &subPages, QVariantHash *metadata = nullptr) =0; virtual QString description() const =0; virtual QStringList extensions() const =0; @@ -46,7 +45,6 @@ public: bool reExportWarning() const { return m_reExportWarning; }; protected: - TeletextDocument const *m_document; QStringList m_warnings; QString m_error; bool m_reExportWarning = false; @@ -55,7 +53,7 @@ protected: class LoadTTIFormat : public LoadFormat { public: - bool load(QFile *inFile, TeletextDocument *document, QVariantHash *metadata = nullptr) override; + bool load(QFile *inFile, QList &subPages, QVariantHash *metadata = nullptr) override; QString description() const override { return QString("MRG Systems TTI"); }; QStringList extensions() const override { return QStringList { "tti", "ttix" }; }; @@ -64,7 +62,7 @@ public: class LoadT42Format : public LoadFormat { public: - bool load(QFile *inFile, TeletextDocument *document, QVariantHash *metadata = nullptr) override; + bool load(QFile *inFile, QList &subPages, QVariantHash *metadata = nullptr) override; QString description() const override { return QString("t42 packet stream"); }; QStringList extensions() const override { return QStringList { "t42" }; }; @@ -89,7 +87,7 @@ protected: class LoadEP1Format : public LoadFormat { public: - bool load(QFile *inFile, TeletextDocument *document, QVariantHash *metadata = nullptr) override; + bool load(QFile *inFile, QList &subPages, QVariantHash *metadata = nullptr) override; QString description() const override { return QString("Softel EP1"); }; QStringList extensions() const override { return QStringList { "ep1", "epx" }; }; diff --git a/src/qteletextmaker/mainwindow.cpp b/src/qteletextmaker/mainwindow.cpp index 0fef08c..9a9625c 100644 --- a/src/qteletextmaker/mainwindow.cpp +++ b/src/qteletextmaker/mainwindow.cpp @@ -1069,9 +1069,11 @@ void MainWindow::loadFile(const QString &fileName) QApplication::setOverrideCursor(Qt::WaitCursor); + QList subPages; QVariantHash metadata; - if (loadingFormat->load(&file, m_textWidget->document(), &metadata)) { + if (loadingFormat->load(&file, subPages, &metadata)) { + m_textWidget->document()->loadFromList(subPages); m_textWidget->document()->loadMetaData(metadata); if (m_saveFormats.isExportOnly(QFileInfo(file).suffix()))