Other: bridge-gui-tester.

WIP: Added bridge-gui-test app.
WIP: goos.
WIP: event sending.
WIP: include bridge-gui-tester in frontend project
WIP: app end login event buttons.
WIP: login events. .
WIP: moved and renamed tab code
WIP: wired login logic.
WIP: setColorScheme and loginAbort.
WIP: more calls implemented + random users and numbers.
WIP: mail calls.
WIP: bug reports.
WIP: more signal send via the grpc Qt proxy.
WIP: Qt proxy on the event stream tab.
WIP: user change events wiring.
WIP: GUI changes.
WIP: minor refactoring.
WIP: remove event stream tab.
WIP: GUI changes.
WIP: separate logs, cache and keychain implemented.
WIP: Automatic update.

Other: fix linux build.

WIP: fix for live addition/modification/removal of users on the server side.
This commit is contained in:
Xavier Michelon
2022-08-04 16:51:42 +02:00
committed by Jakub
parent 42e9b6d2f3
commit 4ed9625959
33 changed files with 5504 additions and 2 deletions

View File

@ -0,0 +1,496 @@
// 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 "SettingsTab.h"
#include "GRPCService.h"
#include <bridgepp/GRPC/EventFactory.h>
#include <bridgepp/BridgeUtils.h>
using namespace bridgepp;
namespace
{
QString const colorSchemeDark = "dark"; ///< The dark color scheme name.
QString const colorSchemeLight = "light"; ///< THe light color scheme name.
}
//****************************************************************************************************************************************************
/// \param[in] parent The parent widget of the tab.
//****************************************************************************************************************************************************
SettingsTab::SettingsTab(QWidget *parent)
: QWidget(parent)
{
ui_.setupUi(this);
connect(ui_.buttonInternetOn, &QPushButton::clicked, []() { app().grpc().sendEvent(newInternetStatusEvent(true)); });
connect(ui_.buttonInternetOff, &QPushButton::clicked, []() { app().grpc().sendEvent(newInternetStatusEvent(false)); });
connect(ui_.buttonShowMainWindow, &QPushButton::clicked, []() { app().grpc().sendEvent(newShowMainWindowEvent()); });
connect(ui_.checkNextCacheChangeWillSucceed, &QCheckBox::toggled, this, &SettingsTab::updateGUIState);
this->resetUI();
this->updateGUIState();
}
//****************************************************************************************************************************************************
//
//****************************************************************************************************************************************************
void SettingsTab::updateGUIState()
{
bool connected = app().grpc().isStreaming();
for (QWidget *widget: { ui_.groupVersion, ui_.groupGeneral, ui_.groupMail, ui_.groupPaths, ui_.groupCache })
widget->setEnabled(!connected);
ui_.comboCacheError -> setEnabled(!ui_.checkNextCacheChangeWillSucceed->isChecked());
}
//****************************************************************************************************************************************************
/// \param[in] isStreaming Is the event stream on?
//****************************************************************************************************************************************************
void SettingsTab::setIsStreaming(bool isStreaming)
{
ui_.labelStreamingValue->setText(isStreaming ? "Yes" : "No");
this->updateGUIState();
}
//****************************************************************************************************************************************************
/// \param[in] clientPlatform The client platform.
//****************************************************************************************************************************************************
void SettingsTab::setClientPlatform(QString const &clientPlatform)
{
ui_.labelClientPlatformValue->setText(clientPlatform);
}
//****************************************************************************************************************************************************
/// \return The version of Bridge
//****************************************************************************************************************************************************
QString SettingsTab::bridgeVersion() const
{
return ui_.editVersion->text();
}
//****************************************************************************************************************************************************
/// \return The OS as a Go GOOS compatible value ("darwin", "linux" or "windows").
//****************************************************************************************************************************************************
QString SettingsTab::os() const
{
return ui_.comboOS->currentText();
}
//****************************************************************************************************************************************************
/// \return The value for the 'Current Email Client' edit.
//****************************************************************************************************************************************************
QString SettingsTab::currentEmailClient() const
{
return ui_.editCurrentEmailClient->text();
}
//****************************************************************************************************************************************************
/// \param[in] ready Is the GUI ready?
//****************************************************************************************************************************************************
void SettingsTab::setGUIReady(bool ready)
{
this->updateGUIState();
ui_.labelGUIReadyValue->setText(ready ? "Yes" : "No");
}
//****************************************************************************************************************************************************
/// \return true iff the 'Show On Startup' check box is checked.
//****************************************************************************************************************************************************
bool SettingsTab::showOnStartup() const
{
return ui_.checkShowOnStartup->isChecked();
}
//****************************************************************************************************************************************************
/// \return true iff the 'Show Splash Screen' check box is checked.
//****************************************************************************************************************************************************
bool SettingsTab::showSplashScreen() const
{
return ui_.checkShowSplashScreen->isChecked();
}
//****************************************************************************************************************************************************
/// \return true iff the 'Show Splash Screen' check box is checked.
//****************************************************************************************************************************************************
bool SettingsTab::isFirstGUIStart() const
{
return ui_.checkIsFirstGUIStart->isChecked();
}
//****************************************************************************************************************************************************
/// \return true iff the 'Show Splash Screen' check box is checked.
//****************************************************************************************************************************************************
bool SettingsTab::isAutostartOn() const
{
return ui_.checkAutostart->isChecked();
}
//****************************************************************************************************************************************************
/// \return true iff the 'Show Splash Screen' check box is checked.
//****************************************************************************************************************************************************
void SettingsTab::setIsAutostartOn(bool on)
{
ui_.checkAutostart->setChecked(on);
}
//****************************************************************************************************************************************************
/// \return true if the 'Use Dark Theme' check box is checked.
//****************************************************************************************************************************************************
QString SettingsTab::colorSchemeName() const
{
return ui_.checkDarkTheme->isChecked() ? colorSchemeDark : colorSchemeLight;
}
//****************************************************************************************************************************************************
/// \param[in] name True if the 'Use Dark Theme' check box should be checked.
//****************************************************************************************************************************************************
void SettingsTab::setColorSchemeName(QString const &name)
{
ui_.checkDarkTheme->setChecked(name == colorSchemeDark);
}
//****************************************************************************************************************************************************
/// \return true if the 'Beta Enabled' check box is checked.
//****************************************************************************************************************************************************
bool SettingsTab::isBetaEnabled() const
{
return ui_.checkBetaEnabled->isChecked();
}
//****************************************************************************************************************************************************
/// \param[in] enabled The new state for the 'Beta Enabled' check box.
//****************************************************************************************************************************************************
void SettingsTab::setIsBetaEnabled(bool enabled)
{
ui_.checkBetaEnabled->setChecked(enabled);
}
//****************************************************************************************************************************************************
/// \return The delay to apply before sending automatically generated events.
//****************************************************************************************************************************************************
qint32 SettingsTab::eventDelayMs() const
{
return ui_.spinEventDelay->value();
}
//****************************************************************************************************************************************************
/// \return The path
//****************************************************************************************************************************************************
QString SettingsTab::logsPath() const
{
return ui_.editLogsPath->text();
}
//****************************************************************************************************************************************************
/// \return The path
//****************************************************************************************************************************************************
QString SettingsTab::licensePath() const
{
return ui_.editLicensePath->text();
}
//****************************************************************************************************************************************************
/// \return The link.
//****************************************************************************************************************************************************
QString SettingsTab::releaseNotesPageLink() const
{
return ui_.editReleaseNotesLink->text();
}
//****************************************************************************************************************************************************
/// \return The link.
//****************************************************************************************************************************************************
QString SettingsTab::dependencyLicenseLink() const
{
return ui_.editDependencyLicenseLink->text();
}
//****************************************************************************************************************************************************
/// \return The link.
//****************************************************************************************************************************************************
QString SettingsTab::landingPageLink() const
{
return ui_.editLandingPageLink->text();
}
//****************************************************************************************************************************************************
/// \param[in] osType The OS type.
/// \param[in] osVersion The OS version.
/// \param[in] emailClient The email client.
/// \param[in] address The email address.
/// \param[in] description The description.
/// \param[in] includeLogs Are the log included.
//****************************************************************************************************************************************************
void SettingsTab::setBugReport(QString const &osType, QString const &osVersion, QString const &emailClient, QString const &address,
QString const &description, bool includeLogs)
{
ui_.editOSType->setText(osType);
ui_.editOSVersion->setText(osVersion);
ui_.editEmailClient->setText(emailClient);
ui_.editAddress->setText(address);
ui_.editDescription->setPlainText(description);
ui_.labelIncludeLogsValue->setText(includeLogs ? "Yes" : "No");
}
//****************************************************************************************************************************************************
/// \return The state of the check box.
//****************************************************************************************************************************************************
bool SettingsTab::nextBugReportWillSucceed() const
{
return ui_.checkNextBugReportWillSucceed->isChecked();
}
//****************************************************************************************************************************************************
/// \return The value of the 'Hostname' edit.
//****************************************************************************************************************************************************
QString SettingsTab::hostname() const
{
return ui_.editHostname->text();
}
//****************************************************************************************************************************************************
/// \return The value of the IMAP port spin box.
//****************************************************************************************************************************************************
qint32 SettingsTab::imapPort()
{
return ui_.spinPortIMAP->value();
}
//****************************************************************************************************************************************************
/// \return The value of the SMTP port spin box.
//****************************************************************************************************************************************************
qint32 SettingsTab::smtpPort()
{
return ui_.spinPortSMTP->value();
}
//****************************************************************************************************************************************************
/// \param[in] imapPort The IMAP port.
/// \param[in] smtpPort The SMTP port.
//****************************************************************************************************************************************************
void SettingsTab::changePorts(qint32 imapPort, qint32 smtpPort)
{
ui_.spinPortIMAP->setValue(imapPort);
ui_.spinPortSMTP->setValue(smtpPort);
}
//****************************************************************************************************************************************************
/// \return The state of the 'Use SSL for SMTP' check box.
//****************************************************************************************************************************************************
bool SettingsTab::useSSLForSMTP() const
{
return ui_.checkUseSSLForSMTP->isChecked();
}
//****************************************************************************************************************************************************
/// \param[in] use The state of the 'Use SSL for SMTP' check box.
//****************************************************************************************************************************************************
void SettingsTab::setUseSSLForSMTP(bool use)
{
ui_.checkUseSSLForSMTP->setChecked(use);
}
//****************************************************************************************************************************************************
/// \return The state of the the 'DoH enabled' check box.
//****************************************************************************************************************************************************
bool SettingsTab::isDoHEnabled() const
{
return ui_.checkDoHEnabled->isChecked();
}
//****************************************************************************************************************************************************
/// \param[in] enabled The state of the 'DoH enabled' check box.
//****************************************************************************************************************************************************
void SettingsTab::setIsDoHEnabled(bool enabled)
{
ui_.checkDoHEnabled->setChecked(enabled);
}
//****************************************************************************************************************************************************
/// \return The reply for the next IsPortFree gRPC call.
//****************************************************************************************************************************************************
bool SettingsTab::isPortFree() const
{
return ui_.checkIsPortFree->isChecked();
}
//****************************************************************************************************************************************************
/// \return true iff cache on disk is enabled.
//****************************************************************************************************************************************************
bool SettingsTab::isCacheOnDiskEnabled() const
{
return ui_.checkCacheOnDiskEnabled->isChecked();
}
//****************************************************************************************************************************************************
/// \param[in] enabled Is the cache on disk enabled?
//****************************************************************************************************************************************************
void SettingsTab::changeLocalCache(bool enabled, QString const &path)
{
ui_.checkCacheOnDiskEnabled->setChecked(enabled);
ui_.editDiskCachePath->setText(path);
}
//****************************************************************************************************************************************************
/// \return The disk cache path.
//****************************************************************************************************************************************************
QString SettingsTab::diskCachePath() const
{
return ui_.editDiskCachePath->text();
}
//****************************************************************************************************************************************************
/// \return The value for the 'Next Cache Change Will Succeed' check box.
//****************************************************************************************************************************************************
bool SettingsTab::nextCacheChangeWillSucceed() const
{
return ui_.checkNextCacheChangeWillSucceed->isChecked();
}
//****************************************************************************************************************************************************
/// \return The index of the selected cache error.
//****************************************************************************************************************************************************
qint32 SettingsTab::cacheError() const
{
return ui_.comboCacheError->currentIndex();
}
//****************************************************************************************************************************************************
/// \return the value for the 'Automatic Update' check.
//****************************************************************************************************************************************************
bool SettingsTab::isAutomaticUpdateOn() const
{
return ui_.checkAutomaticUpdate->isChecked();
}
//****************************************************************************************************************************************************
/// \param[in] on The value for the 'Automatic Update' check.
//****************************************************************************************************************************************************
void SettingsTab::setIsAutomaticUpdateOn(bool on)
{
ui_.checkAutomaticUpdate->setChecked(on);
}
//****************************************************************************************************************************************************
//
//****************************************************************************************************************************************************
void SettingsTab::resetUI()
{
this->setGUIReady(false);
this->setIsStreaming(false);
this->setClientPlatform("Unknown");
ui_.editVersion->setText(BRIDGE_APP_VERSION);
ui_.comboOS->setCurrentText(bridgepp::goos());
ui_.editCurrentEmailClient->setText("Thunderbird/102.0.3");
ui_.checkShowOnStartup->setChecked(true);
ui_.checkShowSplashScreen->setChecked(false);
ui_.checkIsFirstGUIStart->setChecked(false);
ui_.checkAutostart->setChecked(true);
ui_.checkBetaEnabled->setChecked(true);
ui_.checkDarkTheme->setChecked(false);
QString const tmpDir = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
QString const logsDir = QDir(tmpDir).absoluteFilePath("logs");
QDir().mkpath(logsDir);
ui_.editLogsPath->setText(QDir::toNativeSeparators(logsDir));
QString const filePath = QDir(tmpDir).absoluteFilePath("LICENSE.txt");
QFile file(filePath);
if (!file.exists())
{
// we don't really care if it fails.
file.open(QIODevice::WriteOnly | QIODevice::Text);
file.write(QString("This is were the license should be.").toLocal8Bit());
file.close();
}
ui_.editLicensePath->setText(filePath);
ui_.editReleaseNotesLink->setText("https://en.wikipedia.org/wiki/Release_notes");
ui_.editDependencyLicenseLink->setText("https://en.wikipedia.org/wiki/Dependency_relation");
ui_.editLandingPageLink->setText("https://proton.me");
ui_.editOSType->setText(QString());
ui_.editOSVersion->setText(QString());
ui_.editEmailClient->setText(QString());
ui_.editAddress->setText(QString());
ui_.editDescription->setPlainText(QString());
ui_.labelIncludeLogsValue->setText(QString());
ui_.checkNextBugReportWillSucceed->setChecked(true);
ui_.editHostname->setText("localhost");
ui_.spinPortIMAP->setValue(1143);
ui_.spinPortSMTP->setValue(1025);
ui_.checkUseSSLForSMTP->setChecked(false);
ui_.checkDoHEnabled->setChecked(true);
ui_.checkIsPortFree->setChecked(true);
ui_.checkCacheOnDiskEnabled->setChecked(true);
QString const cacheDir = QDir(tmpDir).absoluteFilePath("cache");
QDir().mkpath(cacheDir);
ui_.editDiskCachePath->setText(QDir::toNativeSeparators(cacheDir));
ui_.checkNextCacheChangeWillSucceed->setChecked(true);
ui_.comboCacheError->setCurrentIndex(0);
ui_.checkAutomaticUpdate->setChecked(true);
}

View File

@ -0,0 +1,92 @@
// Copyright (c) 2022 Proton AG
//
// This file is part of Proton Mail Bridge.
//
// Proton Mail Bridge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Proton Mail Bridge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
#ifndef BRIDGE_GUI_TESTER_GENERAL_TAB_H
#define BRIDGE_GUI_TESTER_GENERAL_TAB_H
#include "Tab/ui_SettingsTab.h"
//****************************************************************************************************************************************************
/// \brief The 'General' tab of the main window.
//****************************************************************************************************************************************************
class SettingsTab : public QWidget
{
Q_OBJECT
public: // member functions.
explicit SettingsTab(QWidget *parent = nullptr); ///< Default constructor.
SettingsTab(SettingsTab const &) = delete; ///< Disabled copy-constructor.
SettingsTab(SettingsTab &&) = delete; ///< Disabled assignment copy-constructor.
~SettingsTab() = default; ///< Destructor.
SettingsTab &operator=(SettingsTab const &) = delete; ///< Disabled assignment operator.
SettingsTab &operator=(SettingsTab &&) = delete; ///< Disabled move assignment operator.
QString bridgeVersion() const; ///< Get the Bridge version.
QString os() const; ///< Return the OS string.
QString currentEmailClient() const; ///< Return the content of the current email client
void setGUIReady(bool ready); ///< Set the GUI as ready.
bool showOnStartup() const; ///< Get the value for the 'Show On Startup' check.
bool showSplashScreen() const; ///< Get the value for the 'Show Splash Screen' check.
bool isFirstGUIStart() const; ///< Get the value for the 'Is First GUI Start' check.
bool isAutostartOn() const; ///< Get the value for the 'Autostart' check.
bool isBetaEnabled() const; ///< Get the value for the 'Beta Enabled' check.
QString colorSchemeName() const; ///< Get the value of the 'Use Dark Theme' checkbox.
qint32 eventDelayMs() const; ///< Get the delay for sending automatically generated events.
QString logsPath() const; ///< Get the content of the 'Logs Path' edit.
QString licensePath() const; ///< Get the content of the 'License Path' edit.
QString releaseNotesPageLink() const; ///< Get the content of the 'Release Notes Page Link' edit.
QString dependencyLicenseLink() const; ///< Get the content of the 'Dependency License Link' edit.
QString landingPageLink() const; ///< Get the content of the 'Landing Page Link' edit.
bool nextBugReportWillSucceed() const; ///< Get the status of the 'Next Bug Report Will Fail' check box.
QString hostname() const; ///< Get the value of the 'Hostname' edit.
qint32 imapPort(); ///< Get the value of the IMAP port spin.
qint32 smtpPort(); ///< Get the value of the SMTP port spin.
bool useSSLForSMTP() const; ///< Get the value for the 'Use SSL for SMTP' check box.
bool isDoHEnabled() const; ///< Get the value for the 'DoH Enabled' check box.
bool isPortFree() const; ///< Get the value for the "Is Port Free" check box.
bool isCacheOnDiskEnabled() const; ///< get the value for the 'Cache On Disk Enabled' check box.
QString diskCachePath() const; ///< Get the value for the 'Disk Cache Path' edit.
bool nextCacheChangeWillSucceed() const; ///< Get the value for the 'Next Cache Change will succeed' edit.
qint32 cacheError() const; ///< Return the index of the selected cache error.
bool isAutomaticUpdateOn() const; ///<Get the value for the 'Automatic Update' check box.
public: // slots
void updateGUIState(); ///< Update the GUI state.
void setIsStreaming(bool isStreaming); ///< Set the isStreamingEvents value.
void setClientPlatform(QString const &clientPlatform); ///< Set the client platform.
void setIsAutostartOn(bool on); ///< Set the value for the 'Autostart' check.
void setIsBetaEnabled(bool enabled); ///< Get the value for the 'Beta Enabled' check.
void setColorSchemeName(QString const &name); ///< Set the value for the 'Use Dark Theme' checkbox.
void setBugReport(QString const &osType, QString const &osVersion, QString const &emailClient, QString const &address, QString const &description,
bool includeLogs); ///< Set the content of the bug report box.
void changePorts(qint32 imapPort, qint32 smtpPort); ///< Change the IMAP and SMTP ports.
void setUseSSLForSMTP(bool use); ///< Set the value for the 'Use SSL for SMTP' check box.
void setIsDoHEnabled(bool enabled); ///< Set the value for the 'DoH Enabled' check box.
void changeLocalCache(bool enabled, QString const &path); ///< Set the value for the 'Cache On Disk Enabled' check box.
void setIsAutomaticUpdateOn(bool on); ///< Set the value for the 'Automatic Update' check box.
private: // member functions.
void resetUI(); ///< Reset the widget.
private: // data members.
Ui::SettingsTab ui_; ///< The GUI for the tab
};
#endif //BRIDGE_GUI_TESTER_GENERAL_TAB_H

View File

@ -0,0 +1,839 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SettingsTab</class>
<widget class="QWidget" name="SettingsTab">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1066</width>
<height>808</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupVersion">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="title">
<string>Version Info</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="labelVersion">
<property name="text">
<string>Bridge Version</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="editVersion"/>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="labelOS">
<property name="text">
<string>OS</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboOS">
<item>
<property name="text">
<string notr="true">darwin</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">linux</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">windows</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QLabel" name="labelCurrentEmailClient">
<property name="text">
<string>Current Email Client</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="editCurrentEmailClient">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupGeneral">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="title">
<string>General Settings</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QCheckBox" name="checkShowOnStartup">
<property name="text">
<string>Show On Startup</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="checkShowSplashScreen">
<property name="text">
<string>Show Splash Screen</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QCheckBox" name="checkIsFirstGUIStart">
<property name="text">
<string>Is FIrst GUI Start</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="checkAutostart">
<property name="text">
<string>Autostart</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="checkBetaEnabled">
<property name="text">
<string>Beta Enabled</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QCheckBox" name="checkDarkTheme">
<property name="text">
<string>Dark Theme</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="checkAutomaticUpdate">
<property name="text">
<string>Automatic Update</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupMail">
<property name="title">
<string>Mail</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6" stretch="0,0">
<item>
<widget class="QLabel" name="labelHostname">
<property name="text">
<string>Hostname</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="editHostname">
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_7" stretch="0,0,0,0,1">
<item>
<widget class="QLabel" name="labelMAP">
<property name="text">
<string>IMAP Port</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinPortIMAP">
<property name="buttonSymbols">
<enum>QAbstractSpinBox::NoButtons</enum>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>65535</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="labelSMTP">
<property name="text">
<string>SMTP Port</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinPortSMTP">
<property name="buttonSymbols">
<enum>QAbstractSpinBox::NoButtons</enum>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>65535</number>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkUseSSLForSMTP">
<property name="text">
<string>Use SSL For SMTP</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="checkDoHEnabled">
<property name="text">
<string>DoH Enabled</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupPaths">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="title">
<string>Paths &amp;&amp; Links</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="labelLogsPath">
<property name="text">
<string>Logs Path</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="editLogsPath"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelLicensePath">
<property name="text">
<string>License Path</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="editLicensePath"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="labelReleaseNotesLink">
<property name="text">
<string>Release Notes Page Link</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="editReleaseNotesLink"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="labelDependencyLicenseLink">
<property name="text">
<string>Dependency License Link</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="editDependencyLicenseLink"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="labelLandingPageLink">
<property name="text">
<string>Landing Page Link</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="editLandingPageLink"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupCache">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="title">
<string>Cache</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<widget class="QCheckBox" name="checkCacheOnDiskEnabled">
<property name="text">
<string>Cache On Disk Enabled</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_10">
<item>
<widget class="QLabel" name="labelDiskCachePath">
<property name="text">
<string>Disk Cache Path</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="editDiskCachePath"/>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QGroupBox" name="groupStatus">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="title">
<string>Status</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="labelGUIReadyTitle">
<property name="text">
<string>GUI Ready:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="labelGUIReadyValue">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>1</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="labelStreamingTitle">
<property name="text">
<string>Streaming: </string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="labelStreamingValue">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="labelClientPlatformTitle">
<property name="text">
<string>Client Platform: </string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="labelClientPlatformValue">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBugReport">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="title">
<string>Bug Report</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="3">
<widget class="QLineEdit" name="editOSVersion">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="baseSize">
<size>
<width>250</width>
<height>0</height>
</size>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QLineEdit" name="editAddress">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="labelOSType">
<property name="text">
<string>OS Type</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="labelIncludeLogs">
<property name="text">
<string>Include Logs</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="labelAddress">
<property name="text">
<string>Address</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="labelOSVersion">
<property name="text">
<string>OS Version</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="editOSType">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="baseSize">
<size>
<width>250</width>
<height>0</height>
</size>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="1" colspan="3">
<widget class="QLabel" name="labelIncludeLogsValue">
<property name="text">
<string>?</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="labelDescription">
<property name="text">
<string>Description</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="editEmailClient">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelEmailClient">
<property name="text">
<string>Email Cient</string>
</property>
</widget>
</item>
<item row="2" column="1" colspan="4">
<widget class="QPlainTextEdit" name="editDescription">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupApp">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="title">
<string>Events &amp;&amp; Errors</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_8">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_11">
<item>
<widget class="QLabel" name="labelEventDelay">
<property name="toolTip">
<string>Delay applied before sending automatically generated events</string>
</property>
<property name="text">
<string>Delay for asynchronous events</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinEventDelay">
<property name="suffix">
<string> ms</string>
</property>
<property name="maximum">
<number>3600000</number>
</property>
<property name="singleStep">
<number>100</number>
</property>
<property name="value">
<number>1000</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>1</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_9">
<item>
<widget class="QPushButton" name="buttonInternetOff">
<property name="text">
<string>Internet Off</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="buttonInternetOn">
<property name="text">
<string>Internet On</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="buttonShowMainWindow">
<property name="text">
<string>Show Main Window</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="checkIsPortFree">
<property name="text">
<string>Reply true to the next 'Is Port Free' request.</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QCheckBox" name="checkNextCacheChangeWillSucceed">
<property name="text">
<string>Next Cache Change will succeed</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>1</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QComboBox" name="comboCacheError">
<item>
<property name="text">
<string>Cache Unavailable</string>
</property>
</item>
<item>
<property name="text">
<string>Can't Move Cache</string>
</property>
</item>
<item>
<property name="text">
<string>Disk Full</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="checkNextBugReportWillSucceed">
<property name="text">
<string>Next Bug Report Will Succeed</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<tabstops>
<tabstop>checkShowOnStartup</tabstop>
<tabstop>checkShowSplashScreen</tabstop>
<tabstop>checkIsFirstGUIStart</tabstop>
<tabstop>checkAutostart</tabstop>
<tabstop>checkBetaEnabled</tabstop>
<tabstop>checkDarkTheme</tabstop>
<tabstop>editVersion</tabstop>
<tabstop>comboOS</tabstop>
<tabstop>editCurrentEmailClient</tabstop>
<tabstop>editOSType</tabstop>
<tabstop>editOSVersion</tabstop>
<tabstop>editEmailClient</tabstop>
<tabstop>editAddress</tabstop>
<tabstop>editDescription</tabstop>
<tabstop>editLogsPath</tabstop>
<tabstop>editLicensePath</tabstop>
<tabstop>editReleaseNotesLink</tabstop>
<tabstop>editDependencyLicenseLink</tabstop>
<tabstop>editLandingPageLink</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,318 @@
// 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 "UsersTab.h"
#include "MainWindow.h"
#include "UserDialog.h"
#include <bridgepp/BridgeUtils.h>
#include <bridgepp/Exception/Exception.h>
#include <bridgepp/GRPC/EventFactory.h>
using namespace bridgepp;
//****************************************************************************************************************************************************
/// \param[in] parent The parent widget of the tab.
//****************************************************************************************************************************************************
UsersTab::UsersTab(QWidget *parent)
: QWidget(parent)
, users_(nullptr)
{
ui_.setupUi(this);
ui_.tableUserList->setModel(&users_);
QItemSelectionModel *model = ui_.tableUserList->selectionModel();
if (!model)
throw Exception("Could not get user table selection model.");
connect(model, &QItemSelectionModel::selectionChanged, this, &UsersTab::onSelectionChanged);
ui_.tableUserList->setColumnWidth(0, 150);
ui_.tableUserList->setColumnWidth(1, 250);
ui_.tableUserList->setColumnWidth(2, 350);
connect(ui_.buttonNewUser, &QPushButton::clicked, this, &UsersTab::onAddUserButton);
connect(ui_.buttonEditUser, &QPushButton::clicked, this, &UsersTab::onEditUserButton);
connect(ui_.tableUserList, &QTableView::doubleClicked, this, &UsersTab::onEditUserButton);
connect(ui_.buttonRemoveUser, &QPushButton::clicked, this, &UsersTab::onRemoveUserButton);
users_.append(randomUser());
this->updateGUIState();
}
//****************************************************************************************************************************************************
//
//****************************************************************************************************************************************************
void UsersTab::onAddUserButton()
{
SPUser user = randomUser();
UserDialog dialog(user, this);
if (QDialog::Accepted != dialog.exec())
return;
users_.append(user);
GRPCService &grpc = app().grpc();
if (grpc.isStreaming())
grpc.sendEvent(newLoginFinishedEvent(user->id()));
}
//****************************************************************************************************************************************************
//
//****************************************************************************************************************************************************
void UsersTab::onEditUserButton()
{
int index = selectedIndex();
if ((index < 0) || (index >= users_.userCount()))
return;
SPUser user = this->selectedUser();
UserDialog dialog(user, this);
if (QDialog::Accepted != dialog.exec())
return;
users_.touch(index);
GRPCService &grpc = app().grpc();
if (grpc.isStreaming())
grpc.sendEvent(newUserChangedEvent(user->id()));
}
//****************************************************************************************************************************************************
//
//****************************************************************************************************************************************************
void UsersTab::onRemoveUserButton()
{
int index = selectedIndex();
if ((index < 0) || (index >= users_.userCount()))
return;
SPUser const user = users_.userAtIndex(index);
users_.remove(index);
GRPCService &grpc = app().grpc();
if (grpc.isStreaming())
grpc.sendEvent(newUserChangedEvent(user->id()));
}
//****************************************************************************************************************************************************
//
//****************************************************************************************************************************************************
void UsersTab::onSelectionChanged(QItemSelection, QItemSelection)
{
this->updateGUIState();
}
//****************************************************************************************************************************************************
//
//****************************************************************************************************************************************************
void UsersTab::updateGUIState()
{
bool const hasSelectedUser = ui_.tableUserList->selectionModel()->hasSelection();
ui_.buttonEditUser->setEnabled(hasSelectedUser);
ui_.buttonRemoveUser->setEnabled(hasSelectedUser);
}
//****************************************************************************************************************************************************
//
//****************************************************************************************************************************************************
qint32 UsersTab::selectedIndex() const
{
return ui_.tableUserList->selectionModel()->hasSelection() ? ui_.tableUserList->currentIndex().row() : -1;
}
//****************************************************************************************************************************************************
/// \return The selected user.
/// \return A null pointer if no user is selected.
//****************************************************************************************************************************************************
bridgepp::SPUser UsersTab::selectedUser()
{
return users_.userAtIndex(this->selectedIndex());
}
//****************************************************************************************************************************************************
/// \return The list of users.
//****************************************************************************************************************************************************
UserTable &UsersTab::userTable()
{
return users_;
}
//****************************************************************************************************************************************************
/// \param[in] userID The userID.
/// \return The user with the given userID.
/// \return A null pointer if the user is not in the list.
//****************************************************************************************************************************************************
bridgepp::SPUser UsersTab::userWithID(QString const &userID)
{
return users_.userWithID(userID);
}
//****************************************************************************************************************************************************
/// \return true iff the next login attempt should trigger a username/password error.
//****************************************************************************************************************************************************
bool UsersTab::nextUserUsernamePasswordError() const
{
return ui_.checkUsernamePasswordError->isChecked();
}
//****************************************************************************************************************************************************
/// \return true iff the next login attempt should trigger a free user error.
//****************************************************************************************************************************************************
bool UsersTab::nextUserFreeUserError() const
{
return ui_.checkFreeUserError->isChecked();
}
//****************************************************************************************************************************************************
/// \return true iff the next login attempt will require 2FA.
//****************************************************************************************************************************************************
bool UsersTab::nextUserTFARequired() const
{
return ui_.checkTFARequired->isChecked();
}
//****************************************************************************************************************************************************
/// \return true iff the next login attempt should trigger a 2FA error.
//****************************************************************************************************************************************************
bool UsersTab::nextUserTFAError() const
{
return ui_.checkTFAError->isChecked();
}
//****************************************************************************************************************************************************
/// \return true iff the next login attempt should trigger a 2FA error with abort.
//****************************************************************************************************************************************************
bool UsersTab::nextUserTFAAbort() const
{
return ui_.checkTFAAbort->isChecked();
}
//****************************************************************************************************************************************************
/// \return true iff the next login attempt will require a 2nd password.
//****************************************************************************************************************************************************
bool UsersTab::nextUserTwoPasswordsRequired() const
{
return ui_.checkTwoPasswordsRequired->isChecked();
}
//****************************************************************************************************************************************************
/// \return true iff the next login attempt should trigger a 2nd password error.
//****************************************************************************************************************************************************
bool UsersTab::nextUserTwoPasswordsError() const
{
return ui_.checkTwoPasswordsError->isChecked();
}
//****************************************************************************************************************************************************
/// \return true iff the next login attempt should trigger a 2nd password error with abort.
//****************************************************************************************************************************************************
bool UsersTab::nextUserTwoPasswordsAbort() const
{
return ui_.checkTwoPasswordsAbort->isChecked();
}
//****************************************************************************************************************************************************
/// \return true iff the next login attempt should trigger a 2nd password error with abort.
//****************************************************************************************************************************************************
bool UsersTab::nextUserAlreadyLoggedIn() const
{
return ui_.checkAlreadyLoggedIn->isChecked();
}
//****************************************************************************************************************************************************
/// \param[in] userID The userID.
/// \param[in] makeItActive Should split mode be activated.
//****************************************************************************************************************************************************
void UsersTab::setUserSplitMode(QString const &userID, bool makeItActive)
{
qint32 const index = users_.indexOfUser(userID);
SPUser const user = users_.userAtIndex(index);
if (!user)
{
app().log().error(QString("%1 failed. unknown user %1").arg(__FUNCTION__, userID));
return;
}
user->setSplitMode(makeItActive);
users_.touch(index);
MainWindow &mainWindow = app().mainWindow();
mainWindow.sendDelayedEvent(newUserChangedEvent(userID));
mainWindow.sendDelayedEvent(newToggleSplitModeFinishedEvent(userID));
}
//****************************************************************************************************************************************************
/// \param[in] userID The userID.
//****************************************************************************************************************************************************
void UsersTab::logoutUser(QString const &userID)
{
qint32 const index = users_.indexOfUser(userID);
SPUser const user = users_.userAtIndex(index);
if (!user)
{
app().log().error(QString("%1 failed. unknown user %1").arg(__FUNCTION__, userID));
return;
}
user->setLoggedIn(false);
users_.touch(index);
app().mainWindow().sendDelayedEvent(newUserChangedEvent(userID));
}
//****************************************************************************************************************************************************
/// \param[in] userID The userID.
//****************************************************************************************************************************************************
void UsersTab::removeUser(QString const &userID)
{
qint32 const index = users_.indexOfUser(userID);
SPUser const user = users_.userAtIndex(index);
if (!user)
{
app().log().error(QString("%1 failed. unknown user %1").arg(__FUNCTION__, userID));
return;
}
users_.remove(index);
app().mainWindow().sendDelayedEvent(newUserChangedEvent(userID));
}
//****************************************************************************************************************************************************
/// \param[in] userID The userID.
/// \param[in] address The address.
//****************************************************************************************************************************************************
void UsersTab::configureUserAppleMail(QString const &userID, QString const &address)
{
app().log().info(QString("Apple mail configuration was requested for user %1, address %2").arg(userID, address));
}

View File

@ -0,0 +1,75 @@
// Copyright (c) 2022 Proton AG
//
// This file is part of Proton Mail Bridge.
//
// Proton Mail Bridge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Proton Mail Bridge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
#ifndef BRIDGE_GUI_TESTER_USERS_TAB_H
#define BRIDGE_GUI_TESTER_USERS_TAB_H
#include "Tabs/ui_UsersTab.h"
#include "UserTable.h"
//****************************************************************************************************************************************************
/// \brief The 'Users' tab of the main window.
//****************************************************************************************************************************************************
class UsersTab : public QWidget
{
Q_OBJECT
public: // member functions.
explicit UsersTab(QWidget *parent = nullptr); ///< Default constructor.
UsersTab(UsersTab const &) = delete; ///< Disabled copy-constructor.
UsersTab(UsersTab &&) = delete; ///< Disabled assignment copy-constructor.
~UsersTab() override = default; ///< Destructor.
UsersTab &operator=(UsersTab const &) = delete; ///< Disabled assignment operator.
UsersTab &operator=(UsersTab &&) = delete; ///< Disabled move assignment operator.
UserTable &userTable(); ///< Returns a reference to the user table.
bridgepp::SPUser userWithID(QString const &userID); ///< Get the user with the given ID.
bool nextUserUsernamePasswordError() const; ///< Check if next user login should trigger a username/password error.
bool nextUserFreeUserError() const; ///< Check if next user login should trigger a Free user error.
bool nextUserTFARequired() const; ///< Check if next user login should requires 2FA.
bool nextUserTFAError() const; ///< Check if next user login should trigger 2FA error
bool nextUserTFAAbort() const; ///< Check if next user login should trigger 2FA abort.
bool nextUserTwoPasswordsRequired() const; ///< Check if next user login requires 2nd password
bool nextUserTwoPasswordsError() const; ///< Check if next user login should trigger 2nd password error.
bool nextUserTwoPasswordsAbort() const; ///< Check if next user login should trigger 2nd password abort.
bool nextUserAlreadyLoggedIn() const; ///< Check if next user login should report user as already logged in.
public slots:
void setUserSplitMode(QString const &userID, bool makeItActive); ///< Slot for the split mode.
void logoutUser(QString const &userID); ///< slot for the logging out of a user.
void removeUser(QString const &userID); ///< Slot for the removal of a user.
void configureUserAppleMail(QString const &userID, QString const &address); ///< Slot for the configuration of Apple mail.
private slots:
void onAddUserButton(); ///< Add a user to the user list.
void onEditUserButton(); ///< Edit the currently selected user.
void onRemoveUserButton(); ///< Remove the currently selected user.
void onSelectionChanged(QItemSelection, QItemSelection); ///< Slot for the change of the selection.
private: // member functions.
void updateGUIState(); ///< Update the GUI state.
qint32 selectedIndex() const; ///< Get the index of the selected row.
bridgepp::SPUser selectedUser(); ///< Get the selected user.
private: // data members.
Ui::UsersTab ui_ {}; ///< The UI for the tab.
UserTable users_; ///< The User list.
};
#endif //BRIDGE_GUI_TESTER_USERS_TAB_H

View File

@ -0,0 +1,159 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>UsersTab</class>
<widget class="QWidget" name="UsersTab">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1207</width>
<height>709</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QTableView" name="tableUserList">
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPushButton" name="buttonNewUser">
<property name="text">
<string>New User</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonEditUser">
<property name="text">
<string>Edit User</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonRemoveUser">
<property name="text">
<string>Remove User</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="minimumSize">
<size>
<width>0</width>
<height>100</height>
</size>
</property>
<property name="title">
<string>Next Login Attempt</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QCheckBox" name="checkUsernamePasswordError">
<property name="text">
<string>Username/password error</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkFreeUserError">
<property name="text">
<string>Free user error</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkTFARequired">
<property name="text">
<string>2FA required</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkTFAError">
<property name="text">
<string>2FA error</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkTFAAbort">
<property name="text">
<string>2FA abort</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkTwoPasswordsRequired">
<property name="text">
<string>2nd password required</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkTwoPasswordsError">
<property name="text">
<string>2nd password error</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkTwoPasswordsAbort">
<property name="text">
<string>2nd password abort</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkAlreadyLoggedIn">
<property name="text">
<string>Already logged in</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<tabstops>
<tabstop>buttonNewUser</tabstop>
<tabstop>buttonEditUser</tabstop>
<tabstop>buttonRemoveUser</tabstop>
<tabstop>tableUserList</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>