Other: introduced bridgepp static C++ library.

This commit is contained in:
Xavier Michelon
2022-08-03 12:03:52 +02:00
committed by Jakub
parent 3f189c430b
commit 345cc45a3e
41 changed files with 1554 additions and 786 deletions

View File

@ -16,13 +16,15 @@
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
#include "Pch.h"
#include "AppController.h"
#include "QMLBackend.h"
#include "GRPC/GRPCClient.h"
#include "Log.h"
#include "BridgeMonitor.h"
#include "Exception.h"
#include <bridgepp/GRPC/GRPCClient.h>
#include <bridgepp/Exception/Exception.h>
#include <bridgepp/Log/Log.h>
using namespace bridgepp;
//****************************************************************************************************************************************************
@ -43,7 +45,6 @@ AppController::AppController()
, grpc_(std::make_unique<GRPCClient>())
, log_(std::make_unique<Log>())
{
}

View File

@ -21,10 +21,16 @@
class QMLBackend;
class GRPCClient;
class BridgeMonitor;
namespace bridgepp
{
class Log;
class Overseer;
class BridgeMonitor;
class GRPCClient;
}
//****************************************************************************************************************************************************
/// \brief App controller class.
@ -41,9 +47,9 @@ public: // member functions.
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.
GRPCClient& grpc() { return *grpc_; } ///< Return a reference to the GRPC client.
Log& log() { return *log_; } ///< Return a reference to the log.
std::unique_ptr<Overseer>& bridgeOverseer() { return bridgeOverseer_; }; ///< Returns a reference the bridge overseer
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
BridgeMonitor* bridgeMonitor() const; ///< Return the bridge worker.
private: // member functions
@ -51,9 +57,9 @@ private: // member functions
private: // data members
std::unique_ptr<QMLBackend> backend_; ///< The backend.
std::unique_ptr<GRPCClient> grpc_; ///< The RPC client.
std::unique_ptr<Log> log_; ///< The log.
std::unique_ptr<Overseer> bridgeOverseer_; ///< The overseer for the bridge monitor worker.
std::unique_ptr<bridgepp::GRPCClient> grpc_; ///< The RPC client.
std::unique_ptr<bridgepp::Log> log_; ///< The log.
std::unique_ptr<bridgepp::Overseer> bridgeOverseer_; ///< The overseer for the bridge monitor worker.
};

View File

@ -17,7 +17,10 @@
#include "BridgeMonitor.h"
#include "Exception.h"
#include <bridgepp/Exception/Exception.h>
using namespace bridgepp;
namespace

View File

@ -21,13 +21,13 @@
#define BRIDGE_GUI_BRIDGE_MONITOR_H
#include "Worker/Worker.h"
#include <bridgepp/Worker/Worker.h>
//**********************************************************************************************************************
/// \brief Bridge process launcher and monitor class.
//**********************************************************************************************************************
class BridgeMonitor: public Worker
class BridgeMonitor: public bridgepp::Worker
{
Q_OBJECT
public: // static member functions

View File

@ -17,41 +17,16 @@
cmake_minimum_required(VERSION 3.22)
# We rely on vcpkg for to get gRPC / Protobuf
# run build.sh / build.ps1 to get gRPC / Protobuf and dependencies installed.
include_guard()
set(VCPKG_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../../../extern/vcpkg")
message(STATUS "VCPKG_ROOT is ${VCPKG_ROOT}")
if (WIN32)
find_program(VCPKG_EXE "${VCPKG_ROOT}/vcpkg.exe")
else()
find_program(VCPKG_EXE "${VCPKG_ROOT}/vcpkg")
endif()
include(../bridgepp/bridge_setup.cmake)
# For now we support only a single architecture for macOS (ARM64 or x86_64). We need to investigate how to build universal binaries with vcpkg.
if (APPLE)
if (NOT DEFINED CMAKE_OSX_ARCHITECTURES)
execute_process(COMMAND "uname" "-m" OUTPUT_VARIABLE UNAME_RESULT OUTPUT_STRIP_TRAILING_WHITESPACE)
set(CMAKE_OSX_ARCHITECTURES ${UNAME_RESULT} CACHE STRING "osx_architectures")
endif()
#*****************************************************************************************************************************************************
# Project
#*****************************************************************************************************************************************************
if (CMAKE_OSX_ARCHITECTURES STREQUAL "arm64")
message(STATUS "Building for Apple Silicon Mac computers")
set(VCPKG_TARGET_TRIPLET arm64-osx)
elseif (CMAKE_OSX_ARCHITECTURES STREQUAL "x86_64")
message(STATUS "Building for Intel based Mac computers")
set(VCPKG_TARGET_TRIPLET x64-osx)
else ()
message(FATAL_ERROR "Unknown value for CMAKE_OSX_ARCHITECTURE. Please use one of \"arm64\" and \"x86_64\". Multiple architectures are not supported.")
endif ()
endif()
if (WIN32)
message(STATUS "Building for Intel x64 Windows computers")
set(VCPKG_TARGET_TRIPLET x64-windows)
endif()
set(CMAKE_TOOLCHAIN_FILE "${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" CACHE STRING "toolchain")
project(bridge-gui LANGUAGES CXX)
@ -61,116 +36,70 @@ else()
message(STATUS "Bridge version is ${BRIDGE_APP_VERSION}")
endif()
configure_file(Version.h.in ${CMAKE_SOURCE_DIR}/Version.h)
if (APPLE) # On macOS, we have some Objective-C++ code in DockIcon to deal with the dock icon.
enable_language(OBJC OBJCXX)
endif()
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
if (APPLE) # We need to link the Cocoa framework for the dock icon.
find_library(COCOA_LIBRARY Cocoa REQUIRED)
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})
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_AUTOMOC ON)
find_package(Qt6 COMPONENTS Core Quick Qml QuickControls2 REQUIRED)
qt_standard_project_setup()
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
find_package(Protobuf CONFIG REQUIRED)
message(STATUS "Using protobuf ${Protobuf_VERSION}")
find_package(gRPC CONFIG REQUIRED)
message(STATUS "Using gRPC ${gRPC_VERSION}")
if (APPLE) # We need to link the Cocoa framework for the dock icon.
find_library(COCOA_LIBRARY Cocoa REQ UIRED)
endif()
find_package(Qt6 COMPONENTS
Core
Quick
Qml
QuickControls2
REQUIRED)
message(STATUS "Using Qt ${Qt6_VERSION}")
find_program(PROTOC_EXE protoc REQUIRED)
message(STATUS "protoc found ${PROTOC_EXE}")
message(STATUS "grpc_cpp_plugin ${grpc_cpp_plugin}")
#*****************************************************************************************************************************************************
# Source files and output
#*****************************************************************************************************************************************************
find_program(GRPC_CPP_PLUGIN grpc_cpp_plugin)
if(GRPC_CPP_PLUGIN STREQUAL GRPC_CPP_PLUGIN-NOTFOUND)
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}/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")
configure_file(Version.h.in ${CMAKE_SOURCE_DIR}/Version.h)
add_subdirectory(../bridgepp bridgepp)
if (APPLE)
set(DOCK_ICON_SRC_FILE DockIcon/DockIcon.mm)
else()
set(DOCK_ICON_SRC_FILE DockIcon/DockIcon.cpp)
endif()
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_executable(bridge-gui
Resources.qrc
${PROTO_CPP_FILE} ${PROTO_H_FILE} ${GRPC_CPP_FILE} ${GRPC_H_FILE}
AppController.cpp AppController.h
BridgeMonitor.cpp BridgeMonitor.h
EventStreamWorker.cpp EventStreamWorker.h
Exception.cpp Exception.h
Log.cpp Log.h
main.cpp
Pch.h
Version.h
QMLBackend.cpp QMLBackend.h
UserList.cpp UserList.h
${DOCK_ICON_SRC_FILE} DockIcon/DockIcon.h
GRPC/GRPCClient.cpp GRPC/GRPCClient.h
GRPC/GRPCUtils.cpp GRPC/GRPCUtils.h
User/User.cpp User/User.h User/UserList.cpp User/UserList.h
Worker/Overseer.cpp Worker/Overseer.h
Worker/Worker.h)
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
)
target_precompile_headers(bridge-gui PRIVATE Pch.h)
target_include_directories(bridge-gui PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(bridge-gui
Qt6::Core
Qt6::Quick
Qt6::Qml
Qt6::QuickControls2
protobuf::libprotobuf
gRPC::grpc++
bridgepp
)
if (APPLE)

View File

@ -16,7 +16,6 @@
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
#include "Pch.h"
#ifndef Q_OS_MACOS

View File

@ -16,7 +16,6 @@
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
#include "Pch.h"
#include <Cocoa/Cocoa.h>
#include "DockIcon.h"

View File

@ -16,11 +16,13 @@
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
#include "Pch.h"
#include "EventStreamWorker.h"
#include "GRPC/GRPCClient.h"
#include "Log.h"
#include "Exception.h"
#include <bridgepp/GRPC/GRPCClient.h>
#include <bridgepp/Exception/Exception.h>
#include <bridgepp/Log/Log.h>
using namespace bridgepp;
//****************************************************************************************************************************************************

View File

@ -20,14 +20,13 @@
#define BRIDGE_GUI_EVENT_STREAM_WORKER_H
#include "GRPC/bridge.grpc.pb.h"
#include "Worker/Worker.h"
#include <bridgepp/Worker/Worker.h>
//****************************************************************************************************************************************************
/// \brief Stream reader class.
//****************************************************************************************************************************************************
class EventStreamReader: public Worker
class EventStreamReader: public bridgepp::Worker
{
Q_OBJECT
public: // member functions

View File

@ -1,68 +0,0 @@
// 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 "Pch.h"
#include "Exception.h"
//****************************************************************************************************************************************************
/// \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();
}

View File

@ -1,46 +0,0 @@
// 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_EXCEPTION_H
#define BRIDGE_GUI_EXCEPTION_H
#include <stdexcept>
//****************************************************************************************************************************************************
/// \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
};
#endif //BRIDGE_GUI_EXCEPTION_H

File diff suppressed because it is too large Load Diff

View File

@ -1,222 +0,0 @@
// 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 "GRPC/bridge.grpc.pb.h"
#include "grpc++/grpc++.h"
#include "User/User.h"
#include "Log.h"
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.
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 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 releated 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:
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); ///< Perfom a gRPC call that takes a string as a parameter and returns an Empty.
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.
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

@ -1,84 +0,0 @@
// 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 "Pch.h"
#include "Exception.h"
#include "GRPCUtils.h"
//****************************************************************************************************************************************************
/// \param[in] status The status
/// \param[in] callName The call name.
//****************************************************************************************************************************************************
void logGRPCCallStatus(grpc::Status const& status, QString const &callName)
{
if (status.ok())
app().log().debug(QString("%1()").arg(callName));
else
app().log().error(QString("%1() FAILED").arg(callName));
}
//****************************************************************************************************************************************************
/// \param[in] grpcUser the gRPC user struct
/// \return a user.
//****************************************************************************************************************************************************
SPUser parsegrpcUser(grpc::User const &grpcUser)
{
// As we want to use shared pointers here, we do not want to use the Qt ownership system, so we set parent to nil.
// But: From https://doc.qt.io/qt-5/qtqml-cppintegration-data.html:
// " 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 explicitely indicate that the object is owned by C++.
SPUser user = std::make_shared<User>(nullptr);
QQmlEngine::setObjectOwnership(user.get(), QQmlEngine::CppOwnership);
user->setProperty("username", QString::fromStdString(grpcUser.username()));
user->setProperty("avatarText", QString::fromStdString(grpcUser.avatartext()));
user->setProperty("loggedIn", grpcUser.loggedin());
user->setProperty("splitMode", grpcUser.splitmode());
user->setProperty("setupGuideSeen", grpcUser.setupguideseen());
user->setProperty("usedBytes", float(grpcUser.usedbytes()));
user->setProperty("totalBytes", float(grpcUser.totalbytes()));
user->setProperty("password", QString::fromStdString(grpcUser.password()));
QStringList addresses;
for (int j = 0; j < grpcUser.addresses_size(); ++j)
addresses.append(QString::fromStdString(grpcUser.addresses(j)));
user->setProperty("addresses", addresses);
user->setProperty("id", QString::fromStdString(grpcUser.id()));
return user;
}
//****************************************************************************************************************************************************
/// \param[in] level The log level
//****************************************************************************************************************************************************
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)));
}
}

View File

@ -1,34 +0,0 @@
// 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_GRPCUTILS_H
#define BRIDGE_GUI_GRPCUTILS_H
#include "Log.h"
#include "GRPC/bridge.grpc.pb.h"
#include "grpc++/grpc++.h"
#include "User/User.h"
void logGRPCCallStatus(grpc::Status const& status, QString const &callName); ///< Log the status of a gRPC code.
SPUser parsegrpcUser(grpc::User const& grpcUser); ///< Parse a gRPC user struct and return a User.
grpc::LogLevel logLevelToGRPC(Log::Level level); ///< Convert a Log::Level to gRPC enum value.
#endif // BRIDGE_GUI_GRPCUTILS_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

@ -1,234 +0,0 @@
// 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 "Pch.h"
#include "Log.h"
namespace
{
//****************************************************************************************************************************************************
/// \param[in] type The message type.
/// \param[in] message The message.
//****************************************************************************************************************************************************
void qtMessageHandler(QtMsgType type, QMessageLogContext const &, QString const &message)
{
static Log &log = app().log();
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";
}
}
//****************************************************************************************************************************************************
/// \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 logEntryToString(Log::Level level, QString const &message)
{
return QString("[%1] %2").arg(logLevelToString(level)).arg(message);
}
}
//****************************************************************************************************************************************************
/// the message handle process the message from the Qt logging system.
//****************************************************************************************************************************************************
void Log::installQtMessageHandler()
{
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();
}
}

View File

@ -1,82 +0,0 @@
// 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_LOG_H
#define BRIDGE_GUI_LOG_H
//****************************************************************************************************************************************************
/// \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 [logrus 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 void installQtMessageHandler(); ///< Install the Qt message handler.
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.
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.
};
#endif //BRIDGE_GUI_LOG_H

View File

@ -27,11 +27,4 @@
#include <AppController.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
#endif // BRIDGE_GUI_PCH_H

View File

@ -16,13 +16,15 @@
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
#include "Pch.h"
#include "QMLBackend.h"
#include "Exception.h"
#include "GRPC/GRPCClient.h"
#include "Worker/Overseer.h"
#include "EventStreamWorker.h"
#include "Version.h"
#include <bridgepp/GRPC/GRPCClient.h>
#include <bridgepp/Exception/Exception.h>
#include <bridgepp/Worker/Overseer.h>
using namespace bridgepp;
//****************************************************************************************************************************************************
@ -30,7 +32,6 @@
//****************************************************************************************************************************************************
QMLBackend::QMLBackend()
: QObject()
, users_(new UserList(this))
{
}
@ -40,6 +41,9 @@ QMLBackend::QMLBackend()
//****************************************************************************************************************************************************
void QMLBackend::init()
{
users_ = new UserList(this);
app().grpc().setLog(&app().log());
this->connectGrpcEvents();
QString error;
@ -47,10 +51,11 @@ void QMLBackend::init()
app().log().info("Connected to backend via gRPC service.");
else
throw Exception(QString("Cannot connectToServer to go backend via gRPC: %1").arg(error));
QString bridgeVer;
app().grpc().version(bridgeVer);
if (bridgeVer != PROJECT_VER)
throw Exception(QString("Version Mismatched from Bridge (%1) and Bridge-GUI (%2)").arg(bridgeVer).arg(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);
@ -60,10 +65,10 @@ void QMLBackend::init()
});
// Grab from bridge the value that will not change during the execution of this app (or that will only change locally
logGRPCCallStatus(app().grpc().showSplashScreen(showSplashScreen_), "showSplashScreen");
logGRPCCallStatus(app().grpc().goos(goos_), "goos");
logGRPCCallStatus(app().grpc().logsPath(logsPath_), "logsPath");
logGRPCCallStatus(app().grpc().licensePath(licensePath_), "licensePath");
app().grpc().showSplashScreen(showSplashScreen_);
app().grpc().goos(goos_);
app().grpc().logsPath(logsPath_);
app().grpc().licensePath(licensePath_);
this->retrieveUserList();
}
@ -147,7 +152,16 @@ void QMLBackend::connectGrpcEvents()
void QMLBackend::retrieveUserList()
{
QList<SPUser> users;
logGRPCCallStatus(app().grpc().getUserList(users), "getUserList");
app().grpc().getUserList(users);
// As we want to use shared pointers here, we do not want to use the Qt ownership system, so we set parent to nil.
// But: From https://doc.qt.io/qt-5/qtqml-cppintegration-data.html:
// " 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: users)
QQmlEngine::setObjectOwnership(user.get(), QQmlEngine::CppOwnership);
users_->reset(users);
}
@ -176,7 +190,7 @@ QPoint QMLBackend::getCursorPos()
bool QMLBackend::isPortFree(int port)
{
bool isFree = false;
logGRPCCallStatus(app().grpc().isPortFree(port, isFree), "isPortFree");
app().grpc().isPortFree(port, isFree);
return isFree;
}
@ -186,7 +200,7 @@ bool QMLBackend::isPortFree(int port)
//****************************************************************************************************************************************************
void QMLBackend::guiReady()
{
logGRPCCallStatus(app().grpc().guiReady(), "guiReady");
app().grpc().guiReady();
}
@ -195,7 +209,7 @@ void QMLBackend::guiReady()
//****************************************************************************************************************************************************
void QMLBackend::quit()
{
logGRPCCallStatus(app().grpc().quit(), "quit");
app().grpc().quit();
qApp->exit(0);
}
@ -205,7 +219,7 @@ void QMLBackend::quit()
//****************************************************************************************************************************************************
void QMLBackend::restart()
{
logGRPCCallStatus(app().grpc().restart(), "restart");
app().grpc().restart();
app().log().error("RESTART is not implemented"); /// \todo GODT-1671 implement restart.
}
@ -215,7 +229,7 @@ void QMLBackend::restart()
//****************************************************************************************************************************************************
void QMLBackend::toggleAutostart(bool active)
{
logGRPCCallStatus(app().grpc().setIsAutostartOn(active), "setIsAutostartOn");
app().grpc().setIsAutostartOn(active);
emit isAutostartOnChanged(this->isAutostartOn());
}
@ -225,7 +239,7 @@ void QMLBackend::toggleAutostart(bool active)
//****************************************************************************************************************************************************
void QMLBackend::toggleBeta(bool active)
{
logGRPCCallStatus(app().grpc().setisBetaEnabled(active), "setIsBetaEnabled");
app().grpc().setIsBetaEnabled(active);
emit isBetaEnabledChanged(this->isBetaEnabled());
}
@ -235,7 +249,7 @@ void QMLBackend::toggleBeta(bool active)
//****************************************************************************************************************************************************
void QMLBackend::changeColorScheme(QString const &scheme)
{
logGRPCCallStatus(app().grpc().setColorSchemeName(scheme), "setIsBetaEnabled");
app().grpc().setColorSchemeName(scheme);
emit colorSchemeNameChanged(this->colorSchemeName());
}
@ -245,9 +259,7 @@ void QMLBackend::changeColorScheme(QString const &scheme)
//****************************************************************************************************************************************************
void QMLBackend::toggleUseSSLforSMTP(bool makeItActive)
{
grpc::Status status = app().grpc().setUseSSLForSMTP(makeItActive);
logGRPCCallStatus(status, "setUseSSLForSMTP");
if (status.ok())
if (app().grpc().setUseSSLForSMTP(makeItActive).ok())
emit useSSLforSMTPChanged(makeItActive);
}
@ -258,9 +270,7 @@ void QMLBackend::toggleUseSSLforSMTP(bool makeItActive)
//****************************************************************************************************************************************************
void QMLBackend::changePorts(int imapPort, int smtpPort)
{
grpc::Status status = app().grpc().changePorts(imapPort, smtpPort);
logGRPCCallStatus(status, "changePorts");
if (status.ok())
if (app().grpc().changePorts(imapPort, smtpPort).ok())
{
emit portIMAPChanged(imapPort);
emit portSMTPChanged(smtpPort);
@ -273,9 +283,7 @@ void QMLBackend::changePorts(int imapPort, int smtpPort)
//****************************************************************************************************************************************************
void QMLBackend::toggleDoH(bool active)
{
grpc::Status status = app().grpc().setIsDoHEnabled(active);
logGRPCCallStatus(status, "toggleDoH");
if (status.ok())
if (app().grpc().setIsDoHEnabled(active).ok())
emit isDoHEnabledChanged(active);
}
@ -285,9 +293,7 @@ void QMLBackend::toggleDoH(bool active)
//****************************************************************************************************************************************************
void QMLBackend::changeKeychain(QString const &keychain)
{
grpc::Status status = app().grpc().setCurrentKeychain(keychain);
logGRPCCallStatus(status, "setCurrentKeychain");
if (status.ok())
if (app().grpc().setCurrentKeychain(keychain).ok())
emit currentKeychainChanged(keychain);
}
@ -297,9 +303,7 @@ void QMLBackend::changeKeychain(QString const &keychain)
//****************************************************************************************************************************************************
void QMLBackend::toggleAutomaticUpdate(bool active)
{
grpc::Status status = app().grpc().setIsAutomaticUpdateOn(active);
logGRPCCallStatus(status, "toggleAutomaticUpdate");
if (status.ok())
if (app().grpc().setIsAutomaticUpdateOn(active).ok())
emit isAutomaticUpdateOnChanged(active);
}
@ -309,7 +313,7 @@ void QMLBackend::toggleAutomaticUpdate(bool active)
//****************************************************************************************************************************************************
void QMLBackend::checkUpdates()
{
logGRPCCallStatus(app().grpc().checkUpdate(), "checkUpdate");
app().grpc().checkUpdate();
}
@ -318,7 +322,7 @@ void QMLBackend::checkUpdates()
//****************************************************************************************************************************************************
void QMLBackend::installUpdate()
{
logGRPCCallStatus(app().grpc().installUpdate(), "installUpdate");
app().grpc().installUpdate();
}
@ -327,5 +331,5 @@ void QMLBackend::installUpdate()
//****************************************************************************************************************************************************
void QMLBackend::triggerReset()
{
logGRPCCallStatus(app().grpc().triggerReset(), "triggerReset");
app().grpc().triggerReset();
}

View File

@ -16,16 +16,15 @@
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
#ifndef BRIDGE_GUI_QMLBACKEND_H
#define BRIDGE_GUI_QMLBACKEND_H
#ifndef BRIDGE_GUI_QML_BACKEND_H
#define BRIDGE_GUI_QML_BACKEND_H
#include <grpcpp/support/status.h>
#include "DockIcon/DockIcon.h"
#include "GRPC/GRPCClient.h"
#include "GRPC/GRPCUtils.h"
#include "Worker/Overseer.h"
#include "User/UserList.h"
#include "UserList.h"
#include <bridgepp/GRPC/GRPCClient.h>
#include <bridgepp/GRPC/GRPCUtils.h>
#include <bridgepp/Worker/Overseer.h>
//****************************************************************************************************************************************************
@ -78,31 +77,31 @@ public: // Qt/QML properties. Note that the NOTIFY-er signal is required even fo
Q_PROPERTY(bool dockIconVisible READ dockIconVisible WRITE setDockIconVisible NOTIFY dockIconVisibleChanged) // _ bool `property:dockIconVisible`
// Qt Property system setters & getters.
bool showOnStartup() const { bool v = false; logGRPCCallStatus(app().grpc().showOnStartup(v), "showOnStartup"); 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); } }
QString goos() { return goos_; }
QUrl logsPath() const { return logsPath_; }
QUrl licensePath() const { return licensePath_; }
QUrl releaseNotesLink() const { QUrl link; logGRPCCallStatus(app().grpc().releaseNotesPageLink(link), "releaseNotesPageLink"); return link; }
QUrl dependencyLicensesLink() const { QUrl link; logGRPCCallStatus(app().grpc().dependencyLicensesLink(link), "dependencyLicensesLink"); return link; }
QUrl landingPageLink() const { QUrl link; logGRPCCallStatus(app().grpc().landingPageLink(link), "landingPageLink"); return link; }
QString version() const { QString version; logGRPCCallStatus(app().grpc().version(version), "version"); return version; }
QString hostname() const { QString hostname; logGRPCCallStatus(app().grpc().hostname(hostname), "hostname"); return hostname; }
bool isAutostartOn() const { bool v; logGRPCCallStatus(app().grpc().isAutostartOn(v), "isAutostartOn"); return v; };
bool isBetaEnabled() const { bool v; logGRPCCallStatus(app().grpc().isBetaEnabled(v), "isBetaEnabled"); return v; }
QString colorSchemeName() const { QString name; logGRPCCallStatus(app().grpc().colorSchemeName(name), "colorSchemeName"); return name; }
bool isDiskCacheEnabled() const { bool enabled; logGRPCCallStatus(app().grpc().isCacheOnDiskEnabled(enabled), "isCacheOnDiskEnabled"); return enabled;}
QUrl diskCachePath() const { QUrl path; logGRPCCallStatus(app().grpc().diskCachePath(path), "diskCachePath"); return path; }
bool useSSLForSMTP() const{ bool useSSL; logGRPCCallStatus(app().grpc().useSSLForSMTP(useSSL), "useSSLForSMTP"); return useSSL; }
int portIMAP() const { int port; logGRPCCallStatus(app().grpc().portIMAP(port), "portIMAP"); return port; }
int portSMTP() const { int port; logGRPCCallStatus(app().grpc().portSMTP(port), "portSMTP"); return port; }
bool isDoHEnabled() const { bool isEnabled; logGRPCCallStatus(app().grpc().isDoHEnabled(isEnabled), "isDoHEnabled"); return isEnabled;}
bool isFirstGUIStart() const { bool v; logGRPCCallStatus(app().grpc().isFirstGUIStart(v), "isFirstGUIStart"); return v; };
bool isAutomaticUpdateOn() const { bool isOn = false; logGRPCCallStatus(app().grpc().isAutomaticUpdateOn(isOn), "isAutomaticUpdateOn"); return isOn; }
QString currentEmailClient() { QString client; logGRPCCallStatus(app().grpc().currentEmailClient(client), "currentEmailClient"); return client;}
QStringList availableKeychain() const { QStringList keychains; logGRPCCallStatus(app().grpc().availableKeychains(keychains), "availableKeychain"); return keychains; }
QString currentKeychain() const { QString keychain; logGRPCCallStatus(app().grpc().currentKeychain(keychain), "currentKeychain"); return keychain; }
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 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; }
QString colorSchemeName() const { QString name; app().grpc().colorSchemeName(name); return name; }
bool isDiskCacheEnabled() const { bool enabled; app().grpc().isCacheOnDiskEnabled(enabled); return enabled;}
QUrl diskCachePath() const { QUrl path; app().grpc().diskCachePath(path); return path; }
bool useSSLForSMTP() const{ bool useSSL; app().grpc().useSSLForSMTP(useSSL); return useSSL; }
int portIMAP() const { int port; app().grpc().portIMAP(port); return port; }
int portSMTP() const { int port; app().grpc().portSMTP(port); return 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 dockIconVisible() const { return getDockIconVisibleState(); };
void setDockIconVisible(bool visible) { setDockIconVisibleState(visible); emit dockIconVisibleChanged(visible); }
@ -137,12 +136,11 @@ public slots: // slot for signals received from QML -> To be forwarded to Bridge
void toggleAutostart(bool active); // _ func(makeItActive bool) `slot:"toggleAutostart"`
void toggleBeta(bool active); // _ func(makeItActive bool) `slot:"toggleBeta"`
void changeColorScheme(QString const &scheme); // _ func(string) `slot:"changeColorScheme"`
void changeLocalCache(bool enable, QUrl const& path) { logGRPCCallStatus(app().grpc().changeLocalCache(enable, path), "changeLocalCache"); } // _ func(enableDiskCache bool, diskCachePath core.QUrl) `slot:"changeLocalCache"`
void login(QString const& username, QString const& password) { logGRPCCallStatus(app().grpc().login(username, password), "login");} // _ func(username, password string) `slot:"login"`
void login2FA(QString const& username, QString const& code) { logGRPCCallStatus(app().grpc().login2FA(username, code), "login2FA");} // _ func(username, code string) `slot:"login2FA"`
void login2Password(QString const& username, QString const& password) { logGRPCCallStatus(app().grpc().login2Passwords(username, password),
"login2Passwords");} // _ func(username, password string) `slot:"login2Password"`
void loginAbort(QString const& username){ logGRPCCallStatus(app().grpc().loginAbort(username), "loginAbort");} // _ func(username string) `slot:"loginAbort"`
void changeLocalCache(bool enable, QUrl const& path) { app().grpc().changeLocalCache(enable, path); } // _ func(enableDiskCache bool, diskCachePath core.QUrl) `slot:"changeLocalCache"`
void login(QString const& username, QString const& password) { app().grpc().login(username, password);} // _ func(username, password string) `slot:"login"`
void login2FA(QString const& username, QString const& code) { app().grpc().login2FA(username, code);} // _ func(username, code string) `slot:"login2FA"`
void login2Password(QString const& username, QString const& password) { app().grpc().login2Passwords(username, password);} // _ func(username, password string) `slot:"login2Password"`
void loginAbort(QString const& username){ app().grpc().loginAbort(username);} // _ func(username string) `slot:"loginAbort"`
void toggleUseSSLforSMTP(bool makeItActive); // _ func(makeItActive bool) `slot:"toggleUseSSLforSMTP"`
void changePorts(int imapPort, int smtpPort); // _ func(imapPort, smtpPort int) `slot:"changePorts"`
void toggleDoH(bool active); // _ func(makeItActive bool) `slot:"toggleDoH"`
@ -156,7 +154,7 @@ public slots: // slot for signals received from QML -> To be forwarded to Bridge
void installUpdate(); // _ func() `slot:"installUpdate"`
void triggerReset(); // _ func() `slot:"triggerReset"`
void reportBug(QString const &description, QString const& address, QString const &emailClient, bool includeLogs) {
logGRPCCallStatus(app().grpc().reportBug(description, address, emailClient, includeLogs), "reportBug"); } // _ func(description, address, emailClient string, includeLogs bool) `slot:"reportBug"`
app().grpc().reportBug(description, address, emailClient, includeLogs); } // _ func(description, address, emailClient string, includeLogs bool) `slot:"reportBug"`
signals: // Signals received from the Go backend, to be forwarded to QML
void toggleAutostartFinished(); // _ func() `signal:"toggleAutostartFinished"`
@ -211,7 +209,7 @@ private: // member functions
private: // data members
UserList* users_ { nullptr }; ///< The user list. Owned by backend.
std::unique_ptr<Overseer> eventStreamOverseer_; ///< The event stream overseer.
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.
QUrl logsPath_; ///< The logs path. Retrieved from bridge on startup.
@ -221,4 +219,4 @@ private: // data members
};
#endif // BRIDGE_GUI_QMLBACKEND_H
#endif // BRIDGE_GUI_QML_BACKEND_H

View File

@ -1,95 +0,0 @@
// 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 "Pch.h"
#include "User.h"
#include "GRPC/GRPCUtils.h"
#include "GRPC/GRPCClient.h"
//****************************************************************************************************************************************************
/// \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->setProperty("username", user.username_);
this->setProperty("avatarText", user.avatarText_);
this->setProperty("loggedIn", user.loggedIn_);
this->setProperty("splitMode", user.splitMode_);
this->setProperty("setupGuideSeen", user.setupGuideSeen_);
this->setProperty("usedBytes", user.usedBytes_);
this->setProperty("totalBytes", user.totalBytes_);
this->setProperty("password", user.password_);
this->setProperty("addresses", user.addresses_);
this->setProperty("id", user.id_);
}
//****************************************************************************************************************************************************
/// \param[in] makeItActive Should split mode be made active.
//****************************************************************************************************************************************************
void User::toggleSplitMode(bool makeItActive)
{
logGRPCCallStatus(app().grpc().setUserSplitMode(id_, makeItActive), "toggleSplitMode");
}
//****************************************************************************************************************************************************
//
//****************************************************************************************************************************************************
void User::logout()
{
logGRPCCallStatus(app().grpc().logoutUser(id_), "logoutUser");
}
//****************************************************************************************************************************************************
//
//****************************************************************************************************************************************************
void User::remove()
{
logGRPCCallStatus(app().grpc().removeUser(id_), "removeUser");
}
//****************************************************************************************************************************************************
/// \param[in] address The email address to configure Apple Mail for.
//****************************************************************************************************************************************************
void User::configureAppleMail(QString const &address)
{
logGRPCCallStatus(app().grpc().configureAppleMail(id_, address), "configureAppleMail");
}
//****************************************************************************************************************************************************
// 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()
{
this->setProperty("splitMode", QVariant::fromValue(!this->property("splitMode").toBool()));
emit toggleSplitModeFinished();
}

View File

@ -1,93 +0,0 @@
// 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
#include "Log.h"
//****************************************************************************************************************************************************
/// \brief User class.
//****************************************************************************************************************************************************
class User : public QObject
{
Q_OBJECT
public: // member functions.
explicit User(QObject *parent = nullptr); ///< Default constructor.
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"`
// slots for external signals
void emitToggleSplitModeFinished();
public:
Q_PROPERTY(QString username MEMBER username_ NOTIFY usernameChanged) // _ string `property:"username"`
Q_PROPERTY(QString avatarText MEMBER avatarText_ NOTIFY avatarTextChanged) // _ string `property:"avatarText"`
Q_PROPERTY(bool loggedIn MEMBER loggedIn_ NOTIFY loggedInChanged) // _ bool `property:"loggedIn"`
Q_PROPERTY(bool splitMode MEMBER splitMode_ NOTIFY splitModeChanged) // _ bool `property:"splitMode"`
Q_PROPERTY(bool setupGuideSeen MEMBER setupGuideSeen_ NOTIFY setupGuideSeenChanged) // _ bool `property:"setupGuideSeen"`
Q_PROPERTY(float usedBytes MEMBER usedBytes_ NOTIFY usedBytesChanged) // _ float32 `property:"usedBytes"`
Q_PROPERTY(float totalBytes MEMBER totalBytes_ NOTIFY totalBytesChanged) // _ float32 `property:"totalBytes"`
Q_PROPERTY(QString password MEMBER password_ NOTIFY passwordChanged) // _ string `property:"password"`
Q_PROPERTY(QStringList addresses MEMBER addresses_ NOTIFY addressesChanged) // _ []string `property:"addresses"`
Q_PROPERTY(QString id MEMBER id_ NOTIFY idChanged) // _ string ID
signals:
// signals used for Qt properties
void usernameChanged(QString const &username);
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 passwordChanged(QString const &);
void addressesChanged(QStringList const &);
void idChanged(QStringList const &id);
void toggleSplitModeFinished();
private:
QString id_; ///< The userID.
QString username_; ///< The username
QString avatarText_; ///< The avatar text (i.e. initials of the user)
bool loggedIn_{false}; ///< 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_{0.0f}; ///< The storage quota of the user.
QString password_; ///< The IMAP password of the user.
QStringList addresses_; ///< The email address list of the user.
};
typedef std::shared_ptr<User> SPUser;
#endif // BRIDGE_GUI_USER_H

View File

@ -16,9 +16,10 @@
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
#include "Pch.h"
#include "UserList.h"
#include "GRPC/GRPCClient.h"
using namespace bridgepp;
//****************************************************************************************************************************************************
@ -36,11 +37,12 @@ UserList::UserList(QObject *parent)
//****************************************************************************************************************************************************
void UserList::connectGRPCEvents() const
{
GRPCClient* client = &app().grpc();
connect(client, &GRPCClient::userChanged, this, &UserList::onUserChanged);
connect(client, &GRPCClient::toggleSplitModeFinished, this, &UserList::onToggleSplitModeFinished);
GRPCClient& client = app().grpc();
connect(&client, &GRPCClient::userChanged, this, &UserList::onUserChanged);
connect(&client, &GRPCClient::toggleSplitModeFinished, this, &UserList::onToggleSplitModeFinished);
}
//****************************************************************************************************************************************************
//
//****************************************************************************************************************************************************
@ -60,7 +62,7 @@ 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();
int const row = index.row();
if ((row < 0) || (row >= users_.size()))
return QVariant();
return QVariant::fromValue(users_[row].get());
@ -91,6 +93,7 @@ void UserList::reset()
this->endResetModel();
}
//****************************************************************************************************************************************************
/// \param[in] users The new user list.
//****************************************************************************************************************************************************
@ -105,7 +108,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);
@ -135,7 +138,7 @@ void UserList::updateUserAtRow(int row, User const &user)
{
if ((row < 0) || (row >= users_.count()))
{
app().log().error(QString("invalid user at row %2 (user count = %2)").arg(row).arg(users_.count()));
app().log().error(QString("invalid user at row %2 (user userCount = %2)").arg(row).arg(users_.count()));
return;
}
@ -153,11 +156,11 @@ User *UserList::get(int row) const
{
if ((row < 0) || (row >= users_.count()))
{
app().log().error(QString("Requesting invalid user at row %1 (user count = %2)").arg(row).arg(users_.count()));
app().log().error(QString("Requesting invalid user at row %1 (user userCount = %2)").arg(row).arg(users_.count()));
return nullptr;
}
app().log().debug(QString("Retrieving user at row %1 (user count = %2)").arg(row).arg(users_.count()));
app().log().debug(QString("Retrieving user at row %1 (user userCount = %2)").arg(row).arg(users_.count()));
return users_[row].get();
}
@ -170,11 +173,13 @@ 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.
{
app().log().debug(QString("Removing user from userlist: %1").arg(userID));
app().log().debug(QString("Removing user from user list: %1").arg(userID));
this->removeUserAt(index);
}
return;
@ -182,12 +187,12 @@ void UserList::onUserChanged(QString const &userID)
if (index < 0)
{
app().log().debug(QString("Adding user in userlist: %1").arg(userID));
app().log().debug(QString("Adding user in user list: %1").arg(userID));
this->appendUser(user);
return;
}
app().log().debug(QString("Updating user in userlist: %1").arg(userID));
app().log().debug(QString("Updating user in user list: %1").arg(userID));
this->updateUserAtRow(index, *user);
}

View File

@ -19,45 +19,49 @@
#ifndef BRIDGE_GUI_USER_LIST_H
#define BRIDGE_GUI_USER_LIST_H
#include "User.h"
#include <bridgepp/User/User.h>
#include <bridgepp/Log/Log.h>
#include <bridgepp/GRPC/GRPCClient.h>
//****************************************************************************************************************************************************
/// \brief User list class.
//****************************************************************************************************************************************************
class UserList: public QAbstractListModel
class UserList : public QAbstractListModel
{
Q_OBJECT
Q_OBJECT
public: // member functions.
explicit UserList(QObject *parent = nullptr); ///< Default constructor.
UserList(UserList const &other) = delete ; ///< Disabled copy-constructor.
UserList& operator=(UserList const& other) = delete; ///< Disabled assignment operator.
UserList(QObject *parent); ///< Default constructor.
UserList(UserList const &other) = delete; ///< Disabled copy-constructor.
UserList &operator=(UserList const &other) = delete; ///< Disabled assignment operator.
~UserList() override = default; ///< Destructor
void connectGRPCEvents() const; ///< Connects gRPC event to the model.
int rowCount(QModelIndex const &parent) const override; ///< Return the number of row in the model
QVariant data(QModelIndex const &index, int role) const override; ///< Retrieve model data.
void reset(); ///< Reset the user list.
void reset(QList<SPUser> const &users); ///< Replace the user list.
void reset(QList<bridgepp::SPUser> const &users); ///< Replace the user list.
int rowOfUserID(QString const &userID) const;
void removeUserAt(int row); ///< Remove the user at a given row
void appendUser(SPUser const& user); ///< Add a new user.
void updateUserAtRow(int row, User const& user); ///< Update the user at 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.
// the count property.
// the userCount property.
Q_PROPERTY(int count READ count NOTIFY countChanged)
int count() const; ///< The count property getter.
int count() const; ///< The userCount property getter.
signals:
void countChanged(int count); ///< Signal for the count property.
void countChanged(int count); ///< Signal for the userCount property.
public:
Q_INVOKABLE User* get(int row) const;
Q_INVOKABLE bridgepp::User *get(int row) const;
public slots: ///< handler for signals coming from the gRPC service
void onUserChanged(QString const &userID);
void onToggleSplitModeFinished(QString const &userID);
private: // data members
QList<SPUser> users_; ///< The user list.
QList<bridgepp::SPUser> users_; ///< The user list.
};

View File

@ -1,114 +0,0 @@
// 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 "Pch.h"
#include "Overseer.h"
#include "Exception.h"
//****************************************************************************************************************************************************
/// \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(); }); // for unkwown reason, connect to the QThread::quit slot does not work...
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_;
}

View File

@ -1,56 +0,0 @@
// 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_OVERSEER_H
#define BRIDGE_GUI_OVERSEER_H
#include "Worker.h"
//****************************************************************************************************************************************************
/// \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.
#endif //BRIDGE_GUI_OVERSEER_H

View File

@ -1,46 +0,0 @@
// 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_WORKER_H
#define BRIDGE_GUI_WORKER_H
//****************************************************************************************************************************************************
/// \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.
};
#endif //BRIDGE_GUI_WORKER_H

View File

@ -16,12 +16,14 @@
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
#include "Pch.h"
#include "Exception.h"
#include "QMLBackend.h"
#include "Log.h"
#include "BridgeMonitor.h"
#include "Version.h"
#include <bridgepp/Log/Log.h>
#include <bridgepp/Exception/Exception.h>
using namespace bridgepp;
//****************************************************************************************************************************************************
@ -49,7 +51,7 @@ Log &initLog()
Log &log = app().log();
log.setEchoInConsole(true);
log.setLevel(Log::Level::Debug);
Log::installQtMessageHandler();
log.registerAsQtMessageHandler();
return log;
}
@ -63,7 +65,7 @@ QQmlComponent *createRootQmlComponent(QQmlApplicationEngine &engine)
qmlRegisterSingletonInstance("Proton", 1, 0, "Backend", &app().backend());
qmlRegisterType<UserList>("Proton", 1, 0, "UserList");
qmlRegisterType<User>("Proton", 1, 0, "User");
qmlRegisterType<bridgepp::User>("Proton", 1, 0, "User");
auto rootComponent = new QQmlComponent(&engine, &engine);
@ -138,7 +140,7 @@ void parseArguments(int argc, char **argv, bool &outAttach, QString &outExePath)
void closeBridgeApp()
{
UPOverseer& overseer = app().bridgeOverseer();
if (!overseer) // The app was ran in 'attach' mode and attached to an existing instance of Bridge. No need to close.
if (!overseer) // The app was run in 'attach' mode and attached to an existing instance of Bridge. No need to close.
return;
app().grpc().quit(); // this will cause the grpc service and the bridge app to close.
@ -186,7 +188,7 @@ int main(int argc, char *argv[])
QMetaObject::Connection connection;
if (bridgeMonitor)
connection = QObject::connect(bridgeMonitor, &BridgeMonitor::processExited, [&](int returnCode) {
// GODT-1671 We need to find a 'safe' way to check if brige crashed and restart instead of just quitting. Is returnCode enough?
// GODT-1671 We need to find a 'safe' way to check if Bridge crashed and restart instead of just quitting. Is returnCode enough?
bridgeExited = true;// clazy:exclude=lambda-in-connect
qGuiApp->exit(returnCode);
});