Repository navigation
Expand file tree
/
Copy pathmain.cpp
More file actions
86 lines (72 loc) · 3.15 KB
/
Copy pathmain.cpp
File metadata and controls
86 lines (72 loc) · 3.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QDebug>
#include <QFileInfo>
#include <QLockFile>
#include <QTimer>
#include <QtQml>
#include "ui_controller.hpp"
#include "crash_logger.hpp"
#include "program_highlighter.hpp"
int main(int argc, char *argv[]) {
QGuiApplication app(argc, argv);
app.setApplicationName(QStringLiteral("tux-ti83"));
// Single-instance guard (BUG-024). Two instances sharing one state.json
// race on save (last write wins), silently dropping saved programs —
// most visibly after a rebuild if the old process is still running.
// The lock sits beside state.json; QLockFile auto-reclaims a stale lock
// left by a crashed process (dead PID), so this doesn't wedge on kill.
const QString lockPath =
QFileInfo(tux_ti83::UIController::stateFilePath()).absolutePath() +
QStringLiteral("/tux-ti83.lock");
QLockFile instanceLock(lockPath);
if (!instanceLock.tryLock(200)) {
qWarning() << "Another Tux-TI83 instance is already running — "
"exiting to protect saved state.";
return 0;
}
// Crash logger comes up before anything else so it captures the
// entire session — see graph_ui/include/crash_logger.hpp.
tux_ti83::CrashLogger::init();
// Create the engine first
QQmlApplicationEngine engine;
// Create the controller
static tux_ti83::UIController uiController;
// Restore previous session's variables / matrices / Y= buffers /
// MODE settings / viewport. Bails silently if no state file
// exists (first run) or it fails to parse — leaves the controller
// in default state in that case.
uiController.loadState();
// Periodic save — protects against crashes that skip the
// post-exec saveState(). Fires every 30s; saveState() is
// idempotent and cheap (single ~1 KB JSON file). Tests / CLI /
// REPL don't run a Qt event loop so no timer for them.
QTimer autoSaveTimer;
autoSaveTimer.setInterval(30 * 1000);
QObject::connect(&autoSaveTimer, &QTimer::timeout,
&uiController, &tux_ti83::UIController::saveState);
autoSaveTimer.start();
// EXPLICIT LINK: Register the controller BEFORE loading the file
engine.rootContext()->setContextProperty("uiController", &uiController);
// Syntax highlighter for the PRGM editor — usable from QML as
// `import Tux 1.0; ProgramHighlighter { textDocument: area.textDocument }`.
qmlRegisterType<tux_ti83::ProgramHighlighter>("Tux", 1, 0, "ProgramHighlighter");
const QUrl url("qrc:/App/Main.qml");
QObject::connect(&engine, &QQmlApplicationEngine::warnings, [](const QList<QQmlError> &warnings) {
for (const auto &error : warnings) {
qDebug() << "QML Error:" << error.toString();
}
});
engine.load(url);
if (engine.rootObjects().isEmpty()) {
tux_ti83::CrashLogger::shutdown();
return -1;
}
int rc = app.exec();
// Persist before the crash logger shuts down so a saveState
// failure still gets logged.
uiController.saveState();
tux_ti83::CrashLogger::shutdown();
return rc;
}