[Added][Fixed] Added JSON parse libraries, and fixed namespace structure.

Signed-off-by: Leroy.H.Y <lhy20010403@hotmail.com>

Former-commit-id: 7aaff60ff4
This commit is contained in:
Leroy.H.Y 2019-07-03 00:18:39 +08:00
parent a0fb909d10
commit d3e3f14ae2
29 changed files with 3021 additions and 1691 deletions

View File

@ -2,6 +2,7 @@ install:
- set QTDIR=C:\Qt\5.10\mingw53_32 - set QTDIR=C:\Qt\5.10\mingw53_32
- choco install -y InnoSetup - choco install -y InnoSetup
- set PATH=%QTDIR%\bin;C:\Qt\Tools\mingw730_32\bin;%PATH%;"C:\Program Files (x86)\Inno Setup 5" - set PATH=%QTDIR%\bin;C:\Qt\Tools\mingw730_32\bin;%PATH%;"C:\Program Files (x86)\Inno Setup 5"
- git submodule update --init
build_script: build_script:
- mkdir python37 && xcopy C:\Python37 python37 /E /H /Q - mkdir python37 && xcopy C:\Python37 python37 /E /H /Q

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "3rdparty/jsoncons"]
path = 3rdparty/jsoncons
url = https://github.com/danielaparker/jsoncons

View File

@ -21,6 +21,7 @@ before_script:
- if [ "$BADGE" = "osx" ]; then export PATH="/usr/local/opt/qt/bin:$PATH"; fi - if [ "$BADGE" = "osx" ]; then export PATH="/usr/local/opt/qt/bin:$PATH"; fi
script: script:
- git submodule update --init
- lrelease ./Hv2ray.pro - lrelease ./Hv2ray.pro
- mkdir build && cd ./build - mkdir build && cd ./build
- QT_SELECT=5 QTDIR=/usr/share/qt5 qmake ../ - QT_SELECT=5 QTDIR=/usr/share/qt5 qmake ../

1
3rdparty/jsoncons vendored Submodule

@ -0,0 +1 @@
Subproject commit 11d0da64cf9e8725aa9963c307c8df4957359eef

View File

@ -22,44 +22,49 @@ DEFINES += QT_DEPRECATED_WARNINGS
# You can also select to disable deprecated APIs only up to a certain version of Qt. # You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
CONFIG += c++11 CONFIG += c++17
QMAKE_CXXFLAGS += -std=c++17
SOURCES += \ SOURCES += \
./src/w_MainWindow.cpp \ src/Hutils.cpp \
./src/w_ConnectionEditWindow.cpp \ src/w_MainWindow.cpp \
./src/w_ImportConfig.cpp \ src/w_ConnectionEditWindow.cpp \
./src/w_PrefrencesWindow.cpp \ src/w_ImportConfig.cpp \
./src/main.cpp \ src/w_PrefrencesWindow.cpp \
./src/vinteract.cpp \ src/main.cpp \
./src/utils.cpp \ src/vinteract.cpp \
./src/runguard.cpp src/runguard.cpp
HEADERS += \ HEADERS += \
./src/w_MainWindow.h \ src/HUtils.h \
./src/w_ConnectionEditWindow.h \ src/Hv2ConfigObject.h \
./src/w_ImportConfig.h \ src/w_MainWindow.h \
./src/w_PrefrencesWindow.h \ src/w_ConnectionEditWindow.h \
./src/constants.h \ src/w_ImportConfig.h \
./src/vinteract.h \ src/w_PrefrencesWindow.h \
./src/utils.h \ src/vinteract.h \
./src/runguard.h src/runguard.h
FORMS += \ FORMS += \
./src/w_MainWindow.ui \ src/w_MainWindow.ui \
./src/w_ConnectionEditWindow.ui \ src/w_ConnectionEditWindow.ui \
./src/w_ImportConfig.ui \ src/w_ImportConfig.ui \
./src/w_PrefrencesWindow.ui src/w_PrefrencesWindow.ui
RESOURCES += \ RESOURCES += \
./resources.qrc resources.qrc
TRANSLATIONS += \ TRANSLATIONS += \
./translations/zh-CN.ts \ translations/zh-CN.ts \
./translations/en-US.ts translations/en-US.ts
RC_ICONS += ./icons/Hv2ray.ico RC_ICONS += ./icons/Hv2ray.ico
INCLUDEPATH += 3rdparty/\
3rdparty/jsoncons/include
# Default rules for deployment. # Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin

46
src/HUtils.h Normal file
View File

@ -0,0 +1,46 @@
#include <QDir>
#include <QFile>
#include <QMap>
#include <QFileInfo>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QMessageBox>
#include <QWidget>
#include <assert.h>
#include "Hv2ConfigObject.h"
#ifndef UTILS_H
#define UTILS_H
namespace Hv2ray::Utils
{
QJsonObject switchJsonArrayObject(QJsonObject objest, QString value);
QJsonObject findValueFromJsonArray(QJsonArray arr, QString key, QString val);
QJsonObject loadRootObjFromConf();
QJsonArray getInbounds();
void showWarnMessageBox(QWidget *parent, QString title, QString text);
void overrideInbounds(QString path);
int getIndexByValue(QJsonArray array, QString key, QString val);
QStringList getAllFilesList(QDir *dir);
bool hasFile(QDir *dir, QString fileName);
template <typename TYPE>
QString StructToJSON(const TYPE &t)
{
string s;
encode_json<TYPE>(t, s, indenting::indent);
return QString::fromStdString(s);
}
template <typename TYPE>
TYPE StructFromJSON(const std::string &str)
{
TYPE v = decode_json<TYPE>(str);
return v;
}
}
#endif // UTILS_H

View File

@ -1,13 +1,8 @@
#include <QJsonArray> #include "HUtils.h"
#include <QJsonObject>
#include <QJsonDocument>
#include <QFile>
#include <QFileInfo>
#include <QMessageBox>
#include "utils.h" using namespace Hv2ray;
QJsonObject switchJsonArrayObject(QJsonObject obj, QString value) QJsonObject Utils::switchJsonArrayObject(QJsonObject obj, QString value)
{ {
QJsonObject returnObj = obj.value(value).isNull() QJsonObject returnObj = obj.value(value).isNull()
? obj.value(value).toObject() ? obj.value(value).toObject()
@ -15,17 +10,18 @@ QJsonObject switchJsonArrayObject(QJsonObject obj, QString value)
return returnObj; return returnObj;
} }
QJsonObject findValueFromJsonArray(QJsonArray arr, QString key, QString val) QJsonObject Utils::findValueFromJsonArray(QJsonArray arr, QString key, QString val)
{ {
for (const auto obj : arr) { for (const auto obj : arr) {
if (obj.toObject().value(key).toString() == val) { if (obj.toObject().value(key).toString() == val) {
return obj.toObject(); return obj.toObject();
} }
} }
return QJsonObject(); return QJsonObject();
} }
QJsonObject loadRootObjFromConf() QJsonObject Utils::loadRootObjFromConf()
{ {
QFile globalConfigFile("Hv2ray.conf"); QFile globalConfigFile("Hv2ray.conf");
globalConfigFile.open(QIODevice::ReadOnly); globalConfigFile.open(QIODevice::ReadOnly);
@ -36,25 +32,19 @@ QJsonObject loadRootObjFromConf()
return rootObj; return rootObj;
} }
QJsonArray getInbounds() QJsonArray Utils::getInbounds()
{ {
QJsonArray inbounds; QJsonArray inbounds;
inbounds = loadRootObjFromConf().value("inbounds").toArray(); inbounds = loadRootObjFromConf().value("inbounds").toArray();
return inbounds; return inbounds;
} }
bool getRootEnabled() void Utils::showWarnMessageBox(QWidget *parent, QString title, QString text)
{
return loadRootObjFromConf().value("v2suidEnabled").toBool();
}
void showWarnMessageBox(QWidget* parent, QString title, QString text)
{ {
QMessageBox::warning(parent, title, text, QMessageBox::Ok | QMessageBox::Default, 0); QMessageBox::warning(parent, title, text, QMessageBox::Ok | QMessageBox::Default, 0);
} }
void overrideInbounds(QString path) void Utils::overrideInbounds(QString path)
{ {
QFile confFile(path); QFile confFile(path);
confFile.open(QIODevice::ReadOnly); confFile.open(QIODevice::ReadOnly);
@ -74,15 +64,29 @@ void overrideInbounds(QString path)
confFile.close(); confFile.close();
} }
int getIndexByValue(QJsonArray array, QString key, QString val) int Utils::getIndexByValue(QJsonArray array, QString key, QString val)
{ {
QJsonArray::iterator it; QJsonArray::iterator it;
int index = 0; int index = 0;
for (it = array.begin(); it != array.end(); it++) { for (it = array.begin(); it != array.end(); it++) {
if (it->toObject().value(key) == val) { if (it->toObject().value(key) == val) {
return index; return index;
} }
index++; index++;
} }
return -1; return -1;
} }
/// Get file list in a Dir
QStringList Utils::getAllFilesList(QDir *dir)
{
return dir->entryList(QStringList() << "*" << "*.*", QDir::Hidden | QDir::Files);
}
bool Utils::hasFile(QDir *dir, QString fileName)
{
return getAllFilesList(dir).indexOf(fileName) >= 0;
}

387
src/Hv2ConfigObject.h Normal file
View File

@ -0,0 +1,387 @@
#include <QDir>
#include <list>
#include <string>
#include <jsoncons/json.hpp>
#include <string>
#define USE_JSON_CONS
#ifdef USE_JSON_CONS
#include <jsoncons/json.hpp>
#else
#include <x2struct/x2struct.hpp>
using namespace x2struct;
#endif
#ifndef V2CONFIG_H
#define V2CONFIG_H
// Macros
#define HV2RAY_CONFIG_DIR_NAME "/.hv2ray"
using namespace std;
using namespace jsoncons; // for convenience
/*------------------------------------------------------------------------------------------------------------*/
namespace Hv2ray::V2ConfigModels
{
struct LogObject {
string access;
string error;
string loglevel;
LogObject(): access(), error(), loglevel() {}
//XTOSTRUCT(O(access, error, loglevel))
};
struct ApiObject {
string tag;
list<string> services;
ApiObject() : tag(), services() {}
//XTOSTRUCT(O(tag, services))
};
struct ServerObject {
string address;
int port;
list<string> domains;
ServerObject(): address(), port(), domains() {}
//XTOSTRUCT(O(address, port, domains))
};
struct DnsObject {
map<string, string> hosts;
tuple<string, string, list<ServerObject>> servers;
DnsObject(): hosts(), servers() {}
//XTOSTRUCT(O(hosts, servers))
};
struct RuleObject {
string type = "field";
list<string> domain;
list<string> ip;
string port;
string network;
list<string> source;
list<string> user;
string inboundTag;
string protocol;
string attrs;
RuleObject() : type(), domain(), ip(), port(), network(), source(), user(), inboundTag(), protocol(), attrs() {}
//XTOSTRUCT(O(type, domain, ip, port, network, source, user, inboundTag, protocol, attrs))
};
struct BalancerObject {
string tag ;
list<string> selector;
BalancerObject() : tag(), selector() {}
//XTOSTRUCT(O(tag, selector))
};
struct RoutingObject {
string domainStrategy;
list<RuleObject> rules;
list<BalancerObject> balancers;
RoutingObject() : domainStrategy(), rules(), balancers() {}
//XTOSTRUCT(O(domainStrategy, rules, balancers))
};
struct SystemPolicyObject {
bool statsInboundUplink;
bool statsInboundDownlink;
SystemPolicyObject() : statsInboundUplink(), statsInboundDownlink() {}
//XTOSTRUCT(O(statsInboundUplink, statsInboundDownlink))
};
struct LevelPolicyObject {
int handshake;
int connIdle;
int uplinkOnly;
int downlinkOnly;
bool statsUserUplink;
bool statsUserDownlink;
int bufferSize;
LevelPolicyObject(): handshake(), connIdle(), uplinkOnly(), downlinkOnly(), statsUserUplink(), statsUserDownlink(), bufferSize() {}
//XTOSTRUCT(O(handshake, connIdle, uplinkOnly, downlinkOnly, statsUserUplink, statsUserDownlink, bufferSize))
};
struct PolicyObject {
map<int, LevelPolicyObject> level;
list<SystemPolicyObject> system;
PolicyObject(): level(), system() {}
//XTOSTRUCT(O(level, system))
};
struct HTTPRequestObject {
string version;
string method;
list<string> path;
map<string, list<string>> headers;
HTTPRequestObject(): version(), method(), path(), headers() {}
//XTOSTRUCT(O(version, method, path, headers))
};
struct HTTPResponseObject {
string version;
string status;
string reason;
map<string, list<string>> headers;
HTTPResponseObject(): version(), status(), reason(), headers() {}
//XTOSTRUCT(O(version, status, reason, headers))
};
struct TCPHeader_M_Object {
string type;
HTTPRequestObject request;
HTTPResponseObject response;
TCPHeader_M_Object(): type(), request(), response() {}
//XTOSTRUCT(O(type, request, response))
};
struct TCPObject {
TCPHeader_M_Object header;
TCPObject(): header() {}
//XTOSTRUCT(O(header))
};
struct HeaderObject {
string type;
HeaderObject(): type() {}
//XTOSTRUCT(O(type))
};
struct KCPObject {
int mtu;
int tti;
int uplinkCapacity;
int downlinkCapacity;
bool congestion;
int readBufferSize;
int writeBufferSize;
HeaderObject header;
KCPObject(): mtu(), tti(), uplinkCapacity(), downlinkCapacity(), congestion(), readBufferSize(), writeBufferSize(), header() {}
//XTOSTRUCT(O(mtu, tti, uplinkCapacity, downlinkCapacity, congestion, readBufferSize, writeBufferSize, header))
};
struct WebSocketObject {
string path;
map<string, string> headers;
WebSocketObject(): path(), headers() {}
//XTOSTRUCT(O(path, headers))
};
struct HttpObject {
list<string> host;
string path;
HttpObject() : host(), path() {}
//XTOSTRUCT(O(host, path))
};
struct DomainSocketObject {
string path;
DomainSocketObject(): path() {}
//XTOSTRUCT(O(path))
};
struct QuicObject {
string security;
string key;
HeaderObject header;
QuicObject(): security(), key(), header() {}
//XTOSTRUCT(O(security, key, header))
};
struct TransportObject {
TCPObject tcpSettings;
KCPObject kcpSettings;
WebSocketObject wsSettings;
HttpObject httpSettings;
DomainSocketObject dsSettings;
QuicObject quicSettings;
TransportObject(): tcpSettings(), kcpSettings(), wsSettings(), httpSettings(), dsSettings(), quicSettings() {}
//XTOSTRUCT(O(tcpSettings, kcpSettings, wsSettings, httpSettings, dsSettings, quicSettings))
};
struct SniffingObject {
bool enabled;
string destOverride;
SniffingObject(): enabled(), destOverride() {}
//XTOSTRUCT(O(enabled, destOverride))
};
struct AllocateObject {
string strategy;
int refresh;
int concurrency;
AllocateObject(): strategy(), refresh(), concurrency() {}
//XTOSTRUCT(O(strategy, refresh, concurrency))
};
struct InboundObject {
int port;
string listen;
string protocol;
string settings;
TransportObject streamSettings;
string tag;
SniffingObject sniffing;
AllocateObject allocate;
InboundObject(): port(), listen(), protocol(), settings(), streamSettings(), tag(), sniffing(), allocate() {}
//XTOSTRUCT(O(port, listen, protocol, settings, streamSettings, tag, sniffing, allocate))
};
struct ProxySettingsObject {
string tag;
ProxySettingsObject(): tag() {}
//XTOSTRUCT(O(tag))
};
struct MuxObject {
bool enabled;
int concurrency;
MuxObject(): enabled(), concurrency() {}
//XTOSTRUCT(O(enabled, concurrency))
};
struct OutboundObject {
string sendThrough;
string protocol;
string settings;
string tag;
TransportObject streamSettings;
ProxySettingsObject proxySettings;
MuxObject mux;
OutboundObject(): sendThrough(), protocol(), settings(), tag(), streamSettings(), proxySettings(), mux() {}
//XTOSTRUCT(O(sendThrough, protocol, settings, tag, streamSettings, proxySettings, mux))
};
struct StatsObject {
bool _; // Placeholder...
StatsObject(): _() {}
};
struct BridgeObject {
string tag;
string domain;
BridgeObject() : tag(), domain() {}
//XTOSTRUCT(O(tag, domain))
};
struct PortalObject {
string tag;
string domain;
PortalObject() : tag(), domain() {}
//XTOSTRUCT(O(tag, domain))
};
struct ReverseObject {
list<BridgeObject> bridges;
list<PortalObject> portals;
ReverseObject() : bridges(), portals() {}
//XTOSTRUCT(O(bridges, portals))
};
struct RootObject {
LogObject log;
ApiObject api;
DnsObject dns;
RoutingObject routing;
list<InboundObject> inbounds;
list<OutboundObject> outbounds;
TransportObject transport;
StatsObject stats;
ReverseObject reverse;
RootObject(): log(), api(), dns(), routing(), inbounds(), outbounds(), transport(), stats(), reverse() {}
//XTOSTRUCT(O(log, api, dns, routing, inbounds, outbounds, transport, stats, reverse))
};
}
JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::LogObject, access, error, loglevel)
JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::ApiObject, tag, services)
JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::ServerObject, address, port, domains)
JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::DnsObject, hosts, servers)
JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::RuleObject, type, domain, ip, port, network, source, user, inboundTag, protocol, attrs)
JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::BalancerObject, tag, selector)
JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::RoutingObject, domainStrategy, rules, balancers)
JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::SystemPolicyObject, statsInboundUplink, statsInboundDownlink)
JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::LevelPolicyObject, handshake, connIdle, uplinkOnly, downlinkOnly, statsUserUplink, statsUserDownlink, bufferSize)
JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::PolicyObject, level, system)
JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::HTTPRequestObject, version, method, path, headers)
JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::HTTPResponseObject, version, status, reason, headers)
JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::TCPHeader_M_Object, type, request, response)
JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::TCPObject, header)
JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::HeaderObject, type)
JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::KCPObject, mtu, tti, uplinkCapacity, downlinkCapacity, congestion, readBufferSize, writeBufferSize, header)
JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::WebSocketObject, path, headers)
JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::HttpObject, host, path)
JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::DomainSocketObject, path)
JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::QuicObject, security, key, header)
JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::TransportObject, tcpSettings, kcpSettings, wsSettings, httpSettings, dsSettings, quicSettings)
JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::SniffingObject, enabled, destOverride)
JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::AllocateObject, strategy, refresh, concurrency)
JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::InboundObject, port, listen, protocol, settings, streamSettings, tag, sniffing, allocate)
JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::ProxySettingsObject, tag)
JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::MuxObject, enabled, concurrency)
JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::OutboundObject, sendThrough, protocol, settings, tag, streamSettings, proxySettings, mux)
JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::StatsObject, _)
JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::BridgeObject, tag, domain)
JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::PortalObject, tag, domain)
JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::ReverseObject, bridges, portals)
JSONCONS_MEMBER_TRAITS_DECL(Hv2ray::V2ConfigModels::RootObject, log, api, dns, routing, inbounds, outbounds, transport, stats, reverse)
namespace Hv2ray::HConfigModels
{
struct HInbondSetting {
bool enabled;
string ip;
int port;
bool useAuthentication;
string authUsername;
string authPassword;
HInbondSetting() {}
HInbondSetting(bool _enabled, string _ip, int _port)
: ip(_ip), authUsername(""), authPassword("")
{
enabled = _enabled;
port = _port;
useAuthentication = false;
}
HInbondSetting(bool _enabled, string _ip, int _port, string _username, string _password)
: ip(_ip), authUsername(_username), authPassword(_password)
{
enabled = _enabled;
port = _port;
useAuthentication = true;
}
//XTOSTRUCT(O(enabled, ip, port, useAuthentication, authUsername, authPassword))
};
struct Hv2Config {
string language;
bool runAsRoot;
string logLevel;
//Hv2ray::V2ConfigModels::MuxObject muxSetting;
HInbondSetting httpSetting;
HInbondSetting socksSetting;
Hv2Config() {}
Hv2Config(string lang, const bool _runAsRoot, const string _loglevel, HInbondSetting _http, HInbondSetting _socks)
: httpSetting(_http),
socksSetting(_socks)
{
language = lang;
runAsRoot = _runAsRoot;
logLevel = _loglevel;
}
//XTOSTRUCT(O(language, runAsRoot, logLevel, httpSetting, socksSetting))
};
}
using namespace Hv2ray;
JSONCONS_MEMBER_TRAITS_DECL(HConfigModels::Hv2Config, language, runAsRoot, logLevel, httpSetting, socksSetting)
JSONCONS_MEMBER_TRAITS_DECL(HConfigModels::HInbondSetting, enabled, ip, port, useAuthentication, authUsername, authPassword)
namespace Hv2ray
{
/// ConfigGlobalConfigthis is platform-independent as it's solved to be in the best
/// place at first in main.cpp
static QDir ConfigDir;
static HConfigModels::Hv2Config GlobalConfig;
}
#endif // V2CONFIG_H

View File

@ -1,15 +0,0 @@
#include <QString>
#include <QDir>
#ifndef CONSTANTS_H
#define CONSTANTS_H
// Macros
#define HV2RAY_CONFIG_DIR_NAME ".hv2ray"
namespace Hv2rayUtils {
static QDir ConfigDir;
} // namespace Hv2rayConsts
#endif // CONSTANTS_H

View File

@ -1,100 +1,112 @@
#include <QApplication> #include <QApplication>
#include <QDir>
#include <iostream>
#include <QDebug> #include <QDebug>
#include <QDir>
#include <QFileInfo> #include <QFileInfo>
#include <QStandardPaths>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray> #include <QJsonArray>
#include <QJsonValue> #include <QJsonDocument>
#include <QStandardPaths>
#include <QTranslator> #include <QTranslator>
#include <iostream>
#include <jsoncons/json.hpp>
#include "runguard.h" #include "runguard.h"
#include "utils.h" #include "HUtils.h"
#include "w_MainWindow.h" #include "Hv2ConfigObject.h"
#include "w_ConnectionEditWindow.h" #include "w_ConnectionEditWindow.h"
#include "constants.h" #include "w_MainWindow.h"
using namespace std; using namespace std;
using namespace Hv2rayUtils; using namespace Hv2ray;
using namespace Hv2ray::HConfigModels;
void firstRunCheck() bool firstRunCheck()
{ {
ConfigDir = QDir(QDir::homePath() + HV2RAY_CONFIG_DIR_NAME); /// Hv2ray Config Path.
QString configPath = "";
#if defined(__WIN32) || defined(__APPLE__)
// For Windows and MacOS, there's no such 'installation' of a software
// package, So as what ShadowSocks and v2rayX does, save config files next to
// the executable.
configPath = HV2RAY_CONFIG_DIR_NAME;
#else
// However, for linux, this software can be and/or will be provided as a
// package and install to whatever /usr/bin or /usr/local/bin or even /opt/
// Thus we save config files in the user's home directory.
configPath = QDir::homePath() + HV2RAY_CONFIG_DIR_NAME;
#endif
ConfigDir = QDir(configPath);
if (!ConfigDir.exists()) { if (!ConfigDir.exists()) {
QDir(QDir::homePath()).mkdir(".hv2ray"); auto result = QDir().mkdir(configPath);
qDebug() << "Config directory created.";
if (result) {
qDebug() << "Created hv2ray config file path at: " + configPath;
} else {
// We cannot continue as it failed to create a dir.
qDebug() << "Failed to create config file folder under " + configPath;
return false;
}
} }
QFileInfo hvConfInfo("conf/Hv2ray.config.json"); if (!Utils::hasFile(&ConfigDir, ".initialised")) {
// This is first run!
// These below genenrated very basic global config.
HInbondSetting inHttp = HInbondSetting(true, "127.0.0.1", 8080);
HInbondSetting inSocks = HInbondSetting(true, "127.0.0.1", 1080);
GlobalConfig = Hv2Config("zh-CN", false, "info", inHttp, inSocks);
QString jsonConfig = Utils::StructToJSON(GlobalConfig);
QFile configFile(configPath + "/hv2ray.conf");
// First Run? if (!configFile.open(QIODevice::WriteOnly)) {
if(!hvConfInfo.exists()) { qDebug() << "Failed to create main config file.";
QFile confFile("conf/Hv2ray.config.json"); return false;
if(!confFile.open(QIODevice::ReadWrite)) {
qDebug() << "Can not open Hv2ray.conf.json for read and write.";
} }
QJsonObject settings; QTextStream stream(&configFile);
settings.insert("auth", "noauth"); stream << jsonConfig;
settings.insert("udp", true); stream.flush();
settings.insert("ip", "127.0.0.1"); configFile.close();
// Create Placeholder for initialise indicator.
QJsonObject socks; QFile initPlaceHolder(configPath + "/.initialised");
socks.insert("settings", QJsonValue(settings)); initPlaceHolder.open(QFile::WriteOnly);
socks.insert("tag", "socks-in"); initPlaceHolder.close();
socks.insert("port", 1080);
socks.insert("listen", "127.0.0.1");
socks.insert("protocol", "socks");
QJsonArray inbounds;
inbounds.append(socks);
QJsonObject rootObj;
rootObj.insert("inbounds", QJsonValue(inbounds));
rootObj.insert("v2suidEnabled", false);
QJsonDocument defaultConf;
defaultConf.setObject(rootObj);
QByteArray byteArray = defaultConf.toJson(QJsonDocument::Indented);
confFile.write(byteArray);
confFile.close();
} }
return true;
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
QApplication _qApp(argc, argv); QApplication _qApp(argc, argv);
QTranslator translator; QTranslator translator;
if (translator.load(":/translations/zh-CN.qm", "translations"))
{ //
cout << "Loaded Chinese translations" << endl; if (translator.load(":/translations/zh-CN.qm", "translations")) {
} cout << "Loaded zh-CN translations" << endl;
else if (translator.load(":/translations/en-US.qm", "translations")){ } else if (translator.load(":/translations/en-US.qm", "translations")) {
cout << "Loaded English translations" << endl; cout << "Loaded en-US translations" << endl;
} else { } else {
showWarnMessageBox(nullptr, "Failed to load translations", Utils::showWarnMessageBox(
"Failed to load translations, user experience may be downgraded. \r\n \ nullptr, "Failed to load translations 无法加载语言文件",
."); "Failed to load translations, user experience may be downgraded. \r\n"
"无法加载语言文件,用户体验可能会降级.");
} }
_qApp.installTranslator(&translator); _qApp.installTranslator(&translator);
RunGuard guard("Hv2ray-Instance-Identifier"); RunGuard guard("Hv2ray-Instance-Identifier");
if (!guard.isSingleInstance()) { if (!guard.isSingleInstance()) {
showWarnMessageBox(nullptr, QObject::tr("Hv2Ray"), QObject::tr("AnotherInstanceRunning")); Utils::showWarnMessageBox(nullptr, QObject::tr("Hv2Ray"), QObject::tr("AnotherInstanceRunning"));
return -1; return -1;
} }
// GlobalConfig = StructFromJSON("");
// Set file startup path as Path
// WARNING: This may be changed in the future.
QDir::setCurrent(QFileInfo(QCoreApplication::applicationFilePath()).path()); QDir::setCurrent(QFileInfo(QCoreApplication::applicationFilePath()).path());
firstRunCheck(); firstRunCheck();
MainWindow w; // Show MainWindow
Ui::MainWindow w;
w.show(); w.show();
return _qApp.exec(); return _qApp.exec();
} }

View File

@ -1,12 +1,11 @@
#include <QCryptographicHash> #include <QCryptographicHash>
#include "runguard.h" #include "runguard.h"
namespace Hv2ray
//from https://stackoverflow.com/a/28172162
namespace
{ {
QString generateKeyHash( const QString& key, const QString& salt ) //from https://stackoverflow.com/a/28172162
QString RunGuard::generateKeyHash(const QString &key, const QString &salt)
{ {
QByteArray data; QByteArray data;
data.append(key.toUtf8()); data.append(key.toUtf8());
@ -14,10 +13,6 @@ namespace
data = QCryptographicHash::hash(data, QCryptographicHash::Sha1).toHex(); data = QCryptographicHash::hash(data, QCryptographicHash::Sha1).toHex();
return data; return data;
} }
}
RunGuard::RunGuard(const QString &key) RunGuard::RunGuard(const QString &key)
: key(key) : key(key)
, memLockKey(generateKeyHash(key, "_memLockKey")) , memLockKey(generateKeyHash(key, "_memLockKey"))
@ -43,11 +38,14 @@ bool RunGuard::isAnotherRunning()
if (sharedMem.isAttached()) { if (sharedMem.isAttached()) {
return false; return false;
} }
memLock.acquire(); memLock.acquire();
const bool isRunning = sharedMem.attach(); const bool isRunning = sharedMem.attach();
if (isRunning) { if (isRunning) {
sharedMem.detach(); sharedMem.detach();
} }
memLock.release(); memLock.release();
return isRunning; return isRunning;
} }
@ -57,21 +55,27 @@ bool RunGuard::isSingleInstance()
if (isAnotherRunning()) { // Extra check if (isAnotherRunning()) { // Extra check
return false; return false;
} }
memLock.acquire(); memLock.acquire();
const bool result = sharedMem.create(sizeof(quint64)); const bool result = sharedMem.create(sizeof(quint64));
memLock.release(); memLock.release();
if (!result) { if (!result) {
release(); release();
return false; return false;
} }
return true; return true;
} }
void RunGuard::release() void RunGuard::release()
{ {
memLock.acquire(); memLock.acquire();
if (sharedMem.isAttached()) { if (sharedMem.isAttached()) {
sharedMem.detach(); sharedMem.detach();
} }
memLock.release(); memLock.release();
} }
}

View File

@ -5,12 +5,13 @@
#include <QSharedMemory> #include <QSharedMemory>
#include <QSystemSemaphore> #include <QSystemSemaphore>
namespace Hv2ray
{
// From https://stackoverflow.com/a/28172162 // From https://stackoverflow.com/a/28172162
class RunGuard class RunGuard
{ {
public: public:
RunGuard( const QString& key ); explicit RunGuard(const QString &key);
~RunGuard(); ~RunGuard();
bool isAnotherRunning(); bool isAnotherRunning();
@ -18,6 +19,7 @@ public:
void release(); void release();
private: private:
QString generateKeyHash(const QString &key, const QString &salt);
const QString key; const QString key;
const QString memLockKey; const QString memLockKey;
const QString sharedmemKey; const QString sharedmemKey;
@ -27,5 +29,5 @@ private:
Q_DISABLE_COPY(RunGuard) Q_DISABLE_COPY(RunGuard)
}; };
}
#endif // RUNGUARD_H #endif // RUNGUARD_H

View File

@ -1,15 +0,0 @@
#include <QWidget>
#ifndef UTILS_H
#define UTILS_H
#include <QJsonObject>
QJsonObject switchJsonArrayObject(QJsonObject objest, QString value);
QJsonObject findValueFromJsonArray(QJsonArray arr, QString key, QString val);
QJsonObject loadRootObjFromConf();
QJsonArray getInbounds();
void showWarnMessageBox(QWidget* parent, QString title, QString text);
void overrideInbounds(QString path);
int getIndexByValue(QJsonArray array, QString key, QString val);
#endif // UTILS_H

View File

@ -1,21 +1,23 @@
#include <QProcess>
#include <QDebug> #include <QDebug>
#include <QProcess>
#include <QDir> #include <QDir>
#include <QProcess>
#include "utils.h" #include "HUtils.h"
#include "w_MainWindow.h"
#include "vinteract.h" #include "vinteract.h"
#include "w_MainWindow.h"
bool v2Instance::checkConfigFile(QString path) namespace Hv2ray
{
bool v2Instance::checkConfigFile(const QString path)
{ {
if (checkVCoreExes()) { if (checkVCoreExes()) {
QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
env.insert("V2RAY_LOCATION_ASSET", QDir::currentPath()); env.insert("V2RAY_LOCATION_ASSET", QDir::currentPath());
QProcess process; QProcess process;
process.setProcessEnvironment(env); process.setProcessEnvironment(env);
process.start("v2ray", QStringList() << "-test" << "-config" << path, QIODevice::ReadWrite | QIODevice::Text); process.start("v2ray", QStringList() << "-test"
<< "-config" << path,
QIODevice::ReadWrite | QIODevice::Text);
if (!process.waitForFinished()) { if (!process.waitForFinished()) {
qDebug() << "v2ray core failed with exit code " << process.exitCode(); qDebug() << "v2ray core failed with exit code " << process.exitCode();
@ -25,27 +27,28 @@ bool v2Instance::checkConfigFile(QString path)
QString output = QString(process.readAllStandardOutput()); QString output = QString(process.readAllStandardOutput());
if (!output.contains("Configuration OK")) { if (!output.contains("Configuration OK")) {
showWarnMessageBox(nullptr, QObject::tr("ConfigurationError"), output.mid(output.indexOf("anti-censorship.") + 17)); Utils::showWarnMessageBox(nullptr, QObject::tr("ConfigurationError"), output.mid(output.indexOf("anti-censorship.") + 17));
return false;
} else
return true;
} else
return false; return false;
}
else return true;
}
else return false;
} }
v2Instance::v2Instance(QWidget *parent) v2Instance::v2Instance(QWidget *parent)
{ {
this->vProcess = new QProcess(); QProcess *proc = new QProcess();
this->vProcess = proc;
QObject::connect(vProcess, SIGNAL(readyReadStandardOutput()), parent, SLOT(updateLog())); QObject::connect(vProcess, SIGNAL(readyReadStandardOutput()), parent, SLOT(updateLog()));
processStatus = STOPPED;
} }
bool v2Instance::checkVCoreExes() bool v2Instance::checkVCoreExes()
{ {
if (QFileInfo("v2ray").exists() && QFileInfo("geoip.dat").exists() && QFileInfo("geosite.dat").exists() && QFileInfo("v2ctl").exists()) { if (QFileInfo("v2ray").exists() && QFileInfo("geoip.dat").exists() && QFileInfo("geosite.dat").exists() && QFileInfo("v2ctl").exists()) {
return true; return true;
} } else {
else { Utils::showWarnMessageBox(nullptr, QObject::tr("CoreNotFound"), QObject::tr("CoreFileNotFoundExplaination"));
showWarnMessageBox(nullptr, QObject::tr("CoreNotFound"), QObject::tr("CoreFileNotFoundExplaination"));
return false; return false;
} }
} }
@ -55,16 +58,19 @@ bool v2Instance::start()
if (this->vProcess->state() == QProcess::Running) { if (this->vProcess->state() == QProcess::Running) {
this->stop(); this->stop();
} }
if (checkVCoreExes()) { if (checkVCoreExes()) {
QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
env.insert("V2RAY_LOCATION_ASSET", QDir::currentPath()); env.insert("V2RAY_LOCATION_ASSET", QDir::currentPath());
this->vProcess->setProcessEnvironment(env); this->vProcess->setProcessEnvironment(env);
this->vProcess->start("./v2ray", QStringList() << "-config" << "config.json", QIODevice::ReadWrite | QIODevice::Text); this->vProcess->start("./v2ray", QStringList() << "-config"
<< "config.json",
QIODevice::ReadWrite | QIODevice::Text);
this->vProcess->waitForStarted(); this->vProcess->waitForStarted();
processStatus = STARTED; processStatus = STARTED;
return true; return true;
} } else
else return false; return false;
} }
void v2Instance::stop() void v2Instance::stop()
@ -77,3 +83,5 @@ v2Instance::~v2Instance()
{ {
this->stop(); this->stop();
} }
}

View File

@ -1,8 +1,10 @@
#ifndef VINTERACT_H #ifndef VINTERACT_H
#define VINTERACT_H #define VINTERACT_H
#include <QString>
#include <QProcess> #include <QProcess>
#include <QString>
namespace Hv2ray
{
enum V2RAY_INSTANCE_STARTUP_STATUS { enum V2RAY_INSTANCE_STARTUP_STATUS {
STOPPED, STOPPED,
STARTING, STARTING,
@ -22,8 +24,10 @@ public:
static bool checkConfigFile(QString path); static bool checkConfigFile(QString path);
~v2Instance(); ~v2Instance();
QProcess *vProcess; QProcess *vProcess;
private: private:
V2RAY_INSTANCE_STARTUP_STATUS processStatus; V2RAY_INSTANCE_STARTUP_STATUS processStatus;
}; };
}
#endif // VINTERACT_H #endif // VINTERACT_H

View File

@ -1,14 +1,15 @@
#include "w_ConnectionEditWindow.h" #include "w_ConnectionEditWindow.h"
#include "ui_w_ConnectionEditWindow.h"
#include <iostream>
#include "w_MainWindow.h" #include "w_MainWindow.h"
#include <QDebug> #include <QDebug>
#include <QFile> #include <QFile>
#include <QIntValidator> #include <QIntValidator>
#include <iostream>
ConnectionEditWindow::ConnectionEditWindow(QWidget *parent) : namespace Hv2ray::Ui
QDialog(parent), {
ui(new Ui::ConnectionEditWindow) ConnectionEditWindow::ConnectionEditWindow(QWidget *parent)
: QDialog(parent)
, ui(new Ui_ConnectionEditWindow)
{ {
ui->setupUi(this); ui->setupUi(this);
ui->portLineEdit->setValidator(new QIntValidator()); ui->portLineEdit->setValidator(new QIntValidator());
@ -19,18 +20,15 @@ ConnectionEditWindow::~ConnectionEditWindow()
{ {
delete ui; delete ui;
} }
int Hv2Config::save()
{
return -1;
}
void Hv2Config::getConfigFromDialog(Ui::ConnectionEditWindow *ui) //void ConnectionEditWindow::getConfigFromDialog(Ui::ConnectionEditWindow *ui)
{ //{
this->host = ui->ipLineEdit->text(); //this->host = ui->ipLineEdit->text();
this->port = ui->portLineEdit->text(); //this->port = ui->portLineEdit->text();
this->alias = ui->aliasLineEdit->text(); //this->alias = ui->aliasLineEdit->text();
this->uuid = ui->idLineEdit->text(); //this->uuid = ui->idLineEdit->text();
this->alterid = ui->alterLineEdit->text(); //this->alterid = ui->alterLineEdit->text();
this->security = ui->securityCombo->currentText(); //this->security = ui->securityCombo->currentText();
this->isCustom = 0; //this->isCustom = 0;
//}
} }

View File

@ -2,28 +2,10 @@
#define CONFEDIT_H #define CONFEDIT_H
#include <QDialog> #include <QDialog>
#include "ui_w_ConnectionEditWindow.h"
namespace Ui namespace Hv2ray::Ui
{ {
class ConnectionEditWindow;
}
class Hv2Config
{
public:
QString host;
QString port;
QString alias;
QString uuid;
QString alterid;
QString security;
int isCustom;
int save();
void getConfigFromDialog(Ui::ConnectionEditWindow *ui);
private:
};
class ConnectionEditWindow : public QDialog class ConnectionEditWindow : public QDialog
{ {
Q_OBJECT Q_OBJECT
@ -31,10 +13,9 @@ class ConnectionEditWindow : public QDialog
public: public:
explicit ConnectionEditWindow(QWidget *parent = nullptr); explicit ConnectionEditWindow(QWidget *parent = nullptr);
~ConnectionEditWindow(); ~ConnectionEditWindow();
private: private:
Ui::ConnectionEditWindow *ui; Ui_ConnectionEditWindow *ui;
}; };
}
#endif // CONFEDIT_H #endif // CONFEDIT_H

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>ConnectionEditWindow</class> <class>Hv2ray::Ui::ConnectionEditWindow</class>
<widget class="QDialog" name="ConnectionEditWindow"> <widget class="QDialog" name="Hv2ray::Ui::ConnectionEditWindow">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
@ -864,7 +864,7 @@
<connection> <connection>
<sender>buttonBox</sender> <sender>buttonBox</sender>
<signal>accepted()</signal> <signal>accepted()</signal>
<receiver>ConnectionEditWindow</receiver> <receiver>Hv2ray::Ui::ConnectionEditWindow</receiver>
<slot>accept()</slot> <slot>accept()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
@ -880,7 +880,7 @@
<connection> <connection>
<sender>buttonBox</sender> <sender>buttonBox</sender>
<signal>rejected()</signal> <signal>rejected()</signal>
<receiver>ConnectionEditWindow</receiver> <receiver>Hv2ray::Ui::ConnectionEditWindow</receiver>
<slot>reject()</slot> <slot>reject()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">

View File

@ -1,25 +1,26 @@
#include <QFileDialog>
#include <QDebug> #include <QDebug>
#include <QFile> #include <QFile>
#include <QFileDialog>
#include <QJsonArray>
#include <QJsonDocument> #include <QJsonDocument>
#include <QJsonObject> #include <QJsonObject>
#include <QJsonArray>
#pragma push_macro("slots") #pragma push_macro("slots")
#undef slots #undef slots
#include "Python.h" #include "Python.h"
#pragma pop_macro("slots") #pragma pop_macro("slots")
#include "w_ConnectionEditWindow.h" #include "HUtils.h"
#include "vinteract.h" #include "vinteract.h"
#include "utils.h" #include "w_ConnectionEditWindow.h"
#include "w_ImportConfig.h" #include "w_ImportConfig.h"
#include "ui_w_ImportConfig.h"
using namespace Hv2ray;
ImportConfig::ImportConfig(QWidget *parent) : namespace Hv2ray::Ui
QDialog(parent), {
ui(new Ui::ImportConfig) ImportConfig::ImportConfig(QWidget *parent)
: QDialog(parent)
, ui(new Ui_ImportConfig)
{ {
ui->setupUi(this); ui->setupUi(this);
connect(this, SIGNAL(updateConfTable()), parentWidget(), SLOT(updateConfTable())); connect(this, SIGNAL(updateConfTable()), parentWidget(), SLOT(updateConfTable()));
@ -38,63 +39,64 @@ void ImportConfig::on_pushButton_clicked()
void ImportConfig::savefromFile(QString path, QString alias) void ImportConfig::savefromFile(QString path, QString alias)
{ {
Hv2Config newConfig; Q_UNUSED(path)
newConfig.alias = alias; Q_UNUSED(alias)
QFile configFile(path); //Hv2Config newConfig;
if(!configFile.open(QIODevice::ReadOnly)) { //newConfig.alias = alias;
showWarnMessageBox(this, tr("ImportConfig"), tr("CannotOpenFile")); //QFile configFile(path);
qDebug() << "ImportConfig::CannotOpenFile"; //if(!configFile.open(QIODevice::ReadOnly)) {
return; // showWarnMessageBox(this, tr("ImportConfig"), tr("CannotOpenFile"));
} // qDebug() << "ImportConfig::CannotOpenFile";
QByteArray allData = configFile.readAll(); // return;
configFile.close(); //}
QJsonDocument v2conf(QJsonDocument::fromJson(allData)); //QByteArray allData = configFile.readAll();
QJsonObject rootobj = v2conf.object(); //configFile.close();
QJsonObject outbound; //QJsonDocument v2conf(QJsonDocument::fromJson(allData));
if(rootobj.contains("outbounds")) { //QJsonObject rootobj = v2conf.object();
outbound = rootobj.value("outbounds").toArray().first().toObject(); //QJsonObject outbound;
} else { //if(rootobj.contains("outbounds")) {
outbound = rootobj.value("outbound").toObject(); // outbound = rootobj.value("outbounds").toArray().first().toObject();
} //} else {
QJsonObject vnext = switchJsonArrayObject(outbound.value("settings").toObject(), "vnext"); // outbound = rootobj.value("outbound").toObject();
QJsonObject user = switchJsonArrayObject(vnext, "users"); //}
newConfig.host = vnext.value("address").toString(); //QJsonObject vnext = switchJsonArrayObject(outbound.value("settings").toObject(), "vnext");
newConfig.port = QString::number(vnext.value("port").toInt()); //QJsonObject user = switchJsonArrayObject(vnext, "users");
newConfig.alterid = QString::number(user.value("alterId").toInt()); //newConfig.host = vnext.value("address").toString();
newConfig.uuid = user.value("id").toString(); //newConfig.port = QString::number(vnext.value("port").toInt());
newConfig.security = user.value("security").toString(); //newConfig.alterid = QString::number(user.value("alterId").toInt());
if (newConfig.security.isNull()) { //newConfig.uuid = user.value("id").toString();
newConfig.security = "auto"; //newConfig.security = user.value("security").toString();
} //if (newConfig.security.isNull()) {
newConfig.isCustom = 1; // newConfig.security = "auto";
int id = newConfig.save(); //}
if(id < 0) //newConfig.isCustom = 1;
{ //int id = newConfig.save();
showWarnMessageBox(this, tr("ImportConfig"), tr("SaveFailed")); //if(id < 0)
qDebug() << "ImportConfig::SaveFailed"; //{
return; // showWarnMessageBox(this, tr("ImportConfig"), tr("SaveFailed"));
} // qDebug() << "ImportConfig::SaveFailed";
emit updateConfTable(); // return;
QString newFile = "conf/" + QString::number(id) + ".conf"; //}
if(!QFile::copy(path, newFile)) { //emit updateConfTable();
showWarnMessageBox(this, tr("ImportConfig"), tr("CannotCopyCustomConfig")); //QString newFile = "conf/" + QString::number(id) + ".conf";
qDebug() << "ImportConfig::CannotCopyCustomConfig"; //if(!QFile::copy(path, newFile)) {
} // showWarnMessageBox(this, tr("ImportConfig"), tr("CannotCopyCustomConfig"));
// qDebug() << "ImportConfig::CannotCopyCustomConfig";
//}
} }
void ImportConfig::on_buttonBox_accepted() void ImportConfig::on_buttonBox_accepted()
{ {
QString alias = ui->nameTxt->text(); QString alias = ui->nameTxt->text();
if(ui->importSourceCombo->currentIndex() == 0) // From File...
{ if (ui->importSourceCombo->currentIndex() == 0) { // From File...
QString path = ui->fileLineTxt->text(); QString path = ui->fileLineTxt->text();
bool isValid = v2Instance::checkConfigFile(path); bool isValid = v2Instance::checkConfigFile(path);
if (isValid) { if (isValid) {
savefromFile(path, alias); savefromFile(path, alias);
} }
} } else {
else
{
QString vmess = ui->vmessConnectionStringTxt->toPlainText(); QString vmess = ui->vmessConnectionStringTxt->toPlainText();
Py_Initialize(); Py_Initialize();
assert(Py_IsInitialized()); assert(Py_IsInitialized());
@ -108,24 +110,25 @@ void ImportConfig::on_buttonBox_accepted()
PyTuple_SetItem(arg, 0, arg1); PyTuple_SetItem(arg, 0, arg1);
PyObject_CallObject(pFunc, arg); PyObject_CallObject(pFunc, arg);
Py_Finalize(); Py_Finalize();
if (QFile::exists(QCoreApplication::applicationDirPath() + "/config.json.tmp")) { if (QFile::exists(QCoreApplication::applicationDirPath() + "/config.json.tmp")) {
ImportConfig *im = new ImportConfig(this->parentWidget()); ImportConfig *im = new ImportConfig(this->parentWidget());
if (v2Instance::checkConfigFile(QCoreApplication::applicationDirPath() + "/config.json.tmp")) { if (v2Instance::checkConfigFile(QCoreApplication::applicationDirPath() + "/config.json.tmp")) {
im->savefromFile("config.json.tmp", alias); im->savefromFile("config.json.tmp", alias);
} }
QFile::remove("config.json.tmp"); QFile::remove("config.json.tmp");
} else { } else {
showWarnMessageBox(this, tr("ImportConfig"), tr("CannotGenerateConfig")); Utils::showWarnMessageBox(this, tr("ImportConfig"), tr("CannotGenerateConfig"));
qDebug() << "ImportConfig::CannotGenerateConfig"; qDebug() << "ImportConfig::CannotGenerateConfig";
} }
} }
if(ui->useCurrentSettingRidBtn->isChecked()) if (ui->useCurrentSettingRidBtn->isChecked()) {
{
// TODO: Use Current Settings... // TODO: Use Current Settings...
} } else {
else
{
// TODO: Override Inbound.... // TODO: Override Inbound....
} }
} }
}

View File

@ -2,12 +2,12 @@
#define IMPORTCONF_H #define IMPORTCONF_H
#include <QDialog> #include <QDialog>
#include "ui_w_ImportConfig.h"
namespace Hv2ray
{
namespace Ui namespace Ui
{ {
class ImportConfig;
}
class ImportConfig : public QDialog class ImportConfig : public QDialog
{ {
Q_OBJECT Q_OBJECT
@ -24,7 +24,9 @@ signals:
void updateConfTable(); void updateConfTable();
private: private:
Ui::ImportConfig *ui; Ui_ImportConfig *ui;
}; };
}
}
#endif // IMPORTCONF_H #endif // IMPORTCONF_H

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>ImportConfig</class> <class>Hv2ray::Ui::ImportConfig</class>
<widget class="QDialog" name="ImportConfig"> <widget class="QDialog" name="Hv2ray::Ui::ImportConfig">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
@ -162,7 +162,7 @@
<connection> <connection>
<sender>buttonBox</sender> <sender>buttonBox</sender>
<signal>accepted()</signal> <signal>accepted()</signal>
<receiver>ImportConfig</receiver> <receiver>Hv2ray::Ui::ImportConfig</receiver>
<slot>accept()</slot> <slot>accept()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
@ -178,7 +178,7 @@
<connection> <connection>
<sender>buttonBox</sender> <sender>buttonBox</sender>
<signal>rejected()</signal> <signal>rejected()</signal>
<receiver>ImportConfig</receiver> <receiver>Hv2ray::Ui::ImportConfig</receiver>
<slot>reject()</slot> <slot>reject()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">

View File

@ -1,34 +1,33 @@
#include <QHeaderView>
#include <QStandardItemModel>
#include <QDebug>
#include <QMenu>
#include <QAction> #include <QAction>
#include <QFile>
#include <QCloseEvent> #include <QCloseEvent>
#include <QDebug>
#include <QFile>
#include <QFileInfo> #include <QFileInfo>
#include <QHeaderView>
#include <QInputDialog> #include <QInputDialog>
#include <QMenu>
#include <QStandardItemModel>
#include "ui_w_MainWindow.h" #include "HUtils.h"
#include "w_PrefrencesWindow.h" #include "vinteract.h"
#include "w_MainWindow.h"
#include "w_ConnectionEditWindow.h" #include "w_ConnectionEditWindow.h"
#include "w_ImportConfig.h" #include "w_ImportConfig.h"
#include "vinteract.h" #include "w_MainWindow.h"
#include "utils.h" #include "w_PrefrencesWindow.h"
namespace Hv2ray::Ui
{
void MainWindow::CreateTrayIcon() void MainWindow::CreateTrayIcon()
{ {
hTray = new QSystemTrayIcon(); hTray = new QSystemTrayIcon();
hTray->setToolTip(tr("Hv2ray")); hTray->setToolTip(tr("Hv2ray"));
hTray->setIcon(this->windowIcon()); hTray->setIcon(this->windowIcon());
connect(hTray, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(on_activatedTray(QSystemTrayIcon::ActivationReason))); connect(hTray, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(on_activatedTray(QSystemTrayIcon::ActivationReason)));
QAction *actionShow = new QAction(this); QAction *actionShow = new QAction(this);
QAction *actionQuit = new QAction(this); QAction *actionQuit = new QAction(this);
QAction *actionStart = new QAction(this); QAction *actionStart = new QAction(this);
QAction *actionRestart = new QAction(this); QAction *actionRestart = new QAction(this);
QAction *actionStop = new QAction(this); QAction *actionStop = new QAction(this);
actionShow->setText(tr("#Hide")); actionShow->setText(tr("#Hide"));
actionQuit->setText(tr("#Quit")); actionQuit->setText(tr("#Quit"));
actionStart->setText(tr("#Start")); actionStart->setText(tr("#Start"));
@ -37,7 +36,6 @@ void MainWindow::CreateTrayIcon()
actionStart->setEnabled(true); actionStart->setEnabled(true);
actionStop->setEnabled(false); actionStop->setEnabled(false);
actionRestart->setEnabled(false); actionRestart->setEnabled(false);
trayMenu->addAction(actionShow); trayMenu->addAction(actionShow);
trayMenu->addSeparator(); trayMenu->addSeparator();
trayMenu->addAction(actionStart); trayMenu->addAction(actionStart);
@ -45,7 +43,6 @@ void MainWindow::CreateTrayIcon()
trayMenu->addAction(actionRestart); trayMenu->addAction(actionRestart);
trayMenu->addSeparator(); trayMenu->addSeparator();
trayMenu->addAction(actionQuit); trayMenu->addAction(actionQuit);
connect(actionShow, SIGNAL(triggered()), this, SLOT(toggleMainWindowVisibility())); connect(actionShow, SIGNAL(triggered()), this, SLOT(toggleMainWindowVisibility()));
connect(actionStart, SIGNAL(triggered()), this, SLOT(on_startButton_clicked())); connect(actionStart, SIGNAL(triggered()), this, SLOT(on_startButton_clicked()));
connect(actionStop, SIGNAL(triggered()), this, SLOT(on_stopButton_clicked())); connect(actionStop, SIGNAL(triggered()), this, SLOT(on_stopButton_clicked()));
@ -55,9 +52,9 @@ void MainWindow::CreateTrayIcon()
hTray->show(); hTray->show();
} }
MainWindow::MainWindow(QWidget *parent) : MainWindow::MainWindow(QWidget *parent)
QMainWindow(parent), : QMainWindow(parent)
ui(new Ui::MainWindow) , ui(new Ui_MainWindow)
{ {
this->setWindowIcon(QIcon(":/icons/Hv2ray.ico")); this->setWindowIcon(QIcon(":/icons/Hv2ray.ico"));
ui->setupUi(this); ui->setupUi(this);
@ -66,6 +63,7 @@ MainWindow::MainWindow(QWidget *parent) :
// connect(ui->configTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showMenu(QPoint))); // connect(ui->configTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showMenu(QPoint)));
this->vinstance = new v2Instance(this); this->vinstance = new v2Instance(this);
CreateTrayIcon(); CreateTrayIcon();
if (QFileInfo("config.json").exists()) { if (QFileInfo("config.json").exists()) {
vinstance->start(); vinstance->start();
} }
@ -125,26 +123,25 @@ void MainWindow::select_triggered()
void MainWindow::DeleteConfig() void MainWindow::DeleteConfig()
{ {
} }
void MainWindow::UpdateConfigTable() void MainWindow::UpdateConfigTable()
{ {
} }
void MainWindow::GenerateConfig(int idIntable) void MainWindow::GenerateConfig(int idIntable)
{ {
Hv2Config tmpConf; Q_UNUSED(idIntable)
emit UpdateConfigTable(); //Hv2Config tmpConf;
if (tmpConf.isCustom == 1) { //emit UpdateConfigTable();
QString src = "conf/" + QString::number(idIntable) + ".conf"; //if (tmpConf.isCustom == 1) {
overrideInbounds(src); // QString src = "conf/" + QString::number(idIntable) + ".conf";
if (QFile::exists("config.json")) { // overrideInbounds(src);
QFile::remove("config.json"); // if (QFile::exists("config.json")) {
} // QFile::remove("config.json");
QFile::copy(src, "config.json"); // }
} else { // QFile::copy(src, "config.json");
// TODO: Config generator //} else {
} // // TODO: Config generator
//}
} }
void MainWindow::UpdateLog() void MainWindow::UpdateLog()
{ {
@ -202,12 +199,16 @@ void MainWindow::on_activatedTray(QSystemTrayIcon::ActivationReason reason)
toggleMainWindowVisibility(); toggleMainWindowVisibility();
#endif #endif
break; break;
case QSystemTrayIcon::DoubleClick: case QSystemTrayIcon::DoubleClick:
if (this->isHidden()) { if (this->isHidden()) {
this->show(); this->show();
} }
break; break;
case QSystemTrayIcon::MiddleClick: case QSystemTrayIcon::MiddleClick:
// TODO: Check if an alert message box is present. // TODO: Check if an alert message box is present.
// If so, do nothing but please wait for the message box to be closed. // If so, do nothing but please wait for the message box to be closed.
if (this->vinstance->vProcess->state() == QProcess::ProcessState::Running) { if (this->vinstance->vProcess->state() == QProcess::ProcessState::Running) {
@ -215,9 +216,12 @@ void MainWindow::on_activatedTray(QSystemTrayIcon::ActivationReason reason)
} else { } else {
on_startButton_clicked(); on_startButton_clicked();
} }
break; break;
case QSystemTrayIcon::Unknown: case QSystemTrayIcon::Unknown:
break; break;
case QSystemTrayIcon::Context: case QSystemTrayIcon::Context:
break; break;
} }
@ -272,3 +276,4 @@ void MainWindow::on_pushButton_clicked()
auto confedit = new ConnectionEditWindow(); auto confedit = new ConnectionEditWindow();
confedit->show(); confedit->show();
} }
}

View File

@ -1,22 +1,20 @@
#ifndef MAINWINDOW_H #ifndef MAINWINDOW_H
#define MAINWINDOW_H #define MAINWINDOW_H
#include <QMainWindow>
#include "w_ConnectionEditWindow.h" #include "w_ConnectionEditWindow.h"
#include <QSystemTrayIcon> #include <QMainWindow>
#include <QMenu> #include <QMenu>
#include <QScrollBar> #include <QScrollBar>
#include <QSystemTrayIcon>
#include "ui_w_MainWindow.h"
#include "vinteract.h" #include "vinteract.h"
#include "Hv2ConfigObject.h"
namespace Ui namespace Hv2ray::Ui
{ {
class MainWindow;
}
class MainWindow : public QMainWindow class MainWindow : public QMainWindow
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit MainWindow(QWidget *parent = nullptr); explicit MainWindow(QWidget *parent = nullptr);
v2Instance *vinstance; v2Instance *vinstance;
@ -51,10 +49,12 @@ private slots:
void on_pushButton_clicked(); void on_pushButton_clicked();
private: private:
Ui::MainWindow *ui; Ui_MainWindow *ui;
void closeEvent(QCloseEvent *); void closeEvent(QCloseEvent *);
void createTrayAction(); void createTrayAction();
void CreateTrayIcon(); void CreateTrayIcon();
}; };
}
#endif // MAINWINDOW_H #endif // MAINWINDOW_H

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>MainWindow</class> <class>Hv2ray::Ui::MainWindow</class>
<widget class="QMainWindow" name="MainWindow"> <widget class="QMainWindow" name="Hv2ray::Ui::MainWindow">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>

View File

@ -1,42 +1,50 @@
#include <QDebug>
#include <QFile>
#include <QFileInfo>
#include <QIntValidator>
#include <QJsonArray>
#include <QJsonDocument> #include <QJsonDocument>
#include <QJsonObject> #include <QJsonObject>
#include <QFile>
#include <QDebug>
#include <QJsonArray>
#include <QJsonValue> #include <QJsonValue>
#include <QIntValidator>
#include <QFileInfo>
#include <QProcess> #include <QProcess>
#include <unistd.h>
#include <ui_w_PrefrencesWindow.h>
#include "utils.h" #include "HUtils.h"
#include "vinteract.h" #include "vinteract.h"
#include "w_PrefrencesWindow.h" #include "w_PrefrencesWindow.h"
#include <unistd.h>
PrefrencesWindow::PrefrencesWindow(QWidget *parent) : using namespace Hv2ray;
QDialog(parent), using namespace Utils;
ui(new Ui::PrefrencesWindow)
namespace Hv2ray::Ui
{
PrefrencesWindow::PrefrencesWindow(QWidget *parent)
: QDialog(parent)
, ui(new Ui_PrefrencesWindow)
{ {
ui->setupUi(this); ui->setupUi(this);
rootObj = loadRootObjFromConf(); rootObj = loadRootObjFromConf();
QJsonObject http = findValueFromJsonArray(rootObj.value("inbounds").toArray(), "tag", "http-in"); QJsonObject http = findValueFromJsonArray(rootObj.value("inbounds").toArray(), "tag", "http-in");
QJsonObject socks = findValueFromJsonArray(rootObj.value("inbounds").toArray(), "tag", "socks-in"); QJsonObject socks = findValueFromJsonArray(rootObj.value("inbounds").toArray(), "tag", "socks-in");
if (rootObj.value("v2suidEnabled").toBool()) { if (rootObj.value("v2suidEnabled").toBool()) {
ui->runAsRootCheckBox->setCheckState(Qt::Checked); ui->runAsRootCheckBox->setCheckState(Qt::Checked);
} }
if (!http.isEmpty()) { if (!http.isEmpty()) {
ui->httpPortLE->setText(http.value("port").toString()); ui->httpPortLE->setText(http.value("port").toString());
ui->httpCB->setCheckState(Qt::Checked); ui->httpCB->setCheckState(Qt::Checked);
} else { } else {
ui->httpPortLE->setDisabled(true); ui->httpPortLE->setDisabled(true);
} }
if (!socks.isEmpty()) { if (!socks.isEmpty()) {
ui->socksPortLE->setText(socks.value("port").toString()); ui->socksPortLE->setText(socks.value("port").toString());
ui->socksCB->setCheckState(Qt::Checked); ui->socksCB->setCheckState(Qt::Checked);
} else { } else {
ui->socksPortLE->setDisabled(true); ui->socksPortLE->setDisabled(true);
} }
ui->httpPortLE->setValidator(new QIntValidator()); ui->httpPortLE->setValidator(new QIntValidator());
ui->socksPortLE->setValidator(new QIntValidator()); ui->socksPortLE->setValidator(new QIntValidator());
parentMW = parent; parentMW = parent;
@ -55,15 +63,20 @@ void PrefrencesWindow::on_buttonBox_accepted()
QJsonDocument modifiedDoc; QJsonDocument modifiedDoc;
inbounds = rootObj.value("inbounds").toArray(); inbounds = rootObj.value("inbounds").toArray();
int socksId = getIndexByValue(inbounds, "tag", "socks-in"); int socksId = getIndexByValue(inbounds, "tag", "socks-in");
if (socksId != -1) { if (socksId != -1) {
inbounds.removeAt(socksId); inbounds.removeAt(socksId);
} }
int httpId = getIndexByValue(inbounds, "tag", "http-in"); int httpId = getIndexByValue(inbounds, "tag", "http-in");
if (httpId != -1) { if (httpId != -1) {
inbounds.removeAt(httpId); inbounds.removeAt(httpId);
} }
rootObj.remove("inbounds"); rootObj.remove("inbounds");
rootObj.remove("v2suidEnabled"); rootObj.remove("v2suidEnabled");
if (ui->socksCB->isChecked()) { if (ui->socksCB->isChecked()) {
QJsonObject socks; QJsonObject socks;
QJsonObject settings; QJsonObject settings;
@ -77,6 +90,7 @@ void PrefrencesWindow::on_buttonBox_accepted()
socks.insert("settings", QJsonValue(settings)); socks.insert("settings", QJsonValue(settings));
inbounds.append(socks); inbounds.append(socks);
} }
if (ui->httpCB->isChecked()) { if (ui->httpCB->isChecked()) {
QJsonObject http; QJsonObject http;
QJsonObject settings; QJsonObject settings;
@ -90,17 +104,22 @@ void PrefrencesWindow::on_buttonBox_accepted()
http.insert("settings", QJsonValue(settings)); http.insert("settings", QJsonValue(settings));
inbounds.append(http); inbounds.append(http);
} }
rootObj.insert("inbounds", QJsonValue(inbounds)); rootObj.insert("inbounds", QJsonValue(inbounds));
#ifndef _WIN32 #ifndef _WIN32
// Set UID and GID in *nix // Set UID and GID in *nix
QFileInfo v2rayCoreExeFile("v2ray"); QFileInfo v2rayCoreExeFile("v2ray");
if (ui->runAsRootCheckBox->isChecked() && v2rayCoreExeFile.ownerId() != 0) { if (ui->runAsRootCheckBox->isChecked() && v2rayCoreExeFile.ownerId() != 0) {
QProcess::execute("pkexec", QStringList() << "bash" << "-c" << "chown root:root " + QCoreApplication::applicationDirPath() + "/v2ray" + ";chmod +s " + QCoreApplication::applicationDirPath() + "/v2ray"); QProcess::execute("pkexec", QStringList() << "bash"
<< "-c"
<< "chown root:root " + QCoreApplication::applicationDirPath() + "/v2ray" + ";chmod +s " + QCoreApplication::applicationDirPath() + "/v2ray");
} else if (!ui->runAsRootCheckBox->isChecked() && v2rayCoreExeFile.ownerId() == 0) { } else if (!ui->runAsRootCheckBox->isChecked() && v2rayCoreExeFile.ownerId() == 0) {
uid_t uid = getuid(); uid_t uid = getuid();
gid_t gid = getgid(); gid_t gid = getgid();
QProcess::execute("pkexec", QStringList() << "chown" << QString::number(uid) + ":" + QString::number(gid) << QCoreApplication::applicationDirPath() + "/v2ray"); QProcess::execute("pkexec", QStringList() << "chown" << QString::number(uid) + ":" + QString::number(gid) << QCoreApplication::applicationDirPath() + "/v2ray");
} }
v2rayCoreExeFile.refresh(); v2rayCoreExeFile.refresh();
rootObj.insert("v2suidEnabled", v2rayCoreExeFile.ownerId() == 0); rootObj.insert("v2suidEnabled", v2rayCoreExeFile.ownerId() == 0);
#else #else
@ -109,10 +128,12 @@ void PrefrencesWindow::on_buttonBox_accepted()
modifiedDoc.setObject(rootObj); modifiedDoc.setObject(rootObj);
QByteArray byteArray = modifiedDoc.toJson(QJsonDocument::Indented); QByteArray byteArray = modifiedDoc.toJson(QJsonDocument::Indented);
QFile confFile("conf/Hv2ray.config.json"); QFile confFile("conf/Hv2ray.config.json");
if (!confFile.open(QIODevice::WriteOnly)) { if (!confFile.open(QIODevice::WriteOnly)) {
showWarnMessageBox(this, tr("#Prefrences"), tr("#CannotOpenConfigFile")); showWarnMessageBox(this, tr("#Prefrences"), tr("#CannotOpenConfigFile"));
qDebug() << "Cannot open Hv2ray.config.json for modifying"; qDebug() << "Cannot open Hv2ray.config.json for modifying";
} }
confFile.write(byteArray); confFile.write(byteArray);
confFile.close(); confFile.close();
} else { } else {
@ -121,7 +142,6 @@ void PrefrencesWindow::on_buttonBox_accepted()
} }
} }
void PrefrencesWindow::on_httpCB_stateChanged(int checked) void PrefrencesWindow::on_httpCB_stateChanged(int checked)
{ {
if (checked != Qt::Checked) { if (checked != Qt::Checked) {
@ -144,16 +164,15 @@ void PrefrencesWindow::on_socksCB_stateChanged(int checked)
void PrefrencesWindow::on_httpAuthCB_stateChanged(int checked) void PrefrencesWindow::on_httpAuthCB_stateChanged(int checked)
{ {
if(checked) if (checked) {
{
} }
} }
void PrefrencesWindow::on_runAsRootCheckBox_stateChanged(int arg1) void PrefrencesWindow::on_runAsRootCheckBox_stateChanged(int arg1)
{ {
Q_UNUSED(arg1); Q_UNUSED(arg1)
#ifdef _WIN32 #ifdef _WIN32
showWarnMessageBox(this, tr("Prefrences"), tr("RunAsRootNotOnWindows")); showWarnMessageBox(this, tr("Prefrences"), tr("RunAsRootNotOnWindows"));
#endif #endif
} }
}

View File

@ -2,13 +2,11 @@
#define HVCONF_H #define HVCONF_H
#include <QDialog> #include <QDialog>
#include <ui_w_PrefrencesWindow.h>
#include <QJsonObject> #include <QJsonObject>
namespace Ui namespace Hv2ray::Ui
{ {
class PrefrencesWindow;
}
class PrefrencesWindow : public QDialog class PrefrencesWindow : public QDialog
{ {
Q_OBJECT Q_OBJECT
@ -29,7 +27,7 @@ private slots:
void on_runAsRootCheckBox_stateChanged(int arg1); void on_runAsRootCheckBox_stateChanged(int arg1);
private: private:
Ui::PrefrencesWindow *ui; Ui_PrefrencesWindow *ui;
}; };
}
#endif // HVCONF_H #endif // HVCONF_H

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>PrefrencesWindow</class> <class>Hv2ray::Ui::PrefrencesWindow</class>
<widget class="QDialog" name="PrefrencesWindow"> <widget class="QDialog" name="Hv2ray::Ui::PrefrencesWindow">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
@ -345,7 +345,7 @@
<connection> <connection>
<sender>buttonBox</sender> <sender>buttonBox</sender>
<signal>accepted()</signal> <signal>accepted()</signal>
<receiver>PrefrencesWindow</receiver> <receiver>Hv2ray::Ui::PrefrencesWindow</receiver>
<slot>accept()</slot> <slot>accept()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
@ -361,7 +361,7 @@
<connection> <connection>
<sender>buttonBox</sender> <sender>buttonBox</sender>
<signal>rejected()</signal> <signal>rejected()</signal>
<receiver>PrefrencesWindow</receiver> <receiver>Hv2ray::Ui::PrefrencesWindow</receiver>
<slot>reject()</slot> <slot>reject()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff