Refactoring

Ui improvements
Bug fixes
This commit is contained in:
pokamest 2021-01-09 19:55:16 +03:00
parent 3645735053
commit 441811e277
13 changed files with 773 additions and 123 deletions

View file

@ -4,7 +4,7 @@
#include "defs.h" #include "defs.h"
using namespace amnezia; using namespace amnezia;
QString errorString(ErrorCode code){ static QString errorString(ErrorCode code){
switch (code) { switch (code) {
// General error codes // General error codes

View file

@ -55,7 +55,7 @@ ErrorCode ServerController::runScript(const SshConnectionParameters &sshParams,
// QObject::connect(proc.data(), &SshRemoteProcess::readyReadStandardOutput, [proc](){ // QObject::connect(proc.data(), &SshRemoteProcess::readyReadStandardOutput, [proc](){
// QString s = proc->readAllStandardOutput(); // QString s = proc->readAllStandardOutput();
// if (s != "." && !s.isEmpty()) { // if (s != "." && !s.isEmpty()) {
// qDebug().noquote() << s << s.size(); // qDebug().noquote() << s;
// } // }
// }); // });
@ -239,7 +239,7 @@ ErrorCode ServerController::removeServer(const ServerCredentials &credentials, P
{ {
QString scriptFileName; QString scriptFileName;
if (proto == Protocol::OpenVpn) { if (proto == Protocol::OpenVpn || proto == Protocol::Any) {
scriptFileName = ":/server_scripts/remove_openvpn_server.sh"; scriptFileName = ":/server_scripts/remove_openvpn_server.sh";
} }

View file

@ -49,7 +49,7 @@ void LocalClient::onReadyRead()
if (lineLength != -1) { if (lineLength != -1) {
QString line = buf; QString line = buf;
line = line.simplified(); line = line.simplified();
qDebug().noquote() << QString("Readed line: '%1'").arg(line); qDebug().noquote() << QString("Read line: '%1'").arg(line);
emit lineAvailable(line); emit lineAvailable(line);
} }
} }

View file

@ -60,6 +60,8 @@ int main(int argc, char *argv[])
f.setStyleStrategy(QFont::PreferAntialias); f.setStyleStrategy(QFont::PreferAntialias);
app.setFont(f); app.setFont(f);
app.setQuitOnLastWindowClosed(false);
MainWindow mainWindow; MainWindow mainWindow;
mainWindow.show(); mainWindow.show();

View file

@ -45,9 +45,12 @@ void OpenVpnProtocol::onMessageReceived(const Message& message)
void OpenVpnProtocol::stop() void OpenVpnProtocol::stop()
{ {
// TODO: need refactoring
// sendTermSignal() will evet return true while server connected
if ((m_connectionState == VpnProtocol::ConnectionState::Preparing) || if ((m_connectionState == VpnProtocol::ConnectionState::Preparing) ||
(m_connectionState == VpnProtocol::ConnectionState::Connecting) || (m_connectionState == VpnProtocol::ConnectionState::Connecting) ||
(m_connectionState == VpnProtocol::ConnectionState::Connected)) { (m_connectionState == VpnProtocol::ConnectionState::Connected) ||
(m_connectionState == VpnProtocol::ConnectionState::TunnelReconnecting)) {
if (!sendTermSignal()) { if (!sendTermSignal()) {
killOpenVpnProcess(); killOpenVpnProcess();
} }
@ -210,6 +213,9 @@ void OpenVpnProtocol::onReadyReadDataFromManagementServer()
} else if (line.contains("EXITING,SIGTER")) { } else if (line.contains("EXITING,SIGTER")) {
openVpnStateSigTermHandler(); openVpnStateSigTermHandler();
continue; continue;
} else if (line.contains("RECONNECTING")) {
setConnectionState(VpnProtocol::ConnectionState::TunnelReconnecting);
continue;
} }
} }
@ -222,7 +228,6 @@ void OpenVpnProtocol::onReadyReadDataFromManagementServer()
} }
} }
QByteArray data(line.toStdString().c_str()); QByteArray data(line.toStdString().c_str());
if (data.contains(">BYTECOUNT:")) { if (data.contains(">BYTECOUNT:")) {
int beg = data.lastIndexOf(">BYTECOUNT:"); int beg = data.lastIndexOf(">BYTECOUNT:");

View file

@ -3,6 +3,7 @@
#include "communicator.h" #include "communicator.h"
#include "vpnprotocol.h" #include "vpnprotocol.h"
#include "core/errorstrings.h"
Communicator* VpnProtocol::m_communicator = nullptr; Communicator* VpnProtocol::m_communicator = nullptr;
@ -34,7 +35,10 @@ Communicator* VpnProtocol::communicator()
void VpnProtocol::setLastError(ErrorCode lastError) void VpnProtocol::setLastError(ErrorCode lastError)
{ {
m_lastError = lastError; m_lastError = lastError;
qCritical().noquote() << m_lastError; if (lastError){
setConnectionState(ConnectionState::Disconnected);
}
qCritical().noquote() << "VpnProtocol error, code" << m_lastError << errorString(m_lastError);
} }
ErrorCode VpnProtocol::lastError() const ErrorCode VpnProtocol::lastError() const
@ -96,10 +100,10 @@ QString VpnProtocol::textConnectionState(ConnectionState connectionState)
case ConnectionState::Unknown: return tr("Unknown"); case ConnectionState::Unknown: return tr("Unknown");
case ConnectionState::Disconnected: return tr("Disconnected"); case ConnectionState::Disconnected: return tr("Disconnected");
case ConnectionState::Preparing: return tr("Preparing"); case ConnectionState::Preparing: return tr("Preparing");
case ConnectionState::Connecting: return tr("Connecting"); case ConnectionState::Connecting: return tr("Connecting...");
case ConnectionState::Connected: return tr("Connected"); case ConnectionState::Connected: return tr("Connected");
case ConnectionState::Disconnecting: return tr("Disconnecting"); case ConnectionState::Disconnecting: return tr("Disconnecting...");
case ConnectionState::TunnelReconnecting: return tr("TunnelReconnecting"); case ConnectionState::TunnelReconnecting: return tr("Reconnecting...");
case ConnectionState::Error: return tr("Error"); case ConnectionState::Error: return tr("Error");
default: default:
; ;

View file

@ -23,7 +23,7 @@ public:
void setUserName(const QString& login); void setUserName(const QString& login);
void setPassword(const QString& password); void setPassword(const QString& password);
void setServerName(const QString& serverName); void setServerName(const QString& serverName);
void setServerPort(int serverPort); void setServerPort(int serverPort = 22);
void setServerCredentials(const ServerCredentials &credentials); void setServerCredentials(const ServerCredentials &credentials);
QString userName() const { return m_userName; } QString userName() const { return m_userName; }

View file

@ -1,5 +1,9 @@
#include <QApplication>
#include <QDesktopServices>
#include <QKeyEvent> #include <QKeyEvent>
#include <QMenu>
#include <QMessageBox> #include <QMessageBox>
#include <QMetaEnum>
#include <QSysInfo> #include <QSysInfo>
#include <QThread> #include <QThread>
#include <QTimer> #include <QTimer>
@ -38,10 +42,8 @@ MainWindow::MainWindow(QWidget *parent) :
ui->stackedWidget_main->setSpeed(200); ui->stackedWidget_main->setSpeed(200);
ui->stackedWidget_main->setAnimation(QEasingCurve::Linear); ui->stackedWidget_main->setAnimation(QEasingCurve::Linear);
ui->label_new_server_wait_info->setVisible(false); ui->pushButton_blocked_list->setEnabled(false);
ui->progressBar_new_server_connection->setMinimum(0); ui->pushButton_share_connection->setEnabled(false);
ui->progressBar_new_server_connection->setMaximum(300);
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
ui->widget_tittlebar->hide(); ui->widget_tittlebar->hide();
ui->stackedWidget_main->move(0,0); ui->stackedWidget_main->move(0,0);
@ -51,20 +53,13 @@ MainWindow::MainWindow(QWidget *parent) :
// Post initialization // Post initialization
if (m_settings->haveAuthData()) { if (m_settings->haveAuthData()) {
ui->stackedWidget_main->setCurrentWidget(ui->page_amnezia); goToPage(Page::Vpn, true, false);
} else { } else {
ui->stackedWidget_main->setCurrentWidget(ui->page_new_server); goToPage(Page::Start, true, false);
} }
connect(ui->pushButton_blocked_list, SIGNAL(clicked(bool)), this, SLOT(onPushButtonBlockedListClicked(bool))); setupTray();
connect(ui->pushButton_connect, SIGNAL(toggled(bool)), this, SLOT(onPushButtonConnectToggled(bool))); setupUiConnections();
connect(ui->pushButton_settings, SIGNAL(clicked(bool)), this, SLOT(onPushButtonSettingsClicked(bool)));
connect(ui->pushButton_back_from_sites, SIGNAL(clicked(bool)), this, SLOT(onPushButtonBackFromSitesClicked(bool)));
connect(ui->pushButton_back_from_settings, SIGNAL(clicked(bool)), this, SLOT(onPushButtonBackFromSettingsClicked(bool)));
connect(ui->pushButton_new_server_setup, SIGNAL(clicked(bool)), this, SLOT(onPushButtonNewServerSetup(bool)));
connect(ui->pushButton_back_from_new_server, SIGNAL(clicked(bool)), this, SLOT(onPushButtonBackFromNewServerClicked(bool)));
connect(ui->pushButton_new_server_connect_with_new_data, SIGNAL(clicked(bool)), this, SLOT(onPushButtonNewServerConnectWithNewData(bool)));
setFixedSize(width(),height()); setFixedSize(width(),height());
@ -102,11 +97,48 @@ MainWindow::~MainWindow()
qDebug() << "Application closed"; qDebug() << "Application closed";
} }
void MainWindow::goToPage(Page page) void MainWindow::goToPage(Page page, bool reset, bool slide)
{ {
ui->stackedWidget_main->slideInIdx(static_cast<int>(page)); if (reset) {
if (page == Page::NewServer) {
ui->label_new_server_wait_info->hide();
ui->label_new_server_wait_info->clear();
ui->progressBar_new_server_connection->setMinimum(0);
ui->progressBar_new_server_connection->setMaximum(300);
}
if (page == Page::ServerSettings) {
ui->label_server_settings_wait_info->hide();
ui->label_server_settings_wait_info->clear();
ui->label_server_settings_server->setText(QString("%1@%2:%3")
.arg(m_settings->userName())
.arg(m_settings->serverName())
.arg(m_settings->serverPort()));
}
}
if (slide)
ui->stackedWidget_main->slideInWidget(getPageWidget(page));
else
ui->stackedWidget_main->setCurrentWidget(getPageWidget(page));
} }
QWidget *MainWindow::getPageWidget(MainWindow::Page page)
{
switch (page) {
case(Page::Start): return ui->page_start;
case(Page::NewServer): return ui->page_new_server;
case(Page::Vpn): return ui->page_vpn;
case(Page::GeneralSettings): return ui->page_general_settings;
case(Page::ServerSettings): return ui->page_server_settings;
case(Page::ShareConnection): return ui->page_share_connection;
case(Page::Sites): return ui->page_sites;
}
return nullptr;
}
bool MainWindow::eventFilter(QObject *obj, QEvent *event) bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{ {
if (obj == ui->widget_tittlebar) { if (obj == ui->widget_tittlebar) {
@ -150,7 +182,13 @@ void MainWindow::keyPressEvent(QKeyEvent *event)
} }
} }
void MainWindow::onPushButtonNewServerConnectWithNewData(bool clicked) void MainWindow::closeEvent(QCloseEvent *event)
{
event->ignore();
hide();
}
void MainWindow::onPushButtonNewServerConnectWithNewData(bool)
{ {
if (ui->lineEdit_new_server_ip->text().isEmpty() || if (ui->lineEdit_new_server_ip->text().isEmpty() ||
ui->lineEdit_new_server_login->text().isEmpty() || ui->lineEdit_new_server_login->text().isEmpty() ||
@ -170,48 +208,67 @@ void MainWindow::onPushButtonNewServerConnectWithNewData(bool clicked)
serverCredentials.userName = ui->lineEdit_new_server_login->text(); serverCredentials.userName = ui->lineEdit_new_server_login->text();
serverCredentials.password = ui->lineEdit_new_server_password->text(); serverCredentials.password = ui->lineEdit_new_server_password->text();
m_settings->setServerCredentials(serverCredentials); bool ok = installServer(serverCredentials,
m_settings->save(); ui->page_new_server,
ui->progressBar_new_server_connection,
ui->pushButton_new_server_connect_with_new_data,
ui->label_new_server_wait_info);
ui->page_new_server->setEnabled(false); if (ok) {
ui->pushButton_new_server_connect_with_new_data->setVisible(false); m_settings->setServerCredentials(serverCredentials);
ui->label_new_server_wait_info->setVisible(true); m_settings->save();
goToPage(Page::Vpn);
qApp->processEvents();
onConnect();
}
}
bool MainWindow::installServer(ServerCredentials credentials,
QWidget *page, QProgressBar *progress, QPushButton *button, QLabel *info)
{
page->setEnabled(false);
button->setVisible(false);
info->setVisible(true);
info->setText(tr("Please wait, configuring process may take up to 5 minutes"));
QTimer timer; QTimer timer;
connect(&timer, &QTimer::timeout, [&](){ connect(&timer, &QTimer::timeout, [progress](){
ui->progressBar_new_server_connection->setValue(ui->progressBar_new_server_connection->value() + 1); progress->setValue(progress->value() + 1);
}); });
ui->progressBar_new_server_connection->setValue(0); progress->setValue(0);
timer.start(1000); timer.start(1000);
ErrorCode e = ServerController::setupServer(serverCredentials, Protocol::Any); ErrorCode e = ServerController::setupServer(credentials, Protocol::Any);
if (e) { if (e) {
ui->page_new_server->setEnabled(true); page->setEnabled(true);
ui->pushButton_new_server_connect_with_new_data->setVisible(true); button->setVisible(true);
ui->label_new_server_wait_info->setVisible(false); info->setVisible(false);
QMessageBox::warning(this, APPLICATION_NAME, QMessageBox::warning(this, APPLICATION_NAME,
tr("Error occurred while configuring server.") + "\n" + tr("Error occurred while configuring server.") + "\n" +
errorString(e) + "\n" + errorString(e) + "\n" +
tr("See logs for details.")); tr("See logs for details."));
return; return false;
} }
// just ui progressbar tweak // just ui progressbar tweak
timer.stop(); timer.stop();
int remaining_val = ui->progressBar_new_server_connection->maximum() - ui->progressBar_new_server_connection->value(); int remaining_val = progress->maximum() - progress->value();
if (remaining_val > 0) { if (remaining_val > 0) {
QTimer timer1; QTimer timer1;
QEventLoop loop1; QEventLoop loop1;
connect(&timer1, &QTimer::timeout, [&](){ connect(&timer1, &QTimer::timeout, [&](){
ui->progressBar_new_server_connection->setValue(ui->progressBar_new_server_connection->value() + 1); progress->setValue(progress->value() + 1);
if (ui->progressBar_new_server_connection->value() >= ui->progressBar_new_server_connection->maximum()) { if (progress->value() >= progress->maximum()) {
loop1.quit(); loop1.quit();
} }
}); });
@ -220,44 +277,61 @@ void MainWindow::onPushButtonNewServerConnectWithNewData(bool clicked)
loop1.exec(); loop1.exec();
} }
goToPage(Page::Vpn); button->show();
ui->pushButton_connect->setChecked(true); page->setEnabled(true);
info->setText(tr("Amnezia server installed"));
return true;
}
void MainWindow::onPushButtonReinstallServer(bool)
{
onDisconnect();
installServer(m_settings->serverCredentials(),
ui->page_server_settings,
ui->progressBar_server_settings_reinstall,
ui->pushButton_server_settings_reinstall,
ui->label_server_settings_wait_info);
}
void MainWindow::onPushButtonClearServer(bool)
{
onDisconnect();
ErrorCode e = ServerController::removeServer(m_settings->serverCredentials(), Protocol::Any);
if (e) {
QMessageBox::warning(this, APPLICATION_NAME,
tr("Error occurred while configuring server.") + "\n" +
errorString(e) + "\n" +
tr("See logs for details."));
return;
}
else {
ui->label_server_settings_wait_info->show();
ui->label_server_settings_wait_info->setText(tr("Amnezia server successfully uninstalled"));
}
}
void MainWindow::onPushButtonForgetServer(bool)
{
onDisconnect();
m_settings->setUserName("");
m_settings->setPassword("");
m_settings->setServerName("");
m_settings->setServerPort();
m_settings->save();
goToPage(Page::Start);
} }
void MainWindow::onBytesChanged(quint64 receivedData, quint64 sentData) void MainWindow::onBytesChanged(quint64 receivedData, quint64 sentData)
{ {
ui->label_speed_received->setText(VpnConnection::bytesToText(receivedData)); qDebug() << "MainWindow::onBytesChanged" << receivedData << sentData;
ui->label_speed_sent->setText(VpnConnection::bytesToText(sentData)); ui->label_speed_received->setText(VpnConnection::bytesPerSecToText(receivedData));
} ui->label_speed_sent->setText(VpnConnection::bytesPerSecToText(sentData));
void MainWindow::onPushButtonBackFromNewServerClicked(bool)
{
goToPage(Page::Initialization);
}
void MainWindow::onPushButtonNewServerSetup(bool)
{
goToPage(Page::NewServer);
}
void MainWindow::onPushButtonBackFromSettingsClicked(bool)
{
goToPage(Page::Vpn);
}
void MainWindow::onPushButtonBackFromSitesClicked(bool)
{
goToPage(Page::Vpn);
}
void MainWindow::onPushButtonBlockedListClicked(bool)
{
goToPage(Page::Sites);
}
void MainWindow::onPushButtonSettingsClicked(bool)
{
goToPage(Page::SomeSettings);
} }
void MainWindow::onConnectionStateChanged(VpnProtocol::ConnectionState state) void MainWindow::onConnectionStateChanged(VpnProtocol::ConnectionState state)
@ -265,6 +339,8 @@ void MainWindow::onConnectionStateChanged(VpnProtocol::ConnectionState state)
bool pushButtonConnectEnabled = false; bool pushButtonConnectEnabled = false;
ui->label_state->setText(VpnProtocol::textConnectionState(state)); ui->label_state->setText(VpnProtocol::textConnectionState(state));
setTrayState(state);
switch (state) { switch (state) {
case VpnProtocol::ConnectionState::Disconnected: case VpnProtocol::ConnectionState::Disconnected:
onBytesChanged(0,0); onBytesChanged(0,0);
@ -284,7 +360,7 @@ void MainWindow::onConnectionStateChanged(VpnProtocol::ConnectionState state)
pushButtonConnectEnabled = false; pushButtonConnectEnabled = false;
break; break;
case VpnProtocol::ConnectionState::TunnelReconnecting: case VpnProtocol::ConnectionState::TunnelReconnecting:
pushButtonConnectEnabled = false; pushButtonConnectEnabled = true;
break; break;
case VpnProtocol::ConnectionState::Error: case VpnProtocol::ConnectionState::Error:
pushButtonConnectEnabled = true; pushButtonConnectEnabled = true;
@ -300,28 +376,183 @@ void MainWindow::onConnectionStateChanged(VpnProtocol::ConnectionState state)
void MainWindow::onVpnProtocolError(ErrorCode errorCode) void MainWindow::onVpnProtocolError(ErrorCode errorCode)
{ {
QMessageBox::critical(this, APPLICATION_NAME, errorString(errorCode)); // TODO fix crash on Windows when starting vpn and another vpn already connected
//QMessageBox::critical(this, APPLICATION_NAME, errorString(errorCode));
} }
void MainWindow::onPushButtonConnectToggled(bool checked) void MainWindow::onPushButtonConnectClicked(bool checked)
{ {
if (checked) { if (checked) {
// TODO: Call connectToVpn with restricted server account onConnect();
ServerCredentials credentials = m_settings->serverCredentials();
ErrorCode errorCode = m_vpnConnection->connectToVpn(credentials);
if (errorCode) {
ui->pushButton_connect->setChecked(false);
QMessageBox::critical(this, APPLICATION_NAME, errorString(errorCode));
return;
}
ui->pushButton_connect->setEnabled(false);
} else { } else {
m_vpnConnection->disconnectFromVpn(); onDisconnect();
} }
} }
void MainWindow::on_pushButton_close_clicked() void MainWindow::setupTray()
{ {
qApp->exit(); m_menu = new QMenu();
//m_menu->setStyleSheet(styleSheet());
m_menu->addAction(QIcon(":/images/tray/application.png"), tr("Show") + " " + APPLICATION_NAME, this, SLOT(show()));
m_menu->addSeparator();
m_trayActionConnect = m_menu->addAction(tr("Connect"), this, SLOT(onConnect()));
m_trayActionDisconnect = m_menu->addAction(tr("Disconnect"), this, SLOT(onDisconnect()));
m_menu->addSeparator();
m_menu->addAction(QIcon(":/images/tray/link.png"), tr("Visit Website"), [&](){
QDesktopServices::openUrl(QUrl("https://amnezia.org"));
});
m_menu->addAction(QIcon(":/images/tray/cancel.png"), tr("Quit") + " " + APPLICATION_NAME, this, [&](){
QMessageBox msgBox(QMessageBox::Question, tr("Exit"), tr("Do you really want to quit?"),
QMessageBox::Yes | QMessageBox::No, Q_NULLPTR, Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint | Qt::WindowStaysOnTopHint);
msgBox.setDefaultButton(QMessageBox::No);
msgBox.raise();
if (msgBox.exec() == QMessageBox::Yes) {
qApp->quit();
}
});
m_tray.setContextMenu(m_menu);
setTrayState(VpnProtocol::ConnectionState::Disconnected);
m_tray.show();
connect(&m_tray, &QSystemTrayIcon::activated, this, &MainWindow::onTrayActivated);
} }
void MainWindow::setTrayIcon(const QString &iconPath)
{
m_tray.setIcon(QIcon(QPixmap(iconPath).scaled(128,128)));
}
MainWindow::Page MainWindow::currentPage()
{
QWidget *currentPage = ui->stackedWidget_main->currentWidget();
QMetaEnum e = QMetaEnum::fromType<MainWindow::Page>();
for (int k = 0; k < e.keyCount(); k++) {
Page p = static_cast<MainWindow::Page>(e.value(k));
if (currentPage == getPageWidget(p)) return p;
}
return Page::Start;
}
void MainWindow::setupUiConnections()
{
connect(ui->pushButton_close, &QPushButton::clicked, this, [this](){
if (currentPage() == Page::Start || currentPage() == Page::NewServer) qApp->quit();
else hide();
});
connect(ui->pushButton_general_settings_exit, &QPushButton::clicked, this, [&](){ qApp->quit(); });
connect(ui->pushButton_connect, SIGNAL(clicked(bool)), this, SLOT(onPushButtonConnectClicked(bool)));
connect(ui->pushButton_new_server_setup, &QPushButton::clicked, this, [this](){ goToPage(Page::NewServer); });
connect(ui->pushButton_new_server_connect_with_new_data, SIGNAL(clicked(bool)), this, SLOT(onPushButtonNewServerConnectWithNewData(bool)));
connect(ui->pushButton_server_settings_reinstall, SIGNAL(clicked(bool)), this, SLOT(onPushButtonReinstallServer(bool)));
connect(ui->pushButton_server_settings_clear, SIGNAL(clicked(bool)), this, SLOT(onPushButtonClearServer(bool)));
connect(ui->pushButton_server_settings_forget, SIGNAL(clicked(bool)), this, SLOT(onPushButtonForgetServer(bool)));
connect(ui->pushButton_blocked_list, &QPushButton::clicked, this, [this](){ goToPage(Page::Sites); });
connect(ui->pushButton_settings, &QPushButton::clicked, this, [this](){ goToPage(Page::GeneralSettings); });
connect(ui->pushButton_server_settings, &QPushButton::clicked, this, [this](){ goToPage(Page::ServerSettings); });
connect(ui->pushButton_share_connection, &QPushButton::clicked, this, [this](){ goToPage(Page::ShareConnection); });
connect(ui->pushButton_back_from_sites, &QPushButton::clicked, this, [this](){ goToPage(Page::Vpn); });
connect(ui->pushButton_back_from_settings, &QPushButton::clicked, this, [this](){ goToPage(Page::Vpn); });
connect(ui->pushButton_back_from_new_server, &QPushButton::clicked, this, [this](){ goToPage(Page::Start); });
connect(ui->pushButton_back_from_server_settings, &QPushButton::clicked, this, [this](){ goToPage(Page::GeneralSettings); });
connect(ui->pushButton_back_from_share, &QPushButton::clicked, this, [this](){ goToPage(Page::GeneralSettings); });
}
void MainWindow::setTrayState(VpnProtocol::ConnectionState state)
{
QString resourcesPath = ":/images/tray/%1";
m_trayActionDisconnect->setEnabled(state == VpnProtocol::ConnectionState::Connected);
m_trayActionConnect->setEnabled(state == VpnProtocol::ConnectionState::Disconnected);
switch (state) {
case VpnProtocol::ConnectionState::Disconnected:
setTrayIcon(QString(resourcesPath).arg(DisconnectedTrayIconName));
break;
case VpnProtocol::ConnectionState::Preparing:
setTrayIcon(QString(resourcesPath).arg(DisconnectedTrayIconName));
break;
case VpnProtocol::ConnectionState::Connecting:
setTrayIcon(QString(resourcesPath).arg(DisconnectedTrayIconName));
break;
case VpnProtocol::ConnectionState::Connected:
setTrayIcon(QString(resourcesPath).arg(ConnectedTrayIconName));
break;
case VpnProtocol::ConnectionState::Disconnecting:
setTrayIcon(QString(resourcesPath).arg(DisconnectedTrayIconName));
break;
case VpnProtocol::ConnectionState::TunnelReconnecting:
setTrayIcon(QString(resourcesPath).arg(DisconnectedTrayIconName));
break;
case VpnProtocol::ConnectionState::Error:
setTrayIcon(QString(resourcesPath).arg(ErrorTrayIconName));
break;
case VpnProtocol::ConnectionState::Unknown:
default:
setTrayIcon(QString(resourcesPath).arg(DisconnectedTrayIconName));
}
//#ifdef Q_OS_MAC
// // Get theme from current user (note, this app can be launched as root application and in this case this theme can be different from theme of real current user )
// bool darkTaskBar = MacOSFunctions::instance().isMenuBarUseDarkTheme();
// darkTaskBar = forceUseBrightIcons ? true : darkTaskBar;
// resourcesPath = ":/images_mac/tray_icon/%1";
// useIconName = useIconName.replace(".png", darkTaskBar ? "@2x.png" : " dark@2x.png");
//#endif
}
void MainWindow::onTrayActivated(QSystemTrayIcon::ActivationReason reason)
{
if(reason == QSystemTrayIcon::DoubleClick || reason == QSystemTrayIcon::Trigger) {
show();
raise();
setWindowState(Qt::WindowActive);
}
}
void MainWindow::onConnect()
{
ui->pushButton_connect->setChecked(true);
qApp->processEvents();
// TODO: Call connectToVpn with restricted server account
ServerCredentials credentials = m_settings->serverCredentials();
ErrorCode errorCode = m_vpnConnection->connectToVpn(credentials);
if (errorCode) {
//ui->pushButton_connect->setChecked(false);
QMessageBox::critical(this, APPLICATION_NAME, errorString(errorCode));
return;
}
ui->pushButton_connect->setEnabled(false);
}
void MainWindow::onDisconnect()
{
ui->pushButton_connect->setChecked(false);
m_vpnConnection->disconnectFromVpn();
}
void MainWindow::onTrayActionConnect()
{
if(m_trayActionConnect->text() == tr("Connect")) {
onConnect();
} else if(m_trayActionConnect->text() == tr("Disconnect")) {
onDisconnect();
}
}

View file

@ -1,7 +1,11 @@
#ifndef MAINWINDOW_H #ifndef MAINWINDOW_H
#define MAINWINDOW_H #define MAINWINDOW_H
#include <QLabel>
#include <QMainWindow> #include <QMainWindow>
#include <QProgressBar>
#include <QPushButton>
#include <QSystemTrayIcon>
#include "framelesswindow.h" #include "framelesswindow.h"
#include "protocols/vpnprotocol.h" #include "protocols/vpnprotocol.h"
@ -29,35 +33,61 @@ public:
explicit MainWindow(QWidget *parent = nullptr); explicit MainWindow(QWidget *parent = nullptr);
~MainWindow(); ~MainWindow();
enum class Page {Initialization = 0, NewServer = 1, Vpn = 2, Sites = 3, SomeSettings = 4, Share = 5}; enum Page {Start, NewServer, Vpn, GeneralSettings, ServerSettings, ShareConnection, Sites};
Q_ENUM(Page)
private slots: private slots:
void onBytesChanged(quint64 receivedBytes, quint64 sentBytes); void onBytesChanged(quint64 receivedBytes, quint64 sentBytes);
void onConnectionStateChanged(VpnProtocol::ConnectionState state); void onConnectionStateChanged(VpnProtocol::ConnectionState state);
void onVpnProtocolError(amnezia::ErrorCode errorCode); void onVpnProtocolError(amnezia::ErrorCode errorCode);
void onPushButtonBackFromNewServerClicked(bool clicked); void onPushButtonConnectClicked(bool checked);
void onPushButtonBackFromSettingsClicked(bool clicked); void onPushButtonNewServerConnectWithNewData(bool);
void onPushButtonBackFromSitesClicked(bool clicked);
void onPushButtonBlockedListClicked(bool clicked); void onPushButtonReinstallServer(bool);
void onPushButtonConnectToggled(bool checked); void onPushButtonClearServer(bool);
void onPushButtonNewServerConnectWithNewData(bool clicked); void onPushButtonForgetServer(bool);
void onPushButtonNewServerSetup(bool clicked);
void onPushButtonSettingsClicked(bool clicked); void onTrayActionConnect(); // connect from context menu
void setTrayState(VpnProtocol::ConnectionState state);
void onTrayActivated(QSystemTrayIcon::ActivationReason reason);
void onConnect();
void onDisconnect();
void on_pushButton_close_clicked();
private: private:
void goToPage(Page page); void goToPage(Page page, bool reset = true, bool slide = true);
QWidget *getPageWidget(Page page);
Page currentPage();
bool installServer(ServerCredentials credentials, QWidget *page, QProgressBar *progress, QPushButton *button, QLabel *info);
void setupTray();
void setTrayIcon(const QString &iconPath);
void setupUiConnections();
Ui::MainWindow *ui; Ui::MainWindow *ui;
VpnConnection* m_vpnConnection; VpnConnection* m_vpnConnection;
Settings* m_settings; Settings* m_settings;
QAction* m_trayActionConnect;
QAction* m_trayActionDisconnect;
QSystemTrayIcon m_tray;
QMenu* m_menu;
bool canMove = false; bool canMove = false;
QPoint offset; QPoint offset;
bool eventFilter(QObject *obj, QEvent *event) override; bool eventFilter(QObject *obj, QEvent *event) override;
void keyPressEvent(QKeyEvent* event) override; void keyPressEvent(QKeyEvent* event) override;
void closeEvent(QCloseEvent *event) override;
const QString ConnectedTrayIconName = "active.png";
const QString DisconnectedTrayIconName = "default.png";
const QString ErrorTrayIconName = "error.png";
}; };
#endif // MAINWINDOW_H #endif // MAINWINDOW_H

View file

@ -269,7 +269,7 @@ QStackedWidget QWidget {
<property name="currentIndex"> <property name="currentIndex">
<number>2</number> <number>2</number>
</property> </property>
<widget class="QWidget" name="page_connect_server"> <widget class="QWidget" name="page_start">
<widget class="QLabel" name="label_23"> <widget class="QLabel" name="label_23">
<property name="geometry"> <property name="geometry">
<rect> <rect>
@ -671,7 +671,7 @@ border-radius: 4px;
<string>Connect</string> <string>Connect</string>
</property> </property>
</widget> </widget>
<widget class="QPushButton" name="pushButton"> <widget class="QPushButton" name="pushButton_new_server_get_info">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>50</x> <x>50</x>
@ -815,12 +815,12 @@ QPushButton:hover {
<zorder>lineEdit_new_server_login</zorder> <zorder>lineEdit_new_server_login</zorder>
<zorder>lineEdit_new_server_password</zorder> <zorder>lineEdit_new_server_password</zorder>
<zorder>pushButton_new_server_connect_with_new_data</zorder> <zorder>pushButton_new_server_connect_with_new_data</zorder>
<zorder>pushButton</zorder> <zorder>pushButton_new_server_get_info</zorder>
<zorder>pushButton_back_from_new_server</zorder> <zorder>pushButton_back_from_new_server</zorder>
<zorder>label_7</zorder> <zorder>label_7</zorder>
<zorder>label_new_server_wait_info</zorder> <zorder>label_new_server_wait_info</zorder>
</widget> </widget>
<widget class="QWidget" name="page_amnezia"> <widget class="QWidget" name="page_vpn">
<property name="styleSheet"> <property name="styleSheet">
<string notr="true"/> <string notr="true"/>
</property> </property>
@ -1008,6 +1008,9 @@ line-height: 21px;
<height>40</height> <height>40</height>
</rect> </rect>
</property> </property>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="styleSheet"> <property name="styleSheet">
<string notr="true">QPushButton:!checked { <string notr="true">QPushButton:!checked {
image: url(:/images/connect_button_disconnected.png); image: url(:/images/connect_button_disconnected.png);
@ -1392,7 +1395,7 @@ color: #333333;</string>
</property> </property>
</widget> </widget>
</widget> </widget>
<widget class="QWidget" name="page_settings"> <widget class="QWidget" name="page_general_settings">
<widget class="QPushButton" name="pushButton_back_from_settings"> <widget class="QPushButton" name="pushButton_back_from_settings">
<property name="geometry"> <property name="geometry">
<rect> <rect>
@ -1441,7 +1444,7 @@ QPushButton:hover {
<string/> <string/>
</property> </property>
</widget> </widget>
<widget class="QPushButton" name="pushButton_2"> <widget class="QPushButton" name="pushButton_server_settings">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>30</x> <x>30</x>
@ -1450,6 +1453,9 @@ QPushButton:hover {
<height>30</height> <height>30</height>
</rect> </rect>
</property> </property>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="styleSheet"> <property name="styleSheet">
<string notr="true">font-family: Lato; <string notr="true">font-family: Lato;
font-style: normal; font-style: normal;
@ -1487,7 +1493,10 @@ background-repeat: no-repeat;
<string/> <string/>
</property> </property>
</widget> </widget>
<widget class="QPushButton" name="pushButton_3"> <widget class="QPushButton" name="pushButton_share_connection">
<property name="enabled">
<bool>true</bool>
</property>
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>30</x> <x>30</x>
@ -1496,6 +1505,9 @@ background-repeat: no-repeat;
<height>30</height> <height>30</height>
</rect> </rect>
</property> </property>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="styleSheet"> <property name="styleSheet">
<string notr="true">font-family: Lato; <string notr="true">font-family: Lato;
font-style: normal; font-style: normal;
@ -1533,8 +1545,367 @@ background-repeat: no-repeat;
<string/> <string/>
</property> </property>
</widget> </widget>
<widget class="QLabel" name="label_14">
<property name="geometry">
<rect>
<x>10</x>
<y>620</y>
<width>360</width>
<height>1</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">image: url(:/images/line.png);</string>
</property>
<property name="text">
<string/>
</property>
</widget>
<widget class="QPushButton" name="pushButton_general_settings_exit">
<property name="enabled">
<bool>true</bool>
</property>
<property name="geometry">
<rect>
<x>30</x>
<y>570</y>
<width>330</width>
<height>30</height>
</rect>
</property>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="styleSheet">
<string notr="true">font-family: Lato;
font-style: normal;
font-weight: bold;
font-size: 20px;
line-height: 25px;
Text-align:left;
padding-left: 30px;
/* black */
color: #100A44;
background-repeat: no-repeat;
background-position: left center;</string>
</property>
<property name="text">
<string>Exit</string>
</property>
</widget>
<widget class="QLabel" name="label_15">
<property name="geometry">
<rect>
<x>10</x>
<y>550</y>
<width>360</width>
<height>1</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">image: url(:/images/line.png);</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</widget> </widget>
<widget class="QWidget" name="page_share"> <widget class="QWidget" name="page_server_settings">
<widget class="QLabel" name="label_server_settings_wait_info">
<property name="enabled">
<bool>true</bool>
</property>
<property name="geometry">
<rect>
<x>40</x>
<y>490</y>
<width>301</width>
<height>41</height>
</rect>
</property>
<property name="text">
<string>Please wait, configuring process may take up to 5 minutes</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
<widget class="QLabel" name="label_13">
<property name="geometry">
<rect>
<x>40</x>
<y>100</y>
<width>171</width>
<height>21</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">font-family: Lato;
font-style: normal;
font-weight: normal;
font-size: 16px;
line-height: 150%;
/* or 24px */
/* text */
color: #333333;</string>
</property>
<property name="text">
<string>You connected to</string>
</property>
</widget>
<widget class="QPushButton" name="pushButton_server_settings_reinstall">
<property name="geometry">
<rect>
<x>40</x>
<y>220</y>
<width>301</width>
<height>40</height>
</rect>
</property>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="styleSheet">
<string notr="true">QPushButton {
color:rgb(212, 212, 212);
border-radius: 4px;
font-family: Lato;
font-style: normal;
font-weight: normal;
font-size: 16px;
line-height: 21px;
background: #100A44;
border-radius: 4px;
}
</string>
</property>
<property name="text">
<string>Reinstall Amnezia server</string>
</property>
</widget>
<widget class="QPushButton" name="pushButton_back_from_server_settings">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>26</width>
<height>20</height>
</rect>
</property>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="styleSheet">
<string notr="true">QPushButton {
image: url(:/images/arrow_right.png);
image-position: left;
text-align: left;
/*font: 17pt &quot;Ancient&quot;;*/
padding: 1px;
image: url(:/images/arrow_left.png);
}
QPushButton:hover {
padding: 0px;
}
</string>
</property>
<property name="text">
<string/>
</property>
</widget>
<widget class="QLabel" name="label_16">
<property name="geometry">
<rect>
<x>10</x>
<y>40</y>
<width>361</width>
<height>71</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">font-family: Lato;
font-style: normal;
font-weight: bold;
font-size: 24px;
line-height: 25px;
color: #100A44;
</string>
</property>
<property name="text">
<string>Your configured server</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
<widget class="QProgressBar" name="progressBar_server_settings_reinstall">
<property name="geometry">
<rect>
<x>40</x>
<y>220</y>
<width>301</width>
<height>41</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">QProgressBar{
color:rgb(212, 212, 212);
border-radius: 4px;
font-family: Lato;
font-style: normal;
font-weight: normal;
font-size: 16px;
line-height: 21px;
background: #100A44;
border-radius: 4px;
}
QProgressBar::chunk {
background: rgba(255, 255, 255, 0.15);
border-radius: 4px 0px 0px 4px;
}
</string>
</property>
<property name="value">
<number>24</number>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="textVisible">
<bool>true</bool>
</property>
<property name="format">
<string>Configuring...</string>
</property>
</widget>
<widget class="QLabel" name="label_17">
<property name="geometry">
<rect>
<x>110</x>
<y>590</y>
<width>150</width>
<height>22</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">image: url(:/images/AmneziaVPN.png);</string>
</property>
<property name="text">
<string/>
</property>
</widget>
<widget class="QPushButton" name="pushButton_server_settings_clear">
<property name="geometry">
<rect>
<x>40</x>
<y>280</y>
<width>301</width>
<height>40</height>
</rect>
</property>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="styleSheet">
<string notr="true">QPushButton {
color:rgb(212, 212, 212);
border-radius: 4px;
font-family: Lato;
font-style: normal;
font-weight: normal;
font-size: 16px;
line-height: 21px;
background: #100A44;
border-radius: 4px;
}
</string>
</property>
<property name="text">
<string>Clear server from Amnezia software</string>
</property>
</widget>
<widget class="QPushButton" name="pushButton_server_settings_forget">
<property name="geometry">
<rect>
<x>40</x>
<y>340</y>
<width>301</width>
<height>40</height>
</rect>
</property>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="styleSheet">
<string notr="true">QPushButton {
color:rgb(212, 212, 212);
border-radius: 4px;
font-family: Lato;
font-style: normal;
font-weight: normal;
font-size: 16px;
line-height: 21px;
background: #100A44;
border-radius: 4px;
}
</string>
</property>
<property name="text">
<string>Forget this server</string>
</property>
</widget>
<widget class="QLabel" name="label_server_settings_server">
<property name="geometry">
<rect>
<x>40</x>
<y>130</y>
<width>321</width>
<height>41</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">font-family: Lato;
font-style: normal;
font-weight: normal;
font-size: 24px;
color: #333333;</string>
</property>
<property name="text">
<string>root@yourserver.org</string>
</property>
</widget>
<zorder>label_server_settings_wait_info</zorder>
<zorder>label_13</zorder>
<zorder>pushButton_back_from_server_settings</zorder>
<zorder>label_16</zorder>
<zorder>progressBar_server_settings_reinstall</zorder>
<zorder>label_17</zorder>
<zorder>pushButton_server_settings_reinstall</zorder>
<zorder>pushButton_server_settings_clear</zorder>
<zorder>pushButton_server_settings_forget</zorder>
<zorder>label_server_settings_server</zorder>
</widget>
<widget class="QWidget" name="page_share_connection">
<widget class="QPushButton" name="pushButton_back_from_share"> <widget class="QPushButton" name="pushButton_back_from_share">
<property name="geometry"> <property name="geometry">
<rect> <rect>

View file

@ -1,3 +1,4 @@
#include <QApplication>
#include <QDebug> #include <QDebug>
#include <QFile> #include <QFile>
@ -64,9 +65,13 @@ ErrorCode VpnConnection::connectToVpn(const ServerCredentials &credentials, Prot
// TODO: Implement some behavior in case if connection not stable // TODO: Implement some behavior in case if connection not stable
qDebug() << "Connect to VPN"; qDebug() << "Connect to VPN";
emit connectionStateChanged(VpnProtocol::ConnectionState::Connecting);
qApp->processEvents();
if (protocol == Protocol::Any || protocol == Protocol::OpenVpn) { if (protocol == Protocol::Any || protocol == Protocol::OpenVpn) {
ErrorCode e = requestVpnConfig(credentials, Protocol::OpenVpn); ErrorCode e = requestVpnConfig(credentials, Protocol::OpenVpn);
if (e) { if (e) {
emit connectionStateChanged(VpnProtocol::ConnectionState::Error);
return e; return e;
} }
if (m_vpnProtocol) { if (m_vpnProtocol) {
@ -76,6 +81,7 @@ ErrorCode VpnConnection::connectToVpn(const ServerCredentials &credentials, Prot
connect(m_vpnProtocol.data(), &VpnProtocol::protocolError, this, &VpnConnection::vpnProtocolError); connect(m_vpnProtocol.data(), &VpnProtocol::protocolError, this, &VpnConnection::vpnProtocolError);
} }
else if (protocol == Protocol::ShadowSocks) { else if (protocol == Protocol::ShadowSocks) {
emit connectionStateChanged(VpnProtocol::ConnectionState::Error);
return ErrorCode::NotImplementedError; return ErrorCode::NotImplementedError;
} }
@ -85,9 +91,10 @@ ErrorCode VpnConnection::connectToVpn(const ServerCredentials &credentials, Prot
return m_vpnProtocol.data()->start(); return m_vpnProtocol.data()->start();
} }
QString VpnConnection::bytesToText(quint64 bytes) QString VpnConnection::bytesPerSecToText(quint64 bytes)
{ {
return QString("%1 %2").arg(bytes / 1000000).arg(tr("Mbps")); double mbps = bytes * 8 / 1e6;
return QString("%1 %2").arg(QString::number(mbps, 'f', 2)).arg(tr("Mbps")); // Mbit/s
} }
void VpnConnection::disconnectFromVpn() void VpnConnection::disconnectFromVpn()

View file

@ -18,7 +18,7 @@ public:
explicit VpnConnection(QObject* parent = nullptr); explicit VpnConnection(QObject* parent = nullptr);
~VpnConnection() override = default; ~VpnConnection() override = default;
static QString bytesToText(quint64 bytes); static QString bytesPerSecToText(quint64 bytes);
ErrorCode lastError() const; ErrorCode lastError() const;
ErrorCode requestVpnConfig(const ServerCredentials &credentials, Protocol protocol); ErrorCode requestVpnConfig(const ServerCredentials &credentials, Protocol protocol);

View file

@ -62,22 +62,22 @@ void LocalServer::onNewConnection()
if (lineLength != -1) { if (lineLength != -1) {
QString line = buf; QString line = buf;
line = line.simplified(); line = line.simplified();
qDebug().noquote() << QString("Readed line: '%1'").arg(line); qDebug().noquote() << QString("Read line: '%1'").arg(line);
Message icomingMessage(line); Message incomingMessage(line);
if (!icomingMessage.isValid()) { if (!incomingMessage.isValid()) {
qWarning().noquote() << "Message is not valid!"; qWarning().noquote() << "Message is not valid!";
continue; continue;
} }
switch (icomingMessage.state()) { switch (incomingMessage.state()) {
case Message::State::Initialize: case Message::State::Initialize:
sendMessage(Message(Message::State::Initialize, QStringList({"Server"}))); sendMessage(Message(Message::State::Initialize, QStringList({"Server"})));
break; break;
case Message::State::StartRequest: case Message::State::StartRequest:
startProcess(icomingMessage.args()); startProcess(incomingMessage.args());
break; break;
case Message::State::FinishRequest: case Message::State::FinishRequest:
finishProcess(icomingMessage.args()); finishProcess(incomingMessage.args());
break; break;
default: default:
; ;