5 Commits

Author SHA1 Message Date
Gavin MacGregor
6c46aba687 Tag version 0.8.1-beta 2025-10-26 14:20:04 +00:00
Gavin MacGregor
07abbdf928 Fix deeper zooms not being saved properly 2025-10-26 10:53:13 +00:00
Gavin MacGregor
30bff43a14 Restore geometry and state after central widget creation
Attempts to fix a bug where the central page editing widget was sometimes
squashed to a tiny size in the corner.

Also introduces a schema for settings storage. There are no changes in this
schema; this is (mis)used to forget the geometry and state when version
0.8.1 is started for the first time to make sure the central widget is
usuable again.
2025-10-24 22:49:35 +01:00
Gavin MacGregor
d9c93cfe66 Ensure decoder and gif library are built in 2025-10-21 14:43:02 +01:00
Gavin MacGregor
f18cf60b27 Add Clear Files option to Recent Files 2025-10-19 16:17:52 +01:00
5 changed files with 82 additions and 90 deletions

View File

@@ -13,7 +13,7 @@ set(GIF_LIB_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include/3rdparty/giflib)
# Next line was "add_library(${PROJECT_NAME} SHARED" # Next line was "add_library(${PROJECT_NAME} SHARED"
# but it breaks MXE static compilation # but it breaks MXE static compilation
add_library(${PROJECT_NAME} add_library(${PROJECT_NAME} STATIC
${GIF_IMAGE_DIR}/qgifglobal.h ${GIF_IMAGE_DIR}/qgifimage.cpp ${GIF_IMAGE_DIR}/qgifglobal.h ${GIF_IMAGE_DIR}/qgifimage.cpp
${GIF_IMAGE_DIR}/qgifimage.h ${GIF_IMAGE_DIR}/qgifimage_p.h ${GIF_IMAGE_DIR}/qgifimage.h ${GIF_IMAGE_DIR}/qgifimage_p.h

View File

@@ -1,6 +1,6 @@
file (GLOB SOURCES *.cpp) file (GLOB SOURCES *.cpp)
add_library(qteletextdecoder ${SOURCES} teletextfonts.qrc) add_library(qteletextdecoder STATIC ${SOURCES} teletextfonts.qrc)
target_include_directories(qteletextdecoder PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories(qteletextdecoder PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

View File

@@ -30,7 +30,7 @@ int main(int argc, char *argv[])
QApplication::setApplicationDisplayName(QApplication::applicationName()); QApplication::setApplicationDisplayName(QApplication::applicationName());
QApplication::setOrganizationName("gkmac.co.uk"); QApplication::setOrganizationName("gkmac.co.uk");
QApplication::setOrganizationDomain("gkmac.co.uk"); QApplication::setOrganizationDomain("gkmac.co.uk");
QApplication::setApplicationVersion("0.8-beta"); QApplication::setApplicationVersion("0.8.1-beta");
QCommandLineParser parser; QCommandLineParser parser;
parser.setApplicationDescription(QApplication::applicationName()); parser.setApplicationDescription(QApplication::applicationName());
parser.addHelpOption(); parser.addHelpOption();

View File

@@ -397,16 +397,66 @@ void MainWindow::init()
createActions(); createActions();
createStatusBar(); createStatusBar();
readSettings(); QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName());
const int settingsSchema = settings.value("schema", 1).toInt();
// Don't restore geometry/states from pre 0.8.1 versions: they had a bug which sometimes squashed the
// page view unusably small and forgetting the layout could be the only way out of it
const QByteArray geometry = settingsSchema >= 2 ? settings.value("geometry", QByteArray()).toByteArray() : QByteArray();
const QByteArray windowState = settingsSchema >= 2 ? settings.value("windowState", QByteArray()).toByteArray() : QByteArray();
m_viewBorder = settings.value("border", 1).toInt();
m_viewBorder = (m_viewBorder < 0 || m_viewBorder > 2) ? 1 : m_viewBorder;
m_borderActs[m_viewBorder]->setChecked(true);
m_viewAspectRatio = settings.value("aspectratio", 0).toInt();
m_viewAspectRatio = (m_viewAspectRatio < 0 || m_viewAspectRatio > 3) ? 0 : m_viewAspectRatio;
m_aspectRatioActs[m_viewAspectRatio]->setChecked(true);
m_viewSmoothTransform = settings.value("smoothTransform", 0).toBool();
m_smoothTransformAction->blockSignals(true);
m_smoothTransformAction->setChecked(m_viewSmoothTransform);
m_smoothTransformAction->blockSignals(false);
int zoomSliderInit = settings.value("zoom", 2).toInt();
zoomSliderInit = (zoomSliderInit < 0 || zoomSliderInit > 8) ? 2 : zoomSliderInit;
m_textView = new QGraphicsView(this); m_textView = new QGraphicsView(this);
m_textView->setScene(m_textScene); m_textView->setScene(m_textScene);
if (m_viewSmoothTransform) if (m_viewSmoothTransform)
m_textView->setRenderHints(QPainter::SmoothPixmapTransform); m_textView->setRenderHints(QPainter::SmoothPixmapTransform);
m_zoomSlider->setValue(m_viewZoom); m_zoomSlider->setValue(zoomSliderInit);
setSceneDimensions(); setSceneDimensions();
setCentralWidget(m_textView); setCentralWidget(m_textView);
// zoom 0 = 430,385px, 1 = 500,530px, 2 = 650,670px
if (geometry.isEmpty()) {
const QRect availableGeometry = QGuiApplication::primaryScreen()->availableGeometry();
if (availableGeometry.width() < 500 || availableGeometry.height() < 530) {
resize(430, 385);
m_viewZoom = 0;
} else if (availableGeometry.width() < 650 || availableGeometry.height() < 670) {
resize(500, 530);
m_viewZoom = 1;
} else
resize(650, 670);
// m_viewZoom = 2;
move((availableGeometry.width() - width()) / 2, (availableGeometry.height() - height()) / 2);
} else
restoreGeometry(geometry);
if (windowState.isEmpty()) {
m_pageOptionsDockWidget->hide();
m_pageOptionsDockWidget->setFloating(true);
m_pageEnhancementsDockWidget->hide();
m_pageEnhancementsDockWidget->setFloating(true);
m_x26DockWidget->hide();
m_x26DockWidget->setFloating(true);
m_paletteDockWidget->hide();
m_paletteDockWidget->setFloating(true);
m_dClutDockWidget->hide();
m_dClutDockWidget->setFloating(true);
m_pageComposeLinksDockWidget->hide();
m_pageComposeLinksDockWidget->setFloating(true);
} else
restoreState(windowState);
connect(m_textWidget->document(), &TeletextDocument::cursorMoved, this, &MainWindow::updateCursorPosition); connect(m_textWidget->document(), &TeletextDocument::cursorMoved, this, &MainWindow::updateCursorPosition);
connect(m_textWidget->document(), &TeletextDocument::selectionMoved, m_textScene, &LevelOneScene::updateSelection); connect(m_textWidget->document(), &TeletextDocument::selectionMoved, m_textScene, &LevelOneScene::updateSelection);
connect(m_textWidget->document()->undoStack(), &QUndoStack::cleanChanged, this, [=]() { setWindowModified(!m_textWidget->document()->undoStack()->isClean()); } ); connect(m_textWidget->document()->undoStack(), &QUndoStack::cleanChanged, this, [=]() { setWindowModified(!m_textWidget->document()->undoStack()->isClean()); } );
@@ -452,6 +502,8 @@ void MainWindow::createActions()
QToolBar *fileToolBar = addToolBar(tr("File")); QToolBar *fileToolBar = addToolBar(tr("File"));
fileToolBar->setObjectName("fileToolBar"); fileToolBar->setObjectName("fileToolBar");
connect(fileMenu, &QMenu::aboutToShow, this, &MainWindow::updateRecentFileActions);
const QIcon newIcon = QIcon::fromTheme("document-new", QIcon(":/images/new.png")); const QIcon newIcon = QIcon::fromTheme("document-new", QIcon(":/images/new.png"));
QAction *newAct = new QAction(newIcon, tr("&New"), this); QAction *newAct = new QAction(newIcon, tr("&New"), this);
newAct->setShortcuts(QKeySequence::New); newAct->setShortcuts(QKeySequence::New);
@@ -468,6 +520,18 @@ void MainWindow::createActions()
fileMenu->addAction(openAct); fileMenu->addAction(openAct);
fileToolBar->addAction(openAct); fileToolBar->addAction(openAct);
const QIcon recentIcon = QIcon::fromTheme("document-open-recent");
QMenu *recentMenu = fileMenu->addMenu(recentIcon, tr("Open recent"));
m_recentFileSubMenuAct = recentMenu->menuAction();
for (int i = 0; i < m_MaxRecentFiles; ++i) {
m_recentFileActs[i] = recentMenu->addAction(QString(), this, &MainWindow::openRecentFile);
m_recentFileActs[i]->setVisible(false);
}
recentMenu->addSeparator();
const QIcon clearRecentIcon = QIcon::fromTheme("edit-clear-history");
recentMenu->addAction(clearRecentIcon, tr("Clear list"), this, &MainWindow::clearRecentFiles);
const QIcon saveIcon = QIcon::fromTheme("document-save", QIcon(":/images/save.png")); const QIcon saveIcon = QIcon::fromTheme("document-save", QIcon(":/images/save.png"));
QAction *saveAct = new QAction(saveIcon, tr("&Save"), this); QAction *saveAct = new QAction(saveIcon, tr("&Save"), this);
saveAct->setShortcuts(QKeySequence::Save); saveAct->setShortcuts(QKeySequence::Save);
@@ -488,19 +552,6 @@ void MainWindow::createActions()
fileMenu->addSeparator(); fileMenu->addSeparator();
QMenu *recentMenu = fileMenu->addMenu(tr("Recent"));
connect(recentMenu, &QMenu::aboutToShow, this, &MainWindow::updateRecentFileActions);
m_recentFileSubMenuAct = recentMenu->menuAction();
for (int i = 0; i < m_MaxRecentFiles; ++i) {
m_recentFileActs[i] = recentMenu->addAction(QString(), this, &MainWindow::openRecentFile);
m_recentFileActs[i]->setVisible(false);
}
m_recentFileSeparator = fileMenu->addSeparator();
setRecentFilesVisible(MainWindow::hasRecentFiles());
m_exportAutoAct = fileMenu->addAction(tr("Export subpage...")); m_exportAutoAct = fileMenu->addAction(tr("Export subpage..."));
m_exportAutoAct->setEnabled(false); m_exportAutoAct->setEnabled(false);
m_exportAutoAct->setShortcut(tr("Ctrl+E")); m_exportAutoAct->setShortcut(tr("Ctrl+E"));
@@ -1173,67 +1224,16 @@ void MainWindow::createStatusBar()
connect(m_levelRadioButton[3], &QAbstractButton::clicked, [=]() { m_textWidget->pageDecode()->setLevel(3); m_textWidget->update(); m_paletteDockWidget->setLevel3p5Accepted(true);}); connect(m_levelRadioButton[3], &QAbstractButton::clicked, [=]() { m_textWidget->pageDecode()->setLevel(3); m_textWidget->update(); m_paletteDockWidget->setLevel3p5Accepted(true);});
} }
void MainWindow::readSettings()
{
//TODO window sizing
QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName());
const QByteArray geometry = settings.value("geometry", QByteArray()).toByteArray();
const QByteArray windowState = settings.value("windowState", QByteArray()).toByteArray();
m_viewBorder = settings.value("border", 1).toInt();
m_viewBorder = (m_viewBorder < 0 || m_viewBorder > 2) ? 1 : m_viewBorder;
m_borderActs[m_viewBorder]->setChecked(true);
m_viewAspectRatio = settings.value("aspectratio", 0).toInt();
m_viewAspectRatio = (m_viewAspectRatio < 0 || m_viewAspectRatio > 3) ? 0 : m_viewAspectRatio;
m_aspectRatioActs[m_viewAspectRatio]->setChecked(true);
m_viewSmoothTransform = settings.value("smoothTransform", 0).toBool();
m_smoothTransformAction->blockSignals(true);
m_smoothTransformAction->setChecked(m_viewSmoothTransform);
m_smoothTransformAction->blockSignals(false);
m_viewZoom = settings.value("zoom", 2).toInt();
m_viewZoom = (m_viewZoom < 0 || m_viewZoom > 12) ? 2 : m_viewZoom;
// zoom 0 = 430,385px, 1 = 500,530px, 2 = 650,670px
if (geometry.isEmpty()) {
const QRect availableGeometry = QGuiApplication::primaryScreen()->availableGeometry();
if (availableGeometry.width() < 500 || availableGeometry.height() < 530) {
resize(430, 385);
m_viewZoom = 0;
} else if (availableGeometry.width() < 650 || availableGeometry.height() < 670) {
resize(500, 530);
m_viewZoom = 1;
} else
resize(650, 670);
// m_viewZoom = 2;
move((availableGeometry.width() - width()) / 2, (availableGeometry.height() - height()) / 2);
} else
restoreGeometry(geometry);
if (windowState.isEmpty()) {
m_pageOptionsDockWidget->hide();
m_pageOptionsDockWidget->setFloating(true);
m_pageEnhancementsDockWidget->hide();
m_pageEnhancementsDockWidget->setFloating(true);
m_x26DockWidget->hide();
m_x26DockWidget->setFloating(true);
m_paletteDockWidget->hide();
m_paletteDockWidget->setFloating(true);
m_dClutDockWidget->hide();
m_dClutDockWidget->setFloating(true);
m_pageComposeLinksDockWidget->hide();
m_pageComposeLinksDockWidget->setFloating(true);
} else
restoreState(windowState);
}
void MainWindow::writeSettings() void MainWindow::writeSettings()
{ {
QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName()); QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName());
settings.setValue("schema", 2);
settings.setValue("geometry", saveGeometry()); settings.setValue("geometry", saveGeometry());
settings.setValue("windowState", saveState()); settings.setValue("windowState", saveState());
settings.setValue("border", m_viewBorder); settings.setValue("border", m_viewBorder);
settings.setValue("aspectratio", m_viewAspectRatio); settings.setValue("aspectratio", m_viewAspectRatio);
settings.setValue("smoothTransform", m_viewSmoothTransform); settings.setValue("smoothTransform", m_viewSmoothTransform);
settings.setValue("zoom", m_viewZoom); settings.setValue("zoom", m_zoomSlider->value());
} }
bool MainWindow::maybeSave() bool MainWindow::maybeSave()
@@ -1318,12 +1318,6 @@ void MainWindow::loadFile(const QString &fileName)
statusBar()->showMessage(tr("File loaded"), 2000); statusBar()->showMessage(tr("File loaded"), 2000);
} }
void MainWindow::setRecentFilesVisible(bool visible)
{
m_recentFileSubMenuAct->setVisible(visible);
m_recentFileSeparator->setVisible(visible);
}
static inline QString recentFilesKey() { return QStringLiteral("recentFileList"); } static inline QString recentFilesKey() { return QStringLiteral("recentFileList"); }
static inline QString fileKey() { return QStringLiteral("file"); } static inline QString fileKey() { return QStringLiteral("file"); }
@@ -1350,14 +1344,6 @@ static void writeRecentFiles(const QStringList &files, QSettings &settings)
settings.endArray(); settings.endArray();
} }
bool MainWindow::hasRecentFiles()
{
QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName());
const int count = settings.beginReadArray(recentFilesKey());
settings.endArray();
return count > 0;
}
void MainWindow::prependToRecentFiles(const QString &fileName) void MainWindow::prependToRecentFiles(const QString &fileName)
{ {
QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName()); QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName());
@@ -1369,7 +1355,7 @@ void MainWindow::prependToRecentFiles(const QString &fileName)
if (oldRecentFiles != recentFiles) if (oldRecentFiles != recentFiles)
writeRecentFiles(recentFiles, settings); writeRecentFiles(recentFiles, settings);
setRecentFilesVisible(!recentFiles.isEmpty()); m_recentFileSubMenuAct->setEnabled(!recentFiles.isEmpty());
} }
void MainWindow::updateRecentFileActions() void MainWindow::updateRecentFileActions()
@@ -1387,6 +1373,15 @@ void MainWindow::updateRecentFileActions()
} }
for ( ; i < m_MaxRecentFiles; ++i) for ( ; i < m_MaxRecentFiles; ++i)
m_recentFileActs[i]->setVisible(false); m_recentFileActs[i]->setVisible(false);
m_recentFileSubMenuAct->setEnabled(recentFiles.size() != 0);
}
void MainWindow::clearRecentFiles()
{
QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName());
writeRecentFiles(QStringList(), settings);
} }
void MainWindow::updateExportAutoAction() void MainWindow::updateExportAutoAction()

View File

@@ -74,6 +74,7 @@ private slots:
void exportImage(); void exportImage();
void exportM29(); void exportM29();
void updateRecentFileActions(); void updateRecentFileActions();
void clearRecentFiles();
void updateExportAutoAction(); void updateExportAutoAction();
void openRecentFile(); void openRecentFile();
void about(); void about();
@@ -112,15 +113,12 @@ private:
void init(); void init();
void createActions(); void createActions();
void createStatusBar(); void createStatusBar();
void readSettings();
void writeSettings(); void writeSettings();
bool maybeSave(); bool maybeSave();
void openFile(const QString &fileName); void openFile(const QString &fileName);
void loadFile(const QString &fileName); void loadFile(const QString &fileName);
void extractImages(QImage sceneImage[], bool smooth = false, bool flashExtract = false); void extractImages(QImage sceneImage[], bool smooth = false, bool flashExtract = false);
static bool hasRecentFiles();
void prependToRecentFiles(const QString &fileName); void prependToRecentFiles(const QString &fileName);
void setRecentFilesVisible(bool visible);
bool saveFile(const QString &fileName); bool saveFile(const QString &fileName);
void setCurrentFile(const QString &fileName); void setCurrentFile(const QString &fileName);
static QString strippedName(const QString &fullFileName); static QString strippedName(const QString &fullFileName);
@@ -144,7 +142,6 @@ private:
DClutDockWidget *m_dClutDockWidget; DClutDockWidget *m_dClutDockWidget;
QAction *m_recentFileActs[m_MaxRecentFiles]; QAction *m_recentFileActs[m_MaxRecentFiles];
QAction *m_recentFileSeparator;
QAction *m_recentFileSubMenuAct; QAction *m_recentFileSubMenuAct;
QAction *m_exportAutoAct; QAction *m_exportAutoAct;
QAction *m_deleteSubPageAction; QAction *m_deleteSubPageAction;