Client app template and ui
102
client/amnizia-client.pro
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
QT += widgets core gui network xml
|
||||||
|
|
||||||
|
TARGET = amnezia-client
|
||||||
|
TEMPLATE = app
|
||||||
|
|
||||||
|
DEFINES += QT_DEPRECATED_WARNINGS
|
||||||
|
|
||||||
|
|
||||||
|
win32 {
|
||||||
|
|
||||||
|
#win32-g++ {
|
||||||
|
# QMAKE_CXXFLAGS += -Werror
|
||||||
|
#}
|
||||||
|
#win32-msvc*{
|
||||||
|
# QMAKE_CXXFLAGS += /WX
|
||||||
|
#}
|
||||||
|
|
||||||
|
FORMS += ui/mainwindow.ui
|
||||||
|
|
||||||
|
RESOURCES += \
|
||||||
|
res.qrc
|
||||||
|
|
||||||
|
OTHER_FILES += platform_win/vpnclient.rc
|
||||||
|
RC_FILE = platform_win/vpnclient.rc
|
||||||
|
|
||||||
|
HEADERS += publib/winhelp.h
|
||||||
|
|
||||||
|
SOURCES += publib/winhelp.cpp
|
||||||
|
|
||||||
|
CONFIG -= embed_manifest_exe
|
||||||
|
DEFINES += _CRT_SECURE_NO_WARNINGS VPNCLIENT_TAPSIGNED
|
||||||
|
#QMAKE_LFLAGS += /MANIFESTUAC:\"level=\'requireAdministrator\' uiAccess=\'false\'\"
|
||||||
|
|
||||||
|
VERSION = 1.1.1.1
|
||||||
|
QMAKE_TARGET_COMPANY = "AmneziaVPN"
|
||||||
|
QMAKE_TARGET_PRODUCT = "AmneziaVPN"
|
||||||
|
|
||||||
|
CONFIG -= embed_manifest_exe
|
||||||
|
|
||||||
|
LIBS += -luser32 \
|
||||||
|
-lrasapi32 \
|
||||||
|
-lshlwapi \
|
||||||
|
-liphlpapi \
|
||||||
|
-lws2_32 \
|
||||||
|
-liphlpapi \
|
||||||
|
-lgdi32
|
||||||
|
|
||||||
|
|
||||||
|
MT_PATH = \"C:/Program Files (x86)/Microsoft SDKs/Windows/v7.1A/bin/x64/mt.exe\"
|
||||||
|
WIN_PWD = $$replace(PWD, /, \\)
|
||||||
|
OUT_PWD_WIN = $$replace(OUT_PWD, /, \\)
|
||||||
|
|
||||||
|
!win32-g++: QMAKE_POST_LINK = "$$MT_PATH -manifest $$quote($$WIN_PWD\\platform_win\\$$basename(TARGET).exe.manifest) -outputresource:$$quote($$OUT_PWD_WIN\\$(DESTDIR_TARGET);1)"
|
||||||
|
else: QMAKE_POST_LINK = "$$MT_PATH -manifest $$PWD/platform_win/$$basename(TARGET).exe.manifest -outputresource:$$OUT_PWD/$(DESTDIR_TARGET)"
|
||||||
|
}
|
||||||
|
|
||||||
|
macx {
|
||||||
|
|
||||||
|
OBJECTIVE_HEADERS +=
|
||||||
|
OBJECTIVE_SOURCES += publib/macos_functions.mm
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
|
||||||
|
QMAKE_OBJECTIVE_CFLAGS += -F/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/System/Library/Frameworks
|
||||||
|
|
||||||
|
FORMS += ui/mainwindow_mac.ui
|
||||||
|
|
||||||
|
LIBS += -framework CoreServices -framework Foundation -framework AppKit
|
||||||
|
|
||||||
|
RESOURCES += \
|
||||||
|
res_mac.qrc
|
||||||
|
|
||||||
|
ICON = images/main.icns
|
||||||
|
}
|
||||||
|
|
||||||
|
SOURCES += main.cpp\
|
||||||
|
publib/debug.cpp \
|
||||||
|
publib/runguard.cpp \
|
||||||
|
publib/winhelp.cpp \
|
||||||
|
ui/Controls/SlidingStackedWidget.cpp \
|
||||||
|
ui/mainwindow.cpp \
|
||||||
|
ui/customshadoweffect.cpp
|
||||||
|
|
||||||
|
HEADERS += ui/mainwindow.h \
|
||||||
|
publib/debug.h \
|
||||||
|
publib/runguard.h \
|
||||||
|
publib/winhelp.h \
|
||||||
|
ui/customshadoweffect.h \
|
||||||
|
ui/Controls/SlidingStackedWidget.h
|
||||||
|
|
||||||
|
FORMS += ui/mainwindow.ui
|
||||||
|
|
||||||
|
|
||||||
|
TRANSLATIONS = translations/amneziavpn.en.ts \
|
||||||
|
translations/amneziavpn.ru.ts
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
win32: LIBS += -L$$PWD/../../../../../../../OpenSSL-Win32/lib/ -llibcrypto
|
||||||
|
|
BIN
client/fonts/Lato-Black.ttf
Normal file
BIN
client/fonts/Lato-BlackItalic.ttf
Normal file
BIN
client/fonts/Lato-Bold.ttf
Normal file
BIN
client/fonts/Lato-BoldItalic.ttf
Normal file
BIN
client/fonts/Lato-Italic.ttf
Normal file
BIN
client/fonts/Lato-Light.ttf
Normal file
BIN
client/fonts/Lato-LightItalic.ttf
Normal file
BIN
client/fonts/Lato-Regular.ttf
Normal file
BIN
client/fonts/Lato-Thin.ttf
Normal file
BIN
client/fonts/Lato-ThinItalic.ttf
Normal file
BIN
client/images/AmneziaVPN.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
client/images/Line.png
Normal file
After Width: | Height: | Size: 136 B |
BIN
client/images/arrow_left.png
Normal file
After Width: | Height: | Size: 214 B |
BIN
client/images/close.png
Normal file
After Width: | Height: | Size: 342 B |
BIN
client/images/connect_button_connected.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
client/images/connect_button_disconnected.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
client/images/connected_line.png
Normal file
After Width: | Height: | Size: 87 B |
BIN
client/images/controls/check_off.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
client/images/controls/check_on.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
client/images/controls/checkbox_hover.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
client/images/controls/checkbox_unchecked.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
client/images/controls/radio_off.png
Normal file
After Width: | Height: | Size: 491 B |
BIN
client/images/controls/radio_on.png
Normal file
After Width: | Height: | Size: 624 B |
BIN
client/images/download.png
Normal file
After Width: | Height: | Size: 6 KiB |
BIN
client/images/favorites_disabled.png
Normal file
After Width: | Height: | Size: 636 B |
BIN
client/images/favorites_enabled.png
Normal file
After Width: | Height: | Size: 390 B |
BIN
client/images/favorites_hover.png
Normal file
After Width: | Height: | Size: 643 B |
BIN
client/images/listitembg.png
Normal file
After Width: | Height: | Size: 318 B |
BIN
client/images/min.png
Normal file
After Width: | Height: | Size: 1 KiB |
BIN
client/images/settings.png
Normal file
After Width: | Height: | Size: 871 B |
BIN
client/images/tray/active.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
client/images/tray/default.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
client/images/tray/error.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
client/images/underline.png
Normal file
After Width: | Height: | Size: 80 B |
BIN
client/images/upload.png
Normal file
After Width: | Height: | Size: 5.4 KiB |
109
client/main.cpp
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QFontDatabase>
|
||||||
|
#include <QCommandLineParser>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QTranslator>
|
||||||
|
#include <QLibraryInfo>
|
||||||
|
|
||||||
|
#include "publib/runguard.h"
|
||||||
|
#include "publib/debug.h"
|
||||||
|
|
||||||
|
#include "ui/mainwindow.h"
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
#include <Windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ApplicationName "AmneziaVPN"
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
Q_INIT_RESOURCE(res);
|
||||||
|
|
||||||
|
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling, true);
|
||||||
|
RunGuard::instance(ApplicationName).activate();
|
||||||
|
|
||||||
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
|
if (! RunGuard::instance().tryToRun()) {
|
||||||
|
qDebug() << "Tried to run second instance. Exiting...";
|
||||||
|
QMessageBox::information(NULL, QObject::tr("Notify"), QObject::tr("AmneziaVPN is already running."));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFontDatabase::addApplicationFont(":/fonts/Lato-Black.ttf");
|
||||||
|
QFontDatabase::addApplicationFont(":/fonts/Lato-BlackItalic.ttf");
|
||||||
|
QFontDatabase::addApplicationFont(":/fonts/Lato-Bold.ttf");
|
||||||
|
QFontDatabase::addApplicationFont(":/fonts/Lato-BoldItalic.ttf");
|
||||||
|
QFontDatabase::addApplicationFont(":/fonts/Lato-Italic.ttf");
|
||||||
|
QFontDatabase::addApplicationFont(":/fonts/Lato-Light.ttf");
|
||||||
|
QFontDatabase::addApplicationFont(":/fonts/Lato-LightItalic.ttf");
|
||||||
|
QFontDatabase::addApplicationFont(":/fonts/Lato-Regular.ttf");
|
||||||
|
QFontDatabase::addApplicationFont(":/fonts/Lato-Thin.ttf");
|
||||||
|
QFontDatabase::addApplicationFont(":/fonts/Lato-ThinItalic.ttf");
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
QTranslator *translator = new QTranslator;
|
||||||
|
QLocale ru(QLocale("ru_RU"));
|
||||||
|
QLocale::setDefault(ru);
|
||||||
|
if (translator->load(QLocale(), "amnezia-client", ".", QLatin1String(":/translations"))) {
|
||||||
|
bool ok = qApp->installTranslator(translator);
|
||||||
|
qDebug().noquote() << "Main: Installing translator for locale" << ru.name() << ok;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
qDebug().noquote() << "Main: Failed to install translator for locale" << ru.name();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
app.setOrganizationName("AmneziaVPN");
|
||||||
|
app.setOrganizationDomain("AmneziaVPN.ORG");
|
||||||
|
app.setApplicationName(ApplicationName);
|
||||||
|
app.setApplicationDisplayName(ApplicationName);
|
||||||
|
app.setApplicationVersion("1.0.0.0");
|
||||||
|
|
||||||
|
//app.setQuitOnLastWindowClosed(false);
|
||||||
|
|
||||||
|
QCommandLineParser parser;
|
||||||
|
parser.setApplicationDescription("AmneziaVPN");
|
||||||
|
parser.addHelpOption();
|
||||||
|
parser.addVersionOption();
|
||||||
|
|
||||||
|
QCommandLineOption debugToConsoleOption("d", QCoreApplication::translate("main", "Output to console instead log file"));
|
||||||
|
parser.addOption(debugToConsoleOption);
|
||||||
|
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
QCommandLineOption forceUseBrightIconsOption("b", QCoreApplication::translate("main", "Force use bright icons"));
|
||||||
|
parser.addOption(forceUseBrightIconsOption);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Process the actual command line arguments given by the user
|
||||||
|
parser.process(app);
|
||||||
|
|
||||||
|
bool debugToConsole = parser.isSet(debugToConsoleOption);
|
||||||
|
bool forceUseBrightIcons = false;
|
||||||
|
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
forceUseBrightIcons = parser.isSet(forceUseBrightIconsOption);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
qDebug() << "Set output to console: " << debugToConsole;
|
||||||
|
if (!debugToConsole) {
|
||||||
|
if (!Debug::init()) {
|
||||||
|
qCritical() << "Initialization of debug subsystem failed";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QFont f("Lato Regular", 10);
|
||||||
|
f.setStyleStrategy(QFont::PreferAntialias);
|
||||||
|
app.setFont(f);
|
||||||
|
|
||||||
|
MainWindow mainWindow(forceUseBrightIcons);
|
||||||
|
mainWindow.show();
|
||||||
|
|
||||||
|
return app.exec();
|
||||||
|
}
|
48
client/platform_win/vpnclient.rc
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
#include <windows.h>
|
||||||
|
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||||
|
|
||||||
|
IDI_ICON1 ICON "../images/main.ico"
|
||||||
|
|
||||||
|
#define VER_FILEVERSION 1,1,1,1
|
||||||
|
#define VER_FILEVERSION_STR "1.1.1.1\0"
|
||||||
|
|
||||||
|
#define VER_PRODUCTVERSION 1,1,1,1
|
||||||
|
#define VER_PRODUCTVERSION_STR "1.1.1.1\0"
|
||||||
|
|
||||||
|
#define VER_COMPANYNAME_STR "AmneziaVPN"
|
||||||
|
#define VER_FILEDESCRIPTION_STR "AmneziaVPN"
|
||||||
|
#define VER_INTERNALNAME_STR "AmneziaVPN"
|
||||||
|
#define VER_LEGALCOPYRIGHT_STR "AmneziaVPN."
|
||||||
|
#define VER_LEGALTRADEMARKS1_STR "All Rights Reserved"
|
||||||
|
#define VER_LEGALTRADEMARKS2_STR VER_LEGALTRADEMARKS1_STR
|
||||||
|
#define VER_ORIGINALFILENAME_STR "amneziavpn.exe"
|
||||||
|
#define VER_PRODUCTNAME_STR "AmneziaVPN"
|
||||||
|
|
||||||
|
#define VER_COMPANYDOMAIN_STR "http://amnezia.org/"
|
||||||
|
|
||||||
|
VS_VERSION_INFO VERSIONINFO
|
||||||
|
FILEVERSION VER_FILEVERSION
|
||||||
|
PRODUCTVERSION VER_PRODUCTVERSION
|
||||||
|
BEGIN
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
BEGIN
|
||||||
|
BLOCK "040904E4"
|
||||||
|
BEGIN
|
||||||
|
VALUE "CompanyName", VER_COMPANYNAME_STR
|
||||||
|
VALUE "FileDescription", VER_FILEDESCRIPTION_STR
|
||||||
|
VALUE "FileVersion", VER_FILEVERSION_STR
|
||||||
|
VALUE "InternalName", VER_INTERNALNAME_STR
|
||||||
|
VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR
|
||||||
|
VALUE "LegalTrademarks1", VER_LEGALTRADEMARKS1_STR
|
||||||
|
VALUE "LegalTrademarks2", VER_LEGALTRADEMARKS2_STR
|
||||||
|
VALUE "OriginalFilename", VER_ORIGINALFILENAME_STR
|
||||||
|
VALUE "ProductName", VER_PRODUCTNAME_STR
|
||||||
|
VALUE "ProductVersion", VER_PRODUCTVERSION_STR
|
||||||
|
END
|
||||||
|
END
|
||||||
|
|
||||||
|
BLOCK "VarFileInfo"
|
||||||
|
BEGIN
|
||||||
|
VALUE "Translation", 0x409, 1252
|
||||||
|
END
|
||||||
|
END
|
130
client/publib/debug.cpp
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <QStandardPaths>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
|
#define LOGS_DIR "logs"
|
||||||
|
#define CLIENT_LOG_SUFFIX "amneziavpn.log"
|
||||||
|
#define MAX_LOG_FILES 5
|
||||||
|
#define FORMAT_STRING "yyyy-MM-dd--hh-mm-ss"
|
||||||
|
|
||||||
|
QFile Debug::m_clientLog;
|
||||||
|
QTextStream Debug::m_clientLogTextStream;
|
||||||
|
QString Debug::m_clientLogName;
|
||||||
|
|
||||||
|
void debugMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
|
||||||
|
{
|
||||||
|
// Skip Qt warnings
|
||||||
|
if (msg.contains("known incorrect sRGB profile")) return;
|
||||||
|
if (msg.contains("libpng warning")) return;
|
||||||
|
if (msg.contains("Unknown property ffont")) return;
|
||||||
|
|
||||||
|
Debug::m_clientLogTextStream << qFormatLogMessage(type, context, msg) << endl << flush;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Debug::init()
|
||||||
|
{
|
||||||
|
QString path = qApp->applicationDirPath();
|
||||||
|
QDir appDir(path);
|
||||||
|
|
||||||
|
// init function is called before exec application, so data location folder may not exist
|
||||||
|
if (!appDir.exists())
|
||||||
|
{
|
||||||
|
qWarning() << "Debug: init: log directory doesn't exist or mkpath command error:" << path;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!appDir.exists(LOGS_DIR) && !appDir.mkdir(LOGS_DIR))
|
||||||
|
{
|
||||||
|
qWarning() << "Debug: init: log directory doesn't exist or mkdir command error:" << path << LOGS_DIR;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!appDir.cd(LOGS_DIR))
|
||||||
|
{
|
||||||
|
qWarning() << "Debug: init: cd command error:" << path << LOGS_DIR;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//delete older log files
|
||||||
|
auto clientLogsCount = 0;
|
||||||
|
QFileInfoList logDirList = appDir.entryInfoList(
|
||||||
|
QDir::Files | QDir::NoDotAndDotDot,
|
||||||
|
QDir::Time);
|
||||||
|
for (auto fileInfo : logDirList)
|
||||||
|
{
|
||||||
|
if ((fileInfo.completeSuffix() == CLIENT_LOG_SUFFIX &&
|
||||||
|
++clientLogsCount > MAX_LOG_FILES))
|
||||||
|
{
|
||||||
|
appDir.remove(fileInfo.filePath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//prepare log file names
|
||||||
|
auto currentDateTime = QDateTime::currentDateTime().toString(FORMAT_STRING);
|
||||||
|
|
||||||
|
m_clientLogName = QString("%1.%2").arg(currentDateTime).arg(CLIENT_LOG_SUFFIX);
|
||||||
|
return init(appDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Debug::init(QDir& appDir)
|
||||||
|
{
|
||||||
|
Q_UNUSED(appDir)
|
||||||
|
qSetMessagePattern("[%{time}|%{type}] %{message}");
|
||||||
|
|
||||||
|
#ifndef QT_DEBUG
|
||||||
|
m_clientLog.setFileName(appDir.filePath(m_clientLogName));
|
||||||
|
if (!m_clientLog.open(QIODevice::WriteOnly | QIODevice::Append)) {
|
||||||
|
qWarning() << "Debug::init - failed to open m_clientLog file:" << m_clientLogName;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_clientLog.setTextModeEnabled(true);
|
||||||
|
m_clientLogTextStream.setDevice(&m_clientLog);
|
||||||
|
qInstallMessageHandler(debugMessageHandler);
|
||||||
|
#else
|
||||||
|
#ifdef DEBUG_OUTPUT_TWO_DIRECTIONAL
|
||||||
|
m_clientLog.setFileName(appDir.filePath(m_clientLogName));
|
||||||
|
if (!m_clientLog.open(QIODevice::WriteOnly | QIODevice::Append))
|
||||||
|
return false;
|
||||||
|
m_clientLog.setTextModeEnabled(true);
|
||||||
|
m_clientLogTextStream.setDevice(&m_clientLog);
|
||||||
|
defaultMessageHandler = qInstallMessageHandler(debugMessageHandler);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
|
if (!fixOvpnLogPermissions())
|
||||||
|
qWarning() << "Debug: permissions for ovpn.log were not fixed";
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Debug::getPathToClientLog()
|
||||||
|
{
|
||||||
|
QString path = qApp->applicationDirPath();
|
||||||
|
QDir appDir(path);
|
||||||
|
if (!appDir.exists(LOGS_DIR) || !appDir.cd(LOGS_DIR))
|
||||||
|
{
|
||||||
|
qWarning() << "Debug: log directory doesn't exist or cd command error:" << path;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return appDir.filePath(m_clientLogName);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Debug::getPathToLogsDir()
|
||||||
|
{
|
||||||
|
QString path = qApp->applicationDirPath();
|
||||||
|
QDir appDir(path);
|
||||||
|
if (!appDir.exists(LOGS_DIR) || !appDir.cd(LOGS_DIR))
|
||||||
|
{
|
||||||
|
qWarning() << "Debug: log directory doesn't exist or cd command error" << path;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return appDir.absolutePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
27
client/publib/debug.h
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#ifndef DEBUG_H
|
||||||
|
#define DEBUG_H
|
||||||
|
|
||||||
|
#include <QFile>
|
||||||
|
#include <QTextStream>
|
||||||
|
#include <QString>
|
||||||
|
#include <QDir>
|
||||||
|
|
||||||
|
class Debug
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static bool init();
|
||||||
|
static QString getPathToClientLog();
|
||||||
|
static QString getPathToLogsDir();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static bool init(QDir& appDir);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static QFile m_clientLog;
|
||||||
|
static QTextStream m_clientLogTextStream;
|
||||||
|
static QString m_clientLogName;
|
||||||
|
|
||||||
|
friend void debugMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DEBUG_H
|
88
client/publib/runguard.cpp
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
#include "runguard.h"
|
||||||
|
#include <QCryptographicHash>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
QString generateKeyHash( const QString& key, const QString& salt )
|
||||||
|
{
|
||||||
|
QByteArray data;
|
||||||
|
|
||||||
|
data.append( key.toUtf8() );
|
||||||
|
data.append( salt.toUtf8() );
|
||||||
|
data = QCryptographicHash::hash( data, QCryptographicHash::Sha1 ).toHex();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
RunGuard::RunGuard(const QString& key)
|
||||||
|
: key( key )
|
||||||
|
, memLockKey( generateKeyHash( key, "_memLockKey" ) )
|
||||||
|
, sharedmemKey( generateKeyHash( key, "_sharedmemKey" ) )
|
||||||
|
, sharedMem( sharedmemKey )
|
||||||
|
, memLock( memLockKey, 1 )
|
||||||
|
{
|
||||||
|
qDebug() << "RunGuard::RunGuard key" << key;
|
||||||
|
}
|
||||||
|
|
||||||
|
RunGuard &RunGuard::instance(const QString& key)
|
||||||
|
{
|
||||||
|
static RunGuard s(key);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunGuard::activate()
|
||||||
|
{
|
||||||
|
memLock.acquire();
|
||||||
|
{
|
||||||
|
QSharedMemory fix(sharedmemKey); // Fix for *nix: http://habrahabr.ru/post/173281/
|
||||||
|
fix.attach();
|
||||||
|
}
|
||||||
|
memLock.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
RunGuard::~RunGuard()
|
||||||
|
{
|
||||||
|
release();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RunGuard::isAnotherRunning() const
|
||||||
|
{
|
||||||
|
if ( sharedMem.isAttached() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
memLock.acquire();
|
||||||
|
const bool isRunning = sharedMem.attach();
|
||||||
|
if ( isRunning )
|
||||||
|
sharedMem.detach();
|
||||||
|
memLock.release();
|
||||||
|
|
||||||
|
return isRunning;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RunGuard::tryToRun()
|
||||||
|
{
|
||||||
|
if ( isAnotherRunning() ) // Extra check
|
||||||
|
return false;
|
||||||
|
|
||||||
|
memLock.acquire();
|
||||||
|
const bool result = sharedMem.create( sizeof( quint64 ) );
|
||||||
|
memLock.release();
|
||||||
|
if ( !result )
|
||||||
|
{
|
||||||
|
release();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunGuard::release()
|
||||||
|
{
|
||||||
|
memLock.acquire();
|
||||||
|
if ( sharedMem.isAttached() )
|
||||||
|
sharedMem.detach();
|
||||||
|
memLock.release();
|
||||||
|
}
|
37
client/publib/runguard.h
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
#ifndef RUNGUARD_H
|
||||||
|
#define RUNGUARD_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QSharedMemory>
|
||||||
|
#include <QSystemSemaphore>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The RunGuard class - The application single instance (via shared memory)
|
||||||
|
*/
|
||||||
|
class RunGuard
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
static RunGuard &instance(const QString& key = QString());
|
||||||
|
|
||||||
|
~RunGuard();
|
||||||
|
|
||||||
|
void activate();
|
||||||
|
bool isAnotherRunning() const;
|
||||||
|
bool tryToRun();
|
||||||
|
void release();
|
||||||
|
|
||||||
|
private:
|
||||||
|
RunGuard(const QString& key);
|
||||||
|
Q_DISABLE_COPY( RunGuard )
|
||||||
|
|
||||||
|
const QString key;
|
||||||
|
const QString memLockKey;
|
||||||
|
const QString sharedmemKey;
|
||||||
|
|
||||||
|
mutable QSharedMemory sharedMem;
|
||||||
|
mutable QSystemSemaphore memLock;
|
||||||
|
|
||||||
|
};
|
||||||
|
#endif // RUNGUARD_H
|
261
client/publib/winhelp.cpp
Normal file
|
@ -0,0 +1,261 @@
|
||||||
|
#include "winhelp.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <Shlwapi.h>
|
||||||
|
#include <TlHelp32.h>
|
||||||
|
#include <Ras.h>
|
||||||
|
#include <iphlpapi.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define REG_AUTORUN_PATH "Software\\Microsoft\\Windows\\CurrentVersion\\Run"
|
||||||
|
|
||||||
|
int winhelpGetRegistry(const char *name, const char *reg, char *value)
|
||||||
|
{
|
||||||
|
unsigned long nType = REG_SZ, nData = MAX_PATH;
|
||||||
|
if(ERROR_SUCCESS != SHGetValueA(HKEY_CURRENT_USER, reg,
|
||||||
|
name, &nType, value, &nData))
|
||||||
|
return -1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int winhelpSetRegistry(const char *name, const char *reg, const char *value)
|
||||||
|
{
|
||||||
|
if(ERROR_SUCCESS != SHSetValueA(HKEY_CURRENT_USER, reg,
|
||||||
|
name, REG_SZ, value, (DWORD)strlen(value)))
|
||||||
|
return -1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int winhelpLaunchStartupRegister(const char *name, int enable, const char *p)
|
||||||
|
{
|
||||||
|
char path[MAX_PATH] = {0};
|
||||||
|
if(p && strlen(p) == 0)
|
||||||
|
p = NULL;
|
||||||
|
if(p) {
|
||||||
|
if(enable)
|
||||||
|
strcpy(path, "\"");
|
||||||
|
else
|
||||||
|
strcpy(path, ";\"");
|
||||||
|
GetModuleFileNameA(NULL, path + strlen(path), MAX_PATH);
|
||||||
|
strcat(path, "\" ");
|
||||||
|
strcat(path, p);
|
||||||
|
} else {
|
||||||
|
if(enable)
|
||||||
|
strcpy(path, "");
|
||||||
|
else
|
||||||
|
strcpy(path, ";");
|
||||||
|
GetModuleFileNameA(NULL, path + strlen(path), MAX_PATH);
|
||||||
|
}
|
||||||
|
if(winhelpSetRegistry(name, REG_AUTORUN_PATH, path) < 0)
|
||||||
|
return -1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* use the task scheduler, we do not need to care about UAC when start up */
|
||||||
|
int winhelpLaunchStartupTaskScheduler(const char *name, int enable, const char *p)
|
||||||
|
{
|
||||||
|
char cmd[MAX_PATH * 10] = {0};
|
||||||
|
char path[MAX_PATH] = {0};
|
||||||
|
UINT i = 0;
|
||||||
|
GetModuleFileNameA(NULL, path, MAX_PATH);
|
||||||
|
if (QString(path).contains("build-vpn-")) {
|
||||||
|
qDebug() << "winhelpLaunchStartupTaskScheduler : skipping auto launch for build dir";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(enable) {
|
||||||
|
if(p == NULL)
|
||||||
|
p = "";
|
||||||
|
sprintf(cmd, "schtasks /create /sc onlogon /tr \"\\\"%s\\\" %s\" "
|
||||||
|
"/tn \"%s\" /f /rl highest", path, p, name);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
sprintf(cmd, "schtasks /delete /tn \"%s\" /f", name);
|
||||||
|
}
|
||||||
|
qDebug().noquote() << "winhelpLaunchStartupTaskScheduler cmd:" << cmd;
|
||||||
|
i = WinExec(cmd, SW_HIDE);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int winhelpLaunchStartup(const char *name, int enable, const char *p)
|
||||||
|
{
|
||||||
|
OSVERSIONINFOA info = {0};
|
||||||
|
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
|
||||||
|
if(GetVersionExA(&info) < 0)
|
||||||
|
return -2;
|
||||||
|
if(info.dwMajorVersion >= 6)
|
||||||
|
return winhelpLaunchStartupTaskScheduler(name, enable, p);
|
||||||
|
else
|
||||||
|
return winhelpLaunchStartupRegister(name, enable, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
int str2int(const char *s)
|
||||||
|
{
|
||||||
|
int r = 0;
|
||||||
|
while(*s && *(s + 1) && *(s + 2) && *(s + 3)) {
|
||||||
|
r += ((const int *)s)[0];
|
||||||
|
s += 4;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int winhelpOneProcess()
|
||||||
|
{
|
||||||
|
char path[MAX_PATH] = {0};
|
||||||
|
int i = 0, size = 0, cur = 0;
|
||||||
|
GetModuleFileNameA(NULL, path, MAX_PATH);
|
||||||
|
size = strlen(path);
|
||||||
|
for(i = size; i >= 0 && path[i] != '\\' ; i--);
|
||||||
|
cur = i + 1;
|
||||||
|
while(path[i] != '.' && path[i])i++;
|
||||||
|
path[i] = '\0';
|
||||||
|
sprintf(path, "ONE_%s", path + cur);
|
||||||
|
CreateEventA(NULL, FALSE, FALSE, path);
|
||||||
|
if(GetLastError())
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int winhelpSystemBits()
|
||||||
|
{
|
||||||
|
typedef BOOL (WINAPI *LPFN_ISWOW64)(HANDLE, PBOOL);
|
||||||
|
int b64 = FALSE;
|
||||||
|
LPFN_ISWOW64 fnIsWow64 = (LPFN_ISWOW64)GetProcAddress(
|
||||||
|
GetModuleHandleA("kernel32"), "IsWow64Process");
|
||||||
|
if(NULL != fnIsWow64) {
|
||||||
|
if(!fnIsWow64(GetCurrentProcess(),&b64)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return b64 ? 64 : 86;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool winhelpIsSystem_x64()
|
||||||
|
{
|
||||||
|
typedef BOOL (WINAPI *LPFN_ISWOW64)(HANDLE, PBOOL);
|
||||||
|
int b64 = FALSE;
|
||||||
|
LPFN_ISWOW64 fnIsWow64 = (LPFN_ISWOW64)GetProcAddress(
|
||||||
|
GetModuleHandleA("kernel32"), "IsWow64Process");
|
||||||
|
if(NULL != fnIsWow64) {
|
||||||
|
if(!fnIsWow64(GetCurrentProcess(),&b64)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return b64 ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct _PROCESS_QUERY
|
||||||
|
{
|
||||||
|
HANDLE h;
|
||||||
|
PROCESSENTRY32 d;
|
||||||
|
}PROCESS_QUERY;
|
||||||
|
|
||||||
|
int winhelpProcessQuery(void **p)
|
||||||
|
{
|
||||||
|
PROCESS_QUERY *q = (PROCESS_QUERY *)malloc(sizeof(PROCESS_QUERY));
|
||||||
|
if(q == NULL)
|
||||||
|
return -2;
|
||||||
|
q->h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||||
|
if(q->h == INVALID_HANDLE_VALUE) {
|
||||||
|
free(q);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(FALSE == Process32First(q->h, &q->d)) {
|
||||||
|
CloseHandle(q->h);
|
||||||
|
free(q);
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
*p = (void *)q;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int winhelpProcessNext(void *h, char *name)
|
||||||
|
{
|
||||||
|
PROCESS_QUERY *q = (PROCESS_QUERY *)h;
|
||||||
|
int pid = 0;
|
||||||
|
if(q == NULL)
|
||||||
|
return 0;
|
||||||
|
if(q->h == NULL) {
|
||||||
|
free(q);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(name)
|
||||||
|
wsprintfA(name, "%ls", q->d.szExeFile);
|
||||||
|
pid = (int)q->d.th32ProcessID;
|
||||||
|
|
||||||
|
if(FALSE == Process32Next(q->h, &q->d)) {
|
||||||
|
CloseHandle(q->h);
|
||||||
|
q->h = NULL;
|
||||||
|
}
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
int winhelpRecvEvent(const char *event)
|
||||||
|
{
|
||||||
|
HANDLE hEvent = CreateEventA(NULL, FALSE, FALSE, event);
|
||||||
|
if(hEvent == NULL)
|
||||||
|
return 0;
|
||||||
|
WaitForSingleObject(hEvent, INFINITE);
|
||||||
|
CloseHandle(hEvent);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int winhelpSendEvent(const char *event)
|
||||||
|
{
|
||||||
|
HANDLE hEvent = OpenEventA(EVENT_ALL_ACCESS, FALSE, event);
|
||||||
|
if(hEvent == NULL)
|
||||||
|
return 0;
|
||||||
|
SetEvent(hEvent);
|
||||||
|
CloseHandle(hEvent);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int winhelpSystemVersion()
|
||||||
|
{
|
||||||
|
OSVERSIONINFOA ver = {0};
|
||||||
|
int version = 0;
|
||||||
|
ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
|
||||||
|
GetVersionExA(&ver);
|
||||||
|
version = ver.dwMajorVersion * 0x100 + ver.dwMinorVersion;
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
int winhelperSetMTUSize(const char *subname, int size)
|
||||||
|
{
|
||||||
|
char cmd[MAX_PATH] = {0};
|
||||||
|
sprintf(cmd, "netsh interface ipv4 set subinterface \"%s\" mtu=%d store=persistent",
|
||||||
|
subname, size);
|
||||||
|
return (int)WinExec(cmd, SW_HIDE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int winhelpRecvSendBytes(const char *dev, int *recv, int *send)
|
||||||
|
{
|
||||||
|
MIB_IFTABLE *it = NULL;
|
||||||
|
DWORD size = sizeof(MIB_IFTABLE), ret = 0, i = 0;
|
||||||
|
DWORD tr = 0, ts = 0;
|
||||||
|
|
||||||
|
if(it = (MIB_IFTABLE *)malloc(sizeof (MIB_IFTABLE)), it == NULL)
|
||||||
|
return -1;
|
||||||
|
if(GetIfTable(it, &size, FALSE) == ERROR_INSUFFICIENT_BUFFER) {
|
||||||
|
free(it);
|
||||||
|
if(it = (MIB_IFTABLE *)malloc(size), it == NULL)
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
if(ret = GetIfTable(it, &size, FALSE), ret != NO_ERROR) {
|
||||||
|
free(it);
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
for(i = 0; i < it->dwNumEntries; i++) {
|
||||||
|
MIB_IFROW *ir = &it->table[i];
|
||||||
|
if(strstr((const char *)ir->bDescr, dev) == 0)
|
||||||
|
continue;
|
||||||
|
tr += (int)ir->dwInOctets;
|
||||||
|
ts += (int)ir->dwOutOctets;
|
||||||
|
}
|
||||||
|
*recv = tr;
|
||||||
|
*send = ts;
|
||||||
|
free(it);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
26
client/publib/winhelp.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#ifndef WINHELP_H
|
||||||
|
#define WINHELP_H
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern int winhelpLaunchStartup(const char *, int, const char *);
|
||||||
|
extern int winhelpOneProcess();
|
||||||
|
extern int winhelpSystemBits();
|
||||||
|
extern bool winhelpIsSystem_x64();
|
||||||
|
extern int winhelpProcessQuery(void **);
|
||||||
|
extern int winhelpProcessNext(void *, char *);
|
||||||
|
extern int winhelpRecvEvent(const char *);
|
||||||
|
extern int winhelpSendEvent(const char *);
|
||||||
|
extern int winhelpSystemVersion();
|
||||||
|
extern int winhelperSetMTUSize(const char *, int);
|
||||||
|
extern int winhelpRecvSendBytes(const char *, int *, int *);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* WINHELP_H */
|
39
client/res.qrc
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
<RCC>
|
||||||
|
<qresource prefix="/">
|
||||||
|
<file>images/close.png</file>
|
||||||
|
<file>images/listitembg.png</file>
|
||||||
|
<file>images/settings.png</file>
|
||||||
|
<file>images/underline.png</file>
|
||||||
|
<file>images/min.png</file>
|
||||||
|
<file>images/favorites_disabled.png</file>
|
||||||
|
<file>images/favorites_enabled.png</file>
|
||||||
|
<file>images/favorites_hover.png</file>
|
||||||
|
<file>images/controls/check_off.png</file>
|
||||||
|
<file>images/controls/check_on.png</file>
|
||||||
|
<file>images/controls/radio_off.png</file>
|
||||||
|
<file>images/controls/radio_on.png</file>
|
||||||
|
<file>images/connected_line.png</file>
|
||||||
|
<file>images/download.png</file>
|
||||||
|
<file>images/upload.png</file>
|
||||||
|
<file>images/controls/checkbox_hover.png</file>
|
||||||
|
<file>images/controls/checkbox_unchecked.png</file>
|
||||||
|
<file>images/tray/active.png</file>
|
||||||
|
<file>images/tray/default.png</file>
|
||||||
|
<file>images/tray/error.png</file>
|
||||||
|
<file>images/arrow_left.png</file>
|
||||||
|
<file>images/connect_button_connected.png</file>
|
||||||
|
<file>images/connect_button_disconnected.png</file>
|
||||||
|
<file>fonts/Lato-Black.ttf</file>
|
||||||
|
<file>fonts/Lato-BlackItalic.ttf</file>
|
||||||
|
<file>fonts/Lato-Bold.ttf</file>
|
||||||
|
<file>fonts/Lato-BoldItalic.ttf</file>
|
||||||
|
<file>fonts/Lato-Italic.ttf</file>
|
||||||
|
<file>fonts/Lato-Light.ttf</file>
|
||||||
|
<file>fonts/Lato-LightItalic.ttf</file>
|
||||||
|
<file>fonts/Lato-Regular.ttf</file>
|
||||||
|
<file>fonts/Lato-Thin.ttf</file>
|
||||||
|
<file>fonts/Lato-ThinItalic.ttf</file>
|
||||||
|
<file>images/Line.png</file>
|
||||||
|
<file>images/AmneziaVPN.png</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
193
client/ui/Controls/SlidingStackedWidget.cpp
Normal file
|
@ -0,0 +1,193 @@
|
||||||
|
#include "SlidingStackedWidget.h"
|
||||||
|
|
||||||
|
SlidingStackedWidget::SlidingStackedWidget(QWidget *parent)
|
||||||
|
: QStackedWidget(parent)
|
||||||
|
{
|
||||||
|
if (parent != 0) {
|
||||||
|
m_mainwindow = parent;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_mainwindow = this;
|
||||||
|
qDebug().noquote() << "ATTENTION: untested mainwindow case !";
|
||||||
|
}
|
||||||
|
// parent should not be 0; not tested for any other case yet !!
|
||||||
|
|
||||||
|
#ifdef Q_OS_SYMBIAN
|
||||||
|
#ifndef __S60_50__
|
||||||
|
qDebug().noquote() << "WARNING: ONLY TESTED AND 5TH EDITION";
|
||||||
|
#endif // __S60_50__
|
||||||
|
#endif // Q_OS_SYMBIAN
|
||||||
|
|
||||||
|
// Now, initialize some private variables with default values
|
||||||
|
m_vertical = false;
|
||||||
|
// setVerticalMode(true);
|
||||||
|
m_speed = 500;
|
||||||
|
m_animationtype = QEasingCurve::OutBack; // check out the QEasingCurve documentation for different styles
|
||||||
|
m_now = 0;
|
||||||
|
m_next = 0;
|
||||||
|
m_wrap = false;
|
||||||
|
m_pnow = QPoint(0,0);
|
||||||
|
m_active = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SlidingStackedWidget::~SlidingStackedWidget() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void SlidingStackedWidget::setVerticalMode(bool vertical) {
|
||||||
|
m_vertical = vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SlidingStackedWidget::setSpeed(int speed) {
|
||||||
|
m_speed = speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SlidingStackedWidget::setAnimation(enum QEasingCurve::Type animationtype) {
|
||||||
|
m_animationtype = animationtype;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SlidingStackedWidget::setWrap(bool wrap) {
|
||||||
|
m_wrap = wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SlidingStackedWidget::slideInNext() {
|
||||||
|
int now = currentIndex();
|
||||||
|
if (m_wrap || (now < count() - 1))
|
||||||
|
// count is inherit from QStackedWidget
|
||||||
|
slideInIdx(now + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SlidingStackedWidget::slideInPrev() {
|
||||||
|
int now = currentIndex();
|
||||||
|
if (m_wrap || (now > 0))
|
||||||
|
slideInIdx(now - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SlidingStackedWidget::slideInIdx(int idx, enum t_direction direction) {
|
||||||
|
// int idx, t_direction direction=AUTOMATIC
|
||||||
|
if (idx > count() - 1) {
|
||||||
|
direction = m_vertical ? TOP2BOTTOM : RIGHT2LEFT;
|
||||||
|
idx = (idx) % count();
|
||||||
|
}
|
||||||
|
else if (idx < 0) {
|
||||||
|
direction = m_vertical ? BOTTOM2TOP: LEFT2RIGHT;
|
||||||
|
idx = (idx + count()) % count();
|
||||||
|
}
|
||||||
|
slideInWgtImpl(widget(idx), direction);
|
||||||
|
// widget() is a function inherited from QStackedWidget
|
||||||
|
}
|
||||||
|
|
||||||
|
void SlidingStackedWidget::slideInWidget(QWidget *widget, SlidingStackedWidget::t_direction direction)
|
||||||
|
{
|
||||||
|
Q_UNUSED(direction);
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
int idx = indexOf(widget);
|
||||||
|
slideInIdx(idx, direction);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
setCurrentWidget(widget);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void SlidingStackedWidget::slideInWgtImpl(QWidget * newwidget, enum t_direction direction) {
|
||||||
|
if (m_active) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else m_active = true;
|
||||||
|
|
||||||
|
enum t_direction directionhint;
|
||||||
|
int now = currentIndex(); // currentIndex() is a function inherited from QStackedWidget
|
||||||
|
int next = indexOf(newwidget);
|
||||||
|
if (now == next) {
|
||||||
|
m_active = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (now < next) {
|
||||||
|
directionhint = m_vertical ? TOP2BOTTOM : RIGHT2LEFT;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
directionhint = m_vertical ? BOTTOM2TOP : LEFT2RIGHT;
|
||||||
|
}
|
||||||
|
if (direction == AUTOMATIC) {
|
||||||
|
direction = directionhint;
|
||||||
|
}
|
||||||
|
// NOW....
|
||||||
|
// calculate the shifts
|
||||||
|
|
||||||
|
int offsetx = frameRect().width(); // inherited from mother
|
||||||
|
int offsety = frameRect().height(); // inherited from mother
|
||||||
|
|
||||||
|
// the following is important, to ensure that the new widget
|
||||||
|
// has correct geometry information when sliding in first time
|
||||||
|
widget(next)->setGeometry(0, 0, offsetx, offsety);
|
||||||
|
|
||||||
|
if (direction == BOTTOM2TOP) {
|
||||||
|
offsetx = 0;
|
||||||
|
offsety = -offsety;
|
||||||
|
}
|
||||||
|
else if (direction == TOP2BOTTOM) {
|
||||||
|
offsetx = 0;
|
||||||
|
// offsety = offsety;
|
||||||
|
}
|
||||||
|
else if (direction == RIGHT2LEFT) {
|
||||||
|
offsetx = -offsetx;
|
||||||
|
offsety = 0;
|
||||||
|
}
|
||||||
|
else if (direction == LEFT2RIGHT) {
|
||||||
|
// offsetx = offsetx;
|
||||||
|
offsety = 0;
|
||||||
|
}
|
||||||
|
// re-position the next widget outside/aside of the display area
|
||||||
|
QPoint pnext = widget(next)->pos();
|
||||||
|
QPoint pnow = widget(now)->pos();
|
||||||
|
m_pnow = pnow;
|
||||||
|
|
||||||
|
widget(next)->move(pnext.x() - offsetx, pnext.y() - offsety);
|
||||||
|
// make it visible/show
|
||||||
|
widget(next)->show();
|
||||||
|
widget(next)->raise();
|
||||||
|
|
||||||
|
// animate both, the now and next widget to the side, using animation framework
|
||||||
|
QPropertyAnimation *animnow = new QPropertyAnimation(widget(now), "pos");
|
||||||
|
|
||||||
|
animnow->setDuration(m_speed);
|
||||||
|
animnow->setEasingCurve(m_animationtype);
|
||||||
|
animnow->setStartValue(QPoint(pnow.x(), pnow.y()));
|
||||||
|
animnow->setEndValue(QPoint(offsetx + pnow.x(), offsety + pnow.y()));
|
||||||
|
QPropertyAnimation *animnext = new QPropertyAnimation(widget(next), "pos");
|
||||||
|
animnext->setDuration(m_speed);
|
||||||
|
animnext->setEasingCurve(m_animationtype);
|
||||||
|
animnext->setStartValue(QPoint(-offsetx + pnext.x(), offsety + pnext.y()));
|
||||||
|
animnext->setEndValue(QPoint(pnext.x(), pnext.y()));
|
||||||
|
|
||||||
|
QParallelAnimationGroup *animgroup = new QParallelAnimationGroup;
|
||||||
|
|
||||||
|
animgroup->addAnimation(animnow);
|
||||||
|
animgroup->addAnimation(animnext);
|
||||||
|
|
||||||
|
QObject::connect(animgroup, SIGNAL(finished()),this,SLOT(animationDoneSlot()));
|
||||||
|
m_next = next;
|
||||||
|
m_now = now;
|
||||||
|
m_active = true;
|
||||||
|
animgroup->start();
|
||||||
|
|
||||||
|
// note; the rest is done via a connect from the animation ready;
|
||||||
|
// animation->finished() provides a signal when animation is done;
|
||||||
|
// so we connect this to some post processing slot,
|
||||||
|
// that we implement here below in animationDoneSlot.
|
||||||
|
}
|
||||||
|
|
||||||
|
void SlidingStackedWidget::animationDoneSlot(void) {
|
||||||
|
// when ready, call the QStackedWidget slot setCurrentIndex(int)
|
||||||
|
setCurrentIndex(m_next); // this function is inherited from QStackedWidget
|
||||||
|
// then hide the outshifted widget now, and (may be done already implicitely by QStackedWidget)
|
||||||
|
widget(m_now)->hide();
|
||||||
|
// then set the position of the outshifted widget now back to its original
|
||||||
|
widget(m_now)->move(m_pnow);
|
||||||
|
// so that the application could also still call the QStackedWidget original functions/slots for changings
|
||||||
|
// widget(m_now)->update();
|
||||||
|
// setCurrentIndex(m_next); // this function is inherit from QStackedWidget
|
||||||
|
m_active = false;
|
||||||
|
emit animationFinished();
|
||||||
|
}
|
76
client/ui/Controls/SlidingStackedWidget.h
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
#ifndef SLIDINGSTACKEDWIDGET_H
|
||||||
|
#define SLIDINGSTACKEDWIDGET_H
|
||||||
|
|
||||||
|
#include <QStackedWidget>
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QEasingCurve>
|
||||||
|
#include <QPropertyAnimation>
|
||||||
|
#include <QParallelAnimationGroup>
|
||||||
|
|
||||||
|
/* Description
|
||||||
|
|
||||||
|
SlidingStackedWidget is a class that is derived from QtStackedWidget
|
||||||
|
and allows smooth side shifting of widgets, in addition
|
||||||
|
to the original hard switching from one to another as offered by
|
||||||
|
QStackedWidget itself.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class SlidingStackedWidget : public QStackedWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
// This enumeration is used to define the animation direction
|
||||||
|
enum t_direction {
|
||||||
|
LEFT2RIGHT,
|
||||||
|
RIGHT2LEFT,
|
||||||
|
TOP2BOTTOM,
|
||||||
|
BOTTOM2TOP,
|
||||||
|
AUTOMATIC
|
||||||
|
};
|
||||||
|
|
||||||
|
// The Constructor and Destructor
|
||||||
|
SlidingStackedWidget(QWidget *parent);
|
||||||
|
~SlidingStackedWidget(void);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
// Some basic settings API
|
||||||
|
void setSpeed(int speed); // animation duration in milliseconds
|
||||||
|
void setAnimation(enum QEasingCurve::Type animationtype); // check out the QEasingCurve documentation for different styles
|
||||||
|
void setVerticalMode(bool vertical=true);
|
||||||
|
void setWrap(bool wrap); // wrapping is related to slideInNext/Prev;it defines the behaviour when reaching last/first page
|
||||||
|
|
||||||
|
// The Animation / Page Change API
|
||||||
|
void slideInNext();
|
||||||
|
void slideInPrev();
|
||||||
|
void slideInIdx(int idx, enum t_direction direction = AUTOMATIC);
|
||||||
|
void slideInWidget(QWidget *widget, enum t_direction direction = AUTOMATIC);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
// this is used for internal purposes in the class engine
|
||||||
|
void animationFinished(void);
|
||||||
|
|
||||||
|
protected slots:
|
||||||
|
// this is used for internal purposes in the class engine
|
||||||
|
void animationDoneSlot(void);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// this is used for internal purposes in the class engine
|
||||||
|
void slideInWgtImpl(QWidget *widget, enum t_direction direction = AUTOMATIC);
|
||||||
|
|
||||||
|
QWidget *m_mainwindow;
|
||||||
|
|
||||||
|
int m_speed;
|
||||||
|
enum QEasingCurve::Type m_animationtype;
|
||||||
|
bool m_vertical;
|
||||||
|
int m_now;
|
||||||
|
int m_next;
|
||||||
|
bool m_wrap;
|
||||||
|
QPoint m_pnow;
|
||||||
|
bool m_active;
|
||||||
|
|
||||||
|
QList<QWidget*> blockedPageList;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SLIDINGSTACKEDWIDGET_H
|
76
client/ui/customshadoweffect.cpp
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
#include "customshadoweffect.h"
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
|
CustomShadowEffect::CustomShadowEffect(QObject *parent) :
|
||||||
|
QGraphicsEffect(parent),
|
||||||
|
_distance(4.0f),
|
||||||
|
_blurRadius(10.0f),
|
||||||
|
_color(0, 0, 0, 80)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
extern Q_WIDGETS_EXPORT void qt_blurImage(QPainter *p, QImage &blurImage, qreal radius, bool quality, bool alphaOnly, int transposed = 0 );
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
void CustomShadowEffect::draw(QPainter* painter)
|
||||||
|
{
|
||||||
|
// if nothing to show outside the item, just draw source
|
||||||
|
if ((blurRadius() + distance()) <= 0) {
|
||||||
|
drawSource(painter);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PixmapPadMode mode = QGraphicsEffect::PadToEffectiveBoundingRect;
|
||||||
|
QPoint offset;
|
||||||
|
const QPixmap px = sourcePixmap(Qt::DeviceCoordinates, &offset, mode);
|
||||||
|
|
||||||
|
// return if no source
|
||||||
|
if (px.isNull())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// save world transform
|
||||||
|
QTransform restoreTransform = painter->worldTransform();
|
||||||
|
painter->setWorldTransform(QTransform());
|
||||||
|
|
||||||
|
// Calculate size for the background image
|
||||||
|
QSize szi(px.size().width() + 2 * distance(), px.size().height() + 2 * distance());
|
||||||
|
|
||||||
|
QImage tmp(szi, QImage::Format_ARGB32_Premultiplied);
|
||||||
|
QPixmap scaled = px.scaled(szi);
|
||||||
|
tmp.fill(0);
|
||||||
|
QPainter tmpPainter(&tmp);
|
||||||
|
tmpPainter.setCompositionMode(QPainter::CompositionMode_Source);
|
||||||
|
tmpPainter.drawPixmap(QPointF(-distance(), -distance()), scaled);
|
||||||
|
tmpPainter.end();
|
||||||
|
|
||||||
|
// blur the alpha channel
|
||||||
|
QImage blurred(tmp.size(), QImage::Format_ARGB32_Premultiplied);
|
||||||
|
blurred.fill(0);
|
||||||
|
QPainter blurPainter(&blurred);
|
||||||
|
qt_blurImage(&blurPainter, tmp, blurRadius(), false, true);
|
||||||
|
blurPainter.end();
|
||||||
|
|
||||||
|
tmp = blurred;
|
||||||
|
|
||||||
|
// blacken the image...
|
||||||
|
tmpPainter.begin(&tmp);
|
||||||
|
tmpPainter.setCompositionMode(QPainter::CompositionMode_SourceIn);
|
||||||
|
tmpPainter.fillRect(tmp.rect(), color());
|
||||||
|
tmpPainter.end();
|
||||||
|
|
||||||
|
// draw the blurred shadow...
|
||||||
|
painter->drawImage(offset, tmp);
|
||||||
|
|
||||||
|
// draw the actual pixmap...
|
||||||
|
painter->drawPixmap(offset, px, QRectF());
|
||||||
|
|
||||||
|
// restore world transform
|
||||||
|
painter->setWorldTransform(restoreTransform);
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF CustomShadowEffect::boundingRectFor(const QRectF& rect) const
|
||||||
|
{
|
||||||
|
qreal delta = blurRadius() + distance();
|
||||||
|
return rect.united(rect.adjusted(-delta, -delta, delta, delta));
|
||||||
|
}
|
31
client/ui/customshadoweffect.h
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#ifndef CUSTOMSHADOWEFFECT_H
|
||||||
|
#define CUSTOMSHADOWEFFECT_H
|
||||||
|
|
||||||
|
#include <QGraphicsDropShadowEffect>
|
||||||
|
#include <QGraphicsEffect>
|
||||||
|
|
||||||
|
class CustomShadowEffect : public QGraphicsEffect
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit CustomShadowEffect(QObject *parent = 0);
|
||||||
|
|
||||||
|
void draw(QPainter* painter);
|
||||||
|
QRectF boundingRectFor(const QRectF& rect) const;
|
||||||
|
|
||||||
|
inline void setDistance(qreal distance) { _distance = distance; updateBoundingRect(); }
|
||||||
|
inline qreal distance() const { return _distance; }
|
||||||
|
|
||||||
|
inline void setBlurRadius(qreal blurRadius) { _blurRadius = blurRadius; updateBoundingRect(); }
|
||||||
|
inline qreal blurRadius() const { return _blurRadius; }
|
||||||
|
|
||||||
|
inline void setColor(const QColor& color) { _color = color; }
|
||||||
|
inline QColor color() const { return _color; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
qreal _distance;
|
||||||
|
qreal _blurRadius;
|
||||||
|
QColor _color;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CUSTOMSHADOWEFFECT_H
|
36
client/ui/mainwindow.cpp
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#include <QMetaEnum>
|
||||||
|
#include <QMovie>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QMouseEvent>
|
||||||
|
#include <QScroller>
|
||||||
|
#include <QScrollBar>
|
||||||
|
#include <QDesktopWidget>
|
||||||
|
#include <QDesktopServices>
|
||||||
|
#include <QGridLayout>
|
||||||
|
#include <QTime>
|
||||||
|
|
||||||
|
#include "mainwindow.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
#include "ui_mainwindow.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
#include "ui_mainwindow_mac.h"
|
||||||
|
#include "publib/macos_functions.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
MainWindow::MainWindow(bool useForceUseBrightIcons, QWidget *parent) : QMainWindow(parent),
|
||||||
|
ui(new Ui::MainWindow),
|
||||||
|
forceUseBrightIcons(useForceUseBrightIcons)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
MainWindow::~MainWindow()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
43
client/ui/mainwindow.h
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
#ifndef MAINWINDOW_H
|
||||||
|
#define MAINWINDOW_H
|
||||||
|
|
||||||
|
#include <QMainWindow>
|
||||||
|
#include <QSystemTrayIcon>
|
||||||
|
#include <QAction>
|
||||||
|
#include <QMenu>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QClipboard>
|
||||||
|
#include <QStringListModel>
|
||||||
|
#include <QDataStream>
|
||||||
|
|
||||||
|
#include <QGraphicsBlurEffect>
|
||||||
|
#include "customshadoweffect.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class MainWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The MainWindow class - Main application window
|
||||||
|
*/
|
||||||
|
class MainWindow : public QMainWindow
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit MainWindow(bool setForceUseBrightIcons = false, QWidget *parent = nullptr);
|
||||||
|
~MainWindow();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::MainWindow *ui;
|
||||||
|
bool forceUseBrightIcons = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MAINWINDOW_H
|