Separate metadata loading
"Metadata" is data which is stored in a teletext file format but is not part of the page itself, such as DE description and CT cycle time in the TTI file format.
This commit is contained in:
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include <QAbstractListModel>
|
#include <QAbstractListModel>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
#include "document.h"
|
#include "document.h"
|
||||||
|
|
||||||
@@ -200,6 +201,39 @@ void TeletextDocument::unDeleteSubPageFromRecycle(int subPage)
|
|||||||
m_recycleSubPages.removeLast();
|
m_recycleSubPages.removeLast();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TeletextDocument::loadMetaData(QVariantHash const &metadata)
|
||||||
|
{
|
||||||
|
bool valueOk;
|
||||||
|
|
||||||
|
if (const QString description = metadata.value("description").toString(); !description.isEmpty())
|
||||||
|
m_description = description;
|
||||||
|
|
||||||
|
if (const int pageNumber = metadata.value("pageNumber").toInt(&valueOk); valueOk)
|
||||||
|
m_pageNumber = pageNumber;
|
||||||
|
|
||||||
|
if (metadata.value("fastextAbsolute").toBool()) {
|
||||||
|
const int magazineFlip = m_pageNumber & 0x700;
|
||||||
|
|
||||||
|
for (auto &subPage : m_subPages)
|
||||||
|
for (int i=0; i<6; i++)
|
||||||
|
subPage->setFastTextLinkPageNumber(i, subPage->fastTextLinkPageNumber(i) ^ magazineFlip);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i=0; i<numberOfSubPages(); i++) {
|
||||||
|
const QString subPageStr = QString("%1").arg(i, 3, QChar('0'));
|
||||||
|
|
||||||
|
if (int region = metadata.value("region" + subPageStr).toInt(&valueOk); valueOk)
|
||||||
|
subPage(i)->setDefaultCharSet(region);
|
||||||
|
if (int cycleValue = metadata.value("cycleValue" + subPageStr).toInt(&valueOk); valueOk)
|
||||||
|
subPage(i)->setCycleValue(cycleValue);
|
||||||
|
QChar cycleType = metadata.value("cycleType" + subPageStr).toChar();
|
||||||
|
if (cycleType == 'C')
|
||||||
|
subPage(i)->setCycleType(LevelOnePage::CTcycles);
|
||||||
|
else if (cycleType == 'T')
|
||||||
|
subPage(i)->setCycleType(LevelOnePage::CTseconds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TeletextDocument::setPageNumber(int pageNumber)
|
void TeletextDocument::setPageNumber(int pageNumber)
|
||||||
{
|
{
|
||||||
// If the magazine number was changed, we need to update the relative magazine numbers in FastText
|
// If the magazine number was changed, we need to update the relative magazine numbers in FastText
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QUndoStack>
|
#include <QUndoStack>
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
#include "levelonepage.h"
|
#include "levelonepage.h"
|
||||||
|
|
||||||
@@ -74,6 +75,7 @@ public:
|
|||||||
void deleteSubPage(int subPageToDelete);
|
void deleteSubPage(int subPageToDelete);
|
||||||
void deleteSubPageToRecycle(int subPageToRecycle);
|
void deleteSubPageToRecycle(int subPageToRecycle);
|
||||||
void unDeleteSubPageFromRecycle(int subPage);
|
void unDeleteSubPageFromRecycle(int subPage);
|
||||||
|
void loadMetaData(QVariantHash const &metadata);
|
||||||
int pageNumber() const { return m_pageNumber; }
|
int pageNumber() const { return m_pageNumber; }
|
||||||
void setPageNumber(int pageNumber);
|
void setPageNumber(int pageNumber);
|
||||||
void setPageNumberFromString(QString pageNumberString);
|
void setPageNumberFromString(QString pageNumberString);
|
||||||
|
|||||||
@@ -24,24 +24,23 @@
|
|||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QTextStream>
|
#include <QVariant>
|
||||||
|
|
||||||
#include "document.h"
|
#include "document.h"
|
||||||
#include "hamming.h"
|
#include "hamming.h"
|
||||||
#include "levelonepage.h"
|
#include "levelonepage.h"
|
||||||
#include "pagebase.h"
|
#include "pagebase.h"
|
||||||
|
|
||||||
bool LoadTTIFormat::load(QFile *inFile, TeletextDocument *document)
|
bool LoadTTIFormat::load(QFile *inFile, TeletextDocument *document, QVariantHash *metadata)
|
||||||
{
|
{
|
||||||
m_warnings.clear();
|
m_warnings.clear();
|
||||||
m_error.clear();
|
m_error.clear();
|
||||||
|
|
||||||
QByteArray inLine;
|
QByteArray inLine;
|
||||||
|
int pageNum = 0;
|
||||||
|
int currentSubPageNum = 0;
|
||||||
bool firstSubPageAlreadyFound = false;
|
bool firstSubPageAlreadyFound = false;
|
||||||
bool pageBodyPacketsFound = false;
|
bool pageBodyPacketsFound = false;
|
||||||
int cycleCommandsFound = 0;
|
|
||||||
int mostRecentCycleValue = -1;
|
|
||||||
LevelOnePage::CycleTypeEnum mostRecentCycleType;
|
|
||||||
|
|
||||||
LevelOnePage* loadingPage = document->subPage(0);
|
LevelOnePage* loadingPage = document->subPage(0);
|
||||||
|
|
||||||
@@ -49,17 +48,27 @@ bool LoadTTIFormat::load(QFile *inFile, TeletextDocument *document)
|
|||||||
inLine = inFile->readLine(160).trimmed();
|
inLine = inFile->readLine(160).trimmed();
|
||||||
if (inLine.isEmpty())
|
if (inLine.isEmpty())
|
||||||
break;
|
break;
|
||||||
if (inLine.startsWith("DE,"))
|
if (inLine.startsWith("DE,") && metadata != nullptr)
|
||||||
document->setDescription(QString(inLine.remove(0, 3)));
|
metadata->insert("description", QString(inLine.remove(0, 3)));
|
||||||
if (inLine.startsWith("PN,")) {
|
if (inLine.startsWith("PN,")) {
|
||||||
// When second and subsequent PN commands are found, firstSubPageAlreadyFound==true at this point
|
if (!firstSubPageAlreadyFound) {
|
||||||
// This assumes that PN is the first command of a new subpage...
|
// First PN command found, set the page number
|
||||||
if (firstSubPageAlreadyFound) {
|
bool valueOk;
|
||||||
|
|
||||||
|
if (int pageNumRead = inLine.mid(3, 3).toInt(&valueOk, 16); valueOk)
|
||||||
|
if (pageNumRead >= 0x100 && pageNumRead <= 0x8ff) {
|
||||||
|
// Keep page number: to check if page is xFF if we load M/29
|
||||||
|
pageNum = pageNumRead;
|
||||||
|
if (metadata != nullptr)
|
||||||
|
metadata->insert("pageNumber", pageNum);
|
||||||
|
}
|
||||||
|
|
||||||
|
firstSubPageAlreadyFound = true;
|
||||||
|
} else {
|
||||||
|
// Subsequent PN command found; this assumes that PN is the first command of a new subpage
|
||||||
|
currentSubPageNum++;
|
||||||
document->insertSubPage(document->numberOfSubPages(), false);
|
document->insertSubPage(document->numberOfSubPages(), false);
|
||||||
loadingPage = document->subPage(document->numberOfSubPages()-1);
|
loadingPage = document->subPage(document->numberOfSubPages()-1);
|
||||||
} else {
|
|
||||||
document->setPageNumberFromString(inLine.mid(3,3));
|
|
||||||
firstSubPageAlreadyFound = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* if (lineType == "SC,") {
|
/* if (lineType == "SC,") {
|
||||||
@@ -82,37 +91,34 @@ bool LoadTTIFormat::load(QFile *inFile, TeletextDocument *document)
|
|||||||
if (inLine.startsWith("RE,")) {
|
if (inLine.startsWith("RE,")) {
|
||||||
bool regionValueOk;
|
bool regionValueOk;
|
||||||
int regionValueRead = inLine.remove(0, 3).toInt(®ionValueOk);
|
int regionValueRead = inLine.remove(0, 3).toInt(®ionValueOk);
|
||||||
if (regionValueOk)
|
if (regionValueOk && metadata != nullptr)
|
||||||
loadingPage->setDefaultCharSet(regionValueRead);
|
metadata->insert(QString("region%1").arg(currentSubPageNum, 3, QChar('0')), regionValueRead);
|
||||||
}
|
}
|
||||||
if (inLine.startsWith("CT,") && (inLine.endsWith(",C") || inLine.endsWith(",T"))) {
|
if (inLine.startsWith("CT,") && (inLine.endsWith(",C") || inLine.endsWith(",T"))) {
|
||||||
bool cycleValueOk;
|
bool cycleValueOk;
|
||||||
int cycleValueRead = inLine.mid(3, inLine.size()-5).toInt(&cycleValueOk);
|
int cycleValueRead = inLine.mid(3, inLine.size()-5).toInt(&cycleValueOk);
|
||||||
if (cycleValueOk) {
|
if (cycleValueOk && metadata != nullptr) {
|
||||||
cycleCommandsFound++;
|
metadata->insert(QString("cycleValue%1").arg(currentSubPageNum, 3, QChar('0')), cycleValueRead);
|
||||||
// House-keep CT command values, in case it's the only one within multiple subpages
|
metadata->insert(QString("cycleType%1").arg(currentSubPageNum, 3, QChar('0')), inLine.at(inLine.size()-1));
|
||||||
mostRecentCycleValue = cycleValueRead;
|
|
||||||
loadingPage->setCycleValue(cycleValueRead);
|
|
||||||
mostRecentCycleType = inLine.endsWith("C") ? LevelOnePage::CTcycles : LevelOnePage::CTseconds;
|
|
||||||
loadingPage->setCycleType(mostRecentCycleType);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (inLine.startsWith("FL,")) {
|
if (inLine.startsWith("FL,")) {
|
||||||
bool fastTextLinkOk;
|
bool fastTextLinkOk;
|
||||||
int fastTextLinkRead;
|
int fastTextLinkRead;
|
||||||
QString flLine = QString(inLine.remove(0, 3));
|
QString flLine = QString(inLine.remove(0, 3));
|
||||||
if (flLine.count(',') == 5)
|
if (flLine.count(',') == 5) {
|
||||||
for (int i=0; i<6; i++) {
|
for (int i=0; i<6; i++) {
|
||||||
fastTextLinkRead = flLine.section(',', i, i).toInt(&fastTextLinkOk, 16);
|
fastTextLinkRead = flLine.section(',', i, i).toInt(&fastTextLinkOk, 16);
|
||||||
if (fastTextLinkOk) {
|
if (fastTextLinkOk) {
|
||||||
if (fastTextLinkRead == 0)
|
if (fastTextLinkRead == 0)
|
||||||
fastTextLinkRead = 0x8ff;
|
fastTextLinkRead = 0x8ff;
|
||||||
// Stored as page link with relative magazine number, convert from absolute page number that was read
|
else if (fastTextLinkRead >= 0x100 && fastTextLinkRead <= 0x8ff)
|
||||||
fastTextLinkRead ^= document->pageNumber() & 0x700;
|
|
||||||
fastTextLinkRead &= 0x7ff; // Fixes magazine 8 to 0
|
|
||||||
loadingPage->setFastTextLinkPageNumber(i, fastTextLinkRead);
|
loadingPage->setFastTextLinkPageNumber(i, fastTextLinkRead);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (metadata != nullptr)
|
||||||
|
metadata->insert(QString("fastextAbsolute"), true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (inLine.startsWith("OL,")) {
|
if (inLine.startsWith("OL,")) {
|
||||||
bool lineNumberOk;
|
bool lineNumberOk;
|
||||||
@@ -162,7 +168,7 @@ bool LoadTTIFormat::load(QFile *inFile, TeletextDocument *document)
|
|||||||
inLine[i] = inLine.at(i) & 0x3f;
|
inLine[i] = inLine.at(i) & 0x3f;
|
||||||
// Import M/29 whole-magazine packets as X/28 per-page packets
|
// Import M/29 whole-magazine packets as X/28 per-page packets
|
||||||
if (lineNumber == 29) {
|
if (lineNumber == 29) {
|
||||||
if ((document->pageNumber() & 0xff) != 0xff)
|
if ((pageNum & 0xff) != 0xff)
|
||||||
m_warnings.append(QString("M/29/%1 packet found, but page number was not xFF.").arg(designationCode));
|
m_warnings.append(QString("M/29/%1 packet found, but page number was not xFF.").arg(designationCode));
|
||||||
lineNumber = 28;
|
lineNumber = 28;
|
||||||
}
|
}
|
||||||
@@ -177,14 +183,6 @@ bool LoadTTIFormat::load(QFile *inFile, TeletextDocument *document)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there's more than one subpage but only one valid CT command was found, apply it to all subpages
|
|
||||||
// I don't know if this is correct
|
|
||||||
if (cycleCommandsFound == 1 && document->numberOfSubPages()>1)
|
|
||||||
for (int i=0; i<document->numberOfSubPages(); i++) {
|
|
||||||
document->subPage(i)->setCycleValue(mostRecentCycleValue);
|
|
||||||
document->subPage(i)->setCycleType(mostRecentCycleType);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,7 +192,7 @@ bool LoadT42Format::readPacket()
|
|||||||
return m_inFile->read((char *)m_inLine, 42) == 42;
|
return m_inFile->read((char *)m_inLine, 42) == 42;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LoadT42Format::load(QFile *inFile, TeletextDocument *document)
|
bool LoadT42Format::load(QFile *inFile, TeletextDocument *document, QVariantHash *metadata)
|
||||||
{
|
{
|
||||||
int readMagazineNumber, readPacketNumber;
|
int readMagazineNumber, readPacketNumber;
|
||||||
int foundMagazineNumber = -1;
|
int foundMagazineNumber = -1;
|
||||||
@@ -259,10 +257,12 @@ bool LoadT42Format::load(QFile *inFile, TeletextDocument *document)
|
|||||||
foundPageNumber = readPageNumber;
|
foundPageNumber = readPageNumber;
|
||||||
firstPacket0Found = true;
|
firstPacket0Found = true;
|
||||||
|
|
||||||
|
if (metadata != nullptr) {
|
||||||
if (foundMagazineNumber == 0)
|
if (foundMagazineNumber == 0)
|
||||||
document->setPageNumber(0x800 | foundPageNumber);
|
metadata->insert("pageNumber", 0x800 | foundPageNumber);
|
||||||
else
|
else
|
||||||
document->setPageNumber((foundMagazineNumber << 8) | foundPageNumber);
|
metadata->insert("pageNumber", (foundMagazineNumber << 8) | foundPageNumber);
|
||||||
|
}
|
||||||
|
|
||||||
document->subPage(0)->setControlBit(PageBase::C4ErasePage, m_inLine[5] & 0x08);
|
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::C5Newsflash, m_inLine[7] & 0x04);
|
||||||
@@ -435,7 +435,7 @@ bool LoadHTTFormat::readPacket()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool LoadEP1Format::load(QFile *inFile, TeletextDocument *document)
|
bool LoadEP1Format::load(QFile *inFile, TeletextDocument *document, QVariantHash *metadata)
|
||||||
{
|
{
|
||||||
m_warnings.clear();
|
m_warnings.clear();
|
||||||
m_error.clear();
|
m_error.clear();
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QTextStream>
|
#include <QVariant>
|
||||||
|
|
||||||
#include "document.h"
|
#include "document.h"
|
||||||
#include "levelonepage.h"
|
#include "levelonepage.h"
|
||||||
@@ -36,7 +36,7 @@ class LoadFormat
|
|||||||
public:
|
public:
|
||||||
virtual ~LoadFormat() {};
|
virtual ~LoadFormat() {};
|
||||||
|
|
||||||
virtual bool load(QFile *inFile, TeletextDocument *document) =0;
|
virtual bool load(QFile *inFile, TeletextDocument *document, QVariantHash *metadata = nullptr) =0;
|
||||||
|
|
||||||
virtual QString description() const =0;
|
virtual QString description() const =0;
|
||||||
virtual QStringList extensions() const =0;
|
virtual QStringList extensions() const =0;
|
||||||
@@ -55,7 +55,7 @@ protected:
|
|||||||
class LoadTTIFormat : public LoadFormat
|
class LoadTTIFormat : public LoadFormat
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool load(QFile *inFile, TeletextDocument *document) override;
|
bool load(QFile *inFile, TeletextDocument *document, QVariantHash *metadata = nullptr) override;
|
||||||
|
|
||||||
QString description() const override { return QString("MRG Systems TTI"); };
|
QString description() const override { return QString("MRG Systems TTI"); };
|
||||||
QStringList extensions() const override { return QStringList { "tti", "ttix" }; };
|
QStringList extensions() const override { return QStringList { "tti", "ttix" }; };
|
||||||
@@ -64,7 +64,7 @@ public:
|
|||||||
class LoadT42Format : public LoadFormat
|
class LoadT42Format : public LoadFormat
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool load(QFile *inFile, TeletextDocument *document) override;
|
bool load(QFile *inFile, TeletextDocument *document, QVariantHash *metadata = nullptr) override;
|
||||||
|
|
||||||
QString description() const override { return QString("t42 packet stream"); };
|
QString description() const override { return QString("t42 packet stream"); };
|
||||||
QStringList extensions() const override { return QStringList { "t42" }; };
|
QStringList extensions() const override { return QStringList { "t42" }; };
|
||||||
@@ -89,7 +89,7 @@ protected:
|
|||||||
class LoadEP1Format : public LoadFormat
|
class LoadEP1Format : public LoadFormat
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool load(QFile *inFile, TeletextDocument *document) override;
|
bool load(QFile *inFile, TeletextDocument *document, QVariantHash *metadata = nullptr) override;
|
||||||
|
|
||||||
QString description() const override { return QString("Softel EP1"); };
|
QString description() const override { return QString("Softel EP1"); };
|
||||||
QStringList extensions() const override { return QStringList { "ep1", "epx" }; };
|
QStringList extensions() const override { return QStringList { "ep1", "epx" }; };
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
#include <QStatusBar>
|
#include <QStatusBar>
|
||||||
#include <QToolBar>
|
#include <QToolBar>
|
||||||
#include <QToolButton>
|
#include <QToolButton>
|
||||||
|
#include <QVariant>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
@@ -1068,7 +1069,11 @@ void MainWindow::loadFile(const QString &fileName)
|
|||||||
|
|
||||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||||
|
|
||||||
if (loadingFormat->load(&file, m_textWidget->document())) {
|
QVariantHash metadata;
|
||||||
|
|
||||||
|
if (loadingFormat->load(&file, m_textWidget->document(), &metadata)) {
|
||||||
|
m_textWidget->document()->loadMetaData(metadata);
|
||||||
|
|
||||||
if (m_saveFormats.isExportOnly(QFileInfo(file).suffix()))
|
if (m_saveFormats.isExportOnly(QFileInfo(file).suffix()))
|
||||||
m_exportAutoFileName = fileName;
|
m_exportAutoFileName = fileName;
|
||||||
else
|
else
|
||||||
|
|||||||
Reference in New Issue
Block a user