mirror of
https://github.com/ProtonMail/proton-bridge.git
synced 2025-12-22 18:16:43 +00:00
Other: C++ Code reformat.
This commit is contained in:
@ -30,8 +30,7 @@ using namespace bridgepp;
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The AppController instance.
|
||||
//****************************************************************************************************************************************************
|
||||
AppController &app()
|
||||
{
|
||||
AppController &app() {
|
||||
static AppController app;
|
||||
return app;
|
||||
}
|
||||
@ -43,24 +42,24 @@ AppController &app()
|
||||
AppController::AppController()
|
||||
: backend_(std::make_unique<QMLBackend>())
|
||||
, grpc_(std::make_unique<GRPCClient>())
|
||||
, log_(std::make_unique<Log>())
|
||||
{
|
||||
, log_(std::make_unique<Log>()) {
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The bridge worker, which can be null if the application was run in 'attach' mode (-a command-line switch).
|
||||
//****************************************************************************************************************************************************
|
||||
ProcessMonitor *AppController::bridgeMonitor() const
|
||||
{
|
||||
if (!bridgeOverseer_)
|
||||
ProcessMonitor *AppController::bridgeMonitor() const {
|
||||
if (!bridgeOverseer_) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// null bridgeOverseer is OK, it means we run in 'attached' mode (app attached to an already runnning instance of Bridge).
|
||||
// but if bridgeOverseer is not null, its attached worker must be a valid ProcessMonitor instance.
|
||||
auto *monitor = dynamic_cast<ProcessMonitor*>(bridgeOverseer_->worker());
|
||||
if (!monitor)
|
||||
auto *monitor = dynamic_cast<ProcessMonitor *>(bridgeOverseer_->worker());
|
||||
if (!monitor) {
|
||||
throw Exception("Could not retrieve bridge monitor");
|
||||
}
|
||||
|
||||
return monitor;
|
||||
}
|
||||
|
||||
@ -23,11 +23,16 @@
|
||||
class QMLBackend;
|
||||
|
||||
|
||||
namespace bridgepp
|
||||
{
|
||||
namespace bridgepp {
|
||||
class Log;
|
||||
|
||||
|
||||
class Overseer;
|
||||
|
||||
|
||||
class GRPCClient;
|
||||
|
||||
|
||||
class ProcessMonitor;
|
||||
}
|
||||
|
||||
@ -35,22 +40,21 @@ class ProcessMonitor;
|
||||
//****************************************************************************************************************************************************
|
||||
/// \brief App controller class.
|
||||
//****************************************************************************************************************************************************
|
||||
class AppController: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
friend AppController& app();
|
||||
class AppController : public QObject {
|
||||
Q_OBJECT
|
||||
friend AppController &app();
|
||||
|
||||
public: // member functions.
|
||||
AppController(AppController const&) = delete; ///< Disabled copy-constructor.
|
||||
AppController(AppController&&) = delete; ///< Disabled assignment copy-constructor.
|
||||
AppController(AppController const &) = delete; ///< Disabled copy-constructor.
|
||||
AppController(AppController &&) = delete; ///< Disabled assignment copy-constructor.
|
||||
~AppController() override = default; ///< Destructor.
|
||||
AppController& operator=(AppController const&) = delete; ///< Disabled assignment operator.
|
||||
AppController& operator=(AppController&&) = delete; ///< Disabled move assignment operator.
|
||||
QMLBackend& backend() { return *backend_; } ///< Return a reference to the backend.
|
||||
bridgepp::GRPCClient& grpc() { return *grpc_; } ///< Return a reference to the GRPC client.
|
||||
bridgepp::Log& log() { return *log_; } ///< Return a reference to the log.
|
||||
std::unique_ptr<bridgepp::Overseer>& bridgeOverseer() { return bridgeOverseer_; }; ///< Returns a reference the bridge overseer
|
||||
bridgepp::ProcessMonitor* bridgeMonitor() const; ///< Return the bridge worker.
|
||||
AppController &operator=(AppController const &) = delete; ///< Disabled assignment operator.
|
||||
AppController &operator=(AppController &&) = delete; ///< Disabled move assignment operator.
|
||||
QMLBackend &backend() { return *backend_; } ///< Return a reference to the backend.
|
||||
bridgepp::GRPCClient &grpc() { return *grpc_; } ///< Return a reference to the GRPC client.
|
||||
bridgepp::Log &log() { return *log_; } ///< Return a reference to the log.
|
||||
std::unique_ptr<bridgepp::Overseer> &bridgeOverseer() { return bridgeOverseer_; }; ///< Returns a reference the bridge overseer
|
||||
bridgepp::ProcessMonitor *bridgeMonitor() const; ///< Return the bridge worker.
|
||||
|
||||
private: // member functions
|
||||
AppController(); ///< Default constructor.
|
||||
@ -63,7 +67,7 @@ private: // data members
|
||||
};
|
||||
|
||||
|
||||
AppController& app(); ///< Return a reference to the app controller.
|
||||
AppController &app(); ///< Return a reference to the app controller.
|
||||
|
||||
|
||||
#endif // BRIDGE_GUI_APP_CONTROLLER_H
|
||||
|
||||
@ -23,8 +23,7 @@
|
||||
using namespace bridgepp;
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
namespace {
|
||||
|
||||
|
||||
QString const launcherFlag = "--launcher"; ///< launcher flag parameter used for bridge.
|
||||
@ -37,25 +36,25 @@ QString const softwareRendererFlag = "--software-renderer"; ///< The 'software-r
|
||||
/// \param[in] argv The list of arguments passed to the application.
|
||||
/// \param[in] paramNames the list of names for the parameter
|
||||
//****************************************************************************************************************************************************
|
||||
QString parseGoCLIStringArgument(int argc, char *argv[], QStringList paramNames)
|
||||
{
|
||||
QString parseGoCLIStringArgument(int argc, char *argv[], QStringList paramNames) {
|
||||
// go cli package is pretty permissive when it comes to parsing arguments. For each name 'param', all the following seems to be accepted:
|
||||
// -param value
|
||||
// --param value
|
||||
// -param=value
|
||||
// --param=value
|
||||
|
||||
for (QString const ¶mName: paramNames)
|
||||
for (qsizetype i = 1; i < argc; ++i)
|
||||
{
|
||||
for (QString const ¶mName: paramNames) {
|
||||
for (qsizetype i = 1; i < argc; ++i) {
|
||||
QString const arg(QString::fromLocal8Bit(argv[i]));
|
||||
if ((i < argc - 1) && ((arg == "-" + paramName) || (arg == "--" + paramName)))
|
||||
if ((i < argc - 1) && ((arg == "-" + paramName) || (arg == "--" + paramName))) {
|
||||
return QString(argv[i + 1]);
|
||||
}
|
||||
|
||||
QRegularExpressionMatch match = QRegularExpression(QString("^-{1,2}%1=(.+)$").arg(paramName)).match(arg);
|
||||
if (match.hasMatch())
|
||||
if (match.hasMatch()) {
|
||||
return match.captured(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
@ -68,11 +67,11 @@ QString parseGoCLIStringArgument(int argc, char *argv[], QStringList paramNames)
|
||||
/// \param[in] argv The list of arguments passed to the application.
|
||||
/// \return The log level. if not specified on the command-line, the default log level is returned.
|
||||
//****************************************************************************************************************************************************
|
||||
Log::Level parseLogLevel(int argc, char *argv[])
|
||||
{
|
||||
Log::Level parseLogLevel(int argc, char *argv[]) {
|
||||
QString levelStr = parseGoCLIStringArgument(argc, argv, { "l", "log-level" });
|
||||
if (levelStr.isEmpty())
|
||||
if (levelStr.isEmpty()) {
|
||||
return Log::defaultLevel;
|
||||
}
|
||||
|
||||
Log::Level level = Log::defaultLevel;
|
||||
Log::stringToLevel(levelStr, level);
|
||||
@ -98,33 +97,29 @@ CommandLineOptions parseCommandLine(int argc, char *argv[]) {
|
||||
QString const &arg = QString::fromLocal8Bit(argv[i]);
|
||||
// we can't use QCommandLineParser here since it will fail on unknown options.
|
||||
// Arguments may contain some bridge flags.
|
||||
if (arg == softwareRendererFlag)
|
||||
if (arg == softwareRendererFlag) {
|
||||
options.useSoftwareRenderer = true;
|
||||
if (arg == noWindowFlag)
|
||||
{
|
||||
}
|
||||
if (arg == noWindowFlag) {
|
||||
options.noWindow = true;
|
||||
}
|
||||
if (arg == launcherFlag)
|
||||
{
|
||||
if (arg == launcherFlag) {
|
||||
options.bridgeArgs.append(arg);
|
||||
options.launcher = QString::fromLocal8Bit(argv[++i]);
|
||||
options.bridgeArgs.append(options.launcher);
|
||||
flagFound = true;
|
||||
}
|
||||
#ifdef QT_DEBUG
|
||||
else if (arg == "--attach" || arg == "-a")
|
||||
{
|
||||
else if (arg == "--attach" || arg == "-a") {
|
||||
// we don't keep the attach mode within the args since we don't need it for Bridge.
|
||||
options.attach = true;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
else {
|
||||
options.bridgeArgs.append(arg);
|
||||
}
|
||||
}
|
||||
if (!flagFound)
|
||||
{
|
||||
if (!flagFound) {
|
||||
// add bridge-gui as launcher
|
||||
options.bridgeArgs.append(launcherFlag);
|
||||
options.bridgeArgs.append(options.launcher);
|
||||
|
||||
@ -22,6 +22,8 @@
|
||||
|
||||
|
||||
void setDockIconVisibleState(bool visible) { Q_UNUSED(visible) }
|
||||
|
||||
|
||||
bool getDockIconVisibleState() { return true; }
|
||||
|
||||
|
||||
|
||||
@ -30,8 +30,7 @@ using namespace bridgepp;
|
||||
/// \param[in] parent The parent object.
|
||||
//****************************************************************************************************************************************************
|
||||
EventStreamReader::EventStreamReader(QObject *parent)
|
||||
: Worker(parent)
|
||||
{
|
||||
: Worker(parent) {
|
||||
connect(this, &EventStreamReader::started, this, &EventStreamReader::onStarted);
|
||||
connect(this, &EventStreamReader::finished, this, &EventStreamReader::onFinished);
|
||||
connect(this, &EventStreamReader::error, &app().log(), &Log::error);
|
||||
@ -41,20 +40,18 @@ EventStreamReader::EventStreamReader(QObject *parent)
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void EventStreamReader::run()
|
||||
{
|
||||
try
|
||||
{
|
||||
void EventStreamReader::run() {
|
||||
try {
|
||||
emit started();
|
||||
|
||||
grpc::Status const status = app().grpc().runEventStreamReader();
|
||||
if (!status.ok())
|
||||
if (!status.ok()) {
|
||||
throw Exception(QString::fromStdString(status.error_message()));
|
||||
}
|
||||
|
||||
emit finished();
|
||||
}
|
||||
catch (Exception const &e)
|
||||
{
|
||||
catch (Exception const &e) {
|
||||
reportSentryException(SENTRY_LEVEL_ERROR, "Error during event stream read", "Exception", e.what());
|
||||
emit error(e.qwhat());
|
||||
}
|
||||
@ -64,8 +61,7 @@ void EventStreamReader::run()
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void EventStreamReader::onStarted() const
|
||||
{
|
||||
void EventStreamReader::onStarted() const {
|
||||
app().log().debug("EventStreamReader started");
|
||||
}
|
||||
|
||||
@ -73,11 +69,9 @@ void EventStreamReader::onStarted() const
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void EventStreamReader::onFinished() const
|
||||
{
|
||||
void EventStreamReader::onFinished() const {
|
||||
app().log().debug("EventStreamReader finished");
|
||||
if (!app().bridgeMonitor())
|
||||
{
|
||||
if (!app().bridgeMonitor()) {
|
||||
// no bridge monitor means we are in a debug environment, running in attached mode. Event stream has terminated, so bridge is shutting
|
||||
// down. Because we're in attached mode, bridge-gui will not get notified that bridge is going down, so we shutdown manually here.
|
||||
qApp->exit(EXIT_SUCCESS);
|
||||
|
||||
@ -26,16 +26,15 @@
|
||||
//****************************************************************************************************************************************************
|
||||
/// \brief Stream reader class.
|
||||
//****************************************************************************************************************************************************
|
||||
class EventStreamReader: public bridgepp::Worker
|
||||
{
|
||||
Q_OBJECT
|
||||
class EventStreamReader : public bridgepp::Worker {
|
||||
Q_OBJECT
|
||||
public: // member functions
|
||||
explicit EventStreamReader(QObject *parent); ///< Default constructor.
|
||||
EventStreamReader(EventStreamReader const&) = delete; ///< Disabled copy-constructor.
|
||||
EventStreamReader(EventStreamReader&&) = delete; ///< Disabled assignment copy-constructor.
|
||||
EventStreamReader(EventStreamReader const &) = delete; ///< Disabled copy-constructor.
|
||||
EventStreamReader(EventStreamReader &&) = delete; ///< Disabled assignment copy-constructor.
|
||||
~EventStreamReader() override = default; ///< Destructor.
|
||||
EventStreamReader& operator=(EventStreamReader const&) = delete; ///< Disabled assignment operator.
|
||||
EventStreamReader& operator=(EventStreamReader&&) = delete; ///< Disabled move assignment operator.
|
||||
EventStreamReader &operator=(EventStreamReader const &) = delete; ///< Disabled assignment operator.
|
||||
EventStreamReader &operator=(EventStreamReader &&) = delete; ///< Disabled move assignment operator.
|
||||
|
||||
public slots:
|
||||
void run() override; ///< Run the reader.
|
||||
|
||||
@ -31,38 +31,38 @@ using namespace bridgepp;
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
QMLBackend::QMLBackend()
|
||||
: QObject()
|
||||
{
|
||||
: QObject() {
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] serviceConfig
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::init(GRPCConfig const &serviceConfig)
|
||||
{
|
||||
void QMLBackend::init(GRPCConfig const &serviceConfig) {
|
||||
users_ = new UserList(this);
|
||||
|
||||
Log& log = app().log();
|
||||
Log &log = app().log();
|
||||
log.info(QString("Connecting to gRPC service"));
|
||||
app().grpc().setLog(&log);
|
||||
this->connectGrpcEvents();
|
||||
|
||||
QString error;
|
||||
if (app().grpc().connectToServer(serviceConfig, app().bridgeMonitor(), error))
|
||||
if (app().grpc().connectToServer(serviceConfig, app().bridgeMonitor(), error)) {
|
||||
app().log().info("Connected to backend via gRPC service.");
|
||||
else
|
||||
} else {
|
||||
throw Exception(QString("Cannot connectToServer to go backend via gRPC: %1").arg(error));
|
||||
}
|
||||
|
||||
QString bridgeVer;
|
||||
app().grpc().version(bridgeVer);
|
||||
if (bridgeVer != PROJECT_VER)
|
||||
if (bridgeVer != PROJECT_VER) {
|
||||
throw Exception(QString("Version Mismatched from Bridge (%1) and Bridge-GUI (%2)").arg(bridgeVer, PROJECT_VER));
|
||||
}
|
||||
|
||||
eventStreamOverseer_ = std::make_unique<Overseer>(new EventStreamReader(nullptr), nullptr);
|
||||
eventStreamOverseer_->startWorker(true);
|
||||
|
||||
connect(&app().log(), &Log::entryAdded, [&](Log::Level level, QString const& message) {
|
||||
connect(&app().log(), &Log::entryAdded, [&](Log::Level level, QString const &message) {
|
||||
app().grpc().addLogEntry(level, "frontend/bridge-gui", message);
|
||||
});
|
||||
|
||||
@ -87,8 +87,7 @@ void QMLBackend::init(GRPCConfig const &serviceConfig)
|
||||
/// never times out.
|
||||
/// \return false if and only if the timeout delay was reached.
|
||||
//****************************************************************************************************************************************************
|
||||
bool QMLBackend::waitForEventStreamReaderToFinish(qint32 timeoutMs)
|
||||
{
|
||||
bool QMLBackend::waitForEventStreamReaderToFinish(qint32 timeoutMs) {
|
||||
return eventStreamOverseer_->wait(timeoutMs);
|
||||
}
|
||||
|
||||
@ -96,12 +95,11 @@ bool QMLBackend::waitForEventStreamReaderToFinish(qint32 timeoutMs)
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::connectGrpcEvents()
|
||||
{
|
||||
void QMLBackend::connectGrpcEvents() {
|
||||
GRPCClient *client = &app().grpc();
|
||||
|
||||
// app events
|
||||
connect(client, &GRPCClient::internetStatus, this, [&](bool isOn) { if (isOn) emit internetOn(); else emit internetOff(); });
|
||||
connect(client, &GRPCClient::internetStatus, this, [&](bool isOn) { if (isOn) { emit internetOn(); } else { emit internetOff(); }});
|
||||
connect(client, &GRPCClient::toggleAutostartFinished, this, &QMLBackend::toggleAutostartFinished);
|
||||
connect(client, &GRPCClient::resetFinished, this, &QMLBackend::onResetFinished);
|
||||
connect(client, &GRPCClient::reportBugFinished, this, &QMLBackend::reportBugFinished);
|
||||
@ -174,8 +172,7 @@ void QMLBackend::connectGrpcEvents()
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::retrieveUserList()
|
||||
{
|
||||
void QMLBackend::retrieveUserList() {
|
||||
QList<SPUser> newUsers;
|
||||
app().grpc().getUserList(newUsers);
|
||||
|
||||
@ -184,23 +181,22 @@ void QMLBackend::retrieveUserList()
|
||||
// " When data is transferred from C++ to QML, the ownership of the data always remains with C++. The exception to this rule
|
||||
// is when a QObject is returned from an explicit C++ method call: in this case, the QML engine assumes ownership of the object. "
|
||||
// This is the case here, so we explicitly indicate that the object is owned by C++.
|
||||
for (SPUser const& user: newUsers)
|
||||
for (SPUser const &user: newUsers) {
|
||||
|
||||
for (qsizetype i = 0; i < newUsers.size(); ++i)
|
||||
{
|
||||
SPUser newUser = newUsers[i];
|
||||
SPUser existingUser = users_->getUserWithID(newUser->id());
|
||||
if (!existingUser)
|
||||
{
|
||||
// The user is new. We indicate to QML that it is managed by the C++ backend.
|
||||
QQmlEngine::setObjectOwnership(user.get(), QQmlEngine::CppOwnership);
|
||||
continue;
|
||||
for (qsizetype i = 0; i < newUsers.size(); ++i) {
|
||||
SPUser newUser = newUsers[i];
|
||||
SPUser existingUser = users_->getUserWithID(newUser->id());
|
||||
if (!existingUser) {
|
||||
// The user is new. We indicate to QML that it is managed by the C++ backend.
|
||||
QQmlEngine::setObjectOwnership(user.get(), QQmlEngine::CppOwnership);
|
||||
continue;
|
||||
}
|
||||
|
||||
// The user is already listed. QML code may have a pointer because of an ongoing process (for instance in the SetupGuide),
|
||||
// As a consequence we do not want to replace this existing user, but we want to update it.
|
||||
existingUser->update(*newUser);
|
||||
newUsers[i] = existingUser;
|
||||
}
|
||||
|
||||
// The user is already listed. QML code may have a pointer because of an ongoing process (for instance in the SetupGuide),
|
||||
// As a consequence we do not want to replace this existing user, but we want to update it.
|
||||
existingUser->update(*newUser);
|
||||
newUsers[i] = existingUser;
|
||||
}
|
||||
|
||||
users_->reset(newUsers);
|
||||
@ -210,8 +206,7 @@ void QMLBackend::retrieveUserList()
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
QPoint QMLBackend::getCursorPos()
|
||||
{
|
||||
QPoint QMLBackend::getCursorPos() {
|
||||
return QCursor::pos();
|
||||
}
|
||||
|
||||
@ -219,8 +214,7 @@ QPoint QMLBackend::getCursorPos()
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
bool QMLBackend::isPortFree(int port)
|
||||
{
|
||||
bool QMLBackend::isPortFree(int port) {
|
||||
bool isFree = false;
|
||||
app().grpc().isPortFree(port, isFree);
|
||||
return isFree;
|
||||
@ -230,8 +224,7 @@ bool QMLBackend::isPortFree(int port)
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return true the native local file path of the given URL.
|
||||
//****************************************************************************************************************************************************
|
||||
QString QMLBackend::nativePath(QUrl const &url)
|
||||
{
|
||||
QString QMLBackend::nativePath(QUrl const &url) {
|
||||
return QDir::toNativeSeparators(url.toLocalFile());
|
||||
}
|
||||
|
||||
@ -239,8 +232,7 @@ QString QMLBackend::nativePath(QUrl const &url)
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return true iff the two URL point to the same local file or folder.
|
||||
//****************************************************************************************************************************************************
|
||||
bool QMLBackend::areSameFileOrFolder(QUrl const &lhs, QUrl const &rhs)
|
||||
{
|
||||
bool QMLBackend::areSameFileOrFolder(QUrl const &lhs, QUrl const &rhs) {
|
||||
return QFileInfo(lhs.toLocalFile()) == QFileInfo(rhs.toLocalFile());
|
||||
}
|
||||
|
||||
@ -248,8 +240,7 @@ bool QMLBackend::areSameFileOrFolder(QUrl const &lhs, QUrl const &rhs)
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::guiReady()
|
||||
{
|
||||
void QMLBackend::guiReady() {
|
||||
app().grpc().guiReady();
|
||||
}
|
||||
|
||||
@ -257,8 +248,7 @@ void QMLBackend::guiReady()
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::quit()
|
||||
{
|
||||
void QMLBackend::quit() {
|
||||
app().grpc().quit();
|
||||
qApp->exit(0);
|
||||
}
|
||||
@ -267,8 +257,7 @@ void QMLBackend::quit()
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::restart()
|
||||
{
|
||||
void QMLBackend::restart() {
|
||||
app().grpc().restart();
|
||||
}
|
||||
|
||||
@ -276,8 +265,7 @@ void QMLBackend::restart()
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] launcher The path to the launcher.
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::forceLauncher(QString launcher)
|
||||
{
|
||||
void QMLBackend::forceLauncher(QString launcher) {
|
||||
app().grpc().forceLauncher(launcher);
|
||||
}
|
||||
|
||||
@ -285,8 +273,7 @@ void QMLBackend::forceLauncher(QString launcher)
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] active Should we activate autostart.
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::toggleAutostart(bool active)
|
||||
{
|
||||
void QMLBackend::toggleAutostart(bool active) {
|
||||
app().grpc().setIsAutostartOn(active);
|
||||
emit isAutostartOnChanged(this->isAutostartOn());
|
||||
}
|
||||
@ -295,17 +282,16 @@ void QMLBackend::toggleAutostart(bool active)
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] active The new state for the beta enabled property.
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::toggleBeta(bool active)
|
||||
{
|
||||
void QMLBackend::toggleBeta(bool active) {
|
||||
app().grpc().setIsBetaEnabled(active);
|
||||
emit isBetaEnabledChanged(this->isBetaEnabled());
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] active The new state for the All Mail visibility property.
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::changeIsAllMailVisible(bool isVisible)
|
||||
{
|
||||
void QMLBackend::changeIsAllMailVisible(bool isVisible) {
|
||||
app().grpc().setIsAllMailVisible(isVisible);
|
||||
emit isAllMailVisibleChanged(this->isAllMailVisible());
|
||||
}
|
||||
@ -314,17 +300,16 @@ void QMLBackend::changeIsAllMailVisible(bool isVisible)
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] scheme the scheme name
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::changeColorScheme(QString const &scheme)
|
||||
{
|
||||
void QMLBackend::changeColorScheme(QString const &scheme) {
|
||||
app().grpc().setColorSchemeName(scheme);
|
||||
emit colorSchemeNameChanged(this->colorSchemeName());
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] path The path of the disk cache.
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::setDiskCachePath(QUrl const &path) const
|
||||
{
|
||||
void QMLBackend::setDiskCachePath(QUrl const &path) const {
|
||||
app().grpc().setDiskCachePath(path);
|
||||
}
|
||||
|
||||
@ -332,8 +317,7 @@ void QMLBackend::setDiskCachePath(QUrl const &path) const
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The IMAP port.
|
||||
//****************************************************************************************************************************************************
|
||||
int QMLBackend::imapPort() const
|
||||
{
|
||||
int QMLBackend::imapPort() const {
|
||||
return imapPort_;
|
||||
}
|
||||
|
||||
@ -341,10 +325,10 @@ int QMLBackend::imapPort() const
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] port The IMAP port.
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::setIMAPPort(int port)
|
||||
{
|
||||
if (port == imapPort_)
|
||||
void QMLBackend::setIMAPPort(int port) {
|
||||
if (port == imapPort_) {
|
||||
return;
|
||||
}
|
||||
imapPort_ = port;
|
||||
emit imapPortChanged(port);
|
||||
}
|
||||
@ -353,8 +337,7 @@ void QMLBackend::setIMAPPort(int port)
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The SMTP port.
|
||||
//****************************************************************************************************************************************************
|
||||
int QMLBackend::smtpPort() const
|
||||
{
|
||||
int QMLBackend::smtpPort() const {
|
||||
return smtpPort_;
|
||||
}
|
||||
|
||||
@ -362,10 +345,10 @@ int QMLBackend::smtpPort() const
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] port The SMTP port.
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::setSMTPPort(int port)
|
||||
{
|
||||
if (port == smtpPort_)
|
||||
void QMLBackend::setSMTPPort(int port) {
|
||||
if (port == smtpPort_) {
|
||||
return;
|
||||
}
|
||||
smtpPort_ = port;
|
||||
emit smtpPortChanged(port);
|
||||
}
|
||||
@ -374,8 +357,7 @@ void QMLBackend::setSMTPPort(int port)
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The value for the 'Use SSL for IMAP' property.
|
||||
//****************************************************************************************************************************************************
|
||||
bool QMLBackend::useSSLForIMAP() const
|
||||
{
|
||||
bool QMLBackend::useSSLForIMAP() const {
|
||||
return useSSLForIMAP_;
|
||||
}
|
||||
|
||||
@ -383,10 +365,10 @@ bool QMLBackend::useSSLForIMAP() const
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] value The value for the 'Use SSL for IMAP' property.
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::setUseSSLForIMAP(bool value)
|
||||
{
|
||||
if (value == useSSLForIMAP_)
|
||||
void QMLBackend::setUseSSLForIMAP(bool value) {
|
||||
if (value == useSSLForIMAP_) {
|
||||
return;
|
||||
}
|
||||
useSSLForIMAP_ = value;
|
||||
emit useSSLForIMAPChanged(value);
|
||||
}
|
||||
@ -395,8 +377,7 @@ void QMLBackend::setUseSSLForIMAP(bool value)
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The value for the 'Use SSL for SMTP' property.
|
||||
//****************************************************************************************************************************************************
|
||||
bool QMLBackend::useSSLForSMTP() const
|
||||
{
|
||||
bool QMLBackend::useSSLForSMTP() const {
|
||||
return useSSLForSMTP_;
|
||||
}
|
||||
|
||||
@ -404,10 +385,10 @@ bool QMLBackend::useSSLForSMTP() const
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] value The value for the 'Use SSL for SMTP' property.
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::setUseSSLForSMTP(bool value)
|
||||
{
|
||||
if (value == useSSLForSMTP_)
|
||||
void QMLBackend::setUseSSLForSMTP(bool value) {
|
||||
if (value == useSSLForSMTP_) {
|
||||
return;
|
||||
}
|
||||
useSSLForSMTP_ = value;
|
||||
emit useSSLForSMTPChanged(value);
|
||||
}
|
||||
@ -419,8 +400,7 @@ void QMLBackend::setUseSSLForSMTP(bool value)
|
||||
/// \param[in] useSSLForIMAP The value for the 'Use SSL for IMAP' property
|
||||
/// \param[in] useSSLForSMTP The value for the 'Use SSL for SMTP' property
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::setMailServerSettings(int imapPort, int smtpPort, bool useSSLForIMAP, bool useSSLForSMTP)
|
||||
{
|
||||
void QMLBackend::setMailServerSettings(int imapPort, int smtpPort, bool useSSLForIMAP, bool useSSLForSMTP) {
|
||||
app().grpc().setMailServerSettings(imapPort, smtpPort, useSSLForIMAP, useSSLForSMTP);
|
||||
}
|
||||
|
||||
@ -429,8 +409,7 @@ void QMLBackend::setMailServerSettings(int imapPort, int smtpPort, bool useSSLFo
|
||||
/// \param[in] userID the userID.
|
||||
/// \param[in] wasSignedOut Was the user signed-out.
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::onLoginFinished(QString const &userID, bool wasSignedOut)
|
||||
{
|
||||
void QMLBackend::onLoginFinished(QString const &userID, bool wasSignedOut) {
|
||||
this->retrieveUserList();
|
||||
qint32 const index = users_->rowOfUserID(userID);
|
||||
emit loginFinished(index, wasSignedOut);
|
||||
@ -440,19 +419,18 @@ void QMLBackend::onLoginFinished(QString const &userID, bool wasSignedOut)
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] userID the userID.
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::onLoginAlreadyLoggedIn(QString const &userID)
|
||||
{
|
||||
void QMLBackend::onLoginAlreadyLoggedIn(QString const &userID) {
|
||||
this->retrieveUserList();
|
||||
qint32 const index = users_->rowOfUserID(userID);
|
||||
emit loginAlreadyLoggedIn(index);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] useSSLForIMAP The value for the 'Use SSL for IMAP' property
|
||||
/// \param[in] useSSLForSMTP The value for the 'Use SSL for SMTP' property
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::onMailServerSettingsChanged(int imapPort, int smtpPort, bool useSSLForIMAP, bool useSSLForSMTP)
|
||||
{
|
||||
void QMLBackend::onMailServerSettingsChanged(int imapPort, int smtpPort, bool useSSLForIMAP, bool useSSLForSMTP) {
|
||||
this->setIMAPPort(imapPort);
|
||||
this->setSMTPPort(smtpPort);
|
||||
this->setUseSSLForIMAP(useSSLForIMAP);
|
||||
@ -463,8 +441,7 @@ void QMLBackend::onMailServerSettingsChanged(int imapPort, int smtpPort, bool us
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::onGenericError(ErrorInfo const &info)
|
||||
{
|
||||
void QMLBackend::onGenericError(ErrorInfo const &info) {
|
||||
emit genericError(info.title, info.description);
|
||||
}
|
||||
|
||||
@ -472,38 +449,37 @@ void QMLBackend::onGenericError(ErrorInfo const &info)
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] active Should DoH be active.
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::toggleDoH(bool active)
|
||||
{
|
||||
if (app().grpc().setIsDoHEnabled(active).ok())
|
||||
void QMLBackend::toggleDoH(bool active) {
|
||||
if (app().grpc().setIsDoHEnabled(active).ok()) {
|
||||
emit isDoHEnabledChanged(active);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] keychain The new keychain.
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::changeKeychain(QString const &keychain)
|
||||
{
|
||||
if (app().grpc().setCurrentKeychain(keychain).ok())
|
||||
void QMLBackend::changeKeychain(QString const &keychain) {
|
||||
if (app().grpc().setCurrentKeychain(keychain).ok()) {
|
||||
emit currentKeychainChanged(keychain);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] active Should automatic update be turned on.
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::toggleAutomaticUpdate(bool active)
|
||||
{
|
||||
if (app().grpc().setIsAutomaticUpdateOn(active).ok())
|
||||
void QMLBackend::toggleAutomaticUpdate(bool active) {
|
||||
if (app().grpc().setIsAutomaticUpdateOn(active).ok()) {
|
||||
emit isAutomaticUpdateOnChanged(active);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::checkUpdates()
|
||||
{
|
||||
void QMLBackend::checkUpdates() {
|
||||
app().grpc().checkUpdate();
|
||||
}
|
||||
|
||||
@ -511,8 +487,7 @@ void QMLBackend::checkUpdates()
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::installUpdate()
|
||||
{
|
||||
void QMLBackend::installUpdate() {
|
||||
app().grpc().installUpdate();
|
||||
}
|
||||
|
||||
@ -520,8 +495,7 @@ void QMLBackend::installUpdate()
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::triggerReset()
|
||||
{
|
||||
void QMLBackend::triggerReset() {
|
||||
app().grpc().triggerReset();
|
||||
}
|
||||
|
||||
@ -529,8 +503,7 @@ void QMLBackend::triggerReset()
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::onResetFinished()
|
||||
{
|
||||
void QMLBackend::onResetFinished() {
|
||||
emit resetFinished();
|
||||
this->restart();
|
||||
}
|
||||
@ -539,8 +512,7 @@ void QMLBackend::onResetFinished()
|
||||
//****************************************************************************************************************************************************
|
||||
// onVersionChanged update dynamic link related to version
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::onVersionChanged()
|
||||
{
|
||||
void QMLBackend::onVersionChanged() {
|
||||
emit releaseNotesLinkChanged(releaseNotesLink());
|
||||
emit landingPageLinkChanged(landingPageLink());
|
||||
}
|
||||
@ -549,10 +521,10 @@ void QMLBackend::onVersionChanged()
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::exportTLSCertificates()
|
||||
{
|
||||
void QMLBackend::exportTLSCertificates() {
|
||||
QString const folderPath = QFileDialog::getExistingDirectory(nullptr, QObject::tr("Select directory"),
|
||||
QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
|
||||
if (!folderPath.isEmpty())
|
||||
if (!folderPath.isEmpty()) {
|
||||
app().grpc().exportTLSCertificates(folderPath);
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,8 +31,7 @@
|
||||
//****************************************************************************************************************************************************
|
||||
/// \brief Bridge C++ backend class.
|
||||
//****************************************************************************************************************************************************
|
||||
class QMLBackend: public QObject
|
||||
{
|
||||
class QMLBackend : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public: // member functions.
|
||||
@ -79,28 +78,109 @@ public: // Qt/QML properties. Note that the NOTIFY-er signal is required even fo
|
||||
Q_PROPERTY(QString currentEmailClient READ currentEmailClient NOTIFY currentEmailClientChanged)
|
||||
Q_PROPERTY(QStringList availableKeychain READ availableKeychain NOTIFY availableKeychainChanged)
|
||||
Q_PROPERTY(QString currentKeychain READ currentKeychain NOTIFY currentKeychainChanged)
|
||||
Q_PROPERTY(UserList* users MEMBER users_ NOTIFY usersChanged)
|
||||
Q_PROPERTY(UserList *users MEMBER users_ NOTIFY usersChanged)
|
||||
Q_PROPERTY(bool dockIconVisible READ dockIconVisible WRITE setDockIconVisible NOTIFY dockIconVisibleChanged)
|
||||
|
||||
|
||||
// Qt Property system setters & getters.
|
||||
bool showOnStartup() const { bool v = false; app().grpc().showOnStartup(v); return v; };
|
||||
bool showOnStartup() const {
|
||||
bool v = false;
|
||||
app().grpc().showOnStartup(v);
|
||||
return v;
|
||||
};
|
||||
|
||||
|
||||
bool showSplashScreen() const { return showSplashScreen_; };
|
||||
void setShowSplashScreen(bool show) { if (show != showSplashScreen_) { showSplashScreen_ = show; emit showSplashScreenChanged(show); } }
|
||||
|
||||
|
||||
void setShowSplashScreen(bool show) { if (show != showSplashScreen_) { showSplashScreen_ = show; emit showSplashScreenChanged(show); }}
|
||||
|
||||
|
||||
QString goos() { return goos_; }
|
||||
|
||||
|
||||
QUrl logsPath() const { return logsPath_; }
|
||||
|
||||
|
||||
QUrl licensePath() const { return licensePath_; }
|
||||
QUrl releaseNotesLink() const { QUrl link; app().grpc().releaseNotesPageLink(link); return link; }
|
||||
QUrl dependencyLicensesLink() const { QUrl link; app().grpc().dependencyLicensesLink(link); return link; }
|
||||
QUrl landingPageLink() const { QUrl link; app().grpc().landingPageLink(link); return link; }
|
||||
|
||||
|
||||
QUrl releaseNotesLink() const {
|
||||
QUrl link;
|
||||
app().grpc().releaseNotesPageLink(link);
|
||||
return link;
|
||||
}
|
||||
|
||||
|
||||
QUrl dependencyLicensesLink() const {
|
||||
QUrl link;
|
||||
app().grpc().dependencyLicensesLink(link);
|
||||
return link;
|
||||
}
|
||||
|
||||
|
||||
QUrl landingPageLink() const {
|
||||
QUrl link;
|
||||
app().grpc().landingPageLink(link);
|
||||
return link;
|
||||
}
|
||||
|
||||
|
||||
QString appname() const { return QString(PROJECT_FULL_NAME); }
|
||||
|
||||
|
||||
QString vendor() const { return QString(PROJECT_VENDOR); }
|
||||
QString version() const { QString version; app().grpc().version(version); return version; }
|
||||
QString hostname() const { QString hostname; app().grpc().hostname(hostname); return hostname; }
|
||||
bool isAutostartOn() const { bool v; app().grpc().isAutostartOn(v); return v; };
|
||||
bool isBetaEnabled() const { bool v; app().grpc().isBetaEnabled(v); return v; }
|
||||
bool isAllMailVisible() const { bool v; app().grpc().isAllMailVisible(v); return v; }
|
||||
QString colorSchemeName() const { QString name; app().grpc().colorSchemeName(name); return name; }
|
||||
QUrl diskCachePath() const { QUrl path; app().grpc().diskCachePath(path); return path; }
|
||||
|
||||
|
||||
QString version() const {
|
||||
QString version;
|
||||
app().grpc().version(version);
|
||||
return version;
|
||||
}
|
||||
|
||||
|
||||
QString hostname() const {
|
||||
QString hostname;
|
||||
app().grpc().hostname(hostname);
|
||||
return hostname;
|
||||
}
|
||||
|
||||
|
||||
bool isAutostartOn() const {
|
||||
bool v;
|
||||
app().grpc().isAutostartOn(v);
|
||||
return v;
|
||||
};
|
||||
|
||||
|
||||
bool isBetaEnabled() const {
|
||||
bool v;
|
||||
app().grpc().isBetaEnabled(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
bool isAllMailVisible() const {
|
||||
bool v;
|
||||
app().grpc().isAllMailVisible(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
QString colorSchemeName() const {
|
||||
QString name;
|
||||
app().grpc().colorSchemeName(name);
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
QUrl diskCachePath() const {
|
||||
QUrl path;
|
||||
app().grpc().diskCachePath(path);
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
bool useSSLForIMAP() const;
|
||||
void setUseSSLForIMAP(bool value);
|
||||
bool useSSLForSMTP() const;
|
||||
@ -109,15 +189,56 @@ public: // Qt/QML properties. Note that the NOTIFY-er signal is required even fo
|
||||
void setIMAPPort(int port);
|
||||
int smtpPort() const;
|
||||
void setSMTPPort(int port);
|
||||
bool isDoHEnabled() const { bool isEnabled; app().grpc().isDoHEnabled(isEnabled); return isEnabled;}
|
||||
bool isFirstGUIStart() const { bool v; app().grpc().isFirstGUIStart(v); return v; };
|
||||
bool isAutomaticUpdateOn() const { bool isOn = false; app().grpc().isAutomaticUpdateOn(isOn); return isOn; }
|
||||
QString currentEmailClient() { QString client; app().grpc().currentEmailClient(client); return client;}
|
||||
QStringList availableKeychain() const { QStringList keychains; app().grpc().availableKeychains(keychains); return keychains; }
|
||||
QString currentKeychain() const { QString keychain; app().grpc().currentKeychain(keychain); return keychain; }
|
||||
|
||||
|
||||
bool isDoHEnabled() const {
|
||||
bool isEnabled;
|
||||
app().grpc().isDoHEnabled(isEnabled);
|
||||
return isEnabled;
|
||||
}
|
||||
|
||||
|
||||
bool isFirstGUIStart() const {
|
||||
bool v;
|
||||
app().grpc().isFirstGUIStart(v);
|
||||
return v;
|
||||
};
|
||||
|
||||
|
||||
bool isAutomaticUpdateOn() const {
|
||||
bool isOn = false;
|
||||
app().grpc().isAutomaticUpdateOn(isOn);
|
||||
return isOn;
|
||||
}
|
||||
|
||||
|
||||
QString currentEmailClient() {
|
||||
QString client;
|
||||
app().grpc().currentEmailClient(client);
|
||||
return client;
|
||||
}
|
||||
|
||||
|
||||
QStringList availableKeychain() const {
|
||||
QStringList keychains;
|
||||
app().grpc().availableKeychains(keychains);
|
||||
return keychains;
|
||||
}
|
||||
|
||||
|
||||
QString currentKeychain() const {
|
||||
QString keychain;
|
||||
app().grpc().currentKeychain(keychain);
|
||||
return keychain;
|
||||
}
|
||||
|
||||
|
||||
bool dockIconVisible() const { return getDockIconVisibleState(); };
|
||||
|
||||
|
||||
void setDockIconVisible(bool visible) { setDockIconVisibleState(visible); emit dockIconVisibleChanged(visible); }
|
||||
|
||||
|
||||
signals: // Signal used by the Qt property system. Many of them are unused but required to avoid warning from the QML engine.
|
||||
void showSplashScreenChanged(bool value);
|
||||
void showOnStartupChanged(bool value);
|
||||
@ -145,7 +266,7 @@ signals: // Signal used by the Qt property system. Many of them are unused but r
|
||||
void availableKeychainChanged(QStringList const &keychains);
|
||||
void hostnameChanged(QString const &hostname);
|
||||
void isAutostartOnChanged(bool value);
|
||||
void usersChanged(UserList* users);
|
||||
void usersChanged(UserList *users);
|
||||
void dockIconVisibleChanged(bool value);
|
||||
|
||||
public slots: // slot for signals received from QML -> To be forwarded to Bridge via RPC Client calls.
|
||||
@ -153,14 +274,28 @@ public slots: // slot for signals received from QML -> To be forwarded to Bridge
|
||||
void toggleBeta(bool active);
|
||||
void changeIsAllMailVisible(bool isVisible);
|
||||
void changeColorScheme(QString const &scheme);
|
||||
void setDiskCachePath(QUrl const& path) const;
|
||||
void login(QString const& username, QString const& password) { app().grpc().login(username, password);}
|
||||
void login2FA(QString const& username, QString const& code) { app().grpc().login2FA(username, code);}
|
||||
void login2Password(QString const& username, QString const& password) { app().grpc().login2Passwords(username, password);}
|
||||
void loginAbort(QString const& username){ app().grpc().loginAbort(username);}
|
||||
void setDiskCachePath(QUrl const &path) const;
|
||||
|
||||
|
||||
void login(QString const &username, QString const &password) { app().grpc().login(username, password); }
|
||||
|
||||
|
||||
void login2FA(QString const &username, QString const &code) { app().grpc().login2FA(username, code); }
|
||||
|
||||
|
||||
void login2Password(QString const &username, QString const &password) { app().grpc().login2Passwords(username, password); }
|
||||
|
||||
|
||||
void loginAbort(QString const &username) { app().grpc().loginAbort(username); }
|
||||
|
||||
|
||||
void toggleDoH(bool active);
|
||||
void toggleAutomaticUpdate(bool makeItActive);
|
||||
|
||||
|
||||
void updateCurrentMailClient() { emit currentEmailClientChanged(currentEmailClient()); }
|
||||
|
||||
|
||||
void changeKeychain(QString const &keychain);
|
||||
void guiReady();
|
||||
void quit();
|
||||
@ -169,8 +304,13 @@ public slots: // slot for signals received from QML -> To be forwarded to Bridge
|
||||
void checkUpdates();
|
||||
void installUpdate();
|
||||
void triggerReset();
|
||||
void reportBug(QString const &description, QString const& address, QString const &emailClient, bool includeLogs) {
|
||||
app().grpc().reportBug(description, address, emailClient, includeLogs); }
|
||||
|
||||
|
||||
void reportBug(QString const &description, QString const &address, QString const &emailClient, bool includeLogs) {
|
||||
app().grpc().reportBug(description, address, emailClient, includeLogs);
|
||||
}
|
||||
|
||||
|
||||
void exportTLSCertificates();
|
||||
void onResetFinished();
|
||||
void onVersionChanged();
|
||||
@ -178,7 +318,7 @@ public slots: // slot for signals received from QML -> To be forwarded to Bridge
|
||||
|
||||
public slots: // slot for signals received from gRPC that need transformation instead of simple forwarding
|
||||
void onMailServerSettingsChanged(int imapPort, int smtpPort, bool useSSLForIMAP, bool useSSLForSMTP); ///< Slot for the ConnectionModeChanged gRPC event.
|
||||
void onGenericError(bridgepp::ErrorInfo const& info); ///< Slot for generic errors received from the gRPC service.
|
||||
void onGenericError(bridgepp::ErrorInfo const &info); ///< Slot for generic errors received from the gRPC service.
|
||||
void onLoginFinished(QString const &userID, bool wasSignedOut); ///< Slot for LoginFinished gRPC event.
|
||||
void onLoginAlreadyLoggedIn(QString const &userID); ///< Slot for the LoginAlreadyLoggedIn gRPC event.
|
||||
|
||||
@ -192,17 +332,17 @@ signals: // Signals received from the Go backend, to be forwarded to QML
|
||||
void loginFreeUserError();
|
||||
void loginConnectionError(QString const &errorMsg);
|
||||
void login2FARequested(QString const &username);
|
||||
void login2FAError(QString const& errorMsg);
|
||||
void login2FAErrorAbort(QString const& errorMsg);
|
||||
void login2FAError(QString const &errorMsg);
|
||||
void login2FAErrorAbort(QString const &errorMsg);
|
||||
void login2PasswordRequested();
|
||||
void login2PasswordError(QString const& errorMsg);
|
||||
void login2PasswordErrorAbort(QString const& errorMsg);
|
||||
void login2PasswordError(QString const &errorMsg);
|
||||
void login2PasswordErrorAbort(QString const &errorMsg);
|
||||
void loginFinished(int index, bool wasSignedOut);
|
||||
void loginAlreadyLoggedIn(int index);
|
||||
void updateManualReady(QString const& version);
|
||||
void updateManualReady(QString const &version);
|
||||
void updateManualRestartNeeded();
|
||||
void updateManualError();
|
||||
void updateForce(QString const& version);
|
||||
void updateForce(QString const &version);
|
||||
void updateForceError();
|
||||
void updateSilentRestartNeeded();
|
||||
void updateSilentError();
|
||||
@ -218,11 +358,11 @@ signals: // Signals received from the Go backend, to be forwarded to QML
|
||||
void changeKeychainFinished();
|
||||
void notifyHasNoKeychain();
|
||||
void notifyRebuildKeychain();
|
||||
void noActiveKeyForRecipient(QString const& email);
|
||||
void addressChanged(QString const& address);
|
||||
void addressChangedLogout(QString const& address);
|
||||
void noActiveKeyForRecipient(QString const &email);
|
||||
void addressChanged(QString const &address);
|
||||
void addressChangedLogout(QString const &address);
|
||||
void apiCertIssue();
|
||||
void userDisconnected(QString const& username);
|
||||
void userDisconnected(QString const &username);
|
||||
void internetOff();
|
||||
void internetOn();
|
||||
void resetFinished();
|
||||
@ -231,14 +371,14 @@ signals: // Signals received from the Go backend, to be forwarded to QML
|
||||
void bugReportSendError();
|
||||
void showMainWindow();
|
||||
void hideMainWindow();
|
||||
void genericError(QString const& title, QString const& description);
|
||||
void genericError(QString const &title, QString const &description);
|
||||
|
||||
private: // member functions
|
||||
void retrieveUserList(); ///< Retrieve the list of users via gRPC.
|
||||
void connectGrpcEvents(); ///< Connect gRPC that need to be forwarded to QML via backend signals
|
||||
|
||||
private: // data members
|
||||
UserList* users_ { nullptr }; ///< The user list. Owned by backend.
|
||||
UserList *users_ { nullptr }; ///< The user list. Owned by backend.
|
||||
std::unique_ptr<bridgepp::Overseer> eventStreamOverseer_; ///< The event stream overseer.
|
||||
bool showSplashScreen_ { false }; ///< The cached version of show splash screen. Retrieved on startup from bridge, and potentially modified locally.
|
||||
QString goos_; ///< The cached version of the GOOS variable.
|
||||
|
||||
@ -17,14 +17,17 @@
|
||||
|
||||
#include "SentryUtils.h"
|
||||
|
||||
static constexpr const char* LoggerName = "bridge-gui";
|
||||
|
||||
void reportSentryEvent(sentry_level_t level, const char* message) {
|
||||
static constexpr const char *LoggerName = "bridge-gui";
|
||||
|
||||
|
||||
void reportSentryEvent(sentry_level_t level, const char *message) {
|
||||
auto event = sentry_value_new_message_event(level, LoggerName, message);
|
||||
sentry_capture_event(event);
|
||||
}
|
||||
|
||||
void reportSentryException(sentry_level_t level, const char* message, const char* exceptionType, const char* exception) {
|
||||
|
||||
void reportSentryException(sentry_level_t level, const char *message, const char *exceptionType, const char *exception) {
|
||||
auto event = sentry_value_new_message_event(level, LoggerName, message);
|
||||
sentry_event_add_exception(event, sentry_value_new_exception(exceptionType, exception));
|
||||
sentry_capture_event(event);
|
||||
|
||||
@ -18,9 +18,11 @@
|
||||
#ifndef BRIDGE_GUI_SENTRYUTILS_H
|
||||
#define BRIDGE_GUI_SENTRYUTILS_H
|
||||
|
||||
|
||||
#include <sentry.h>
|
||||
|
||||
void reportSentryEvent(sentry_level_t level, const char* message);
|
||||
void reportSentryException(sentry_level_t level, const char* message, const char* exceptionType, const char* exception);
|
||||
|
||||
void reportSentryEvent(sentry_level_t level, const char *message);
|
||||
void reportSentryException(sentry_level_t level, const char *message, const char *exceptionType, const char *exception);
|
||||
|
||||
#endif //BRIDGE_GUI_SENTRYUTILS_H
|
||||
|
||||
@ -26,8 +26,7 @@ using namespace bridgepp;
|
||||
/// \param[in] parent The parent object of the user list.
|
||||
//****************************************************************************************************************************************************
|
||||
UserList::UserList(QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
{
|
||||
: QAbstractListModel(parent) {
|
||||
/// \todo use mutex to prevent concurrent access
|
||||
}
|
||||
|
||||
@ -35,9 +34,8 @@ UserList::UserList(QObject *parent)
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void UserList::connectGRPCEvents() const
|
||||
{
|
||||
GRPCClient& client = app().grpc();
|
||||
void UserList::connectGRPCEvents() const {
|
||||
GRPCClient &client = app().grpc();
|
||||
connect(&client, &GRPCClient::userChanged, this, &UserList::onUserChanged);
|
||||
connect(&client, &GRPCClient::toggleSplitModeFinished, this, &UserList::onToggleSplitModeFinished);
|
||||
}
|
||||
@ -46,8 +44,7 @@ void UserList::connectGRPCEvents() const
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
int UserList::rowCount(QModelIndex const &) const
|
||||
{
|
||||
int UserList::rowCount(QModelIndex const &) const {
|
||||
return users_.size();
|
||||
}
|
||||
|
||||
@ -57,14 +54,14 @@ int UserList::rowCount(QModelIndex const &) const
|
||||
/// \param[in] role The role to retrieve data for.
|
||||
/// \return The data at the index for the given role.
|
||||
//****************************************************************************************************************************************************
|
||||
QVariant UserList::data(QModelIndex const &index, int role) const
|
||||
{
|
||||
QVariant UserList::data(QModelIndex const &index, int role) const {
|
||||
/// This It does not seem to be used, but the method is required by the base class.
|
||||
/// From the original QtThe recipe QML backend User model, the User is always returned, regardless of the role.
|
||||
Q_UNUSED(role)
|
||||
int const row = index.row();
|
||||
if ((row < 0) || (row >= users_.size()))
|
||||
if ((row < 0) || (row >= users_.size())) {
|
||||
return QVariant();
|
||||
}
|
||||
return QVariant::fromValue(users_[row].get());
|
||||
}
|
||||
|
||||
@ -74,11 +71,12 @@ QVariant UserList::data(QModelIndex const &index, int role) const
|
||||
/// \return the row of the user.
|
||||
/// \return -1 if the userID is not in the list
|
||||
//****************************************************************************************************************************************************
|
||||
int UserList::rowOfUserID(QString const &userID) const
|
||||
{
|
||||
for (qint32 row = 0; row < users_.count(); ++row)
|
||||
if (userID == users_[row]->property("id"))
|
||||
int UserList::rowOfUserID(QString const &userID) const {
|
||||
for (qint32 row = 0; row < users_.count(); ++row) {
|
||||
if (userID == users_[row]->property("id")) {
|
||||
return row;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -86,8 +84,7 @@ int UserList::rowOfUserID(QString const &userID) const
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] users The new user list.
|
||||
//****************************************************************************************************************************************************
|
||||
void UserList::reset(QList<SPUser> const &users)
|
||||
{
|
||||
void UserList::reset(QList<SPUser> const &users) {
|
||||
this->beginResetModel();
|
||||
users_ = users;
|
||||
this->endResetModel();
|
||||
@ -98,8 +95,7 @@ void UserList::reset(QList<SPUser> const &users)
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] user The user.
|
||||
//****************************************************************************************************************************************************
|
||||
void UserList::appendUser(SPUser const &user)
|
||||
{
|
||||
void UserList::appendUser(SPUser const &user) {
|
||||
int const size = users_.size();
|
||||
this->beginInsertRows(QModelIndex(), size, size);
|
||||
users_.append(user);
|
||||
@ -111,10 +107,10 @@ void UserList::appendUser(SPUser const &user)
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] row The row.
|
||||
//****************************************************************************************************************************************************
|
||||
void UserList::removeUserAt(int row)
|
||||
{
|
||||
if ((row < 0) && (row >= users_.size()))
|
||||
void UserList::removeUserAt(int row) {
|
||||
if ((row < 0) && (row >= users_.size())) {
|
||||
return;
|
||||
}
|
||||
this->beginRemoveRows(QModelIndex(), row, row);
|
||||
users_.removeAt(row);
|
||||
this->endRemoveRows();
|
||||
@ -126,10 +122,8 @@ void UserList::removeUserAt(int row)
|
||||
/// \param[in] row The row.
|
||||
/// \param[in] user The user.
|
||||
//****************************************************************************************************************************************************
|
||||
void UserList::updateUserAtRow(int row, User const &user)
|
||||
{
|
||||
if ((row < 0) || (row >= users_.count()))
|
||||
{
|
||||
void UserList::updateUserAtRow(int row, User const &user) {
|
||||
if ((row < 0) || (row >= users_.count())) {
|
||||
app().log().error(QString("invalid user at row %2 (user userCount = %2)").arg(row).arg(users_.count()));
|
||||
return;
|
||||
}
|
||||
@ -146,10 +140,10 @@ void UserList::updateUserAtRow(int row, User const &user)
|
||||
/// \return The user with the given ID.
|
||||
/// \return A null pointer if the user could not be found.
|
||||
//****************************************************************************************************************************************************
|
||||
bridgepp::SPUser UserList::getUserWithID(QString const &userID) const
|
||||
{
|
||||
QList<SPUser>::const_iterator it = std::find_if(users_.begin(), users_.end(), [userID](SPUser const & user) -> bool {
|
||||
return user && user->id() == userID; });
|
||||
bridgepp::SPUser UserList::getUserWithID(QString const &userID) const {
|
||||
QList<SPUser>::const_iterator it = std::find_if(users_.begin(), users_.end(), [userID](SPUser const &user) -> bool {
|
||||
return user && user->id() == userID;
|
||||
});
|
||||
return (it == users_.end()) ? nullptr : *it;
|
||||
}
|
||||
|
||||
@ -157,10 +151,10 @@ bridgepp::SPUser UserList::getUserWithID(QString const &userID) const
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] row The row.
|
||||
//****************************************************************************************************************************************************
|
||||
User *UserList::get(int row) const
|
||||
{
|
||||
if ((row < 0) || (row >= users_.count()))
|
||||
User *UserList::get(int row) const {
|
||||
if ((row < 0) || (row >= users_.count())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
app().log().trace(QString("Retrieving user at row %1 (user userCount = %2)").arg(row).arg(users_.count()));
|
||||
return users_[row].get();
|
||||
@ -170,25 +164,21 @@ User *UserList::get(int row) const
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] userID The userID.
|
||||
//****************************************************************************************************************************************************
|
||||
void UserList::onUserChanged(QString const &userID)
|
||||
{
|
||||
void UserList::onUserChanged(QString const &userID) {
|
||||
int const index = this->rowOfUserID(userID);
|
||||
SPUser user;
|
||||
grpc::Status status = app().grpc().getUser(userID, user);
|
||||
QQmlEngine::setObjectOwnership(user.get(), QQmlEngine::CppOwnership);
|
||||
|
||||
if ((!user) || (!status.ok()))
|
||||
{
|
||||
if (index >= 0) // user exists here but not in the go backend. we delete it.
|
||||
{
|
||||
if ((!user) || (!status.ok())) {
|
||||
if (index >= 0) { // user exists here but not in the go backend. we delete it.
|
||||
app().log().trace(QString("Removing user from user list: %1").arg(userID));
|
||||
this->removeUserAt(index);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (index < 0)
|
||||
{
|
||||
if (index < 0) {
|
||||
app().log().trace(QString("Adding user in user list: %1").arg(userID));
|
||||
this->appendUser(user);
|
||||
return;
|
||||
@ -205,11 +195,9 @@ void UserList::onUserChanged(QString const &userID)
|
||||
///
|
||||
/// \param[in] userID the userID.
|
||||
//****************************************************************************************************************************************************
|
||||
void UserList::onToggleSplitModeFinished(QString const &userID)
|
||||
{
|
||||
void UserList::onToggleSplitModeFinished(QString const &userID) {
|
||||
int const index = this->rowOfUserID(userID);
|
||||
if (index < 0)
|
||||
{
|
||||
if (index < 0) {
|
||||
app().log().error(QString("Received toggleSplitModeFinished event for unknown userID %1").arg(userID));
|
||||
return;
|
||||
}
|
||||
@ -221,7 +209,6 @@ void UserList::onToggleSplitModeFinished(QString const &userID)
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return THe number of items in the list.
|
||||
//****************************************************************************************************************************************************
|
||||
int UserList::count() const
|
||||
{
|
||||
int UserList::count() const {
|
||||
return users_.size();
|
||||
}
|
||||
|
||||
@ -28,8 +28,7 @@
|
||||
//****************************************************************************************************************************************************
|
||||
/// \brief User list class.
|
||||
//****************************************************************************************************************************************************
|
||||
class UserList : public QAbstractListModel
|
||||
{
|
||||
class UserList : public QAbstractListModel {
|
||||
Q_OBJECT
|
||||
public: // member functions.
|
||||
UserList(QObject *parent); ///< Default constructor.
|
||||
@ -44,7 +43,7 @@ public: // member functions.
|
||||
void removeUserAt(int row); ///< Remove the user at a given row
|
||||
void appendUser(bridgepp::SPUser const &user); ///< Add a new user.
|
||||
void updateUserAtRow(int row, bridgepp::User const &user); ///< Update the user at given row.
|
||||
bridgepp::SPUser getUserWithID(QString const& userID) const; ///< Retrieve the user with the given ID.
|
||||
bridgepp::SPUser getUserWithID(QString const &userID) const; ///< Retrieve the user with the given ID.
|
||||
|
||||
// the userCount property.
|
||||
Q_PROPERTY(int count READ count NOTIFY countChanged)
|
||||
|
||||
@ -30,18 +30,16 @@
|
||||
#include <project_sentry_config.h>
|
||||
|
||||
|
||||
|
||||
using namespace bridgepp;
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
namespace {
|
||||
|
||||
/// \brief The file extension for the bridge executable file.
|
||||
#ifdef Q_OS_WIN32
|
||||
QString const exeSuffix = ".exe";
|
||||
QString const exeSuffix = ".exe";
|
||||
#else
|
||||
QString const exeSuffix;
|
||||
QString const exeSuffix;
|
||||
#endif
|
||||
|
||||
QString const bridgeLock = "bridge-v3-gui.lock"; ///< file name used for the lock file.
|
||||
@ -56,20 +54,20 @@ qint64 const grpcServiceConfigWaitDelayMs = 180000; ///< The wait delay for the
|
||||
/// \return The path of the bridge executable.
|
||||
/// \return A null string if the executable could not be located.
|
||||
//****************************************************************************************************************************************************
|
||||
QString locateBridgeExe()
|
||||
{
|
||||
QString locateBridgeExe() {
|
||||
QFileInfo const fileInfo(QDir(QCoreApplication::applicationDirPath()).absoluteFilePath(exeName));
|
||||
return (fileInfo.exists() && fileInfo.isFile() && fileInfo.isExecutable()) ? fileInfo.absoluteFilePath() : QString();
|
||||
return (fileInfo.exists() && fileInfo.isFile() && fileInfo.isExecutable()) ? fileInfo.absoluteFilePath() : QString();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// // initialize the Qt application.
|
||||
//****************************************************************************************************************************************************
|
||||
void initQtApplication()
|
||||
{
|
||||
void initQtApplication() {
|
||||
QString const qsgInfo = QProcessEnvironment::systemEnvironment().value("QSG_INFO");
|
||||
if ((!qsgInfo.isEmpty()) && (qsgInfo != "0"))
|
||||
if ((!qsgInfo.isEmpty()) && (qsgInfo != "0")) {
|
||||
QLoggingCategory::setFilterRules("qt.scenegraph.general=true");
|
||||
}
|
||||
|
||||
QGuiApplication::setApplicationName(PROJECT_FULL_NAME);
|
||||
QGuiApplication::setApplicationVersion(PROJECT_VER);
|
||||
@ -92,28 +90,30 @@ void initQtApplication()
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return A reference to the log.
|
||||
//****************************************************************************************************************************************************
|
||||
Log &initLog()
|
||||
{
|
||||
Log &initLog() {
|
||||
Log &log = app().log();
|
||||
log.registerAsQtMessageHandler();
|
||||
log.setEchoInConsole(true);
|
||||
|
||||
// remove old gui log files
|
||||
QDir const logsDir(userLogsDir());
|
||||
for (QFileInfo const fileInfo: logsDir.entryInfoList({ "gui_v*.log" }, QDir::Filter::Files)) // entryInfolist apparently only support wildcards, not regex.
|
||||
for (QFileInfo const fileInfo: logsDir.entryInfoList({ "gui_v*.log" }, QDir::Filter::Files)) { // entryInfolist apparently only support wildcards, not regex.
|
||||
QFile(fileInfo.absoluteFilePath()).remove();
|
||||
}
|
||||
|
||||
// create new GUI log file
|
||||
QString error;
|
||||
if (!log.startWritingToFile(logsDir.absoluteFilePath(QString("gui_v%1_%2.log").arg(PROJECT_VER).arg(QDateTime::currentSecsSinceEpoch())), &error))
|
||||
if (!log.startWritingToFile(logsDir.absoluteFilePath(QString("gui_v%1_%2.log").arg(PROJECT_VER).arg(QDateTime::currentSecsSinceEpoch())), &error)) {
|
||||
log.error(error);
|
||||
}
|
||||
|
||||
log.info("bridge-gui starting");
|
||||
QString const qtCompileTimeVersion = QT_VERSION_STR;
|
||||
QString const qtRuntimeVersion = qVersion();
|
||||
QString msg = QString("Using Qt %1").arg(qtRuntimeVersion);
|
||||
if (qtRuntimeVersion != qtCompileTimeVersion)
|
||||
if (qtRuntimeVersion != qtCompileTimeVersion) {
|
||||
msg += QString(" (compiled against %1)").arg(qtCompileTimeVersion);
|
||||
}
|
||||
log.info(msg);
|
||||
|
||||
return log;
|
||||
@ -123,8 +123,7 @@ Log &initLog()
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] engine The QML component.
|
||||
//****************************************************************************************************************************************************
|
||||
QQmlComponent *createRootQmlComponent(QQmlApplicationEngine &engine)
|
||||
{
|
||||
QQmlComponent *createRootQmlComponent(QQmlApplicationEngine &engine) {
|
||||
QString const qrcQmlDir = "qrc:/qml";
|
||||
qmlRegisterSingletonInstance("Proton", 1, 0, "Backend", &app().backend());
|
||||
qmlRegisterType<UserList>("Proton", 1, 0, "UserList");
|
||||
@ -138,8 +137,7 @@ QQmlComponent *createRootQmlComponent(QQmlApplicationEngine &engine)
|
||||
QQuickStyle::setStyle("Proton");
|
||||
|
||||
rootComponent->loadUrl(QUrl(qrcQmlDir + "/Bridge.qml"));
|
||||
if (rootComponent->status() != QQmlComponent::Status::Ready)
|
||||
{
|
||||
if (rootComponent->status() != QQmlComponent::Status::Ready) {
|
||||
app().log().error(rootComponent->errorString());
|
||||
throw Exception("Could not load QML component");
|
||||
}
|
||||
@ -151,21 +149,18 @@ QQmlComponent *createRootQmlComponent(QQmlApplicationEngine &engine)
|
||||
/// \param[in] lock The lock file to be checked.
|
||||
/// \return True if the lock can be taken, false otherwise.
|
||||
//****************************************************************************************************************************************************
|
||||
bool checkSingleInstance(QLockFile &lock)
|
||||
{
|
||||
bool checkSingleInstance(QLockFile &lock) {
|
||||
lock.setStaleLockTime(0);
|
||||
if (!lock.tryLock())
|
||||
{
|
||||
if (!lock.tryLock()) {
|
||||
qint64 pid;
|
||||
QString hostname, appName, details;
|
||||
if (lock.getLockInfo(&pid, &hostname, &appName))
|
||||
if (lock.getLockInfo(&pid, &hostname, &appName)) {
|
||||
details = QString("(PID : %1 - Host : %2 - App : %3)").arg(pid).arg(hostname, appName);
|
||||
}
|
||||
|
||||
app().log().error(QString("Instance already exists %1 %2").arg(lock.fileName(), details));
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
app().log().info(QString("lock file created %1").arg(lock.fileName()));
|
||||
}
|
||||
return true;
|
||||
@ -175,8 +170,7 @@ bool checkSingleInstance(QLockFile &lock)
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return QUrl to reach the bridge API.
|
||||
//****************************************************************************************************************************************************
|
||||
QUrl getApiUrl()
|
||||
{
|
||||
QUrl getApiUrl() {
|
||||
QUrl url;
|
||||
// use default url.
|
||||
url.setScheme("http");
|
||||
@ -185,17 +179,17 @@ QUrl getApiUrl()
|
||||
|
||||
// override with what can be found in the prefs.json file.
|
||||
QFile prefFile(QString("%1/%2").arg(bridgepp::userConfigDir(), "prefs.json"));
|
||||
if (prefFile.exists())
|
||||
{
|
||||
prefFile.open(QIODevice::ReadOnly|QIODevice::Text);
|
||||
if (prefFile.exists()) {
|
||||
prefFile.open(QIODevice::ReadOnly | QIODevice::Text);
|
||||
QByteArray data = prefFile.readAll();
|
||||
prefFile.close();
|
||||
QJsonDocument doc = QJsonDocument::fromJson(data);
|
||||
if (!doc.isNull()) {
|
||||
QString userPortApi = "user_port_api";
|
||||
QJsonObject obj = doc.object();
|
||||
if (!obj.isEmpty() && obj.contains(userPortApi))
|
||||
if (!obj.isEmpty() && obj.contains(userPortApi)) {
|
||||
url.setPort(doc.object()[userPortApi].toString().toInt());
|
||||
}
|
||||
}
|
||||
}
|
||||
return url;
|
||||
@ -205,8 +199,7 @@ QUrl getApiUrl()
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The URL for the focus endpoint of the bridge API URL.
|
||||
//****************************************************************************************************************************************************
|
||||
QUrl getFocusUrl()
|
||||
{
|
||||
QUrl getFocusUrl() {
|
||||
QUrl url = getApiUrl();
|
||||
url.setPath("/focus");
|
||||
return url;
|
||||
@ -216,8 +209,7 @@ QUrl getFocusUrl()
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return true if an instance of bridge is already running.
|
||||
//****************************************************************************************************************************************************
|
||||
bool isBridgeRunning()
|
||||
{
|
||||
bool isBridgeRunning() {
|
||||
FocusGRPCClient client;
|
||||
return client.connectToServer(500); // we time out after 1 second and consider no other instance is running;
|
||||
}
|
||||
@ -226,19 +218,18 @@ bool isBridgeRunning()
|
||||
//****************************************************************************************************************************************************
|
||||
/// \brief Use api to bring focus on existing bridge instance.
|
||||
//****************************************************************************************************************************************************
|
||||
void focusOtherInstance()
|
||||
{
|
||||
try
|
||||
{
|
||||
void focusOtherInstance() {
|
||||
try {
|
||||
FocusGRPCClient client;
|
||||
QString error;
|
||||
if (!client.connectToServer(5000, &error))
|
||||
if (!client.connectToServer(5000, &error)) {
|
||||
throw Exception(QString("Could not connect to bridge focus service for a raise call: %1").arg(error));
|
||||
if (!client.raise().ok())
|
||||
}
|
||||
if (!client.raise().ok()) {
|
||||
throw Exception(QString("The raise call to the bridge focus service failed."));
|
||||
}
|
||||
}
|
||||
catch (Exception const& e)
|
||||
{
|
||||
catch (Exception const &e) {
|
||||
app().log().error(e.qwhat());
|
||||
reportSentryException(SENTRY_LEVEL_ERROR, "Exception occurred during focusOtherInstance()", "Exception", e.what());
|
||||
}
|
||||
@ -248,22 +239,22 @@ void focusOtherInstance()
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param [in] args list of arguments to pass to bridge.
|
||||
//****************************************************************************************************************************************************
|
||||
void launchBridge(QStringList const &args)
|
||||
{
|
||||
UPOverseer& overseer = app().bridgeOverseer();
|
||||
void launchBridge(QStringList const &args) {
|
||||
UPOverseer &overseer = app().bridgeOverseer();
|
||||
overseer.reset();
|
||||
|
||||
const QString bridgeExePath = locateBridgeExe();
|
||||
|
||||
if (bridgeExePath.isEmpty())
|
||||
if (bridgeExePath.isEmpty()) {
|
||||
throw Exception("Could not locate the bridge executable path");
|
||||
else
|
||||
} else {
|
||||
app().log().debug(QString("Bridge executable path: %1").arg(QDir::toNativeSeparators(bridgeExePath)));
|
||||
}
|
||||
|
||||
qint64 const pid = qApp->applicationPid();
|
||||
QStringList const params = QStringList { "--grpc", "--parent-pid", QString::number(pid) } + args ;
|
||||
QStringList const params = QStringList { "--grpc", "--parent-pid", QString::number(pid) } + args;
|
||||
app().log().info(QString("Launching bridge process with command \"%1\" %2").arg(bridgeExePath, params.join(" ")));
|
||||
overseer = std::make_unique<Overseer>(new ProcessMonitor(bridgeExePath, params , nullptr), nullptr);
|
||||
overseer = std::make_unique<Overseer>(new ProcessMonitor(bridgeExePath, params, nullptr), nullptr);
|
||||
overseer->startWorker(true);
|
||||
}
|
||||
|
||||
@ -271,16 +262,15 @@ void launchBridge(QStringList const &args)
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void closeBridgeApp()
|
||||
{
|
||||
void closeBridgeApp() {
|
||||
app().grpc().quit(); // this will cause the grpc service and the bridge app to close.
|
||||
|
||||
UPOverseer& overseer = app().bridgeOverseer();
|
||||
if (!overseer) // The app was run in 'attach' mode and attached to an existing instance of Bridge. We're not monitoring it.
|
||||
UPOverseer &overseer = app().bridgeOverseer();
|
||||
if (!overseer) { // The app was run in 'attach' mode and attached to an existing instance of Bridge. We're not monitoring it.
|
||||
return;
|
||||
}
|
||||
|
||||
while (!overseer->isFinished())
|
||||
{
|
||||
while (!overseer->isFinished()) {
|
||||
QThread::msleep(20);
|
||||
}
|
||||
}
|
||||
@ -291,10 +281,9 @@ void closeBridgeApp()
|
||||
/// \param[in] argv The list of command-line arguments.
|
||||
/// \return The exit code for the application.
|
||||
//****************************************************************************************************************************************************
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int main(int argc, char *argv[]) {
|
||||
// Init sentry.
|
||||
sentry_options_t* sentryOptions = sentry_options_new();
|
||||
sentry_options_t *sentryOptions = sentry_options_new();
|
||||
sentry_options_set_dsn(sentryOptions, SentryDNS);
|
||||
{
|
||||
const QString sentryCachePath = sentryCacheDir();
|
||||
@ -307,24 +296,23 @@ int main(int argc, char *argv[])
|
||||
std::cerr << "Failed to initialize sentry" << std::endl;
|
||||
}
|
||||
|
||||
auto sentryClose = qScopeGuard([]{sentry_close();});
|
||||
auto sentryClose = qScopeGuard([] { sentry_close(); });
|
||||
|
||||
// The application instance is needed to display system message boxes. As we may have to do it in the exception handler,
|
||||
// application instance is create outside the try/catch clause.
|
||||
if (QSysInfo::productType() != "windows")
|
||||
if (QSysInfo::productType() != "windows") {
|
||||
QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);
|
||||
}
|
||||
|
||||
QApplication guiApp(argc, argv);
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
initQtApplication();
|
||||
|
||||
Log &log = initLog();
|
||||
|
||||
QLockFile lock(bridgepp::userCacheDir() + "/" + bridgeLock);
|
||||
if (!checkSingleInstance(lock))
|
||||
{
|
||||
if (!checkSingleInstance(lock)) {
|
||||
focusOtherInstance();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@ -340,10 +328,10 @@ int main(int argc, char *argv[])
|
||||
// these outputs and output them on the command-line.
|
||||
log.setLevel(cliOptions.logLevel);
|
||||
|
||||
if (!cliOptions.attach)
|
||||
{
|
||||
if (isBridgeRunning())
|
||||
if (!cliOptions.attach) {
|
||||
if (isBridgeRunning()) {
|
||||
throw Exception("An orphan instance of bridge is already running. Please terminate it and relaunch the application.");
|
||||
}
|
||||
|
||||
// before launching bridge, we remove any trailing service config file, because we need to make sure we get a newly generated one.
|
||||
GRPCClient::removeServiceConfigFile();
|
||||
@ -352,8 +340,9 @@ int main(int argc, char *argv[])
|
||||
|
||||
log.info(QString("Retrieving gRPC service configuration from '%1'").arg(QDir::toNativeSeparators(grpcServerConfigPath())));
|
||||
app().backend().init(GRPCClient::waitAndRetrieveServiceConfig(cliOptions.attach ? 0 : grpcServiceConfigWaitDelayMs, app().bridgeMonitor()));
|
||||
if (!cliOptions.attach)
|
||||
if (!cliOptions.attach) {
|
||||
GRPCClient::removeServiceConfigFile();
|
||||
}
|
||||
|
||||
// gRPC communication is established. From now on, log events will be sent to bridge via gRPC. bridge will write these to file,
|
||||
// and will output then on console if appropriate. If we are not running in attached mode we intercept bridge stdout & stderr and
|
||||
@ -370,19 +359,18 @@ int main(int argc, char *argv[])
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
std::unique_ptr<QQmlComponent> rootComponent(createRootQmlComponent(engine));
|
||||
std::unique_ptr<QObject>rootObject(rootComponent->create(engine.rootContext()));
|
||||
if (!rootObject)
|
||||
std::unique_ptr<QObject> rootObject(rootComponent->create(engine.rootContext()));
|
||||
if (!rootObject) {
|
||||
throw Exception("Could not create root object.");
|
||||
}
|
||||
|
||||
ProcessMonitor *bridgeMonitor = app().bridgeMonitor();
|
||||
bool bridgeExited = false;
|
||||
bool startError = false;
|
||||
QMetaObject::Connection connection;
|
||||
if (bridgeMonitor)
|
||||
{
|
||||
const ProcessMonitor::MonitorStatus& status = bridgeMonitor->getStatus();
|
||||
if (status.ended && !cliOptions.attach)
|
||||
{
|
||||
if (bridgeMonitor) {
|
||||
const ProcessMonitor::MonitorStatus &status = bridgeMonitor->getStatus();
|
||||
if (status.ended && !cliOptions.attach) {
|
||||
// ProcessMonitor already stopped meaning we are attached to an orphan Bridge.
|
||||
// Restart the full process to be sure there is no more bridge orphans
|
||||
app().log().error("Found orphan bridge, need to restart.");
|
||||
@ -390,21 +378,18 @@ int main(int argc, char *argv[])
|
||||
app().backend().restart();
|
||||
bridgeExited = true;
|
||||
startError = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
app().log().debug(QString("Monitoring Bridge PID : %1").arg(status.pid));
|
||||
|
||||
connection = QObject::connect(bridgeMonitor, &ProcessMonitor::processExited, [&](int returnCode) {
|
||||
bridgeExited = true;// clazy:exclude=lambda-in-connect
|
||||
qGuiApp->exit(returnCode);
|
||||
});
|
||||
bridgeExited = true;// clazy:exclude=lambda-in-connect
|
||||
qGuiApp->exit(returnCode);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
int result = 0;
|
||||
if (!startError)
|
||||
{
|
||||
if (!startError) {
|
||||
// we succeeded in launching bridge, so we can be set as mainExecutable.
|
||||
app().grpc().setMainExecutable(QString::fromLocal8Bit(argv[0]));
|
||||
result = QGuiApplication::exec();
|
||||
@ -412,21 +397,22 @@ int main(int argc, char *argv[])
|
||||
|
||||
QObject::disconnect(connection);
|
||||
app().grpc().stopEventStreamReader();
|
||||
if (!app().backend().waitForEventStreamReaderToFinish(5000))
|
||||
if (!app().backend().waitForEventStreamReaderToFinish(5000)) {
|
||||
log.warn("Event stream reader took too long to finish.");
|
||||
}
|
||||
|
||||
// We manually delete the QML components to avoid warnings error due to order of deletion of C++ / JS objects and singletons.
|
||||
rootObject.reset();
|
||||
rootComponent.reset();
|
||||
|
||||
if (!bridgeExited)
|
||||
if (!bridgeExited) {
|
||||
closeBridgeApp();
|
||||
}
|
||||
// release the lock file
|
||||
lock.unlock();
|
||||
return result;
|
||||
}
|
||||
catch (Exception const &e)
|
||||
{
|
||||
catch (Exception const &e) {
|
||||
reportSentryException(SENTRY_LEVEL_ERROR, "Exception occurred during main", "Exception", e.what());
|
||||
QMessageBox::critical(nullptr, "Error", e.qwhat());
|
||||
QTextStream(stderr) << e.qwhat() << "\n";
|
||||
|
||||
Reference in New Issue
Block a user