Files
BloomPatched/src/Insight/Insight.cpp

136 lines
5.4 KiB
C++
Raw Normal View History

2021-04-04 21:04:12 +01:00
#include <typeindex>
#include <QTimer>
#include "Insight.hpp"
#include "InsightWorker.hpp"
#include "src/Helpers/Paths.hpp"
2021-04-04 21:04:12 +01:00
#include "src/Logger/Logger.hpp"
#include "src/Exceptions/InvalidConfig.hpp"
#include "src/Targets/TargetState.hpp"
using namespace Bloom;
using namespace Bloom::Events;
using namespace Bloom::Exceptions;
2021-04-04 21:04:12 +01:00
void Insight::run() {
try {
this->startup();
this->workerThread->start();
this->setThreadState(ThreadState::READY);
2021-04-04 21:04:12 +01:00
Logger::info("Insight ready");
this->application->exec();
} catch (const Exception& exception) {
Logger::error("Insight encountered a fatal error. See below for errors:");
Logger::error(exception.getMessage());
} catch (const std::exception& exception) {
Logger::error("Insight encountered a fatal error. See below for errors:");
Logger::error(std::string(exception.what()));
}
this->shutdown();
}
void Insight::startup() {
Logger::info("Starting Insight");
this->setThreadState(ThreadState::STARTING);
2021-04-04 21:04:12 +01:00
this->eventManager.registerListener(this->eventListener);
this->eventListener->registerCallbackForEventType<ShutdownApplication>(
std::bind(&Insight::onShutdownApplicationEvent, this, std::placeholders::_1)
);
this->eventListener->registerCallbackForEventType<TargetControllerThreadStateChanged>(
std::bind(&Insight::onTargetControllerThreadStateChangedEvent, this, std::placeholders::_1)
2021-04-04 21:04:12 +01:00
);
auto targetDescriptor = this->targetControllerConsole.getTargetDescriptor();
2021-04-04 21:04:12 +01:00
#ifndef BLOOM_DEBUG_BUILD
QCoreApplication::addLibraryPath(QString::fromStdString(Paths::applicationDirPath() + "/plugins"));
#endif
2021-04-04 21:04:12 +01:00
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true);
this->application = new QApplication(this->qtApplicationArgc, this->qtApplicationArgv.data());
2021-04-04 21:04:12 +01:00
this->application->setQuitOnLastWindowClosed(true);
2021-05-30 16:53:24 +01:00
qRegisterMetaType<Bloom::Targets::TargetDescriptor>();
2021-04-04 21:04:12 +01:00
qRegisterMetaType<Bloom::Targets::TargetPinDescriptor>();
qRegisterMetaType<Bloom::Targets::TargetPinState>();
qRegisterMetaType<Bloom::Targets::TargetState>();
qRegisterMetaType<std::map<int, Bloom::Targets::TargetPinState>>();
2021-05-30 16:53:24 +01:00
this->mainWindow.setInsightConfig(this->insightConfig);
this->mainWindow.setEnvironmentConfig(this->environmentConfig);
this->mainWindow.init(
*(this->application),
2021-05-30 16:53:24 +01:00
targetDescriptor
);
2021-05-30 16:53:24 +01:00
2021-04-04 21:04:12 +01:00
this->mainWindow.show();
/*
* We can't run our own event loop here - we have to use Qt's event loop. But we still need to be able to
* process our events. To address this, we use a QTimer to dispatch our events on an interval.
*
* This allows us to use Qt's event loop whilst still being able to process our own events.
*/
auto eventDispatchTimer = new QTimer(this->application);
connect(eventDispatchTimer, &QTimer::timeout, this, &Insight::dispatchEvents);
eventDispatchTimer->start(100);
// Prepare worker thread
auto worker = new InsightWorker(this->eventManager);
this->workerThread = new QThread();
this->workerThread->setObjectName("IW");
worker->moveToThread(this->workerThread);
connect(this->workerThread, &QThread::started, worker, &InsightWorker::startup);
connect(this->workerThread, &QThread::finished, worker, &QObject::deleteLater);
connect(this->workerThread, &QThread::finished, this->workerThread, &QThread::deleteLater);
2021-05-30 16:53:24 +01:00
connect(worker, &InsightWorker::targetControllerSuspended, &(this->mainWindow), &InsightWindow::onTargetControllerSuspended);
connect(worker, &InsightWorker::targetControllerResumed, &(this->mainWindow), &InsightWindow::onTargetControllerResumed);
2021-04-04 21:04:12 +01:00
connect(worker, &InsightWorker::targetStateUpdated, &(this->mainWindow), &InsightWindow::onTargetStateUpdate);
connect(worker, &InsightWorker::targetProgramCounterUpdated, &(this->mainWindow), &InsightWindow::onTargetProgramCounterUpdate);
connect(worker, &InsightWorker::targetPinStatesUpdated, &(this->mainWindow), &InsightWindow::onTargetPinStatesUpdate);
connect(worker, &InsightWorker::targetIoPortsUpdated, &(this->mainWindow), &InsightWindow::onTargetIoPortsUpdate);
connect(&(this->mainWindow), &InsightWindow::refreshTargetPinStates, worker, &InsightWorker::requestPinStates);
connect(&(this->mainWindow), &InsightWindow::setTargetPinState, worker, &InsightWorker::requestPinStateUpdate);
}
void Insight::shutdown() {
if (this->getThreadState() == ThreadState::STOPPED) {
2021-04-04 21:04:12 +01:00
return;
}
Logger::info("Shutting down Insight");
this->mainWindow.close();
if (this->workerThread != nullptr && this->workerThread->isRunning()) {
this->workerThread->quit();
}
if (this->application != nullptr) {
this->application->exit(0);
}
this->setThreadState(ThreadState::STOPPED);
2021-04-04 21:04:12 +01:00
}
void Insight::onShutdownApplicationEvent(EventPointer<ShutdownApplication>) {
/*
* Once Insight shuts down, control of the main thread will be returned to Application::run(), which
* will pickup the ShutdownApplication event and proceed with the shutdown.
*/
this->shutdown();
}
void Insight::onTargetControllerThreadStateChangedEvent(EventPointer<TargetControllerThreadStateChanged> event) {
2021-04-04 21:04:12 +01:00
if (event->getState() == ThreadState::STOPPED) {
// Something horrible has happened with the TargetController - Insight is useless without the TargetController
this->shutdown();
}
}