Compare commits
8 Commits
0.5.5-alph
...
0.6-alpha
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3125762133 | ||
|
|
c0670c8281 | ||
|
|
7493c8f527 | ||
|
|
9bd9f180c2 | ||
|
|
c64be6a4c9 | ||
|
|
eb752835fd | ||
|
|
72a2ef9660 | ||
|
|
213eace512 |
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
|
||||
2
decode.h
2
decode.h
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
|
||||
12
keymap.h
12
keymap.h
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
@@ -528,15 +528,15 @@ static const QMap<QChar, char> keymapping[24] = {
|
||||
|
||||
// Native scan codes to toggle mosaic bits - different platforms have different scan codes!
|
||||
// Order is top left, top right, middle left, middle right, bottom left, bottom right,
|
||||
// invert, set all, clear all
|
||||
// invert, set all, clear all, dither
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
static constexpr quint32 mosaicNativeScanCodes[9] = {
|
||||
0x18, 0x19, 0x26, 0x27, 0x34, 0x35, 0x1b, 0x29, 0x36
|
||||
static constexpr quint32 mosaicNativeScanCodes[10] = {
|
||||
0x18, 0x19, 0x26, 0x27, 0x34, 0x35, 0x1b, 0x29, 0x36, 0x28
|
||||
};
|
||||
#elif defined(Q_OS_WIN)
|
||||
static constexpr quint32 mosaicNativeScanCodes[9] = {
|
||||
0x10, 0x11, 0x1e, 0x1f, 0x2c, 0x2d, 0x13, 0x21, 0x2e
|
||||
static constexpr quint32 mosaicNativeScanCodes[10] = {
|
||||
0x10, 0x11, 0x1e, 0x1f, 0x2c, 0x2d, 0x13, 0x21, 0x2e, 0x20
|
||||
};
|
||||
#else
|
||||
#define QTTM_NONATIVESCANCODES
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
@@ -106,6 +106,8 @@ ToggleMosaicBitCommand::ToggleMosaicBitCommand(TeletextDocument *teletextDocumen
|
||||
m_oldCharacter = teletextDocument->currentSubPage()->character(m_row, m_column);
|
||||
if (bitToToggle == 0x20 || bitToToggle == 0x7f)
|
||||
m_newCharacter = bitToToggle;
|
||||
else if (bitToToggle == 0x66)
|
||||
m_newCharacter = (m_row & 1) ? 0x66 : 0x39;
|
||||
else
|
||||
m_newCharacter = m_oldCharacter ^ bitToToggle;
|
||||
|
||||
@@ -413,8 +415,18 @@ PasteCommand::PasteCommand(TeletextDocument *teletextDocument, int pageCharSet,
|
||||
if (m_selectionActive) {
|
||||
m_selectionCornerRow = m_teletextDocument->selectionCornerRow();
|
||||
m_selectionCornerColumn = m_teletextDocument->selectionCornerColumn();
|
||||
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_pasteLeftColumn = m_column;
|
||||
// m_pasteBottomRow and m_pasteRightColumn will be filled in later
|
||||
// when the size of the clipboard data is known
|
||||
}
|
||||
|
||||
// Zero size here represents invalid or empty clipboard data
|
||||
m_clipboardDataHeight = m_clipboardDataWidth = 0;
|
||||
|
||||
// Try to get something from the clipboard
|
||||
@@ -422,6 +434,7 @@ PasteCommand::PasteCommand(TeletextDocument *teletextDocument, int pageCharSet,
|
||||
nativeData = mimeData->data("application/x-teletext");
|
||||
if (nativeData.size() > 2) {
|
||||
// Native clipboard data: we put it there ourselves
|
||||
m_plainText = false;
|
||||
m_clipboardDataHeight = nativeData.at(0);
|
||||
m_clipboardDataWidth = nativeData.at(1);
|
||||
|
||||
@@ -429,25 +442,119 @@ PasteCommand::PasteCommand(TeletextDocument *teletextDocument, int pageCharSet,
|
||||
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
|
||||
else {
|
||||
// Invalidate
|
||||
m_clipboardDataHeight = m_clipboardDataWidth = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_selectionActive) {
|
||||
m_pasteBottomRow = m_row + m_clipboardDataHeight - 1;
|
||||
m_pasteRightColumn = m_column + m_clipboardDataWidth - 1;
|
||||
}
|
||||
} else if (mimeData->hasText()) {
|
||||
// Plain text
|
||||
m_plainText = true;
|
||||
|
||||
const int rightColumn = m_selectionActive ? m_pasteRightColumn : 39;
|
||||
|
||||
// Parse line-feeds in the clipboard data
|
||||
QStringList plainTextData = mimeData->text().split(QRegExp("\n|\r\n|\r"));
|
||||
|
||||
// "if" statement will be false if clipboard data is a single line of text
|
||||
// that will fit from the cursor position
|
||||
if (plainTextData.size() != 1 || m_pasteLeftColumn + plainTextData.at(0).size() - 1 > rightColumn) {
|
||||
bool wrappingNeeded = false;
|
||||
|
||||
if (!m_selectionActive) {
|
||||
// If selection is NOT active, use the full width of the page to paste.
|
||||
// The second and subsequent lines will start at column 1, unless the
|
||||
// cursor is explicitly on column 0.
|
||||
if (m_pasteLeftColumn != 0)
|
||||
m_pasteLeftColumn = 1;
|
||||
|
||||
// Check if first word in the first line will fit from the cursor position
|
||||
bool firstWordFits = true;
|
||||
const int firstSpace = plainTextData.at(0).indexOf(' ');
|
||||
|
||||
if (firstSpace == -1 && m_column + plainTextData.at(0).size() > 40)
|
||||
firstWordFits = false; // Only one word in first line, and it won't fit
|
||||
else if (m_column + firstSpace > 40)
|
||||
firstWordFits = false; // First word in first line won't fit
|
||||
|
||||
// If the first word WILL fit at the cursor position, pad the first line
|
||||
// to match the cursor position using null characters.
|
||||
// In the QString null characters represent character cells in the
|
||||
// pasting rectangle that won't overwrite what's on the page.
|
||||
// If the first word WON'T fit, start pasting at the beginning of the next row.
|
||||
if (firstWordFits)
|
||||
plainTextData[0] = QString(m_column-m_pasteLeftColumn, QChar::Null) + plainTextData.at(0);
|
||||
else if (m_pasteTopRow < 24)
|
||||
m_pasteTopRow++;
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
const int pasteWidth = rightColumn - m_pasteLeftColumn + 1;
|
||||
|
||||
// Find out if we need to word-wrap
|
||||
for (int i=0; i<plainTextData.size(); i++)
|
||||
if (plainTextData.at(i).size() > pasteWidth) {
|
||||
wrappingNeeded = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (wrappingNeeded) {
|
||||
QStringList wrappedText;
|
||||
|
||||
for (int i=0; i<plainTextData.size(); i++) {
|
||||
// Split this line into individual words
|
||||
QStringList lineWords = plainTextData.at(i).split(' ');
|
||||
|
||||
// If there's any words which are too long to fit,
|
||||
// break them across multiple lines
|
||||
for (int j=0; j<lineWords.size(); j++)
|
||||
if (lineWords.at(j).size() > pasteWidth) {
|
||||
lineWords.insert(j+1, lineWords.at(j).mid(pasteWidth));
|
||||
lineWords[j].truncate(pasteWidth);
|
||||
}
|
||||
|
||||
// Now reassemble the words into lines that will fit
|
||||
QString currentLine = lineWords.at(0);
|
||||
|
||||
for (int j=1; j<lineWords.size(); j++)
|
||||
if (currentLine.size() + 1 + lineWords.at(j).size() <= pasteWidth)
|
||||
currentLine.append(' ' + lineWords.at(j));
|
||||
else {
|
||||
wrappedText.append(currentLine);
|
||||
currentLine = lineWords.at(j);
|
||||
}
|
||||
|
||||
wrappedText.append(currentLine);
|
||||
}
|
||||
plainTextData.swap(wrappedText);
|
||||
}
|
||||
}
|
||||
|
||||
m_clipboardDataHeight = plainTextData.size();
|
||||
m_clipboardDataWidth = 0;
|
||||
|
||||
// Convert the unicode clipboard text into teletext bytes matching the current Level 1
|
||||
// character set of this page
|
||||
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))
|
||||
// Map a null character in the QString to 0xff (or -1)
|
||||
// In the QByteArray 0xff bytes represent character cells in the pasting rectangle
|
||||
// that won't overwrite what's on the page
|
||||
if (charToConvert == QChar::Null)
|
||||
convertedChar = -1;
|
||||
else if (charToConvert >= 0x01 && charToConvert <= 0x1f)
|
||||
convertedChar = ' ';
|
||||
else if (keymapping[pageCharSet].contains(charToConvert))
|
||||
// Remapped character or non-Latin character converted successfully
|
||||
convertedChar = keymapping[pageCharSet].value(charToConvert);
|
||||
else {
|
||||
@@ -463,26 +570,19 @@ PasteCommand::PasteCommand(TeletextDocument *teletextDocument, int pageCharSet,
|
||||
}
|
||||
m_clipboardDataWidth = qMax(m_pastingCharacters.at(r).size(), m_clipboardDataWidth);
|
||||
}
|
||||
// Pad short lines with spaces to make a box
|
||||
// Pad the end of 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_selectionActive) {
|
||||
m_pasteBottomRow = m_pasteTopRow + m_clipboardDataHeight - 1;
|
||||
m_pasteRightColumn = m_pasteLeftColumn + m_clipboardDataWidth - 1;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -517,11 +617,21 @@ void PasteCommand::redo()
|
||||
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++));
|
||||
// Check for 0xff bytes using "-1"
|
||||
// gcc complains about "comparision always true due to limited range"
|
||||
if (m_pastingCharacters.at(arrayR).at(arrayC) != -1)
|
||||
m_teletextDocument->currentSubPage()->setCharacter(r, c, m_pastingCharacters.at(arrayR).at(arrayC));
|
||||
|
||||
arrayC++;
|
||||
|
||||
// If paste area is wider than clipboard data, repeat the pattern
|
||||
if (arrayC == m_clipboardDataWidth)
|
||||
// if it wasn't plain text
|
||||
if (arrayC == m_clipboardDataWidth) {
|
||||
if (!m_plainText)
|
||||
arrayC = 0;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (r < 25)
|
||||
@@ -529,8 +639,13 @@ void PasteCommand::redo()
|
||||
|
||||
arrayR++;
|
||||
// If paste area is taller than clipboard data, repeat the pattern
|
||||
if (arrayR == m_clipboardDataHeight)
|
||||
// if it wasn't plain text
|
||||
if (arrayR == m_clipboardDataHeight) {
|
||||
if (!m_plainText)
|
||||
arrayR = 0;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_selectionActive) {
|
||||
@@ -556,8 +671,11 @@ void PasteCommand::undo()
|
||||
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 && c < 40) {
|
||||
m_teletextDocument->currentSubPage()->setCharacter(r, c, m_deletedCharacters[arrayR].at(arrayC));
|
||||
|
||||
arrayC++;
|
||||
}
|
||||
|
||||
if (r < 25)
|
||||
emit m_teletextDocument->contentsChange(r);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
@@ -179,7 +179,7 @@ private:
|
||||
int m_pasteTopRow, m_pasteBottomRow, m_pasteLeftColumn, m_pasteRightColumn;
|
||||
int m_clipboardDataHeight, m_clipboardDataWidth;
|
||||
int m_selectionCornerRow, m_selectionCornerColumn;
|
||||
bool m_selectionActive;
|
||||
bool m_selectionActive, m_plainText;
|
||||
};
|
||||
#endif // !QT_NO_CLIPBOARD
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
|
||||
4
main.cpp
4
main.cpp
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
@@ -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.5.5-alpha");
|
||||
QApplication::setApplicationVersion("0.6-alpha");
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription(QApplication::applicationName());
|
||||
parser.addHelpOption();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
@@ -259,7 +259,7 @@ void TeletextWidget::keyPressEvent(QKeyEvent *event)
|
||||
mappedKeyPress = 0x7f;
|
||||
if (m_pageDecode.level1MosaicAttribute(m_teletextDocument->cursorRow(), m_teletextDocument->cursorColumn()) && (mappedKeyPress < 0x40 || mappedKeyPress > 0x5f)) {
|
||||
// We're on a mosaic and a blast-through character was NOT pressed
|
||||
if (event->key() >= Qt::Key_1 && event->key() <= Qt::Key_9 && event->modifiers() & Qt::KeypadModifier) {
|
||||
if (event->key() >= Qt::Key_0 && event->key() <= Qt::Key_9 && event->modifiers() & Qt::KeypadModifier) {
|
||||
switch (event->key()) {
|
||||
case Qt::Key_7:
|
||||
toggleCharacterBit(0x01); // Top left
|
||||
@@ -288,6 +288,9 @@ void TeletextWidget::keyPressEvent(QKeyEvent *event)
|
||||
case Qt::Key_3:
|
||||
toggleCharacterBit(0x20); // Clear all
|
||||
break;
|
||||
case Qt::Key_0:
|
||||
toggleCharacterBit(0x66); // Dither
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -328,6 +331,9 @@ void TeletextWidget::keyPressEvent(QKeyEvent *event)
|
||||
case mosaicNativeScanCodes[8]:
|
||||
toggleCharacterBit(0x20); // Clear all
|
||||
break;
|
||||
case mosaicNativeScanCodes[9]:
|
||||
toggleCharacterBit(0x66); // Dither
|
||||
break;
|
||||
}
|
||||
return;
|
||||
} else
|
||||
@@ -688,18 +694,13 @@ void LevelOneScene::toggleGrid(bool gridOn)
|
||||
void LevelOneScene::hideGUIElements(bool hidden)
|
||||
{
|
||||
if (hidden) {
|
||||
m_mainGridItemGroup->setVisible(false);
|
||||
m_cursorRectItem->setVisible(false);
|
||||
m_selectionRectItem->setVisible(false);
|
||||
for (int i=0; i<32; i++)
|
||||
if (m_sidePanelGridNeeded[i])
|
||||
m_sidePanelGridItemGroup[i]->setVisible(false);
|
||||
} else {
|
||||
if (static_cast<TeletextWidget *>(m_levelOneProxyWidget->widget())->document()->selectionActive())
|
||||
m_selectionRectItem->setVisible(true);
|
||||
|
||||
m_cursorRectItem->setVisible(true);
|
||||
toggleGrid(m_grid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
@@ -186,9 +186,6 @@ void MainWindow::exportPNG()
|
||||
// Prepare widget image for extraction
|
||||
m_textWidget->pauseFlash(true);
|
||||
m_textScene->hideGUIElements(true);
|
||||
bool reshowControlCodes = m_textWidget->showControlCodes();
|
||||
if (reshowControlCodes)
|
||||
m_textWidget->setShowControlCodes(false);
|
||||
// Disable exporting in Mix mode as it corrupts the background
|
||||
bool reMix = m_textWidget->pageRender()->mix();
|
||||
if (reMix) {
|
||||
@@ -206,8 +203,6 @@ void MainWindow::exportPNG()
|
||||
|
||||
// Now we've extracted the image we can put the GUI things back
|
||||
m_textScene->hideGUIElements(false);
|
||||
if (reshowControlCodes)
|
||||
m_textWidget->setShowControlCodes(true);
|
||||
if (reMix) {
|
||||
m_textWidget->setMix(true);
|
||||
m_textScene->setMix(true);
|
||||
@@ -246,7 +241,7 @@ void MainWindow::about()
|
||||
QMessageBox::about(this, tr("About"), QString("<b>%1</b><br>"
|
||||
"An open source Level 2.5 teletext page editor.<br>"
|
||||
"<i>Version %2</i><br><br>"
|
||||
"Copyright (C) 2020-2022 Gavin MacGregor<br><br>"
|
||||
"Copyright (C) 2020-2023 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>").arg(QApplication::applicationDisplayName()).arg(QApplication::applicationVersion()));
|
||||
}
|
||||
@@ -376,9 +371,16 @@ void MainWindow::createActions()
|
||||
|
||||
setRecentFilesVisible(MainWindow::hasRecentFiles());
|
||||
|
||||
m_exportAutoAct = fileMenu->addAction(tr("Export subpage..."));
|
||||
m_exportAutoAct->setEnabled(false);
|
||||
m_exportAutoAct->setShortcut(tr("Ctrl+E"));
|
||||
m_exportAutoAct->setStatusTip("Export this subpage back to the imported file");
|
||||
connect(fileMenu, &QMenu::aboutToShow, this, &MainWindow::updateExportAutoAction);
|
||||
connect(m_exportAutoAct, &QAction::triggered, this, &MainWindow::exportAuto);
|
||||
|
||||
QAction *exportT42Act = fileMenu->addAction(tr("Export subpage as t42..."));
|
||||
exportT42Act->setStatusTip("Export this subpage as a t42 file");
|
||||
connect(exportT42Act, &QAction::triggered, this, &MainWindow::exportT42);
|
||||
connect(exportT42Act, &QAction::triggered, this, [=]() { exportT42(false); });
|
||||
|
||||
QMenu *exportHashStringSubMenu = fileMenu->addMenu(tr("Export subpage to online editor"));
|
||||
|
||||
@@ -939,10 +941,13 @@ void MainWindow::loadFile(const QString &fileName)
|
||||
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
||||
if (fileInfo.suffix() == "t42")
|
||||
if (fileInfo.suffix() == "t42") {
|
||||
importT42(&file, m_textWidget->document());
|
||||
else
|
||||
m_exportAutoFileName = fileName;
|
||||
} else {
|
||||
loadTTI(&file, m_textWidget->document());
|
||||
m_exportAutoFileName.clear();
|
||||
}
|
||||
|
||||
levelSeen = m_textWidget->document()->levelRequired();
|
||||
m_levelRadioButton[levelSeen]->toggle();
|
||||
@@ -1026,6 +1031,18 @@ void MainWindow::updateRecentFileActions()
|
||||
m_recentFileActs[i]->setVisible(false);
|
||||
}
|
||||
|
||||
void MainWindow::updateExportAutoAction()
|
||||
{
|
||||
if (m_exportAutoFileName.isEmpty()) {
|
||||
m_exportAutoAct->setText(tr("Export subpage..."));
|
||||
m_exportAutoAct->setEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
m_exportAutoAct->setText(tr("Overwrite &%1").arg(MainWindow::strippedName(m_exportAutoFileName)));
|
||||
m_exportAutoAct->setEnabled(true);
|
||||
}
|
||||
|
||||
void MainWindow::openRecentFile()
|
||||
{
|
||||
if (const QAction *action = qobject_cast<const QAction *>(sender()))
|
||||
@@ -1056,16 +1073,30 @@ bool MainWindow::saveFile(const QString &fileName)
|
||||
return true;
|
||||
}
|
||||
|
||||
void MainWindow::exportT42()
|
||||
void MainWindow::exportAuto()
|
||||
{
|
||||
// Menu should be disabled if m_exportAutoFileName is empty, but just in case...
|
||||
if (m_exportAutoFileName.isEmpty())
|
||||
return;
|
||||
|
||||
exportT42(true);
|
||||
}
|
||||
|
||||
void MainWindow::exportT42(bool fromAuto)
|
||||
{
|
||||
QString errorMessage;
|
||||
QString exportFileName = m_curFile;
|
||||
QString exportFileName;
|
||||
|
||||
if (fromAuto)
|
||||
exportFileName = m_exportAutoFileName;
|
||||
else {
|
||||
exportFileName = m_curFile;
|
||||
changeSuffixFromTTI(exportFileName, "t42");
|
||||
|
||||
exportFileName = QFileDialog::getSaveFileName(this, tr("Export t42"), exportFileName, "t42 stream (*.t42)");
|
||||
if (exportFileName.isEmpty())
|
||||
return;
|
||||
}
|
||||
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
QSaveFile file(exportFileName);
|
||||
@@ -1077,8 +1108,15 @@ void MainWindow::exportT42()
|
||||
errorMessage = tr("Cannot open file %1 for writing:\n%2.").arg(QDir::toNativeSeparators(exportFileName), file.errorString());
|
||||
QApplication::restoreOverrideCursor();
|
||||
|
||||
if (!errorMessage.isEmpty())
|
||||
if (!errorMessage.isEmpty()) {
|
||||
QMessageBox::warning(this, QApplication::applicationDisplayName(), errorMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
MainWindow::prependToRecentFiles(exportFileName);
|
||||
|
||||
m_exportAutoFileName = exportFileName;
|
||||
statusBar()->showMessage(tr("File exported"), 2000);
|
||||
}
|
||||
|
||||
void MainWindow::exportM29()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
@@ -60,12 +60,14 @@ private slots:
|
||||
bool save();
|
||||
bool saveAs();
|
||||
void reload();
|
||||
void exportT42();
|
||||
void exportAuto();
|
||||
void exportT42(bool);
|
||||
void exportZXNet();
|
||||
void exportEditTF();
|
||||
void exportPNG();
|
||||
void exportM29();
|
||||
void updateRecentFileActions();
|
||||
void updateExportAutoAction();
|
||||
void openRecentFile();
|
||||
void about();
|
||||
void updatePageWidgets();
|
||||
@@ -121,6 +123,7 @@ private:
|
||||
QAction *m_recentFileActs[m_MaxRecentFiles];
|
||||
QAction *m_recentFileSeparator;
|
||||
QAction *m_recentFileSubMenuAct;
|
||||
QAction *m_exportAutoAct;
|
||||
QAction *m_deleteSubPageAction;
|
||||
QAction *m_borderActs[3];
|
||||
QAction *m_aspectRatioActs[4];
|
||||
@@ -131,7 +134,7 @@ private:
|
||||
QPushButton *m_insertModePushButton;
|
||||
QRadioButton *m_levelRadioButton[4];
|
||||
|
||||
QString m_curFile;
|
||||
QString m_curFile, m_exportAutoFileName;
|
||||
bool m_isUntitled;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
|
||||
2
render.h
2
render.h
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
@@ -1036,9 +1036,11 @@ void X26DockWidget::insertTriplet(int modeExt, bool after)
|
||||
{
|
||||
QModelIndex index = m_x26View->currentIndex();
|
||||
X26Triplet newTriplet(modeExt < 0x20 ? 41 : 0, modeExt & 0x1f, 0);
|
||||
int row;
|
||||
int newListRow;
|
||||
|
||||
if (index.isValid()) {
|
||||
newListRow = index.row()+after;
|
||||
|
||||
// If we're inserting a column triplet next to another column triplet,
|
||||
// duplicate the column number
|
||||
// Avoid the PDC and reserved mode triplets
|
||||
@@ -1048,9 +1050,26 @@ void X26DockWidget::insertTriplet(int modeExt, bool after)
|
||||
if (existingTripletModeExt >= 0x20 && existingTripletModeExt != 0x24 && existingTripletModeExt != 0x25 && existingTripletModeExt != 0x26 && existingTripletModeExt != 0x2a)
|
||||
newTriplet.setAddress(index.model()->data(index.model()->index(index.row(), 0), Qt::UserRole).toInt());
|
||||
}
|
||||
row = index.row()+after;
|
||||
// If we're inserting a Set Active Position or Full Row Colour triplet,
|
||||
// look for a previous row setting triplet and set this one to the row after
|
||||
if (modeExt == 0x04 || modeExt == 0x01) {
|
||||
for (int i=newListRow-1; i>=0; i--) {
|
||||
const int scanTripletModeExt = index.model()->data(index.model()->index(i, 2), Qt::EditRole).toInt();
|
||||
|
||||
if (scanTripletModeExt == 0x04 || scanTripletModeExt == 0x01) {
|
||||
const int scanActivePositionRow = index.model()->data(index.model()->index(i, 0), Qt::EditRole).toInt()+1;
|
||||
|
||||
if (scanActivePositionRow < 25)
|
||||
newTriplet.setAddressRow(scanActivePositionRow);
|
||||
else
|
||||
newTriplet.setAddressRow(24);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
row = 0;
|
||||
newListRow = 0;
|
||||
|
||||
// For character triplets, ensure Data is not reserved
|
||||
if (modeExt == 0x21 || modeExt == 0x22 || modeExt == 0x29 || modeExt == 0x2b || modeExt >= 0x2f)
|
||||
@@ -1061,7 +1080,7 @@ void X26DockWidget::insertTriplet(int modeExt, bool after)
|
||||
newTriplet.setData(7);
|
||||
}
|
||||
|
||||
m_x26Model->insertRows(row, 1, QModelIndex(), newTriplet);
|
||||
m_x26Model->insertRows(newListRow, 1, QModelIndex(), newTriplet);
|
||||
}
|
||||
|
||||
void X26DockWidget::insertTripletCopy()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Gavin MacGregor
|
||||
* Copyright (C) 2020-2023 Gavin MacGregor
|
||||
*
|
||||
* This file is part of QTeletextMaker.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user