diff --git a/loadsave.cpp b/loadsave.cpp index e5dee9e..04e4628 100644 --- a/loadsave.cpp +++ b/loadsave.cpp @@ -535,6 +535,58 @@ void saveTTI(QSaveFile &file, const TeletextDocument &document) } } +void exportM29File(QSaveFile &file, const TeletextDocument &document) +{ + const PageBase &subPage = *document.currentSubPage(); + QTextStream outStream(&file); + + auto writeM29Packet=[&](int designationCode) + { + if (subPage.packetExists(28, designationCode)) { + QByteArray outLine = subPage.packet(28, designationCode); + + outStream << QString("OL,29,"); + // TTI stores raw values with bit 6 set, doesn't do Hamming encoding + outLine[0] = designationCode | 0x40; + for (int c=1; c= 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 + + // Force page number to xFF + outStream << QString("PN,%1ff00").arg(document.pageNumber() >> 8, 1, 16); +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + outStream << Qt::endl; +#else + outStream << endl; +#endif + + outStream << "PS,8000"; +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + outStream << Qt::endl; +#else + outStream << endl; +#endif + + writeM29Packet(0); + writeM29Packet(1); + writeM29Packet(4); +} + void exportT42File(QSaveFile &file, const TeletextDocument &document) { const PageBase &subPage = *document.currentSubPage(); diff --git a/loadsave.h b/loadsave.h index 7b31206..c1d8a05 100644 --- a/loadsave.h +++ b/loadsave.h @@ -37,6 +37,7 @@ int controlBitsToPS(PageBase *); void saveTTI(QSaveFile &, const TeletextDocument &); void exportT42File(QSaveFile &, const TeletextDocument &); +void exportM29File(QSaveFile &, const TeletextDocument &); QByteArray rowPacketAlways(PageBase *, int); diff --git a/mainwindow.cpp b/mainwindow.cpp index 86e87b6..d01c126 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -353,6 +354,10 @@ void MainWindow::createActions() exportPNGAct->setStatusTip("Export a PNG image of this subpage"); connect(exportPNGAct, &QAction::triggered, this, &MainWindow::exportPNG); + QAction *exportM29Act = fileMenu->addAction(tr("Export subpage X/28 as M/29...")); + exportM29Act->setStatusTip("Export this subpage's X/28 packets as a tti file with M/29 packets"); + connect(exportM29Act, &QAction::triggered, this, &MainWindow::exportM29); + fileMenu->addSeparator(); QAction *closeAct = fileMenu->addAction(tr("&Close"), this, &QWidget::close); @@ -1031,6 +1036,57 @@ void MainWindow::exportT42() QMessageBox::warning(this, tr("QTeletextMaker"), errorMessage); } +void MainWindow::exportM29() +{ + QString errorMessage; + QString exportFileName = m_curFile; + + if (m_isUntitled || !QFileInfo(m_curFile).exists()) + exportFileName = QString("P%1FF.tti").arg(m_textWidget->document()->pageNumber() >> 8, 1, 16); + else { + exportFileName = QFileInfo(m_curFile).fileName(); + // Suggest a new filename to avoid clobbering the original file + if (QRegExp(("^[Pp]?[1-8][0-9A-Fa-f][0-9A-Fa-f]")).indexIn(exportFileName) != -1) { + // Page number forms start of file name, change it to xFF + if (exportFileName.at(0) == 'P' || exportFileName.at(0) == 'p') { + exportFileName[2] = 'F'; + exportFileName[3] = 'F'; + } else { + exportFileName[1] = 'F'; + exportFileName[2] = 'F'; + } + // No page number at start of file name. Try to insert "-m29" while preserving .tti(x) suffix + } else if (exportFileName.endsWith(".tti", Qt::CaseInsensitive)) { + exportFileName.chop(4); + exportFileName.append("-m29.tti"); + } else if (exportFileName.endsWith(".ttix", Qt::CaseInsensitive)) { + exportFileName.chop(5); + exportFileName.append("-m29.ttix"); + } else + // Shouldn't get here, bit of a messy escape but still better than clobbering the original file + exportFileName.append("-m29.tti"); + + exportFileName = QDir(QFileInfo(m_curFile).absoluteDir()).filePath(exportFileName); + } + + exportFileName = QFileDialog::getSaveFileName(this, tr("Export M/29 tti"), exportFileName, "TTI teletext page (*.tti *.ttix)"); + if (exportFileName.isEmpty()) + return; + + QApplication::setOverrideCursor(Qt::WaitCursor); + QSaveFile file(exportFileName); + if (file.open(QFile::WriteOnly | QFile::Text)) { + exportM29File(file, *m_textWidget->document()); + if (!file.commit()) + errorMessage = tr("Cannot write file %1:\n%2.").arg(QDir::toNativeSeparators(exportFileName), file.errorString()); + } else + errorMessage = tr("Cannot open file %1 for writing:\n%2.").arg(QDir::toNativeSeparators(exportFileName), file.errorString()); + QApplication::restoreOverrideCursor(); + + if (!errorMessage.isEmpty()) + QMessageBox::warning(this, tr("QTeletextMaker"), errorMessage); +} + void MainWindow::setCurrentFile(const QString &fileName) { static int sequenceNumber = 1; diff --git a/mainwindow.h b/mainwindow.h index 91be6f5..c4f5150 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -62,6 +62,7 @@ private slots: void exportZXNet(); void exportEditTF(); void exportPNG(); + void exportM29(); void updateRecentFileActions(); void openRecentFile(); void about();