diff --git a/OSBindings/Qt/ClockSignal.pro b/OSBindings/Qt/ClockSignal.pro index 8d8ce6204..57e7ccb10 100644 --- a/OSBindings/Qt/ClockSignal.pro +++ b/OSBindings/Qt/ClockSignal.pro @@ -252,6 +252,7 @@ HEADERS += \ functionthread.h \ mainwindow.h \ scantargetwidget.h \ + settings.h \ timer.h FORMS += \ diff --git a/OSBindings/Qt/mainwindow.cpp b/OSBindings/Qt/mainwindow.cpp index 06e5e8410..c6b391414 100644 --- a/OSBindings/Qt/mainwindow.cpp +++ b/OSBindings/Qt/mainwindow.cpp @@ -3,6 +3,7 @@ #include #include "mainwindow.h" +#include "settings.h" #include "timer.h" #include "../../Numeric/CRC.hpp" @@ -15,38 +16,54 @@ affect the window, so isn't useful for this project). Therefore the emulation window resizes freely. */ -MainWindow::MainWindow(QWidget *parent) - : QMainWindow(parent) - , ui(new Ui::MainWindow) -{ - ui->setupUi(this); - createActions(); +MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { + init(); + setVisibleWidgetSet(WidgetSet::MachinePicker); +} + +MainWindow::MainWindow(const QString &fileName) { + init(); + launchFile(fileName); +} + +void MainWindow::init() { qApp->installEventFilter(this); - timer = std::make_unique(this); - - setVisibleWidgetSet(WidgetSet::MachinePicker); + ui = std::make_unique(); + ui->setupUi(this); romRequestBaseText = ui->missingROMsBox->toPlainText(); + + createActions(); + restoreSelections(); + + timer = std::make_unique(this); } void MainWindow::createActions() { // Create a file menu. - QMenu *fileMenu = menuBar()->addMenu(tr("&File")); + QMenu *const fileMenu = menuBar()->addMenu(tr("&File")); - // Add file option: 'New...' - QAction *newAct = new QAction(tr("&New"), this); + // Add file option: 'New' + QAction *const newAct = new QAction(tr("&New"), this); newAct->setShortcuts(QKeySequence::New); newAct->setStatusTip(tr("Create a new file")); connect(newAct, &QAction::triggered, this, &MainWindow::newFile); fileMenu->addAction(newAct); // Add file option: 'Open...' - QAction *openAct = new QAction(tr("&Open..."), this); + QAction *const openAct = new QAction(tr("&Open..."), this); openAct->setShortcuts(QKeySequence::Open); openAct->setStatusTip(tr("Open an existing file")); connect(openAct, &QAction::triggered, this, &MainWindow::open); fileMenu->addAction(openAct); + // Add a separator and then an 'Insert...'. + fileMenu->addSeparator(); + QAction *const insertAct = new QAction(tr("&Insert..."), this); + insertAct->setStatusTip(tr("Open an existing file")); + connect(insertAct, &QAction::triggered, this, &MainWindow::insert); + fileMenu->addAction(insertAct); + // Add Help menu, with an 'About...' option. QMenu *helpMenu = menuBar()->addMenu(tr("&Help")); QAction *aboutAct = helpMenu->addAction(tr("&About"), this, &MainWindow::about); @@ -59,26 +76,61 @@ void MainWindow::createActions() { void MainWindow::open() { QString fileName = QFileDialog::getOpenFileName(this); if(!fileName.isEmpty()) { - targets = Analyser::Static::GetTargets(fileName.toStdString()); - if(!targets.empty()) { - launchMachine(); + // My understanding of SDI: if a file was opened for a 'vacant' window, launch it directly there; + // otherwise create a new window for it. + if(machine) { + MainWindow *const other = new MainWindow(fileName); + other->tile(this); + other->show(); + } else { + launchFile(fileName); } } } -void MainWindow::newFile() { +void MainWindow::insert() { } +void MainWindow::launchFile(const QString &fileName) { + targets = Analyser::Static::GetTargets(fileName.toStdString()); + if(!targets.empty()) { + launchMachine(); + } +} + +void MainWindow::newFile() { + MainWindow *other = new MainWindow; + other->tile(this); + other->show(); +} + +void MainWindow::tile(const QMainWindow *previous) +{ + // This entire function is essentially verbatim from the Qt SDI example. + if (!previous) + return; + + int topFrameWidth = previous->geometry().top() - previous->pos().y(); + if (!topFrameWidth) + topFrameWidth = 40; + + const QPoint pos = previous->pos() + 2 * QPoint(topFrameWidth, topFrameWidth); + if (screen()->availableGeometry().contains(rect().bottomRight() + pos)) + move(pos); +} + + void MainWindow::about() { QMessageBox::about(this, tr("About Clock Signal"), - tr( "

Clock Signal is an emulator of various platforms by " - "Thomas Harte.

" + tr( "

Clock Signal is an emulator of various platforms.

" "

This emulator is offered under the MIT licence; its source code " "is available from GitHub.

" "

This port is experimental, especially with regard to latency; " - "please don't hesitate to provide feedback.

" + "please don't hesitate to provide feedback, " + "by email or via the " + "GitHub issue tracker.

" )); } @@ -94,6 +146,9 @@ MainWindow::~MainWindow() { }); audioThread.stop(); } + + // Store the current user selections. + storeSelections(); } // MARK: Machine launch. @@ -424,7 +479,6 @@ void MainWindow::startMachine() { #define TEST(x) \ if(selectedTab == ui->x ## Tab) { \ - qDebug() << #x; \ start_##x(); \ return; \ } @@ -602,3 +656,14 @@ void MainWindow::launchTarget(std::unique_ptr &&target targets.push_back(std::move(target)); launchMachine(); } + +// MARK - UI state + +void MainWindow::storeSelections() { + Settings settings; + + settings.setValue("machineSelection", ui->machineSelectionTabs->currentIndex()); +} + +void MainWindow::restoreSelections() { +} diff --git a/OSBindings/Qt/mainwindow.h b/OSBindings/Qt/mainwindow.h index e1953df31..a9846b8db 100644 --- a/OSBindings/Qt/mainwindow.h +++ b/OSBindings/Qt/mainwindow.h @@ -25,6 +25,7 @@ class MainWindow : public QMainWindow, public Outputs::Speaker::Speaker::Delegat public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); + explicit MainWindow(const QString &fileName); protected: bool eventFilter(QObject *obj, QEvent *event) override; @@ -70,6 +71,7 @@ class MainWindow : public QMainWindow, public Outputs::Speaker::Speaker::Delegat void open(); void newFile(); void about(); + void insert(); void startMachine(); private: @@ -84,7 +86,14 @@ class MainWindow : public QMainWindow, public Outputs::Speaker::Speaker::Delegat void start_zx80(); void start_zx81(); + void launchFile(const QString &fileName); void launchTarget(std::unique_ptr &&); + + void restoreSelections(); + void storeSelections(); + + void init(); + void tile(const QMainWindow *previous); }; #endif // MAINWINDOW_H diff --git a/OSBindings/Qt/settings.h b/OSBindings/Qt/settings.h new file mode 100644 index 000000000..234d8a8d9 --- /dev/null +++ b/OSBindings/Qt/settings.h @@ -0,0 +1,11 @@ +#ifndef SETTINGS_H +#define SETTINGS_H + +#include + +class Settings: public QSettings { + public: + Settings() : QSettings("thomasharte", "Clock Signal") {} +}; + +#endif // SETTINGS_H