Other: move frontend C++ code ini a subfolder.

This commit is contained in:
Xavier Michelon
2022-08-04 16:51:42 +02:00
committed by Jakub
parent 22a8aab151
commit a8788feb50
161 changed files with 145 additions and 121 deletions

View File

@ -0,0 +1,122 @@
# Copyright (c) 2022 Proton AG
#
# This file is part of Proton Mail Bridge.
#
# Proton Mail Bridge is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Proton Mail Bridge is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
cmake_minimum_required(VERSION 3.22)
set(VCPKG_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../../../../extern/vcpkg")
include(../BridgeSetup.cmake)
#****************************************************************************************************************************************************
# Base project setup
#****************************************************************************************************************************************************
project(bridgepp LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
if (NOT DEFINED BRIDGE_APP_VERSION)
message(FATAL_ERROR "BRIDGE_APP_VERSION is not defined.")
else()
message(STATUS "Bridge version is ${BRIDGE_APP_VERSION}")
endif()
#****************************************************************************************************************************************************
# Qt
#****************************************************************************************************************************************************
if (NOT DEFINED ENV{QT6DIR})
message(FATAL_ERROR "QT6DIR needs to be defined and point to the root of your Qt 6 folder (e.g. /Users/MyName/Qt/6.3.1/clang_64).")
endif ()
set(CMAKE_PREFIX_PATH $ENV{QT6DIR} ${CMAKE_PREFIX_PATH})
find_package(Qt6 COMPONENTS Core REQUIRED)
qt_standard_project_setup()
#****************************************************************************************************************************************************
# gRPC / Protobuf
#****************************************************************************************************************************************************
find_package(Protobuf CONFIG REQUIRED)
message(STATUS "Using protobuf ${Protobuf_VERSION}")
find_package(gRPC CONFIG REQUIRED)
message(STATUS "Using gRPC ${gRPC_VERSION}")
find_program(PROTOC_EXE protoc REQUIRED)
message(STATUS "protoc found ${PROTOC_EXE}")
message(STATUS "grpc_cpp_plugin ${grpc_cpp_plugin}")
find_program(GRPC_CPP_PLUGIN grpc_cpp_plugin)
if (NOT GRPC_CPP_PLUGIN)
message(FATAL_ERROR "grpc_cpp_plugin exe could not be found. Please add it to your path. it should be located in \${VCPKG_ROOT}/installed/arm64-osx/tools/grpc")
else ()
message(STATUS "grpc_cpp_plugin found at ${GRPC_CPP_PLUGIN}")
endif ()
set(PROTO_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../grpc")
set(PROTO_FILE "${PROTO_DIR}/bridge.proto")
set(GRPC_OUT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/bridgepp/GRPC")
set(PROTO_CPP_FILE "${GRPC_OUT_DIR}/bridge.pb.cc")
set(PROTO_H_FILE "${GRPC_OUT_DIR}/bridge.pb.h")
set(GRPC_CPP_FILE "${GRPC_OUT_DIR}/bridge.grpc.pb.cc")
set(GRPC_H_FILE "${GRPC_OUT_DIR}/bridge.grpc.pb.h")
#*****************************************************************************************************************************************************
# Source files and output
#*****************************************************************************************************************************************************
add_custom_command(
OUTPUT
${PROTO_CPP_FILE}
${PROTO_H_FILE}
${GRPC_CPP_FILE}
${GRPC_H_FILE}
COMMAND
${PROTOC_EXE}
ARGS
--proto_path=${PROTO_DIR}
--plugin=protoc-gen-grpc="${GRPC_CPP_PLUGIN}"
--cpp_out=${GRPC_OUT_DIR}
--grpc_out=${GRPC_OUT_DIR}
${PROTO_FILE}
DEPENDS
${PROTO_FILE}
COMMENT "Generating gPRC/Protobuf C++ code"
)
add_library(bridgepp
bridgepp/BridgeUtils.cpp bridgepp/BridgeUtils.h
bridgepp/Exception/Exception.h bridgepp/Exception/Exception.cpp
bridgepp/GRPC/GRPCClient.cpp bridgepp/GRPC/GRPCClient.h
bridgepp/GRPC/GRPCUtils.cpp bridgepp/GRPC/GRPCUtils.h
${PROTO_CPP_FILE} ${PROTO_H_FILE} ${GRPC_CPP_FILE} ${GRPC_H_FILE}
bridgepp/Log/Log.h bridgepp/Log/Log.cpp
bridgepp/User/User.cpp bridgepp/User/User.h
bridgepp/Worker/Worker.h bridgepp/Worker/Overseer.h bridgepp/Worker/Overseer.cpp
)
target_include_directories(bridgepp PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(bridgepp
Qt6::Core
protobuf::libprotobuf
gRPC::grpc++
)
target_precompile_headers(bridgepp PRIVATE Pch.h)

View File

@ -0,0 +1,26 @@
// Copyright (c) 2022 Proton AG
//
// This file is part of Proton Mail Bridge.
//
// Proton Mail Bridge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Proton Mail Bridge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
#ifndef BRIDGE_PP_PCH_H
#define BRIDGE_PP_PCH_H
#include <QtCore>
#endif // BRIDGE_PP_PCH_H

View File

@ -0,0 +1,56 @@
// Copyright (c) 2022 Proton AG
//
// This file is part of Proton Mail Bridge.
//
// Proton Mail Bridge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Proton Mail Bridge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
#include "BridgeUtils.h"
#include "Exception/Exception.h"
namespace bridgepp
{
//****************************************************************************************************************************************************
/// \return user configuration directory used by bridge (based on Golang OS/File's UserConfigDir).
//****************************************************************************************************************************************************
QString userConfigDir()
{
QString dir;
#ifdef Q_OS_WIN
dir = qgetenv ("AppData");
if (dir.isEmpty())
throw Exception("%AppData% is not defined.");
#elif defined(Q_OS_IOS) || defined(Q_OS_DARWIN)
dir = qgetenv("HOME");
if (dir.isEmpty())
throw Exception("$HOME is not defined.");
dir += "/Library/Application Support";
#else
dir = qgetenv ("XDG_CONFIG_HOME");
if (dir.isEmpty())
dir = qgetenv ("HOME");
if (dir.isEmpty())
throw Exception("neither $XDG_CONFIG_HOME nor $HOME are defined");
dir += "/.config";
#endif
QString folder = dir + "/protonmail/bridge";
QDir().mkpath(folder);
return folder;
}
} // namespace bridgepp

View File

@ -0,0 +1,33 @@
// Copyright (c) 2022 Proton AG
//
// This file is part of Proton Mail Bridge.
//
// Proton Mail Bridge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Proton Mail Bridge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
#ifndef BRIDGE_GUI_TESTER_BRIDGE_UTILS_H
#define BRIDGE_GUI_TESTER_BRIDGE_UTILS_H
namespace bridgepp {
QString userConfigDir(); ///< Get the path of the user configuration folder.
} // namespace
#endif // BRIDGE_GUI_TESTER_BRIDGE_UTILS_H

View File

@ -0,0 +1,74 @@
// Copyright (c) 2022 Proton AG
//
// This file is part of Proton Mail Bridge.
//
// Proton Mail Bridge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Proton Mail Bridge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
#include "Exception.h"
namespace bridgepp
{
//****************************************************************************************************************************************************
/// \param[in] what A description of the exception
//****************************************************************************************************************************************************
Exception::Exception(QString what) noexcept
: std::exception()
, what_(std::move(what))
{
}
//****************************************************************************************************************************************************
/// \param[in] ref The Exception to copy from
//****************************************************************************************************************************************************
Exception::Exception(Exception const& ref) noexcept
: std::exception(ref)
, what_(ref.what_)
{
}
//****************************************************************************************************************************************************
/// \param[in] ref The Exception to copy from
//****************************************************************************************************************************************************
Exception::Exception(Exception&& ref) noexcept
: std::exception(ref)
, what_(ref.what_)
{
}
//****************************************************************************************************************************************************
/// \return a string describing the exception
//****************************************************************************************************************************************************
QString const& Exception::qwhat() const noexcept
{
return what_;
}
//****************************************************************************************************************************************************
/// \return A pointer to the description string of the exception.
//****************************************************************************************************************************************************
const char* Exception::what() const noexcept
{
return what_.toLocal8Bit().constData();
}
} // namespace bridgepp

View File

@ -0,0 +1,53 @@
// Copyright (c) 2022 Proton AG
//
// This file is part of Proton Mail Bridge.
//
// Proton Mail Bridge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Proton Mail Bridge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
#ifndef BRIDGE_PP_EXCEPTION_H
#define BRIDGE_PP_EXCEPTION_H
#include <stdexcept>
namespace bridgepp
{
//****************************************************************************************************************************************************
/// \brief Exception class.
//****************************************************************************************************************************************************
class Exception : public std::exception
{
public: // member functions
explicit Exception(QString what = QString()) noexcept; ///< Constructor
Exception(Exception const &ref) noexcept; ///< copy constructor
Exception(Exception &&ref) noexcept; ///< copy constructor
Exception &operator=(Exception const &) = delete; ///< Disabled assignment operator
Exception &operator=(Exception &&) = delete; ///< Disabled assignment operator
~Exception() noexcept override = default; ///< Destructor
QString const &qwhat() const noexcept; ///< Return the description of the exception as a QString
const char *what() const noexcept override; ///< Return the description of the exception as C style string
private: // data members
QString const what_; ///< The description of the exception
};
} // namespace bridgepp
#endif //BRIDGE_PP_EXCEPTION_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,236 @@
// Copyright (c) 2022 Proton AG
//
// This file is part of Proton Mail Bridge.
//
// Proton Mail Bridge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Proton Mail Bridge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
#ifndef BRIDGE_GUI_RPC_CLIENT_H
#define BRIDGE_GUI_RPC_CLIENT_H
#include "../User/User.h"
#include "../Log/Log.h"
#include "bridge.grpc.pb.h"
#include "grpc++/grpc++.h"
namespace bridgepp
{
typedef grpc::Status (grpc::Bridge::Stub::*SimpleMethod)(grpc::ClientContext *, const google::protobuf::Empty &, google::protobuf::Empty *);
typedef grpc::Status (grpc::Bridge::Stub::*BoolSetter)(grpc::ClientContext *, const google::protobuf::BoolValue &, google::protobuf::Empty *);
typedef grpc::Status (grpc::Bridge::Stub::*BoolGetter)(grpc::ClientContext *, const google::protobuf::Empty &, google::protobuf::BoolValue *);
typedef grpc::Status (grpc::Bridge::Stub::*Int32Setter)(grpc::ClientContext *, const google::protobuf::Int32Value &, google::protobuf::Empty *);
typedef grpc::Status (grpc::Bridge::Stub::*Int32Getter)(grpc::ClientContext *, const google::protobuf::Empty &, google::protobuf::Int32Value *);
typedef grpc::Status (grpc::Bridge::Stub::*StringGetter)(grpc::ClientContext *, const google::protobuf::Empty &, google::protobuf::StringValue *);
typedef grpc::Status (grpc::Bridge::Stub::*StringSetter)(grpc::ClientContext *, const google::protobuf::StringValue &, google::protobuf::Empty *);
typedef grpc::Status (grpc::Bridge::Stub::*StringParamMethod)(grpc::ClientContext *, const google::protobuf::StringValue &, google::protobuf::Empty *);
//****************************************************************************************************************************************************
/// \brief gRPC client class. This class encapsulate the gRPC service, abstracting all data type conversions.
//****************************************************************************************************************************************************
class GRPCClient : public QObject
{
Q_OBJECT
public: // member functions.
GRPCClient() = default; ///< Default constructor.
GRPCClient(GRPCClient const &) = delete; ///< Disabled copy-constructor.
GRPCClient(GRPCClient &&) = delete; ///< Disabled assignment copy-constructor.
~GRPCClient() override = default; ///< Destructor.
GRPCClient &operator=(GRPCClient const &) = delete; ///< Disabled assignment operator.
GRPCClient &operator=(GRPCClient &&) = delete; ///< Disabled move assignment operator.
void setLog(Log *log); ///< Set the log for the client.
bool connectToServer(QString &outError); ///< Establish connection to the gRPC server.
grpc::Status addLogEntry(Log::Level level, QString const &package, QString const &message); ///< Performs the "AddLogEntry" gRPC call.
grpc::Status guiReady(); ///< performs the "GuiReady" gRPC call.
grpc::Status isFirstGUIStart(bool &outIsFirst); ///< performs the "IsFirstGUIStart" gRPC call.
grpc::Status isAutostartOn(bool &outIsOn); ///< Performs the "isAutostartOn" gRPC call.
grpc::Status setIsAutostartOn(bool on); ///< Performs the "setIsAutostartOn" gRPC call.
grpc::Status isBetaEnabled(bool &outEnabled); ///< Performs the "isBetaEnabled" gRPC call.
grpc::Status setIsBetaEnabled(bool enabled); ///< Performs the 'setIsBetaEnabled' gRPC call.
grpc::Status colorSchemeName(QString &outName); ///< Performs the "colorSchemeName' gRPC call.
grpc::Status setColorSchemeName(QString const &name); ///< Performs the "setColorSchemeName' gRPC call.
grpc::Status currentEmailClient(QString &outName); ///< Performs the 'currentEmailClient' gRPC call.
grpc::Status reportBug(QString const &description, QString const &address, QString const &emailClient, bool includeLogs); ///< Performs the 'ReportBug' gRPC call.
grpc::Status quit(); ///< Perform the "Quit" gRPC call.
grpc::Status restart(); ///< Performs the Restart gRPC call.
grpc::Status triggerReset(); ///< Performs the triggerReset gRPC call.
grpc::Status forceLauncher(QString const &launcher); ///< Performs the 'ForceLauncher' call.
grpc::Status isPortFree(qint32 port, bool &outFree); ///< Performs the 'IsPortFree' call.
grpc::Status showOnStartup(bool &outValue); ///< Performs the 'ShowOnStartup' call.
grpc::Status showSplashScreen(bool &outValue); ///< Performs the 'ShowSplashScreen' call.
grpc::Status goos(QString &outGoos); ///< Performs the 'GoOs' call.
grpc::Status logsPath(QUrl &outPath); ///< Performs the 'LogsPath' call.
grpc::Status licensePath(QUrl &outPath); ///< Performs the 'LicensePath' call.
grpc::Status dependencyLicensesLink(QUrl &outUrl); ///< Performs the 'DependencyLicensesLink' call.
grpc::Status version(QString &outVersion); ///< Performs the 'Version' call.
grpc::Status releaseNotesPageLink(QUrl &outUrl); ///< Performs the 'releaseNotesPageLink' call.
grpc::Status landingPageLink(QUrl &outUrl); ///< Performs the 'landingPageLink' call.
grpc::Status hostname(QString &outHostname); ///< Performs the 'Hostname' call.
signals: // app related signals
void internetStatus(bool isOn);
void toggleAutostartFinished();
void resetFinished();
void reportBugFinished();
void reportBugSuccess();
void reportBugError();
void showMainWindow();
// cache related calls
public:
grpc::Status isCacheOnDiskEnabled(bool &outEnabled); ///< Performs the 'isCacheOnDiskEnabled' call.
grpc::Status diskCachePath(QUrl &outPath); ///< Performs the 'diskCachePath' call.
grpc::Status changeLocalCache(bool enabled, QUrl const &path); ///< Performs the 'ChangeLocalCache' call.
signals:
void isCacheOnDiskEnabledChanged(bool enabled);
void diskCachePathChanged(QUrl const &outPath);
void cacheUnavailable(); // _ func() `signal:"cacheUnavailable"`
void cacheCantMove(); // _ func() `signal:"cacheCantMove"`
void cacheLocationChangeSuccess(); // _ func() `signal:"cacheLocationChangeSuccess"`
void diskFull(); // _ func() `signal:"diskFull"`
void changeLocalCacheFinished(); // _ func() `signal:"changeLocalCacheFinished"`
// mail settings related calls
public:
grpc::Status useSSLForSMTP(bool &outUseSSL); ///< Performs the 'useSSLForSMTP' gRPC call
grpc::Status setUseSSLForSMTP(bool useSSL); ///< Performs the 'currentEmailClient' gRPC call.
grpc::Status portIMAP(int &outPort); ///< Performs the 'portImap' gRPC call.
grpc::Status portSMTP(int &outPort); ///< Performs the 'portImap' gRPC call.
grpc::Status changePorts(int portIMAP, int portSMTP); ///< Performs the 'changePorts' gRPC call.
grpc::Status isDoHEnabled(bool &outEnabled); ///< Performs the 'isDoHEnabled' gRPC call.
grpc::Status setIsDoHEnabled(bool enabled); ///< Performs the 'setIsDoHEnabled' gRPC call.
signals:
void portIssueIMAP();
void portIssueSMTP();
void toggleUseSSLFinished();
void changePortFinished();
public: // login related calls
grpc::Status login(QString const &username, QString const &password); ///< Performs the 'login' call.
grpc::Status login2FA(QString const &username, QString const &code); ///< Performs the 'login2FA' call.
grpc::Status login2Passwords(QString const &username, QString const &password); ///< Performs the 'login2Passwords' call.
grpc::Status loginAbort(QString const &username); ///< Performs the 'loginAbort' call.
signals:
void loginUsernamePasswordError(QString const &errMsg); // _ func(errorMsg string) `signal:"loginUsernamePasswordError"`
void loginFreeUserError(); // _ func() `signal:"loginFreeUserError"`
void loginConnectionError(QString const &errMsg); // _ func(errorMsg string) `signal:"loginConnectionError"`
void login2FARequested(QString const &userName); // _ func(username string) `signal:"login2FARequested"`
void login2FAError(QString const &errMsg); // _ func(errorMsg string) `signal:"login2FAError"`
void login2FAErrorAbort(QString const &errMsg); // _ func(errorMsg string) `signal:"login2FAErrorAbort"`
void login2PasswordRequested(); // _ func() `signal:"login2PasswordRequested"`
void login2PasswordError(QString const &errMsg); // _ func(errorMsg string) `signal:"login2PasswordError"`
void login2PasswordErrorAbort(QString const &errMsg); // _ func(errorMsg string) `signal:"login2PasswordErrorAbort"`
void loginFinished(QString const &userID); // _ func(index int) `signal:"loginFinished"`
void loginAlreadyLoggedIn(QString const &userID); // _ func(index int) `signal:"loginAlreadyLoggedIn"`
public: // Update related calls
grpc::Status checkUpdate();
grpc::Status installUpdate();
grpc::Status setIsAutomaticUpdateOn(bool on);
grpc::Status isAutomaticUpdateOn(bool &isOn);
signals:
void updateManualError();
void updateForceError();
void updateSilentError();
void updateManualReady(QString const &version);
void updateManualRestartNeeded();
void updateForce(QString const &version);
void updateSilentRestartNeeded();
void updateIsLatestVersion();
void checkUpdatesFinished();
public: // user related calls
grpc::Status getUserList(QList<SPUser> &outUsers);
grpc::Status getUser(QString const &userID, SPUser &outUser);
grpc::Status logoutUser(QString const &userID); ///< Performs the 'logoutUser' call.
grpc::Status removeUser(QString const &userID); ///< Performs the 'removeUser' call.
grpc::Status configureAppleMail(QString const &userID, QString const &address); ///< Performs the 'configureAppleMail' call.
grpc::Status setUserSplitMode(QString const &userID, bool active); ///< Performs the 'SetUserSplitMode' call.
signals:
void toggleSplitModeFinished(QString const &userID);
void userDisconnected(QString const &username);
void userChanged(QString const &userID);
public: // keychain related calls
grpc::Status availableKeychains(QStringList &outKeychains);
grpc::Status currentKeychain(QString &outKeychain);
grpc::Status setCurrentKeychain(QString const &keychain);
signals:
void changeKeychainFinished();
void hasNoKeychain();
void rebuildKeychain();
void certIsReady();
signals: // mail related events
void noActiveKeyForRecipient(QString const &email); // _ func(email string) `signal:noActiveKeyForRecipient`
void addressChanged(QString const &address); // _ func(address string) `signal:addressChanged`
void addressChangedLogout(QString const &address); // _ func(address string) `signal:addressChangedLogout`
void apiCertIssue();
public:
grpc::Status startEventStream(); ///< Retrieve and signal the events in the event stream.
grpc::Status stopEventStream(); ///< Stop the event stream.
private slots:
void configFolderChanged();
private:
void logDebug(QString const &message); ///< Log an event.
void logError(QString const &message); ///< Log an event.
grpc::Status logGRPCCallStatus(grpc::Status const &status, QString const &callName); ///< Log the status of a gRPC code.
grpc::Status simpleMethod(SimpleMethod method); ///< perform a gRPC call to a bool setter.
grpc::Status setBool(BoolSetter setter, bool value); ///< perform a gRPC call to a bool setter.
grpc::Status getBool(BoolGetter getter, bool &outValue); ///< perform a gRPC call to a bool getter.
grpc::Status setInt32(Int32Setter setter, int value); ///< perform a gRPC call to an int setter.
grpc::Status getInt32(Int32Getter getter, int &outValue); ///< perform a gRPC call to an int getter.
grpc::Status setString(StringSetter getter, QString const &value); ///< Perform a gRPC call to a string setter.
grpc::Status getString(StringGetter getter, QString &outValue); ///< Perform a gRPC call to a string getter.
grpc::Status getURLForLocalFile(StringGetter getter, QUrl &outValue); ///< Perform a gRPC call to a string getter, with resulted converted to QUrl for a local file path.
grpc::Status getURL(StringGetter getter, QUrl &outValue); ///< Perform a gRPC call to a string getter, with resulted converted to QUrl.
grpc::Status methodWithStringParam(StringParamMethod method, QString const &str); ///< Perform a gRPC call that takes a string as a parameter and returns an Empty.
SPUser parseGRPCUser(grpc::User const &grpcUser); ///< Parse a gRPC user struct and return a User.
std::string getServerCertificate(); ///< Wait until server certificates is generated and retrieve it.
void processAppEvent(grpc::AppEvent const &event); ///< Process an 'App' event.
void processLoginEvent(grpc::LoginEvent const &event); ///< Process a 'Login' event.
void processUpdateEvent(grpc::UpdateEvent const &event); ///< Process an 'Update' event.
void processCacheEvent(grpc::CacheEvent const &event); ///< Process a 'Cache' event.
void processMailSettingsEvent(grpc::MailSettingsEvent const &event); ///< Process a 'MailSettings' event.
void processKeychainEvent(grpc::KeychainEvent const &event); ///< Process a 'Keychain' event.
void processMailEvent(grpc::MailEvent const &event); ///< Process a 'Mail' event.
void processUserEvent(grpc::UserEvent const &event); ///< Process a 'User' event.
private: // data members.
Log *log_ { nullptr }; ///< The log for the GRPC client.
std::shared_ptr<grpc::Channel> channel_ { nullptr }; ///< The gRPC channel.
std::shared_ptr<grpc::Bridge::Stub> stub_ { nullptr }; ///< The gRPC stub (a.k.a. client).
};
}
#endif // BRIDGE_GUI_RPC_CLIENT_H

View File

@ -0,0 +1,182 @@
// Copyright (c) 2022 Proton AG
//
// This file is part of Proton Mail Bridge.
//
// Proton Mail Bridge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Proton Mail Bridge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
#include "GRPCUtils.h"
#include "../Exception/Exception.h"
#include "../BridgeUtils.h"
#if defined(Q_OS_WIN32) && defined(ERROR)
// The folks at Microsoft have decided that it was OK to `#define ERROR 0` in wingdi.h. It is not OK, because
// any occurrence of ERROR, even scoped, will be substituted. For instance Log::Level::ERROR (case imposed by gRPC).
#undef ERROR
#endif
namespace bridgepp
{
namespace
{
//****************************************************************************************************************************************************
/// \return The server certificate file name
//****************************************************************************************************************************************************
QString serverCertificateFilename()
{
return "cert.pem";
}
//****************************************************************************************************************************************************
//
//****************************************************************************************************************************************************
QString serverKeyFilename()
{
return "key.pem";
}
}
//****************************************************************************************************************************************************
/// \return The absolute path of the server certificate.
//****************************************************************************************************************************************************
QString serverCertificatePath()
{
return QDir(userConfigDir()).absoluteFilePath(serverCertificateFilename());
}
//****************************************************************************************************************************************************
/// \return The absolute path of the server key.
//****************************************************************************************************************************************************
QString serverKeyPath()
{
return QDir(userConfigDir()).absoluteFilePath(serverKeyFilename());
}
//****************************************************************************************************************************************************
/// \param[in] level The Log::Level.
/// \return The grpc::LogLevel.
//****************************************************************************************************************************************************
grpc::LogLevel logLevelToGRPC(Log::Level level)
{
switch (level)
{
case Log::Level::Panic:
return grpc::LogLevel::PANIC;
case Log::Level::Fatal:
return grpc::LogLevel::FATAL;
case Log::Level::Error:
return grpc::LogLevel::ERROR;
case Log::Level::Warn:
return grpc::LogLevel::WARN;
case Log::Level::Info:
return grpc::LogLevel::INFO;
case Log::Level::Debug:
return grpc::LogLevel::DEBUG;
case Log::Level::Trace:
return grpc::LogLevel::TRACE;
default:
throw Exception(QString("unknown log level %1.").arg(qint32(level)));
}
}
//****************************************************************************************************************************************************
/// \param[in] level The level::LogLevel.
/// \return The Log::Level.
//****************************************************************************************************************************************************
Log::Level logLevelFromGRPC(grpc::LogLevel level)
{
switch (level)
{
case grpc::PANIC:
return Log::Level::Panic;
case grpc::FATAL:
return Log::Level::Fatal;
case grpc::ERROR:
return Log::Level::Error;
case grpc::WARN:
return Log::Level::Warn;
case grpc::INFO:
return Log::Level::Info;
case grpc::DEBUG:
return Log::Level::Debug;
case grpc::TRACE:
return Log::Level::Trace;
default:
throw Exception(QString("unknown log level %1.").arg(qint32(level)));
}
}
//****************************************************************************************************************************************************
/// \param[in] grpcUser The gRPC user.
/// \param[in] user The user.
//****************************************************************************************************************************************************
SPUser userFromGRPC(grpc::User const &grpcUser)
{
SPUser user = User::newUser(nullptr);
user->setID(QString::fromStdString(grpcUser.id()));
user->setUsername(QString::fromStdString(grpcUser.username()));
user->setPassword(QString::fromStdString(grpcUser.password()));
QStringList addresses;
for (int j = 0; j < grpcUser.addresses_size(); ++j)
addresses.append(QString::fromStdString(grpcUser.addresses(j)));
user->setAddresses(addresses);
user->setAvatarText(QString::fromStdString(grpcUser.avatartext()));
user->setLoggedIn(grpcUser.loggedin());
user->setSplitMode(grpcUser.splitmode());
user->setSetupGuideSeen(grpcUser.setupguideseen());
user->setUsedBytes(float(grpcUser.usedbytes()));
user->setTotalBytes(float(grpcUser.totalbytes()));
return user;
}
//****************************************************************************************************************************************************
/// \param[in] user the user.
/// \param[out] outGRPCUser The GRPC user.
//****************************************************************************************************************************************************
void userToGRPC(User const &user, grpc::User &outGRPCUser)
{
outGRPCUser.set_id(user.id().toStdString());
outGRPCUser.set_username(user.username().toStdString());
outGRPCUser.set_password(user.password().toStdString());
outGRPCUser.clear_addresses();
for (QString const& address: user.addresses())
outGRPCUser.add_addresses(address.toStdString());
outGRPCUser.set_avatartext(user.avatarText().toStdString());
outGRPCUser.set_loggedin(user.loggedIn());
outGRPCUser.set_splitmode(user.splitMode());
outGRPCUser.set_setupguideseen(user.setupGuideSeen());
outGRPCUser.set_usedbytes(user.usedBytes());
outGRPCUser.set_totalbytes(user.totalBytes());
}
} // namespace bridgepp

View File

@ -0,0 +1,42 @@
// Copyright (c) 2022 Proton AG
//
// This file is part of Proton Mail Bridge.
//
// Proton Mail Bridge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Proton Mail Bridge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
#ifndef BRIDGE_GUI_GRPC_UTILS_H
#define BRIDGE_GUI_GRPC_UTILS_H
#include "../User/User.h"
#include "../Log/Log.h"
#include "bridge.grpc.pb.h"
namespace bridgepp
{
QString serverCertificatePath(); ///< Return the path of the server certificate.
QString serverKeyPath(); ///< Return the path of the server key.
grpc::LogLevel logLevelToGRPC(Log::Level level); ///< Convert a Log::Level to gRPC enum value.
Log::Level logLevelFromGRPC(grpc::LogLevel level); ///< Convert a grpc::LogLevel to a Log::Level.
void userToGRPC(User const &user, grpc::User &outGRPCUser); ///< Convert a bridgepp::User to a grpc::User.
SPUser userFromGRPC(grpc::User const &grpcUser); ///< Create a bridgepp::User from a grpc::User.
}
#endif // BRIDGE_GUI_GRPC_UTILS_H

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,272 @@
// Copyright (c) 2022 Proton AG
//
// This file is part of Proton Mail Bridge.
//
// Proton Mail Bridge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Proton Mail Bridge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
#include "Log.h"
namespace bridgepp
{
namespace
{
Log *qtHandlerLog { nullptr }; ///< The log instance handling qt logs.
QMutex qtHandlerMutex; ///< A mutex used to access qtHandlerLog.
//****************************************************************************************************************************************************
/// \param[in] log The log handling qt log entries. Can be null.
//****************************************************************************************************************************************************
void setQtMessageHandlerLog(Log *log)
{
QMutexLocker locker(&qtHandlerMutex);
qtHandlerLog = log;
}
//****************************************************************************************************************************************************
/// \return The log handling qt log entries. Can be null.
//****************************************************************************************************************************************************
Log *qtMessageHandlerLog()
{
QMutexLocker locker(&qtHandlerMutex);
return qtHandlerLog;
}
//****************************************************************************************************************************************************
/// \param[in] type The message type.
/// \param[in] message The message.
//****************************************************************************************************************************************************
void qtMessageHandler(QtMsgType type, QMessageLogContext const &, QString const &message)
{
Log *log = qtMessageHandlerLog();
if (!log)
return;
switch (type)
{
case QtDebugMsg:
log->debug(message);
break;
case QtWarningMsg:
log->warn(message);
break;
case QtCriticalMsg:
case QtFatalMsg:
log->error(message);
break;
case QtInfoMsg:
default:
log->info(message);
break;
}
}
//****************************************************************************************************************************************************
/// \param[in] level The level.
/// \return A string describing the level.
//****************************************************************************************************************************************************
QString logLevelToString(Log::Level level)
{
switch (level)
{
case Log::Level::Panic:
return "PANIC";
case Log::Level::Fatal:
return "FATAL";
case Log::Level::Error:
return "ERROR";
case Log::Level::Warn:
return "WARN";
case Log::Level::Info:
return "INFO";
case Log::Level::Debug:
return "DEBUG";
case Log::Level::Trace:
return "TRACE";
default:
return "UNKNOWN";
}
}
} // anonymous namespace
//****************************************************************************************************************************************************
/// \brief return a string representing the log entry
///
/// \param[in] level The log entry level.
/// \param[in] message The log entry message.
/// \return The string for the log entry
//****************************************************************************************************************************************************
QString Log::logEntryToString(Log::Level level, QString const &message)
{
return QString("[%1] %2").arg(logLevelToString(level), message);
}
//****************************************************************************************************************************************************
/// the message handle process the message from the Qt logging system.
//****************************************************************************************************************************************************
void Log::registerAsQtMessageHandler()
{
setQtMessageHandlerLog(this);
qInstallMessageHandler(qtMessageHandler);
}
//****************************************************************************************************************************************************
//
//****************************************************************************************************************************************************
Log::Log()
: QObject()
, stdout_(stdout)
, stderr_(stderr)
{
}
//****************************************************************************************************************************************************
/// \param[in] level The log level.
//****************************************************************************************************************************************************
void Log::setLevel(Log::Level level)
{
QMutexLocker locker(&mutex_);
level_ = level;
}
//****************************************************************************************************************************************************
/// \return The log level.
//****************************************************************************************************************************************************
Log::Level Log::level() const
{
QMutexLocker locker(&mutex_);
return Log::Level::Debug;
}
//****************************************************************************************************************************************************
/// \param[in] value Should the log entries be sent to STDOUT/STDERR.
//****************************************************************************************************************************************************
void Log::setEchoInConsole(bool value)
{
QMutexLocker locker(&mutex_);
echoInConsole_ = value;
}
//****************************************************************************************************************************************************
/// \return true iff the log entries be should sent to STDOUT/STDERR.
//****************************************************************************************************************************************************
bool Log::echoInConsole() const
{
QMutexLocker locker(&mutex_);
return echoInConsole_;
}
//****************************************************************************************************************************************************
/// \param[in] message The message.
//****************************************************************************************************************************************************
void Log::panic(QString const &message)
{
return this->addEntry(Level::Panic, message);
}
//****************************************************************************************************************************************************
/// \param[in] message The message.
//****************************************************************************************************************************************************
void Log::fatal(QString const &message)
{
return this->addEntry(Level::Fatal, message);
}
//****************************************************************************************************************************************************
/// \param[in] message The message.
//****************************************************************************************************************************************************
void Log::error(QString const &message)
{
return this->addEntry(Level::Error, message);
}
//****************************************************************************************************************************************************
/// \param[in] message The message.
//****************************************************************************************************************************************************
void Log::warn(QString const &message)
{
return this->addEntry(Level::Warn, message);
}
//****************************************************************************************************************************************************
/// \param[in] message The message.
//****************************************************************************************************************************************************
void Log::info(QString const &message)
{
return this->addEntry(Level::Info, message);
}
//****************************************************************************************************************************************************
/// \param[in] message The message.
//****************************************************************************************************************************************************
void Log::debug(QString const &message)
{
return this->addEntry(Level::Debug, message);
}
//****************************************************************************************************************************************************
/// \param[in] message The message.
//****************************************************************************************************************************************************
void Log::trace(QString const &message)
{
return this->addEntry(Level::Trace, message);
}
//****************************************************************************************************************************************************
/// \param[in] level The level.
/// \param[in] message The message.
//****************************************************************************************************************************************************
void Log::addEntry(Log::Level level, QString const &message)
{
QMutexLocker locker(&mutex_);
if (qint32(level) > qint32(level_))
return;
emit entryAdded(level, message);
if (echoInConsole_)
{
QTextStream &stream = (qint32(level) <= (qint32(Level::Warn))) ? stderr_ : stdout_;
stream << logEntryToString(level, message) << "\n";
stream.flush();
}
}
} // namespace bridgepp

View File

@ -0,0 +1,91 @@
// Copyright (c) 2022 Proton AG
//
// This file is part of Proton Mail Bridge.
//
// Proton Mail Bridge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Proton Mail Bridge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
#ifndef BRIDGE_PP_LOG_H
#define BRIDGE_PP_LOG_H
namespace bridgepp
{
//****************************************************************************************************************************************************
/// \brief Basic log class. No logging to file. Four levels. Rebroadcast received log entries via Qt signals.
//****************************************************************************************************************************************************
class Log : public QObject
{
Q_OBJECT
public: // data types.
/// \brief Log level class. The list matches [loggers log levels](https://pkg.go.dev/github.com/sirupsen/logrus).
enum class Level
{
Panic, ///< Panic log level.
Fatal, ///< Fatal log level.
Error, ///< Error log level.
Warn, ///< Warn log level.
Info, ///< Info log level.
Debug, ///< Debug log level.
Trace ///< Trace log level.
};
public: // static member functions.
static QString logEntryToString(Log::Level level, QString const &message); ///< Return a string describing a log entry.
public: // member functions.
Log(); ///< Default constructor.
Log(Log const &) = delete; ///< Disabled copy-constructor.
Log(Log &&) = delete; ///< Disabled assignment copy-constructor.
~Log() override = default; ///< Destructor.
Log &operator=(Log const &) = delete; ///< Disabled assignment operator.
Log &operator=(Log &&) = delete; ///< Disabled move assignment operator.
void setLevel(Level level); ///< Set the log level.
Level level() const; ///< Get the log level.
void setEchoInConsole(bool value); ///< Set if the log entries should be echoed in STDOUT/STDERR.
bool echoInConsole() const; ///< Check if the log entries should be echoed in STDOUT/STDERR.
void registerAsQtMessageHandler(); ///< Install the Qt message handler.
public slots:
void panic(QString const &message); ///< Adds an panic entry to the log.
void fatal(QString const &message); ///< Adds an fatal entry to the log.
void error(QString const &message); ///< Adds an error entry to the log.
void warn(QString const &message); ///< Adds a warn entry to the log.
void info(QString const &message); ///< Adds an info entry to the log.
void debug(QString const &message); ///< Adds a debug entry in the log.
void trace(QString const &message); ///< Adds a trace entry in the log.
void addEntry(Log::Level level, QString const &message); ///< Adds a trace entry in the log.
signals:
void entryAdded(Log::Level entry, QString const &); ///< Signal emitted when a log entry is added.
private: // data members
mutable QMutex mutex_; ///< The mutex.
Level level_{Level::Debug}; ///< The log level
bool echoInConsole_{false}; ///< Set if the log messages should be sent to STDOUT/STDERR.
QTextStream stdout_; ///< The stdout stream.
QTextStream stderr_; ///< The stderr stream.
};
} // namespace bridgepp
#endif //BRIDGE_PP_LOG_H

View File

@ -0,0 +1,329 @@
// Copyright (c) 2022 Proton AG
//
// This file is part of Proton Mail Bridge.
//
// Proton Mail Bridge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Proton Mail Bridge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
#include "User.h"
namespace bridgepp
{
//****************************************************************************************************************************************************
/// \param[in] parent The parent object of the user.
//****************************************************************************************************************************************************
SPUser User::newUser(QObject *parent)
{
return SPUser(new User(parent));
}
//****************************************************************************************************************************************************
/// \param[in] parent The parent object.
//****************************************************************************************************************************************************
User::User(QObject *parent)
: QObject(parent)
{
}
//****************************************************************************************************************************************************
/// \param[in] user The user to copy from
//****************************************************************************************************************************************************
void User::update(User const &user)
{
this->setID(user.id());
this->setUsername(user.username());
this->setPassword(user.password());
this->setAddresses(user.addresses());
this->setAvatarText(user.avatarText());
this->setLoggedIn(user.loggedIn());
this->setSplitMode(user.splitMode());
this->setSetupGuideSeen(user.setupGuideSeen());
this->setUsedBytes(user.usedBytes());
this->setTotalBytes(user.totalBytes());
}
//****************************************************************************************************************************************************
/// \param[in] makeItActive Should split mode be made active.
//****************************************************************************************************************************************************
void User::toggleSplitMode(bool makeItActive)
{
emit toggleSplitModeForUser(id_, makeItActive);
}
//****************************************************************************************************************************************************
//
//****************************************************************************************************************************************************
void User::logout()
{
emit logoutUser(id_);
}
//****************************************************************************************************************************************************
//
//****************************************************************************************************************************************************
void User::remove()
{
emit removeUser(id_);
}
//****************************************************************************************************************************************************
/// \param[in] address The email address to configure Apple Mail for.
//****************************************************************************************************************************************************
void User::configureAppleMail(QString const &address)
{
emit configureAppleMailForUser(id_, address);
}
//****************************************************************************************************************************************************
// The only purpose of this call is to forward to the QML application the toggleSplitModeFinished(userID) event
// that was received by the UserList model.
//****************************************************************************************************************************************************
void User::emitToggleSplitModeFinished()
{
emit toggleSplitModeFinished();
}
//****************************************************************************************************************************************************
/// \return The userID.
//****************************************************************************************************************************************************
QString User::id() const
{
return id_;
}
//****************************************************************************************************************************************************
/// \param[in] id The userID.
//****************************************************************************************************************************************************
void User::setID(QString const &id)
{
if (id == id_)
return;
id_ = id;
emit idChanged(id_);
}
//****************************************************************************************************************************************************
/// \return The username.
//****************************************************************************************************************************************************
QString User::username() const
{
return username_;
}
//****************************************************************************************************************************************************
/// \param[in] username The username.
//****************************************************************************************************************************************************
void User::setUsername(QString const &username)
{
if (username == username_)
return;
username_ = username;
emit usernameChanged(username_);
}
//****************************************************************************************************************************************************
/// \return The password.
//****************************************************************************************************************************************************
QString User::password() const
{
return password_;
}
//****************************************************************************************************************************************************
/// \param[in] password The password.
//****************************************************************************************************************************************************
void User::setPassword(QString const &password)
{
if (password == password_)
return;
password_ = password;
emit passwordChanged(password_);
}
//****************************************************************************************************************************************************
/// \return The addresses.
//****************************************************************************************************************************************************
QStringList User::addresses() const
{
return addresses_;
}
//****************************************************************************************************************************************************
/// \param[in] addresses The addresses.
//****************************************************************************************************************************************************
void User::setAddresses(QStringList const &addresses)
{
if (addresses == addresses_)
return;
addresses_ = addresses;
emit addressesChanged(addresses_);
}
//****************************************************************************************************************************************************
/// \return The avatar text.
//****************************************************************************************************************************************************
QString User::avatarText() const
{
return avatarText_;
}
//****************************************************************************************************************************************************
/// \param[in] avatarText The avatar text.
//****************************************************************************************************************************************************
void User::setAvatarText(QString const &avatarText)
{
if (avatarText == avatarText_)
return;
avatarText_ = avatarText;
emit usernameChanged(avatarText_);
}
//****************************************************************************************************************************************************
/// \return The login status.
//****************************************************************************************************************************************************
bool User::loggedIn() const
{
return loggedIn_;
}
//****************************************************************************************************************************************************
/// \param[in] loggedIn The login status.
//****************************************************************************************************************************************************
void User::setLoggedIn(bool loggedIn)
{
if (loggedIn == loggedIn_)
return;
loggedIn_ = loggedIn;
emit loggedInChanged(loggedIn_);
}
//****************************************************************************************************************************************************
/// \return The split mode status.
//****************************************************************************************************************************************************
bool User::splitMode() const
{
return splitMode_;
}
//****************************************************************************************************************************************************
/// \param[in] splitMode The split mode status.
//****************************************************************************************************************************************************
void User::setSplitMode(bool splitMode)
{
if (splitMode == splitMode_)
return;
splitMode_ = splitMode;
emit splitModeChanged(splitMode_);
}
//****************************************************************************************************************************************************
/// \return The 'Setup Guide Seen' status.
//****************************************************************************************************************************************************
bool User::setupGuideSeen() const
{
return setupGuideSeen_;
}
//****************************************************************************************************************************************************
/// \param[in] setupGuideSeen The 'Setup Guide Seen' status.
//****************************************************************************************************************************************************
void User::setSetupGuideSeen(bool setupGuideSeen)
{
if (setupGuideSeen == setupGuideSeen_)
return;
setupGuideSeen_ = setupGuideSeen;
emit setupGuideSeenChanged(setupGuideSeen_);
}
//****************************************************************************************************************************************************
/// \return The used bytes.
//****************************************************************************************************************************************************
float User::usedBytes() const
{
return usedBytes_;
}
//****************************************************************************************************************************************************
/// \param[in] usedBytes The used bytes.
//****************************************************************************************************************************************************
void User::setUsedBytes(float usedBytes)
{
if (usedBytes == usedBytes_)
return;
usedBytes_ = usedBytes;
emit usedBytesChanged(usedBytes_);
}
//****************************************************************************************************************************************************
/// \return The total bytes.
//****************************************************************************************************************************************************
float User::totalBytes() const
{
return totalBytes_;
}
//****************************************************************************************************************************************************
/// \param[in] totalBytes The total bytes.
//****************************************************************************************************************************************************
void User::setTotalBytes(float totalBytes)
{
if (totalBytes == totalBytes_)
return;
totalBytes_ = totalBytes;
emit totalBytesChanged(totalBytes_);
}
} // namespace bridgepp

View File

@ -0,0 +1,130 @@
// Copyright (c) 2022 Proton AG
//
// This file is part of Proton Mail Bridge.
//
// Proton Mail Bridge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Proton Mail Bridge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
#ifndef BRIDGE_GUI_USER_H
#define BRIDGE_GUI_USER_H
namespace bridgepp
{
typedef std::shared_ptr<class User> SPUser; ///< Type definition for shared pointer to user.
//****************************************************************************************************************************************************
/// \brief User class.
//****************************************************************************************************************************************************
class User : public QObject
{
Q_OBJECT
public: // static member function
static SPUser newUser(QObject *parent); ///< Create a new user
public: // member functions.
User(User const &) = delete; ///< Disabled copy-constructor.
User(User &&) = delete; ///< Disabled assignment copy-constructor.
~User() override = default; ///< Destructor.
User &operator=(User const &) = delete; ///< Disabled assignment operator.
User &operator=(User &&) = delete; ///< Disabled move assignment operator.
void update(User const &user); ///< Update the user.
public slots:
// slots for QML generated calls
void toggleSplitMode(bool makeItActive); // _ func(makeItActive bool) `slot:"toggleSplitMode"`
void logout(); // _ func() `slot:"logout"`
void remove(); // _ func() `slot:"remove"`
void configureAppleMail(QString const &address); // _ func(address string) `slot:"configureAppleMail"`
void emitToggleSplitModeFinished(); // slot for external signals
signals: // signal used to forward QML event received in the above slots
void toggleSplitModeForUser(QString const &userID, bool makeItActive);
void logoutUser(QString const &userID);
void removeUser(QString const &userID);
void configureAppleMailForUser(QString const &userID, QString const &address);
public:
Q_PROPERTY(QString id READ id WRITE setID NOTIFY idChanged) // _ string ID
Q_PROPERTY(QString username READ username WRITE setUsername NOTIFY usernameChanged) // _ string `property:"username"`
Q_PROPERTY(QString password READ password WRITE setPassword NOTIFY passwordChanged) // _ string `property:"password"`
Q_PROPERTY(QStringList addresses READ addresses WRITE setAddresses NOTIFY addressesChanged) // _ []string `property:"addresses"`
Q_PROPERTY(QString avatarText READ avatarText WRITE setAvatarText NOTIFY avatarTextChanged) // _ string `property:"avatarText"`
Q_PROPERTY(bool loggedIn READ loggedIn WRITE setLoggedIn NOTIFY loggedInChanged) // _ bool `property:"loggedIn"`
Q_PROPERTY(bool splitMode READ splitMode WRITE setSplitMode NOTIFY splitModeChanged) // _ bool `property:"splitMode"`
Q_PROPERTY(bool setupGuideSeen READ setupGuideSeen WRITE setSetupGuideSeen NOTIFY setupGuideSeenChanged) // _ bool `property:"setupGuideSeen"`
Q_PROPERTY(float usedBytes READ usedBytes WRITE setUsedBytes NOTIFY usedBytesChanged) // _ float32 `property:"usedBytes"`
Q_PROPERTY(float totalBytes READ totalBytes WRITE setTotalBytes NOTIFY totalBytesChanged) // _ float32 `property:"totalBytes"`
QString id() const;
void setID(QString const &id);
QString username() const;
void setUsername(QString const &username);
QString password() const;
void setPassword(QString const &password);
QStringList addresses() const;
void setAddresses(QStringList const &addresses);
QString avatarText() const;
void setAvatarText(QString const &avatarText);
bool loggedIn() const;
void setLoggedIn(bool loggedIn);
bool splitMode() const;
void setSplitMode(bool splitMode);
bool setupGuideSeen() const;
void setSetupGuideSeen(bool setupGuideSeen);
float usedBytes() const;
void setUsedBytes(float usedBytes);
float totalBytes() const;
void setTotalBytes(float totalBytes);
signals:
// signals used for Qt properties
void idChanged(QString const &id);
void usernameChanged(QString const &username);
void passwordChanged(QString const &);
void addressesChanged(QStringList const &);
void avatarTextChanged(QString const &avatarText);
void loggedInChanged(bool loggedIn);
void splitModeChanged(bool splitMode);
void setupGuideSeenChanged(bool seen);
void usedBytesChanged(float byteCount);
void totalBytesChanged(float byteCount);
void toggleSplitModeFinished();
private: // member functions.
User(QObject *parent); ///< Default constructor.
private: // data members.
QString id_; ///< The userID.
QString username_; ///< The username
QString password_; ///< The IMAP password of the user.
QStringList addresses_; ///< The email address list of the user.
QString avatarText_; ///< The avatar text (i.e. initials of the user)
bool loggedIn_ { true }; ///< Is the user logged in.
bool splitMode_ { false }; ///< Is split mode active.
bool setupGuideSeen_ { false }; ///< Has the setup guide been seen.
float usedBytes_ { 0.0f }; ///< The storage used by the user.
float totalBytes_ { 1.0f }; ///< The storage quota of the user.
};
} // namespace bridgepp
#endif // BRIDGE_GUI_USER_H

View File

@ -0,0 +1,120 @@
// Copyright (c) 2022 Proton AG
//
// This file is part of Proton Mail Bridge.
//
// Proton Mail Bridge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Proton Mail Bridge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
#include "Overseer.h"
#include "../Exception/Exception.h"
namespace bridgepp
{
//****************************************************************************************************************************************************
/// \param[in] worker The worker.
/// \param[in] parent The parent object of the worker.
//****************************************************************************************************************************************************
Overseer::Overseer(Worker *worker, QObject *parent)
: QObject(parent)
, thread_(new QThread(parent))
, worker_(worker)
{
if (!worker_)
throw Exception("Overseer cannot accept a nil worker.");
}
//****************************************************************************************************************************************************
//
//****************************************************************************************************************************************************
Overseer::~Overseer()
{
this->release();
}
//****************************************************************************************************************************************************
/// \param[in] autorelease Should the overseer automatically release the worker and thread when done.
//****************************************************************************************************************************************************
void Overseer::startWorker(bool autorelease) const
{
if (!worker_)
throw Exception("Cannot start overseer with null worker.");
if (!thread_)
throw Exception("Cannot start overseer with null thread.");
worker_->moveToThread(thread_);
connect(thread_, &QThread::started, worker_, &Worker::run);
connect(worker_, &Worker::finished, [&]() {thread_->quit(); }); // Safety, normally the thread already properly quits.
connect(worker_, &Worker::error, [&]() { thread_->quit(); });
if (autorelease)
{
connect(worker_, &Worker::error, this, &Overseer::release);
connect(worker_, &Worker::finished, this, &Overseer::release);
}
thread_->start();
}
//****************************************************************************************************************************************************
//
//****************************************************************************************************************************************************
void Overseer::release()
{
if (worker_)
{
worker_->deleteLater();
worker_ = nullptr;
}
if (thread_)
{
if (!thread_->isFinished())
{
thread_->quit();
thread_->wait();
}
thread_->deleteLater();
thread_ = nullptr;
}
}
//****************************************************************************************************************************************************
/// \return true iff the worker is finished.
//****************************************************************************************************************************************************
bool Overseer::isFinished() const
{
if ((!worker_) || (!worker_->thread()))
return true;
return worker_->thread()->isFinished();
}
//****************************************************************************************************************************************************
/// \return The worker.
//****************************************************************************************************************************************************
Worker *Overseer::worker() const
{
return worker_;
}
} // namespace bridgepp

View File

@ -0,0 +1,63 @@
// Copyright (c) 2022 Proton AG
//
// This file is part of Proton Mail Bridge.
//
// Proton Mail Bridge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Proton Mail Bridge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
#ifndef BRIDGE_PP_OVERSEER_H
#define BRIDGE_PP_OVERSEER_H
#include "Worker.h"
namespace bridgepp
{
//****************************************************************************************************************************************************
/// \brief Overseer used to manager a worker instance and its associated thread.
//****************************************************************************************************************************************************
class Overseer : public QObject
{
Q_OBJECT
public: // member functions.
explicit Overseer(Worker *worker, QObject *parent); ///< Default constructor.
Overseer(Overseer const &) = delete; ///< Disabled copy-constructor.
Overseer(Overseer &&) = delete; ///< Disabled assignment copy-constructor.
~Overseer() override; ///< Destructor.
Overseer &operator=(Overseer const &) = delete; ///< Disabled assignment operator.
Overseer &operator=(Overseer &&) = delete; ///< Disabled move assignment operator.
bool isFinished() const; ///< Check if the worker is finished.
Worker *worker() const; ///< Return worker.
public slots:
void startWorker(bool autorelease) const; ///< Run the worker.
void release(); ///< Delete the worker and its thread.
public: // data members.
QThread *thread_{nullptr}; ///< The thread.
Worker *worker_{nullptr}; ///< The worker.
};
typedef std::unique_ptr<Overseer> UPOverseer; ///< Type definition for unique pointer to Overseer.
typedef std::shared_ptr<Overseer> SPOverseer; ///< Type definition for shared pointer to Overseer.
} // namespace bridgepp
#endif //BRIDGE_PP_OVERSEER_H

View File

@ -0,0 +1,56 @@
// Copyright (c) 2022 Proton AG
//
// This file is part of Proton Mail Bridge.
//
// Proton Mail Bridge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Proton Mail Bridge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
#ifndef BRIDGE_PP_WORKER_H
#define BRIDGE_PP_WORKER_H
namespace bridgepp
{
//****************************************************************************************************************************************************
/// \brief Pure virtual class for worker intended to perform a threaded operation.
//****************************************************************************************************************************************************
class Worker : public QObject
{
Q_OBJECT
public: // member functions
explicit Worker(QObject *parent)
: QObject(parent)
{} ///< Default constructor.
Worker(Worker const &) = delete; ///< Disabled copy-constructor.
Worker(Worker &&) = delete; ///< Disabled assignment copy-constructor.
~Worker() override = default; ///< Destructor.
Worker &operator=(Worker const &) = delete; ///< Disabled assignment operator.
Worker &operator=(Worker &&) = delete; ///< Disabled move assignment operator.
public slots:
virtual void run() = 0; ///< run the worker.
signals:
void started(); ///< Signal for the start of the worker
void finished(); ///< Signal for the end of the worker
void error(QString const &message); ///< Signal for errors. After an error, worker ends and finished is NOT emitted.
};
} // namespace bridgepp
#endif //BRIDGE_PP_WORKER_H