Moved QApplication instance to main Application class
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
#include "Application.hpp"
|
#include "Application.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <QTimer>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@@ -20,6 +21,15 @@ namespace Bloom
|
|||||||
|
|
||||||
Application::Application(std::vector<std::string>&& arguments)
|
Application::Application(std::vector<std::string>&& arguments)
|
||||||
: arguments(std::move(arguments))
|
: arguments(std::move(arguments))
|
||||||
|
, qtApplication(
|
||||||
|
(
|
||||||
|
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true),
|
||||||
|
#ifndef BLOOM_DEBUG_BUILD
|
||||||
|
QCoreApplication::addLibraryPath(QString::fromStdString(Services::PathService::applicationDirPath() + "/plugins")),
|
||||||
|
#endif
|
||||||
|
QApplication(this->qtApplicationArgc, this->qtApplicationArgv.data())
|
||||||
|
)
|
||||||
|
)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
int Application::run() {
|
int Application::run() {
|
||||||
@@ -57,21 +67,22 @@ namespace Bloom
|
|||||||
this->startup();
|
this->startup();
|
||||||
|
|
||||||
#ifndef EXCLUDE_INSIGHT
|
#ifndef EXCLUDE_INSIGHT
|
||||||
this->insightActivationPending = this->insightConfig->activateOnStartup;
|
if (this->insightConfig->activateOnStartup) {
|
||||||
#endif
|
this->activateInsight();
|
||||||
|
|
||||||
// Main event loop
|
|
||||||
while (Thread::getThreadState() == ThreadState::READY) {
|
|
||||||
#ifndef EXCLUDE_INSIGHT
|
|
||||||
if (this->insightActivationPending) {
|
|
||||||
this->insightActivationPending = false;
|
|
||||||
this->startInsight();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
this->applicationEventListener->waitAndDispatch();
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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->qtApplication));
|
||||||
|
QObject::connect(eventDispatchTimer, &QTimer::timeout, this, &Application::dispatchEvents);
|
||||||
|
eventDispatchTimer->start(100);
|
||||||
|
|
||||||
|
this->qtApplication.exec();
|
||||||
|
|
||||||
} catch (const InvalidConfig& exception) {
|
} catch (const InvalidConfig& exception) {
|
||||||
Logger::error("Invalid project configuration (bloom.yaml) - " + exception.getMessage());
|
Logger::error("Invalid project configuration (bloom.yaml) - " + exception.getMessage());
|
||||||
@@ -176,6 +187,7 @@ namespace Bloom
|
|||||||
this->stopSignalHandler();
|
this->stopSignalHandler();
|
||||||
|
|
||||||
this->saveProjectSettings();
|
this->saveProjectSettings();
|
||||||
|
this->qtApplication.exit(0);
|
||||||
Thread::threadState = ThreadState::STOPPED;
|
Thread::threadState = ThreadState::STOPPED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -498,8 +510,12 @@ namespace Bloom
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Application::dispatchEvents() {
|
||||||
|
this->applicationEventListener->dispatchCurrentEvents();
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef EXCLUDE_INSIGHT
|
#ifndef EXCLUDE_INSIGHT
|
||||||
void Application::startInsight() {
|
void Application::activateInsight() {
|
||||||
assert(!this->insight);
|
assert(!this->insight);
|
||||||
|
|
||||||
this->insight = std::make_unique<Insight>(
|
this->insight = std::make_unique<Insight>(
|
||||||
@@ -507,29 +523,21 @@ namespace Bloom
|
|||||||
this->projectConfig.value(),
|
this->projectConfig.value(),
|
||||||
this->environmentConfig.value(),
|
this->environmentConfig.value(),
|
||||||
this->insightConfig.value(),
|
this->insightConfig.value(),
|
||||||
this->projectSettings.value().insightSettings
|
this->projectSettings.value().insightSettings,
|
||||||
|
&(this->qtApplication)
|
||||||
);
|
);
|
||||||
|
|
||||||
/*
|
this->insight->activate();
|
||||||
* Before letting Insight occupy the main thread, process any pending events that accumulated
|
|
||||||
* during startup.
|
|
||||||
*/
|
|
||||||
this->applicationEventListener->dispatchCurrentEvents();
|
|
||||||
|
|
||||||
if (Thread::getThreadState() == ThreadState::READY) {
|
|
||||||
this->insight->run();
|
|
||||||
Logger::debug("Insight closed");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::onInsightActivationRequest(const Events::InsightActivationRequested&) {
|
void Application::onInsightActivationRequest(const Events::InsightActivationRequested&) {
|
||||||
if (this->insight) {
|
if (this->insight) {
|
||||||
// Insight has already been started
|
// Insight has already been activated
|
||||||
this->insight->showMainWindow();
|
this->insight->showMainWindow();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->insightActivationPending = true;
|
this->activateInsight();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -540,7 +548,7 @@ namespace Bloom
|
|||||||
|
|
||||||
void Application::onTargetControllerThreadStateChanged(const Events::TargetControllerThreadStateChanged& event) {
|
void Application::onTargetControllerThreadStateChanged(const Events::TargetControllerThreadStateChanged& event) {
|
||||||
if (event.getState() == ThreadState::STOPPED || event.getState() == ThreadState::SHUTDOWN_INITIATED) {
|
if (event.getState() == ThreadState::STOPPED || event.getState() == ThreadState::SHUTDOWN_INITIATED) {
|
||||||
// TargetController has unexpectedly shutdown - it must have encountered a fatal error.
|
// TargetController has unexpectedly shutdown.
|
||||||
this->shutdown();
|
this->shutdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <optional>
|
#include <optional>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <QtCore/QtCore>
|
#include <QtCore/QtCore>
|
||||||
|
#include <QApplication>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include "src/Helpers/Thread.hpp"
|
#include "src/Helpers/Thread.hpp"
|
||||||
@@ -35,8 +36,10 @@ namespace Bloom
|
|||||||
* This is the main entry-point of execution for the Bloom program. The methods within will run on the main
|
* This is the main entry-point of execution for the Bloom program. The methods within will run on the main
|
||||||
* thread. If Insight is enabled, execution will be passed over to Insight::run() upon start up.
|
* thread. If Insight is enabled, execution will be passed over to Insight::run() upon start up.
|
||||||
*/
|
*/
|
||||||
class Application: public Thread
|
class Application: public QObject, public Thread
|
||||||
{
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const inline VersionNumber VERSION = VersionNumber(std::string(BLOOM_VERSION));
|
static const inline VersionNumber VERSION = VersionNumber(std::string(BLOOM_VERSION));
|
||||||
|
|
||||||
@@ -52,6 +55,11 @@ namespace Bloom
|
|||||||
private:
|
private:
|
||||||
std::vector<std::string> arguments;
|
std::vector<std::string> arguments;
|
||||||
|
|
||||||
|
std::string qtApplicationName = "Bloom";
|
||||||
|
std::array<char*, 1> qtApplicationArgv = {this->qtApplicationName.data()};
|
||||||
|
int qtApplicationArgc = 1;
|
||||||
|
QApplication qtApplication;
|
||||||
|
|
||||||
EventListenerPointer applicationEventListener = std::make_shared<EventListener>("ApplicationEventListener");
|
EventListenerPointer applicationEventListener = std::make_shared<EventListener>("ApplicationEventListener");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -238,13 +246,18 @@ namespace Bloom
|
|||||||
*/
|
*/
|
||||||
void stopDebugServer();
|
void stopDebugServer();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatches any pending events. This function will be called periodically, via a QTimer.
|
||||||
|
*/
|
||||||
|
void dispatchEvents();
|
||||||
|
|
||||||
#ifndef EXCLUDE_INSIGHT
|
#ifndef EXCLUDE_INSIGHT
|
||||||
/**
|
/**
|
||||||
* Starts the Insight GUI.
|
* Activate the Insight GUI.
|
||||||
*
|
*
|
||||||
* This function should never be called more than once.
|
* This function should never be called more than once.
|
||||||
*/
|
*/
|
||||||
void startInsight();
|
void activateInsight();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles requests to start the Insight GUI.
|
* Handles requests to start the Insight GUI.
|
||||||
|
|||||||
@@ -28,52 +28,24 @@ namespace Bloom
|
|||||||
const ProjectConfig& projectConfig,
|
const ProjectConfig& projectConfig,
|
||||||
const EnvironmentConfig& environmentConfig,
|
const EnvironmentConfig& environmentConfig,
|
||||||
const InsightConfig& insightConfig,
|
const InsightConfig& insightConfig,
|
||||||
InsightProjectSettings& insightProjectSettings
|
InsightProjectSettings& insightProjectSettings,
|
||||||
|
QApplication* parent
|
||||||
)
|
)
|
||||||
: eventListener(eventListener)
|
: QObject(parent)
|
||||||
|
, eventListener(eventListener)
|
||||||
, projectConfig(projectConfig)
|
, projectConfig(projectConfig)
|
||||||
, environmentConfig(environmentConfig)
|
, environmentConfig(environmentConfig)
|
||||||
, insightConfig(insightConfig)
|
, insightConfig(insightConfig)
|
||||||
, insightProjectSettings(insightProjectSettings)
|
, insightProjectSettings(insightProjectSettings)
|
||||||
, application(
|
|
||||||
(
|
|
||||||
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true),
|
|
||||||
#ifndef BLOOM_DEBUG_BUILD
|
|
||||||
QCoreApplication::addLibraryPath(QString::fromStdString(Services::PathService::applicationDirPath() + "/plugins")),
|
|
||||||
#endif
|
|
||||||
QApplication(this->qtApplicationArgc, this->qtApplicationArgv.data())
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void Insight::run() {
|
|
||||||
try {
|
|
||||||
this->startup();
|
|
||||||
|
|
||||||
this->threadState = ThreadState::READY;
|
|
||||||
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::showMainWindow() {
|
void Insight::showMainWindow() {
|
||||||
this->mainWindow->show();
|
this->mainWindow->show();
|
||||||
this->mainWindow->activateWindow();
|
this->mainWindow->activateWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Insight::startup() {
|
void Insight::activate() {
|
||||||
Logger::info("Starting Insight");
|
Logger::info("Starting Insight");
|
||||||
this->threadState = ThreadState::STARTING;
|
|
||||||
|
|
||||||
this->eventListener.registerCallbackForEventType<Events::TargetExecutionStopped>(
|
this->eventListener.registerCallbackForEventType<Events::TargetExecutionStopped>(
|
||||||
std::bind(&Insight::onTargetStoppedEvent, this, std::placeholders::_1)
|
std::bind(&Insight::onTargetStoppedEvent, this, std::placeholders::_1)
|
||||||
@@ -116,8 +88,6 @@ namespace Bloom
|
|||||||
throw Exception("Failed to open global stylesheet file");
|
throw Exception("Failed to open global stylesheet file");
|
||||||
}
|
}
|
||||||
|
|
||||||
this->application.setStyleSheet(globalStylesheet.readAll());
|
|
||||||
|
|
||||||
qRegisterMetaType<Bloom::Targets::TargetDescriptor>();
|
qRegisterMetaType<Bloom::Targets::TargetDescriptor>();
|
||||||
qRegisterMetaType<Bloom::Targets::TargetPinDescriptor>();
|
qRegisterMetaType<Bloom::Targets::TargetPinDescriptor>();
|
||||||
qRegisterMetaType<Bloom::Targets::TargetPinState>();
|
qRegisterMetaType<Bloom::Targets::TargetPinState>();
|
||||||
@@ -168,16 +138,6 @@ namespace Bloom
|
|||||||
QString::fromStdString(Services::PathService::resourcesDirPath() + "/fonts/Ubuntu/Ubuntu-Th.ttf")
|
QString::fromStdString(Services::PathService::resourcesDirPath() + "/fonts/Ubuntu/Ubuntu-Th.ttf")
|
||||||
);
|
);
|
||||||
|
|
||||||
/*
|
|
||||||
* 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));
|
|
||||||
QObject::connect(eventDispatchTimer, &QTimer::timeout, this, &Insight::dispatchEvents);
|
|
||||||
eventDispatchTimer->start(100);
|
|
||||||
|
|
||||||
QObject::connect(
|
QObject::connect(
|
||||||
this->mainWindow,
|
this->mainWindow,
|
||||||
&InsightWindow::activatedSignal,
|
&InsightWindow::activatedSignal,
|
||||||
@@ -185,6 +145,8 @@ namespace Bloom
|
|||||||
&Insight::onInsightWindowActivated
|
&Insight::onInsightWindowActivated
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this->mainWindow->setStyleSheet(globalStylesheet.readAll());
|
||||||
|
|
||||||
this->mainWindow->setInsightConfig(this->insightConfig);
|
this->mainWindow->setInsightConfig(this->insightConfig);
|
||||||
this->mainWindow->setEnvironmentConfig(this->environmentConfig);
|
this->mainWindow->setEnvironmentConfig(this->environmentConfig);
|
||||||
|
|
||||||
@@ -212,10 +174,6 @@ namespace Bloom
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Insight::shutdown() {
|
void Insight::shutdown() {
|
||||||
if (this->getThreadState() == ThreadState::STOPPED) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger::info("Shutting down Insight");
|
Logger::info("Shutting down Insight");
|
||||||
|
|
||||||
this->mainWindow->close();
|
this->mainWindow->close();
|
||||||
@@ -230,9 +188,6 @@ namespace Bloom
|
|||||||
workerThread->wait();
|
workerThread->wait();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this->application.exit(0);
|
|
||||||
this->threadState = ThreadState::STOPPED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Insight::checkBloomVersion() {
|
void Insight::checkBloomVersion() {
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ namespace Bloom
|
|||||||
*
|
*
|
||||||
* The Insight component occupies the Bloom's main thread. See Application::run() for more.
|
* The Insight component occupies the Bloom's main thread. See Application::run() for more.
|
||||||
*/
|
*/
|
||||||
class Insight: public QObject, public Thread
|
class Insight: public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@@ -53,13 +53,14 @@ namespace Bloom
|
|||||||
const ProjectConfig& projectConfig,
|
const ProjectConfig& projectConfig,
|
||||||
const EnvironmentConfig& environmentConfig,
|
const EnvironmentConfig& environmentConfig,
|
||||||
const InsightConfig& insightConfig,
|
const InsightConfig& insightConfig,
|
||||||
InsightProjectSettings& insightProjectSettings
|
InsightProjectSettings& insightProjectSettings,
|
||||||
|
QApplication* parent
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Entry point for Insight.
|
* Entry point for Insight.
|
||||||
*/
|
*/
|
||||||
void run();
|
void activate();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens main window and obtains focus.
|
* Opens main window and obtains focus.
|
||||||
@@ -73,9 +74,6 @@ namespace Bloom
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr std::uint8_t INSIGHT_WORKER_COUNT = 3;
|
static constexpr std::uint8_t INSIGHT_WORKER_COUNT = 3;
|
||||||
std::string qtApplicationName = "Bloom";
|
|
||||||
std::array<char*, 1> qtApplicationArgv = {this->qtApplicationName.data()};
|
|
||||||
int qtApplicationArgc = 1;
|
|
||||||
|
|
||||||
ProjectConfig projectConfig;
|
ProjectConfig projectConfig;
|
||||||
EnvironmentConfig environmentConfig;
|
EnvironmentConfig environmentConfig;
|
||||||
@@ -86,8 +84,6 @@ namespace Bloom
|
|||||||
EventListener& eventListener;
|
EventListener& eventListener;
|
||||||
Services::TargetControllerService targetControllerService = Services::TargetControllerService();
|
Services::TargetControllerService targetControllerService = Services::TargetControllerService();
|
||||||
|
|
||||||
QApplication application;
|
|
||||||
|
|
||||||
std::map<decltype(InsightWorker::id), std::pair<InsightWorker*, QThread*>> insightWorkersById;
|
std::map<decltype(InsightWorker::id), std::pair<InsightWorker*, QThread*>> insightWorkersById;
|
||||||
InsightWindow* mainWindow = new InsightWindow(
|
InsightWindow* mainWindow = new InsightWindow(
|
||||||
this->environmentConfig,
|
this->environmentConfig,
|
||||||
@@ -102,8 +98,6 @@ namespace Bloom
|
|||||||
|
|
||||||
InsightSignals* insightSignals = InsightSignals::instance();
|
InsightSignals* insightSignals = InsightSignals::instance();
|
||||||
|
|
||||||
void startup();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Queries the Bloom server for the latest version number. If the current version number doesn't match the
|
* Queries the Bloom server for the latest version number. If the current version number doesn't match the
|
||||||
* latest version number returned by the server, we'll display a warning in the logs to instruct the user to
|
* latest version number returned by the server, we'll display a warning in the logs to instruct the user to
|
||||||
@@ -111,17 +105,6 @@ namespace Bloom
|
|||||||
*/
|
*/
|
||||||
void checkBloomVersion();
|
void checkBloomVersion();
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispatches any events currently in the queue.
|
|
||||||
*
|
|
||||||
* Because Insight is effectively a Qt application, we cannot use our own event loop. We must use Qt's event
|
|
||||||
* loop. We do this by utilizing a QTimer instance to call this method on an interval.
|
|
||||||
* See Insight::startup() for more.
|
|
||||||
*/
|
|
||||||
void dispatchEvents() {
|
|
||||||
this->eventListener.dispatchCurrentEvents();
|
|
||||||
};
|
|
||||||
|
|
||||||
void onInsightWindowActivated();
|
void onInsightWindowActivated();
|
||||||
void onTargetStoppedEvent(const Events::TargetExecutionStopped& event);
|
void onTargetStoppedEvent(const Events::TargetExecutionStopped& event);
|
||||||
void onTargetResumedEvent(const Events::TargetExecutionResumed& event);
|
void onTargetResumedEvent(const Events::TargetExecutionResumed& event);
|
||||||
|
|||||||
Reference in New Issue
Block a user