mirror of
https://github.com/Qv2ray/Qv2ray.git
synced 2025-05-19 02:10:28 +08:00
Merge branch 'dev-mainwindow-refactor' into dev-streamsettingswidget-refactor
This commit is contained in:
commit
c9661d89aa
18
Qv2ray.pro
18
Qv2ray.pro
@ -45,7 +45,7 @@ include($$PWD/makespec/00-deps.pri)
|
||||
|
||||
# lrelease will not work when adding BEFORE 00-deps.pri
|
||||
CONFIG += lrelease embed_translations
|
||||
DEFINES += QT_DEPRECATED_WARNINGS QV2RAY_VERSION_STRING=\"\\\"v$${VERSION}\\\"\" QAPPLICATION_CLASS=QApplication
|
||||
DEFINES += QT_DEPRECATED_WARNINGS QV2RAY_VERSION_STRING=\"\\\"v$${VERSION}\\\"\" QAPPLICATION_CLASS=QApplication XTOSTRUCT_QT
|
||||
|
||||
# Source file parser
|
||||
include($$PWD/makespec/01-sourcesparser.pri)
|
||||
@ -84,18 +84,23 @@ Qv2rayAddSource(core, config, ConfigUpgrade, cpp)
|
||||
Qv2rayAddSource(core, connection, ConnectionIO, cpp, hpp)
|
||||
Qv2rayAddSource(core, connection, Generation, cpp, hpp)
|
||||
Qv2rayAddSource(core, connection, Serialization, cpp, hpp)
|
||||
Qv2rayAddSource(core, _, CoreUtils, cpp, hpp)
|
||||
Qv2rayAddSource(core, kernel, KernelInteractions, cpp, hpp)
|
||||
Qv2rayAddSource(core, kernel, APIBackend, cpp, hpp)
|
||||
Qv2rayAddSource(core, handler, ConnectionHandler, cpp, hpp)
|
||||
Qv2rayAddSource(core, handler, SubscriptionHandler, cpp)
|
||||
Qv2rayAddSource(core, handler, V2rayInstanceHandler, cpp, hpp)
|
||||
Qv2rayAddSource(core, _, CoreUtils, cpp, hpp)
|
||||
Qv2rayAddSource(core, _, CoreSafeTypes, hpp)
|
||||
Qv2rayAddSource(ui, editors, w_InboundEditor, cpp, hpp, ui)
|
||||
Qv2rayAddSource(ui, editors, w_JsonEditor, cpp, hpp, ui)
|
||||
Qv2rayAddSource(ui, editors, w_OutboundEditor, cpp, hpp, ui)
|
||||
Qv2rayAddSource(ui, editors, w_RoutesEditor, cpp, hpp, ui)
|
||||
Qv2rayAddSource(ui, editors, w_RoutesEditor_extra, cpp)
|
||||
Qv2rayAddSource(ui, nodemodels, InboundNodeModel, cpp, hpp)
|
||||
Qv2rayAddSource(ui, nodemodels, OutboundNodeModel, cpp, hpp)
|
||||
Qv2rayAddSource(ui, nodemodels, RuleNodeModel, cpp, hpp)
|
||||
Qv2rayAddSource(ui, nodemodels, NodeModelsBase, hpp)
|
||||
Qv2rayAddSource(ui, models, InboundNodeModel, cpp, hpp)
|
||||
Qv2rayAddSource(ui, models, OutboundNodeModel, cpp, hpp)
|
||||
Qv2rayAddSource(ui, models, RuleNodeModel, cpp, hpp)
|
||||
Qv2rayAddSource(ui, models, NodeModelsBase, hpp)
|
||||
Qv2rayAddSource(ui, models, ConnectionTreeModel, cpp, hpp)
|
||||
Qv2rayAddSource(ui, messaging, QvMessageBus, cpp, hpp)
|
||||
Qv2rayAddSource(ui, _, w_ExportConfig, cpp, hpp, ui)
|
||||
Qv2rayAddSource(ui, _, w_ImportConfig, cpp, hpp, ui)
|
||||
@ -104,6 +109,7 @@ Qv2rayAddSource(ui, _, w_MainWindow_extra, cpp)
|
||||
Qv2rayAddSource(ui, _, w_PreferencesWindow, cpp, hpp, ui)
|
||||
Qv2rayAddSource(ui, _, w_ScreenShot_Core, cpp, hpp, ui)
|
||||
Qv2rayAddSource(ui, _, w_SubscriptionManager, cpp, hpp, ui)
|
||||
Qv2rayAddSource(ui, widgets, ConnectionWidget, cpp, hpp, ui)
|
||||
Qv2rayAddSource(ui, widgets, StreamSettingsWidget, cpp, hpp, ui)
|
||||
|
||||
SOURCES += $$PWD/src/main.cpp
|
||||
|
@ -1 +1 @@
|
||||
3862
|
||||
3885
|
||||
|
294
qv2ray-config-models.qmodel
Normal file
294
qv2ray-config-models.qmodel
Normal file
@ -0,0 +1,294 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<qmt>
|
||||
<project>
|
||||
<uid>{e33c4c89-9b5b-44c4-9790-17cef05732d8}</uid>
|
||||
<root-package>
|
||||
<instance>
|
||||
<MPackage>
|
||||
<base-MObject>
|
||||
<MObject>
|
||||
<base-MElement>
|
||||
<MElement>
|
||||
<uid>{6035e8ea-cf65-4a95-b11b-59d640802d5e}</uid>
|
||||
</MElement>
|
||||
</base-MElement>
|
||||
<name>Qv2ray-config-models</name>
|
||||
<children>
|
||||
<handles>
|
||||
<handles>
|
||||
<qlist>
|
||||
<item>
|
||||
<handle>
|
||||
<uid>{0a303cb9-6681-4f79-9779-e61a34ac44ea}</uid>
|
||||
<target>
|
||||
<instance type="MCanvasDiagram">
|
||||
<MCanvasDiagram>
|
||||
<base-MDiagram>
|
||||
<MDiagram>
|
||||
<base-MObject>
|
||||
<MObject>
|
||||
<base-MElement>
|
||||
<MElement>
|
||||
<uid>{0a303cb9-6681-4f79-9779-e61a34ac44ea}</uid>
|
||||
</MElement>
|
||||
</base-MElement>
|
||||
<name>Qv2ray-config-models</name>
|
||||
</MObject>
|
||||
</base-MObject>
|
||||
<elements>
|
||||
<qlist>
|
||||
<item>
|
||||
<instance type="DItem">
|
||||
<DItem>
|
||||
<base-DObject>
|
||||
<DObject>
|
||||
<base-DElement>
|
||||
<DElement>
|
||||
<uid>{89aa1d96-388b-49c0-a4e6-bf55bb570889}</uid>
|
||||
</DElement>
|
||||
</base-DElement>
|
||||
<object>{314756b5-bc93-49b8-ae97-957fe8b30d44}</object>
|
||||
<name>BaseGroupObject</name>
|
||||
<pos>x:410;y:235</pos>
|
||||
<rect>x:-75;y:-50;w:150;h:100</rect>
|
||||
<auto-sized>false</auto-sized>
|
||||
<visual-role>0</visual-role>
|
||||
</DObject>
|
||||
</base-DObject>
|
||||
<shape-editable>false</shape-editable>
|
||||
</DItem>
|
||||
</instance>
|
||||
</item>
|
||||
<item>
|
||||
<instance type="DAnnotation">
|
||||
<DAnnotation>
|
||||
<base-DElement>
|
||||
<DElement>
|
||||
<uid>{7dd68311-11eb-43d0-9e64-91daeae12d97}</uid>
|
||||
</DElement>
|
||||
</base-DElement>
|
||||
<text>Display Name</text>
|
||||
<pos>x:350;y:215</pos>
|
||||
<rect>x:0;y:0;w:84.2031;h:30</rect>
|
||||
</DAnnotation>
|
||||
</instance>
|
||||
</item>
|
||||
<item>
|
||||
<instance type="DBoundary">
|
||||
<DBoundary>
|
||||
<base-DElement>
|
||||
<DElement>
|
||||
<uid>{e51a8692-6ecb-4052-8e09-f1b1ee3a2b92}</uid>
|
||||
</DElement>
|
||||
</base-DElement>
|
||||
<text>Connection Groups</text>
|
||||
<pos>x:260;y:230</pos>
|
||||
<rect>x:-235;y:-75;w:470;h:150</rect>
|
||||
</DBoundary>
|
||||
</instance>
|
||||
</item>
|
||||
<item>
|
||||
<instance type="DAnnotation">
|
||||
<DAnnotation>
|
||||
<base-DElement>
|
||||
<DElement>
|
||||
<uid>{b4dc36e8-31f6-4637-9f8f-c27ee155e301}</uid>
|
||||
</DElement>
|
||||
</base-DElement>
|
||||
<text>List<ConnectionId></text>
|
||||
<pos>x:350;y:235</pos>
|
||||
<rect>x:0;y:0;w:111.391;h:30</rect>
|
||||
</DAnnotation>
|
||||
</instance>
|
||||
</item>
|
||||
<item>
|
||||
<instance type="DBoundary">
|
||||
<DBoundary>
|
||||
<base-DElement>
|
||||
<DElement>
|
||||
<uid>{ffc9dfd5-2441-4b3b-b814-3ac76fb03c7e}</uid>
|
||||
</DElement>
|
||||
</base-DElement>
|
||||
<text>Subscriptions</text>
|
||||
<pos>x:565;y:230</pos>
|
||||
<rect>x:-240;y:-75;w:480;h:150</rect>
|
||||
</DBoundary>
|
||||
</instance>
|
||||
</item>
|
||||
<item>
|
||||
<instance type="DAnnotation">
|
||||
<DAnnotation>
|
||||
<base-DElement>
|
||||
<DElement>
|
||||
<uid>{3634dcd7-fac8-4993-b3e7-c10450dae1de}</uid>
|
||||
</DElement>
|
||||
</base-DElement>
|
||||
<text>Nothing here since the base group
|
||||
is enough</text>
|
||||
<pos>x:85;y:215</pos>
|
||||
<rect>x:0;y:0;w:186.047;h:44</rect>
|
||||
</DAnnotation>
|
||||
</instance>
|
||||
</item>
|
||||
<item>
|
||||
<instance type="DAnnotation">
|
||||
<DAnnotation>
|
||||
<base-DElement>
|
||||
<DElement>
|
||||
<uid>{41e1ca4e-8395-472f-8470-912cf2c7b9d1}</uid>
|
||||
</DElement>
|
||||
</base-DElement>
|
||||
<text>Some other metadata of subscription</text>
|
||||
<pos>x:535;y:220</pos>
|
||||
<rect>x:0;y:0;w:199.766;h:30</rect>
|
||||
</DAnnotation>
|
||||
</instance>
|
||||
</item>
|
||||
<item>
|
||||
<instance type="DItem">
|
||||
<DItem>
|
||||
<base-DObject>
|
||||
<DObject>
|
||||
<base-DElement>
|
||||
<DElement>
|
||||
<uid>{d27ab510-0eda-4d06-ac71-cd8b1d68571f}</uid>
|
||||
</DElement>
|
||||
</base-DElement>
|
||||
<object>{48b1692c-e2da-49cb-b1da-dd1030084013}</object>
|
||||
<name>Address, last-renewed......</name>
|
||||
<pos>x:610;y:205</pos>
|
||||
<rect>x:-75;y:-15;w:150;h:30</rect>
|
||||
<visual-role>0</visual-role>
|
||||
</DObject>
|
||||
</base-DObject>
|
||||
<shape-editable>false</shape-editable>
|
||||
</DItem>
|
||||
</instance>
|
||||
</item>
|
||||
</qlist>
|
||||
</elements>
|
||||
<last-modified>1581683831371</last-modified>
|
||||
<toolbarid>General</toolbarid>
|
||||
</MDiagram>
|
||||
</base-MDiagram>
|
||||
</MCanvasDiagram>
|
||||
</instance>
|
||||
</target>
|
||||
</handle>
|
||||
</item>
|
||||
<item>
|
||||
<handle>
|
||||
<uid>{314756b5-bc93-49b8-ae97-957fe8b30d44}</uid>
|
||||
<target>
|
||||
<instance type="MItem">
|
||||
<MItem>
|
||||
<base-MObject>
|
||||
<MObject>
|
||||
<base-MElement>
|
||||
<MElement>
|
||||
<uid>{314756b5-bc93-49b8-ae97-957fe8b30d44}</uid>
|
||||
</MElement>
|
||||
</base-MElement>
|
||||
<name>BaseGroupObject</name>
|
||||
</MObject>
|
||||
</base-MObject>
|
||||
</MItem>
|
||||
</instance>
|
||||
</target>
|
||||
</handle>
|
||||
</item>
|
||||
<item>
|
||||
<handle>
|
||||
<uid>{e2922977-d357-43f0-822a-624245d6b470}</uid>
|
||||
<target>
|
||||
<instance type="MItem">
|
||||
<MItem>
|
||||
<base-MObject>
|
||||
<MObject>
|
||||
<base-MElement>
|
||||
<MElement>
|
||||
<uid>{e2922977-d357-43f0-822a-624245d6b470}</uid>
|
||||
</MElement>
|
||||
</base-MElement>
|
||||
<name>New Item</name>
|
||||
</MObject>
|
||||
</base-MObject>
|
||||
</MItem>
|
||||
</instance>
|
||||
</target>
|
||||
</handle>
|
||||
</item>
|
||||
<item>
|
||||
<handle>
|
||||
<uid>{8a788e13-b40c-4a33-8121-f0a4817428b1}</uid>
|
||||
<target>
|
||||
<instance type="MItem">
|
||||
<MItem>
|
||||
<base-MObject>
|
||||
<MObject>
|
||||
<base-MElement>
|
||||
<MElement>
|
||||
<uid>{8a788e13-b40c-4a33-8121-f0a4817428b1}</uid>
|
||||
</MElement>
|
||||
</base-MElement>
|
||||
<name>Address</name>
|
||||
</MObject>
|
||||
</base-MObject>
|
||||
</MItem>
|
||||
</instance>
|
||||
</target>
|
||||
</handle>
|
||||
</item>
|
||||
<item>
|
||||
<handle>
|
||||
<uid>{ec54fd48-400e-4e7d-9e74-b6333d2101c1}</uid>
|
||||
<target>
|
||||
<instance type="MItem">
|
||||
<MItem>
|
||||
<base-MObject>
|
||||
<MObject>
|
||||
<base-MElement>
|
||||
<MElement>
|
||||
<uid>{ec54fd48-400e-4e7d-9e74-b6333d2101c1}</uid>
|
||||
</MElement>
|
||||
</base-MElement>
|
||||
<name>Some other metadata of subscription</name>
|
||||
</MObject>
|
||||
</base-MObject>
|
||||
</MItem>
|
||||
</instance>
|
||||
</target>
|
||||
</handle>
|
||||
</item>
|
||||
<item>
|
||||
<handle>
|
||||
<uid>{48b1692c-e2da-49cb-b1da-dd1030084013}</uid>
|
||||
<target>
|
||||
<instance type="MItem">
|
||||
<MItem>
|
||||
<base-MObject>
|
||||
<MObject>
|
||||
<base-MElement>
|
||||
<MElement>
|
||||
<uid>{48b1692c-e2da-49cb-b1da-dd1030084013}</uid>
|
||||
</MElement>
|
||||
</base-MElement>
|
||||
<name>Address, last-renewed......</name>
|
||||
</MObject>
|
||||
</base-MObject>
|
||||
</MItem>
|
||||
</instance>
|
||||
</target>
|
||||
</handle>
|
||||
</item>
|
||||
</qlist>
|
||||
</handles>
|
||||
</handles>
|
||||
</children>
|
||||
</MObject>
|
||||
</base-MObject>
|
||||
</MPackage>
|
||||
</instance>
|
||||
</root-package>
|
||||
</project>
|
||||
</qmt>
|
2321
qv2ray-new.qmodel
Normal file
2321
qv2ray-new.qmodel
Normal file
File diff suppressed because it is too large
Load Diff
2187
qv2ray.qmodel
Normal file
2187
qv2ray.qmodel
Normal file
File diff suppressed because it is too large
Load Diff
@ -7,11 +7,6 @@
|
||||
#include <QTranslator>
|
||||
|
||||
// Instantiation for Qv2ray global objects.
|
||||
#ifdef QT_DEBUG
|
||||
const bool isDebugBuild = true;
|
||||
#else
|
||||
const bool isDebugBuild = false;
|
||||
#endif
|
||||
|
||||
namespace Qv2ray
|
||||
{
|
||||
|
@ -44,7 +44,12 @@ using namespace Qv2ray::base::objects::transfer;
|
||||
#define QV2RAY_BUILD_INFO QString(_QV2RAY_BUILD_INFO_STR_)
|
||||
#define QV2RAY_BUILD_EXTRA_INFO QString(_QV2RAY_BUILD_EXTRA_INFO_STR_)
|
||||
|
||||
extern const bool isDebugBuild;
|
||||
#ifdef QT_DEBUG
|
||||
inline const bool isDebugBuild = true;
|
||||
#else
|
||||
inline const bool isDebugBuild = false;
|
||||
#endif
|
||||
|
||||
// Base folder suffix.
|
||||
#ifdef QT_DEBUG
|
||||
# define QV2RAY_CONFIG_DIR_SUFFIX "_debug/"
|
||||
@ -55,6 +60,7 @@ extern const bool isDebugBuild;
|
||||
// Get Configured Config Dir Path
|
||||
#define QV2RAY_CONFIG_DIR (Qv2ray::Qv2rayConfigPath)
|
||||
#define QV2RAY_CONFIG_FILE (QV2RAY_CONFIG_DIR + "Qv2ray.conf")
|
||||
#define QV2RAY_CONNECTIONS_DIR (QV2RAY_CONFIG_DIR + "connections/")
|
||||
#define QV2RAY_SUBSCRIPTION_DIR (QV2RAY_CONFIG_DIR + "subscriptions/")
|
||||
|
||||
// Get GFWList and PAC file path.
|
||||
@ -76,7 +82,7 @@ extern const bool isDebugBuild;
|
||||
#elif defined (QV2RAY_DEFAULT_VCORE_PATH) && defined (QV2RAY_DEFAULT_VASSETS_PATH)
|
||||
// ---- Using user-specified VCore and VAssets path
|
||||
#else
|
||||
# error Both QV2RAY_DEFAULT_VCORE_PATH and QV2RAY_DEFAULT_VASSETS_PATH need to present when specifying the paths.
|
||||
# error Both QV2RAY_DEFAULT_VCORE_PATH and QV2RAY_DEFAULT_VASSETS_PATH need to be presented when using manually specify the paths.
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
@ -106,7 +112,6 @@ extern const bool isDebugBuild;
|
||||
|
||||
#define QSTRN(num) QString::number(num)
|
||||
|
||||
|
||||
#define OUTBOUND_TAG_DIRECT "outBound_DIRECT"
|
||||
#define OUTBOUND_TAG_PROXY "outBound_PROXY"
|
||||
#define OUTBOUND_TAG_FORWARD_PROXY "_QV2RAY_FORWARD_PROXY_"
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include "Qv2rayLog.hpp"
|
||||
#include "GlobalInstances.hpp"
|
||||
#include "Qv2rayBase.hpp"
|
||||
|
||||
namespace Qv2ray::base
|
||||
{
|
||||
|
@ -31,21 +31,23 @@ namespace Qv2ray::base
|
||||
#define DEBUG(MODULE, MSG) __LOG_IMPL(QV2RAY_LOG_DEBUG, (MODULE), (MSG));
|
||||
|
||||
// Log modules used by Qv2ray
|
||||
const inline QString INIT = "INIT" ;
|
||||
const inline QString MESSAGING = "BASE-MESSAGING" ;
|
||||
const inline QString UI = "CORE-UI" ;
|
||||
const inline QString GRAPH = "CORE-UI-GRAPH" ;
|
||||
const inline QString SETTINGS = "CORE-SETTINGS" ;
|
||||
const inline QString VCORE = "CORE-VCORE" ;
|
||||
const inline QString MODULE_INIT = "INIT" ;
|
||||
const inline QString MODULE_MESSAGING = "BASE-MESSAGING" ;
|
||||
const inline QString MODULE_UI = "CORE-UI" ;
|
||||
const inline QString MODULE_GRAPH = "CORE-UI-GRAPH" ;
|
||||
const inline QString MODULE_SETTINGS = "CORE-SETTINGS" ;
|
||||
const inline QString MODULE_VCORE = "CORE-VCORE" ;
|
||||
//
|
||||
const inline QString CONNECTION = "CORE-CONNECTION" ;
|
||||
const inline QString SUBSCRIPTION = "CORE-SUBSCRIPTION" ;
|
||||
const inline QString IMPORT = "CORE-IMPORT" ;
|
||||
const inline QString EXPORT = "CORE-EXPORT" ;
|
||||
const inline QString MODULE_CONNECTION = "CORE-CONNECTION" ;
|
||||
const inline QString MODULE_SUBSCRIPTION = "CORE-SUBSCRIPTION" ;
|
||||
const inline QString MODULE_IMPORT = "CORE-IMPORT" ;
|
||||
const inline QString MODULE_EXPORT = "CORE-EXPORT" ;
|
||||
//
|
||||
const inline QString NETWORK = "COMMON-NETWORK" ;
|
||||
const inline QString FILEIO = "COMMON-FILEIO" ;
|
||||
const inline QString MODULE_NETWORK = "COMMON-NETWORK" ;
|
||||
const inline QString MODULE_FILEIO = "COMMON-FILEIO" ;
|
||||
//
|
||||
const inline QString PROXY = "COMPONENT-PROXY" ;
|
||||
const inline QString UPDATE = "COMPONENT-UPDATE" ;
|
||||
const inline QString PLUGIN = "COMPONENT-PLUGIN" ;
|
||||
const inline QString MODULE_PROXY = "COMPONENT-PROXY" ;
|
||||
const inline QString MODULE_UPDATE = "COMPONENT-UPDATE" ;
|
||||
const inline QString MODULE_PLUGIN = "COMPONENT-PLUGIN" ;
|
||||
// ================================================================
|
||||
const inline QString MODULE_CORE_HANDLER = "libQv2ray: ConnectionHandler";
|
||||
|
@ -4,53 +4,35 @@
|
||||
#include "3rdparty/x2struct/x2struct.hpp"
|
||||
namespace Qv2ray::base
|
||||
{
|
||||
struct ConnectionIdentifier {
|
||||
QString subscriptionName;
|
||||
QString connectionName;
|
||||
ConnectionIdentifier() { };
|
||||
bool isEmpty()
|
||||
{
|
||||
return connectionName.isEmpty();
|
||||
}
|
||||
ConnectionIdentifier(QString connectionName)
|
||||
{
|
||||
this->connectionName = connectionName;
|
||||
}
|
||||
ConnectionIdentifier(QString connectionName, QString subscriptionName)
|
||||
{
|
||||
this->connectionName = connectionName;
|
||||
this->subscriptionName = subscriptionName;
|
||||
}
|
||||
const QString IdentifierString() const
|
||||
{
|
||||
return connectionName + (subscriptionName.isEmpty() ? "" : " (" + subscriptionName + ")");
|
||||
}
|
||||
friend bool operator==(ConnectionIdentifier &left, ConnectionIdentifier &right)
|
||||
{
|
||||
return left.subscriptionName == right.subscriptionName && left.connectionName == right.connectionName;
|
||||
}
|
||||
friend bool operator!=(ConnectionIdentifier &left, ConnectionIdentifier &right)
|
||||
{
|
||||
return !(left == right);
|
||||
}
|
||||
friend bool operator==(ConnectionIdentifier &left, QString &right)
|
||||
{
|
||||
return left.IdentifierString() == right;
|
||||
}
|
||||
friend bool operator!=(ConnectionIdentifier &left, QString &right)
|
||||
{
|
||||
return !(left.IdentifierString() == right);
|
||||
}
|
||||
// To make QMap happy
|
||||
friend bool operator<(const ConnectionIdentifier left, const ConnectionIdentifier right)
|
||||
{
|
||||
return left.IdentifierString() < right.IdentifierString();
|
||||
}
|
||||
friend bool operator>(const ConnectionIdentifier left, const ConnectionIdentifier right)
|
||||
{
|
||||
return left.IdentifierString() > right.IdentifierString();
|
||||
}
|
||||
XTOSTRUCT(O(subscriptionName, connectionName))
|
||||
using namespace std::chrono;
|
||||
// Common struct for Groups and Subscriptions
|
||||
struct _QvGroupObjectBase {
|
||||
QString displayName;
|
||||
QList<QString> connections;
|
||||
_QvGroupObjectBase(): displayName(), connections() { }
|
||||
};
|
||||
|
||||
struct QvGroupObject : _QvGroupObjectBase {
|
||||
QvGroupObject() { }
|
||||
XTOSTRUCT(O(displayName, connections))
|
||||
};
|
||||
|
||||
struct QvSubscriptionObject : _QvGroupObjectBase {
|
||||
QString address;
|
||||
int64_t lastUpdated;
|
||||
float updateInterval;
|
||||
QvSubscriptionObject(): address(""), lastUpdated(system_clock::to_time_t(system_clock::now())), updateInterval(10) { }
|
||||
XTOSTRUCT(O(lastUpdated, updateInterval, address, connections, displayName))
|
||||
};
|
||||
|
||||
struct QvConnectionObject {
|
||||
QString displayName;
|
||||
int64_t importDate;
|
||||
int64_t lastConnected;
|
||||
int64_t latency;
|
||||
int64_t upLinkData;
|
||||
int64_t downLinkData;
|
||||
QvConnectionObject(): displayName(), importDate(system_clock::to_time_t(system_clock::now())), lastConnected(), latency(0), upLinkData(0), downLinkData(0) { }
|
||||
XTOSTRUCT(O(displayName, importDate, lastConnected, latency, upLinkData, downLinkData))
|
||||
};
|
||||
}
|
||||
Q_DECLARE_METATYPE(Qv2ray::base::ConnectionIdentifier);
|
||||
|
@ -4,181 +4,148 @@
|
||||
#include "base/models/QvConfigIdentifier.hpp"
|
||||
#include <chrono>
|
||||
|
||||
const int QV2RAY_CONFIG_VERSION = 8;
|
||||
const int QV2RAY_CONFIG_VERSION = 9;
|
||||
|
||||
namespace Qv2ray::base
|
||||
namespace Qv2ray::base::config
|
||||
{
|
||||
namespace config
|
||||
{
|
||||
struct QvBarLine {
|
||||
QString Family;
|
||||
bool Bold, Italic;
|
||||
int ColorA, ColorR, ColorG, ColorB;
|
||||
int ContentType;
|
||||
double Size;
|
||||
QString Message;
|
||||
QvBarLine(): Family("Consolas"), Bold(true), Italic(false), ColorA(255), ColorR(255), ColorG(255), ColorB(255),
|
||||
ContentType(0), Size(9), Message("") { }
|
||||
XTOSTRUCT(O(Bold, Italic, ColorA, ColorR, ColorG, ColorB, Size, Family, Message, ContentType))
|
||||
};
|
||||
|
||||
struct QvBarPage {
|
||||
int OffsetYpx;
|
||||
QList<QvBarLine> Lines;
|
||||
QvBarPage(): OffsetYpx(5) { }
|
||||
XTOSTRUCT(O(OffsetYpx, Lines))
|
||||
};
|
||||
|
||||
struct QvBarLine {
|
||||
QString Family;
|
||||
bool Bold;
|
||||
bool Italic;
|
||||
int ColorA;
|
||||
int ColorR;
|
||||
int ColorG;
|
||||
int ColorB;
|
||||
int ContentType;
|
||||
double Size;
|
||||
QString Message;
|
||||
QvBarLine()
|
||||
: Family("Consolas")
|
||||
, Bold(true)
|
||||
, Italic(false)
|
||||
, ColorA(255), ColorR(255), ColorG(255), ColorB(255)
|
||||
, ContentType(0)
|
||||
, Size(9),
|
||||
Message("") { }
|
||||
XTOSTRUCT(O(Bold, Italic, ColorA, ColorR, ColorG, ColorB, Size, Family, Message, ContentType))
|
||||
};
|
||||
struct Qv2rayToolBarConfig {
|
||||
QList<QvBarPage> Pages;
|
||||
XTOSTRUCT(O(Pages))
|
||||
};
|
||||
|
||||
struct QvBarPage {
|
||||
int OffsetYpx;
|
||||
QList<QvBarLine> Lines;
|
||||
QvBarPage() : OffsetYpx(5) { }
|
||||
XTOSTRUCT(O(OffsetYpx, Lines))
|
||||
};
|
||||
struct Qv2rayPACConfig {
|
||||
bool enablePAC;
|
||||
int port;
|
||||
QString localIP;
|
||||
bool useSocksProxy;
|
||||
Qv2rayPACConfig(): enablePAC(false), port(8989), useSocksProxy(false) { }
|
||||
XTOSTRUCT(O(enablePAC, port, localIP, useSocksProxy))
|
||||
};
|
||||
|
||||
struct Qv2rayToolBarConfig {
|
||||
QList<QvBarPage> Pages;
|
||||
XTOSTRUCT(O(Pages))
|
||||
};
|
||||
struct Qv2rayForwardProxyConfig {
|
||||
bool enableForwardProxy;
|
||||
QString type;
|
||||
QString serverAddress;
|
||||
int port;
|
||||
bool useAuth;
|
||||
QString username;
|
||||
QString password;
|
||||
Qv2rayForwardProxyConfig(): enableForwardProxy(false), type("http"), serverAddress("127.0.0.1"), port(8008),
|
||||
useAuth(false), username(), password() { }
|
||||
XTOSTRUCT(O(enableForwardProxy, type, serverAddress, port, useAuth, username, password))
|
||||
};
|
||||
|
||||
struct Qv2raySubscriptionConfig {
|
||||
time_t lastUpdated;
|
||||
float updateInterval;
|
||||
QString address;
|
||||
Qv2raySubscriptionConfig() : lastUpdated(std::chrono::system_clock::to_time_t(std::chrono::system_clock::now())), updateInterval(5), address("") { }
|
||||
XTOSTRUCT(O(lastUpdated, updateInterval, address))
|
||||
};
|
||||
struct Qv2rayInboundsConfig {
|
||||
QString listenip;
|
||||
bool setSystemProxy;
|
||||
Qv2rayPACConfig pacConfig;
|
||||
|
||||
struct Qv2rayPACConfig {
|
||||
bool enablePAC;
|
||||
int port;
|
||||
QString localIP;
|
||||
bool useSocksProxy;
|
||||
Qv2rayPACConfig() : enablePAC(false), port(8989), useSocksProxy(false) { }
|
||||
XTOSTRUCT(O(enablePAC, port, localIP, useSocksProxy))
|
||||
};
|
||||
// SOCKS
|
||||
bool useSocks;
|
||||
int socks_port;
|
||||
bool socks_useAuth;
|
||||
bool socksUDP;
|
||||
QString socksLocalIP;
|
||||
objects::AccountObject socksAccount;
|
||||
// HTTP
|
||||
bool useHTTP;
|
||||
int http_port;
|
||||
bool http_useAuth;
|
||||
objects::AccountObject httpAccount;
|
||||
|
||||
struct Qv2rayForwardProxyConfig {
|
||||
bool enableForwardProxy;
|
||||
QString type;
|
||||
QString serverAddress;
|
||||
int port;
|
||||
bool useAuth;
|
||||
QString username;
|
||||
QString password;
|
||||
Qv2rayInboundsConfig():
|
||||
listenip("127.0.0.1"), setSystemProxy(false), pacConfig(),
|
||||
useSocks(true), socks_port(1088), socks_useAuth(false), socksUDP(true), socksLocalIP("127.0.0.1"), socksAccount(),
|
||||
useHTTP(true), http_port(8888), http_useAuth(false), httpAccount() {}
|
||||
|
||||
Qv2rayForwardProxyConfig() :
|
||||
enableForwardProxy(false),
|
||||
type("http"), serverAddress("127.0.0.1"), port(8008), useAuth(false),
|
||||
username("username"), password("password")
|
||||
{ }
|
||||
XTOSTRUCT(O(setSystemProxy, pacConfig, listenip, useSocks, useHTTP, socks_port, socks_useAuth, socksAccount, socksUDP, socksLocalIP, http_port, http_useAuth, httpAccount))
|
||||
};
|
||||
|
||||
XTOSTRUCT(O(enableForwardProxy, type, serverAddress, port, useAuth, username, password))
|
||||
};
|
||||
struct Qv2rayUIConfig {
|
||||
QString theme;
|
||||
QString language;
|
||||
bool useDarkTheme;
|
||||
bool useDarkTrayIcon;
|
||||
int maximumLogLines;
|
||||
Qv2rayUIConfig() : theme("Fusion"), language("en_US"), useDarkTheme(false), useDarkTrayIcon(true), maximumLogLines(500) { }
|
||||
XTOSTRUCT(O(theme, language, useDarkTheme, useDarkTrayIcon, maximumLogLines))
|
||||
};
|
||||
|
||||
struct Qv2rayInboundsConfig {
|
||||
QString listenip;
|
||||
bool setSystemProxy;
|
||||
Qv2rayPACConfig pacConfig;
|
||||
struct Qv2rayConnectionConfig {
|
||||
bool bypassCN;
|
||||
bool enableProxy;
|
||||
bool withLocalDNS;
|
||||
QList<QString> dnsList;
|
||||
Qv2rayForwardProxyConfig forwardProxyConfig;
|
||||
Qv2rayConnectionConfig() : bypassCN(true), enableProxy(true), withLocalDNS(false), dnsList(QStringList() << "8.8.4.4" << "1.1.1.1") { }
|
||||
XTOSTRUCT(O(bypassCN, enableProxy, withLocalDNS, dnsList, forwardProxyConfig))
|
||||
};
|
||||
|
||||
// SOCKS
|
||||
bool useSocks;
|
||||
int socks_port;
|
||||
bool socks_useAuth;
|
||||
bool socksUDP;
|
||||
QString socksLocalIP;
|
||||
objects::AccountObject socksAccount;
|
||||
// HTTP
|
||||
bool useHTTP;
|
||||
int http_port;
|
||||
bool http_useAuth;
|
||||
objects::AccountObject httpAccount;
|
||||
struct Qv2rayAPIConfig {
|
||||
bool enableAPI;
|
||||
int statsPort;
|
||||
Qv2rayAPIConfig(): enableAPI(true), statsPort(15490) { }
|
||||
XTOSTRUCT(O(enableAPI, statsPort))
|
||||
};
|
||||
|
||||
Qv2rayInboundsConfig():
|
||||
listenip("127.0.0.1"), setSystemProxy(false), pacConfig(),
|
||||
useSocks(true), socks_port(1088), socks_useAuth(false), socksUDP(true), socksLocalIP("127.0.0.1"), socksAccount(),
|
||||
useHTTP(true), http_port(8888), http_useAuth(false), httpAccount() {}
|
||||
struct Qv2rayConfig {
|
||||
int config_version;
|
||||
bool tProxySupport;
|
||||
int logLevel;
|
||||
//
|
||||
QString v2CorePath;
|
||||
QString v2AssetsPath;
|
||||
QString ignoredVersion;
|
||||
QString autoStartId;
|
||||
//
|
||||
// Key = groupId, connectionId, subscriptionId
|
||||
QMap<QString, QvGroupObject> groups;
|
||||
QMap<QString, QvSubscriptionObject> subscriptions;
|
||||
/// Connections are used privately.
|
||||
QMap<QString, QvConnectionObject> connections;
|
||||
//
|
||||
Qv2rayUIConfig uiConfig;
|
||||
Qv2rayAPIConfig apiConfig;
|
||||
Qv2rayToolBarConfig toolBarConfig;
|
||||
Qv2rayInboundsConfig inboundConfig;
|
||||
Qv2rayConnectionConfig connectionConfig;
|
||||
|
||||
XTOSTRUCT(O(setSystemProxy, pacConfig, listenip, useSocks, useHTTP, socks_port, socks_useAuth, socksAccount, socksUDP, socksLocalIP, http_port, http_useAuth, httpAccount))
|
||||
};
|
||||
Qv2rayConfig():
|
||||
config_version(QV2RAY_CONFIG_VERSION),
|
||||
tProxySupport(false),
|
||||
logLevel(),
|
||||
v2CorePath(),
|
||||
v2AssetsPath(),
|
||||
ignoredVersion(),
|
||||
groups(),
|
||||
subscriptions(),
|
||||
connections(),
|
||||
uiConfig(), apiConfig(), toolBarConfig(), inboundConfig(), connectionConfig() { }
|
||||
|
||||
struct Qv2rayUIConfig {
|
||||
QString theme;
|
||||
QString language;
|
||||
bool useDarkTheme;
|
||||
bool useDarkTrayIcon;
|
||||
int maximumLogLines;
|
||||
Qv2rayUIConfig() : theme("Fusion"), language("en_US"), useDarkTheme(false), useDarkTrayIcon(true), maximumLogLines(500) { }
|
||||
XTOSTRUCT(O(theme, language, useDarkTheme, useDarkTrayIcon, maximumLogLines))
|
||||
};
|
||||
|
||||
struct Qv2rayConnectionConfig {
|
||||
bool bypassCN;
|
||||
bool enableProxy;
|
||||
bool withLocalDNS;
|
||||
QList<QString> dnsList;
|
||||
Qv2rayForwardProxyConfig forwardProxyConfig;
|
||||
|
||||
Qv2rayConnectionConfig() : bypassCN(true), enableProxy(true), withLocalDNS(false), dnsList(QStringList() << "8.8.4.4" << "1.1.1.1") { }
|
||||
XTOSTRUCT(O(bypassCN, enableProxy, withLocalDNS, dnsList, forwardProxyConfig))
|
||||
};
|
||||
|
||||
struct Qv2rayAPIConfig {
|
||||
bool enableAPI;
|
||||
int statsPort;
|
||||
Qv2rayAPIConfig(): enableAPI(true), statsPort(15490) { }
|
||||
XTOSTRUCT(O(enableAPI, statsPort))
|
||||
};
|
||||
|
||||
struct Qv2rayConfig {
|
||||
int config_version;
|
||||
bool tProxySupport;
|
||||
int logLevel;
|
||||
//
|
||||
QString v2CorePath;
|
||||
QString v2AssetsPath;
|
||||
ConnectionIdentifier autoStartConfig;
|
||||
QString ignoredVersion;
|
||||
//
|
||||
QList<QString> configs;
|
||||
QMap<QString, Qv2raySubscriptionConfig> subscriptions;
|
||||
//
|
||||
Qv2rayUIConfig uiConfig;
|
||||
Qv2rayAPIConfig apiConfig;
|
||||
Qv2rayInboundsConfig inboundConfig;
|
||||
Qv2rayConnectionConfig connectionConfig;
|
||||
Qv2rayToolBarConfig toolBarConfig;
|
||||
|
||||
Qv2rayConfig():
|
||||
config_version(QV2RAY_CONFIG_VERSION),
|
||||
tProxySupport(false),
|
||||
logLevel(),
|
||||
v2CorePath(),
|
||||
v2AssetsPath(),
|
||||
autoStartConfig(),
|
||||
ignoredVersion(),
|
||||
configs(),
|
||||
subscriptions(),
|
||||
uiConfig(),
|
||||
apiConfig(),
|
||||
inboundConfig(),
|
||||
connectionConfig(),
|
||||
toolBarConfig() { }
|
||||
|
||||
XTOSTRUCT(O(config_version,
|
||||
ignoredVersion,
|
||||
tProxySupport,
|
||||
logLevel,
|
||||
autoStartConfig,
|
||||
v2CorePath, v2AssetsPath,
|
||||
configs,
|
||||
uiConfig,
|
||||
subscriptions, inboundConfig, connectionConfig, toolBarConfig, apiConfig))
|
||||
};
|
||||
}
|
||||
XTOSTRUCT(O(config_version, ignoredVersion,
|
||||
tProxySupport,
|
||||
logLevel, uiConfig,
|
||||
v2CorePath, v2AssetsPath,
|
||||
groups, connections, subscriptions,
|
||||
autoStartId, inboundConfig, connectionConfig, toolBarConfig, apiConfig))
|
||||
};
|
||||
}
|
||||
|
@ -1,17 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
|
||||
#define SAFE_TYPEDEF(Base, name) \
|
||||
#define SAFE_TYPEDEF_EXTRA(Base, name, extra) \
|
||||
class name : public Base { \
|
||||
public: \
|
||||
template <class... Args> \
|
||||
explicit name (Args... args) : Base(args...) {} \
|
||||
const Base& raw() const { return *this; } \
|
||||
};
|
||||
extra };
|
||||
|
||||
#define nothing
|
||||
#define SAFE_TYPEDEF(Base, name) SAFE_TYPEDEF_EXTRA(Base, name, nothing)
|
||||
|
||||
using namespace std;
|
||||
namespace Qv2ray::base::safetype
|
||||
{
|
||||
// To prevent anonying QJsonObject misuse
|
||||
@ -22,10 +25,11 @@ namespace Qv2ray::base::safetype
|
||||
SAFE_TYPEDEF(QJsonObject, CONFIGROOT)
|
||||
SAFE_TYPEDEF(QJsonObject, PROXYSETTING)
|
||||
//
|
||||
SAFE_TYPEDEF(QJsonArray, ROUTERULELIST)
|
||||
SAFE_TYPEDEF(QJsonArray, INOUTLIST)
|
||||
SAFE_TYPEDEF(INOUTLIST, OUTBOUNDS)
|
||||
SAFE_TYPEDEF(INOUTLIST, INBOUNDS)
|
||||
SAFE_TYPEDEF(QJsonObject, ROUTING)
|
||||
SAFE_TYPEDEF(QJsonObject, ROUTERULE)
|
||||
SAFE_TYPEDEF(QJsonArray, ROUTERULELIST)
|
||||
SAFE_TYPEDEF(INOUTLIST, OUTBOUNDS)
|
||||
SAFE_TYPEDEF(INOUTLIST, INBOUNDS)
|
||||
}
|
||||
|
||||
|
@ -36,22 +36,22 @@ namespace Qv2ray::common
|
||||
return CommandLineHelpRequested;
|
||||
|
||||
if (parser.isSet(noAPIOption)) {
|
||||
DEBUG(INIT, "noAPIOption is set.")
|
||||
DEBUG(MODULE_INIT, "noAPIOption is set.")
|
||||
StartupOption.noAPI = true;
|
||||
}
|
||||
|
||||
if (parser.isSet(runAsRootOption)) {
|
||||
DEBUG(INIT, "runAsRootOption is set.")
|
||||
DEBUG(MODULE_INIT, "runAsRootOption is set.")
|
||||
StartupOption.forceRunAsRootUser = true;
|
||||
}
|
||||
|
||||
if (parser.isSet(debugOption)) {
|
||||
DEBUG(INIT, "debugOption is set.")
|
||||
DEBUG(MODULE_INIT, "debugOption is set.")
|
||||
StartupOption.debugLog = true;
|
||||
}
|
||||
|
||||
if (parser.isSet(withToolbarOption)) {
|
||||
DEBUG(INIT, "withToolbarOption is set.")
|
||||
DEBUG(MODULE_INIT, "withToolbarOption is set.")
|
||||
StartupOption.enableToolbarPlguin = true;
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ namespace Qv2ray::common
|
||||
QUrl qUrl = QUrl(url);
|
||||
|
||||
if (!qUrl.isValid()) {
|
||||
LOG(NETWORK, "Provided URL is invalid: " + url)
|
||||
LOG(MODULE_NETWORK, "Provided URL is invalid: " + url)
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -29,7 +29,7 @@ namespace Qv2ray::common
|
||||
|
||||
void QvHttpRequestHelper::setHeader(const QByteArray &key, const QByteArray &value)
|
||||
{
|
||||
DEBUG(NETWORK, "Adding HTTP request header: " + key + ":" + value)
|
||||
DEBUG(MODULE_NETWORK, "Adding HTTP request header: " + key + ":" + value)
|
||||
request.setRawHeader(key, value);
|
||||
}
|
||||
|
||||
@ -44,7 +44,7 @@ namespace Qv2ray::common
|
||||
accessManager.setProxy(QNetworkProxy(QNetworkProxy::ProxyType::NoProxy));
|
||||
}
|
||||
|
||||
LOG(NETWORK, "Sync get is using system proxy settings")
|
||||
LOG(MODULE_NETWORK, "Sync get is using system proxy settings")
|
||||
request.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy);
|
||||
reply = accessManager.get(request);
|
||||
connect(reply, &QNetworkReply::finished, this, &QvHttpRequestHelper::onRequestFinished);
|
||||
@ -104,13 +104,13 @@ namespace Qv2ray::common
|
||||
|
||||
void QvHttpRequestHelper::onRequestFinished()
|
||||
{
|
||||
LOG(NETWORK, "Network request errcode: " + QSTRN(reply->error()))
|
||||
LOG(MODULE_NETWORK, "Network request errcode: " + QSTRN(reply->error()))
|
||||
emit httpRequestFinished(this->data);
|
||||
}
|
||||
|
||||
void QvHttpRequestHelper::onReadyRead()
|
||||
{
|
||||
DEBUG(NETWORK, "A request is now ready read")
|
||||
DEBUG(MODULE_NETWORK, "A request is now ready read")
|
||||
this->data += reply->readAll();
|
||||
}
|
||||
}
|
||||
|
@ -27,8 +27,7 @@ namespace Qv2ray::common
|
||||
QString StringFromFile(QFile *source)
|
||||
{
|
||||
source->open(QFile::ReadOnly);
|
||||
QTextStream stream(source);
|
||||
QString str = stream.readAll();
|
||||
QString str = QString::fromUtf8(source->readAll());
|
||||
source->close();
|
||||
return str;
|
||||
}
|
||||
@ -73,7 +72,7 @@ namespace Qv2ray::common
|
||||
if (error.error == QJsonParseError::NoError) {
|
||||
return "";
|
||||
} else {
|
||||
LOG(UI, "WARNING: Json parse returns: " + error.errorString())
|
||||
LOG(MODULE_UI, "WARNING: Json parse returns: " + error.errorString())
|
||||
return error.errorString();
|
||||
}
|
||||
}
|
||||
@ -173,7 +172,7 @@ namespace Qv2ray::common
|
||||
|
||||
if (!QDir(baseDir).exists()) {
|
||||
QDir(baseDir).mkpath(baseDir);
|
||||
LOG(FILEIO, "Making path: " + baseDir)
|
||||
LOG(MODULE_FILEIO, "Making path: " + baseDir)
|
||||
}
|
||||
|
||||
while (true) {
|
||||
@ -181,7 +180,7 @@ namespace Qv2ray::common
|
||||
*fileName = *fileName + "_" + QSTRN(i);
|
||||
return;
|
||||
} else {
|
||||
DEBUG(FILEIO, "File with name: " + *fileName + "_" + QSTRN(i) + extension + " already exists")
|
||||
DEBUG(MODULE_FILEIO, "File with name: " + *fileName + "_" + QSTRN(i) + extension + " already exists")
|
||||
}
|
||||
|
||||
i++;
|
||||
|
@ -37,6 +37,11 @@ namespace Qv2ray::common
|
||||
// This function cannot be marked as inline.
|
||||
QString RemoveInvalidFileName(const QString &fileName);
|
||||
bool IsValidFileName(const QString &fileName);
|
||||
inline QString GenerateUuid()
|
||||
{
|
||||
return GenerateRandomString().toLower();
|
||||
//return QUuid::createUuid().toString(QUuid::WithoutBraces);
|
||||
}
|
||||
//
|
||||
template <typename TYPE>
|
||||
QString StructToJsonString(const TYPE t)
|
||||
|
@ -6,7 +6,7 @@ namespace Qv2ray::components::geosite
|
||||
QStringList ReadGeoSiteFromFile(QString filepath)
|
||||
{
|
||||
QStringList list;
|
||||
LOG(FILEIO, "Reading geosites from: " + filepath)
|
||||
LOG(MODULE_FILEIO, "Reading geosites from: " + filepath)
|
||||
//
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
//
|
||||
@ -14,7 +14,7 @@ namespace Qv2ray::components::geosite
|
||||
bool opened = f.open(QFile::OpenModeFlag::ReadOnly);
|
||||
|
||||
if (!opened) {
|
||||
LOG(FILEIO, "File cannot be opened: " + filepath)
|
||||
LOG(MODULE_FILEIO, "File cannot be opened: " + filepath)
|
||||
return list;
|
||||
}
|
||||
|
||||
@ -29,7 +29,7 @@ namespace Qv2ray::components::geosite
|
||||
list << QString::fromStdString(e.country_code()).toLower();
|
||||
}
|
||||
|
||||
LOG(FILEIO, "Loaded " + QSTRN(list.count()) + " geosite entries from data file.")
|
||||
LOG(MODULE_FILEIO, "Loaded " + QSTRN(list.count()) + " geosite entries from data file.")
|
||||
// Optional: Delete all global objects allocated by libprotobuf.
|
||||
google::protobuf::ShutdownProtobufLibrary();
|
||||
return list;
|
||||
|
@ -19,17 +19,17 @@ namespace Qv2ray::components::pac
|
||||
}
|
||||
void PACServer::SetProxyString(const QString &proxyString)
|
||||
{
|
||||
DEBUG(PROXY, "Setting new PAC proxy string: " + proxyString)
|
||||
DEBUG(MODULE_PROXY, "Setting new PAC proxy string: " + proxyString)
|
||||
this->proxyString = proxyString;
|
||||
}
|
||||
void PACServer::StartListen()
|
||||
{
|
||||
LOG(PROXY, "Starting PAC listener")
|
||||
LOG(MODULE_PROXY, "Starting PAC listener")
|
||||
//
|
||||
auto address = GlobalConfig.inboundConfig.listenip;
|
||||
auto port = GlobalConfig.inboundConfig.pacConfig.port;
|
||||
//
|
||||
DEBUG(PROXY, "PAC Listening local endpoint: " + address + ":" + QSTRN(port))
|
||||
DEBUG(MODULE_PROXY, "PAC Listening local endpoint: " + address + ":" + QSTRN(port))
|
||||
//
|
||||
QString gfwContent = StringFromFile(QV2RAY_RULES_GFWLIST_PATH);
|
||||
pacContent = ConvertGFWToPAC(gfwContent, proxyString);
|
||||
@ -38,9 +38,9 @@ namespace Qv2ray::components::pac
|
||||
|
||||
if (result) {
|
||||
isStarted = true;
|
||||
DEBUG(PROXY, "Started PAC handler")
|
||||
DEBUG(MODULE_PROXY, "Started PAC handler")
|
||||
} else {
|
||||
LOG(PROXY, "Failed to listen on port " + QSTRN(port) + ", possible permission denied.")
|
||||
LOG(MODULE_PROXY, "Failed to listen on port " + QSTRN(port) + ", possible permission denied.")
|
||||
QvMessageBoxWarn(nullptr, tr("PAC Handler"), tr("Failed to listen PAC request on this port, please verify the permissions"));
|
||||
}
|
||||
}
|
||||
@ -49,7 +49,7 @@ namespace Qv2ray::components::pac
|
||||
{
|
||||
if (isStarted) {
|
||||
pacServer.close();
|
||||
DEBUG(PROXY, "PAC Handler stopped.")
|
||||
DEBUG(MODULE_PROXY, "PAC Handler stopped.")
|
||||
isStarted = false;
|
||||
}
|
||||
}
|
||||
@ -61,12 +61,12 @@ namespace Qv2ray::components::pac
|
||||
if (req->method() == QHttpRequest::HTTP_GET) {
|
||||
//
|
||||
if (req->path() == "/pac") {
|
||||
DEBUG(PROXY, "Serving PAC file request.")
|
||||
DEBUG(MODULE_PROXY, "Serving PAC file request.")
|
||||
//
|
||||
rsp->setHeader("Content-Type", "application/javascript; charset=utf-8");
|
||||
rsp->writeHead(QHttpResponse::StatusCode::STATUS_OK);
|
||||
rsp->end(pacContent.toUtf8());
|
||||
DEBUG(PROXY, "Serving a pac file...")
|
||||
DEBUG(MODULE_PROXY, "Serving a pac file...")
|
||||
} else {
|
||||
rsp->writeHead(QHttpResponse::StatusCode::STATUS_NOT_FOUND);
|
||||
rsp->end("NOT FOUND");
|
||||
|
@ -31,13 +31,12 @@ namespace Qv2ray::components::plugins
|
||||
QString GetAnswerToRequest(const QString &pchRequest)
|
||||
{
|
||||
auto instance = MainWindow::mwInstance;
|
||||
|
||||
if (instance == nullptr || instance->vinstance == nullptr) {
|
||||
LOG(PLUGIN, "MainWindow != nullptr Assertion failed!")
|
||||
return "{}";
|
||||
}
|
||||
|
||||
auto vinstance = instance->vinstance;
|
||||
//if (instance == nullptr || instance->vinstance == nullptr) {
|
||||
// LOG(PLUGIN, "MainWindow != nullptr Assertion failed!")
|
||||
// return "{}";
|
||||
//}
|
||||
//
|
||||
//auto vinstance = instance->vinstance;
|
||||
//
|
||||
auto req = pchRequest.trimmed();
|
||||
QString reply = "{}";
|
||||
@ -81,67 +80,67 @@ namespace Qv2ray::components::plugins
|
||||
break;
|
||||
}
|
||||
|
||||
case 104: {
|
||||
// Current Connection Name
|
||||
CL.Message = instance->GetCurrentConnectedConfigName();
|
||||
break;
|
||||
}
|
||||
|
||||
case 105: {
|
||||
// Current Connection Status
|
||||
CL.Message = instance->vinstance->KernelStarted
|
||||
? QObject::tr("Connected")
|
||||
: QObject::tr("Disconnected");
|
||||
break;
|
||||
}
|
||||
|
||||
case 201: {
|
||||
// Total upload speed;
|
||||
CL.Message = FormatBytes(vinstance->getAllSpeedUp()) + "/s";
|
||||
break;
|
||||
}
|
||||
|
||||
case 202: {
|
||||
// Total download speed;
|
||||
CL.Message = FormatBytes(vinstance->getAllSpeedDown()) + "/s";
|
||||
break;
|
||||
}
|
||||
|
||||
case 203: {
|
||||
// Upload speed for tag
|
||||
CL.Message = FormatBytes(vinstance->getTagSpeedUp(CL.Message)) + "/s";
|
||||
break;
|
||||
}
|
||||
|
||||
case 204: {
|
||||
// Download speed for tag
|
||||
CL.Message = FormatBytes(vinstance->getTagSpeedDown(CL.Message)) + "/s";
|
||||
break;
|
||||
}
|
||||
|
||||
case 301: {
|
||||
// Total Upload
|
||||
CL.Message = FormatBytes(vinstance->getAllDataUp());
|
||||
break;
|
||||
}
|
||||
|
||||
case 302: {
|
||||
// Total download
|
||||
CL.Message = FormatBytes(vinstance->getAllDataDown());
|
||||
break;
|
||||
}
|
||||
|
||||
case 303: {
|
||||
// Upload for tag
|
||||
CL.Message = FormatBytes(vinstance->getTagDataUp(CL.Message));
|
||||
break;
|
||||
}
|
||||
|
||||
case 304: {
|
||||
// Download for tag
|
||||
CL.Message = FormatBytes(vinstance->getTagDataDown(CL.Message));
|
||||
break;
|
||||
}
|
||||
//case 104: {
|
||||
// // Current Connection Name
|
||||
// CL.Message = instance->GetCurrentConnectedConfigName();
|
||||
// break;
|
||||
//}
|
||||
//
|
||||
//case 105: {
|
||||
// // Current Connection Status
|
||||
// CL.Message = instance->vinstance->KernelStarted
|
||||
// ? QObject::tr("Connected")
|
||||
// : QObject::tr("Disconnected");
|
||||
// break;
|
||||
//}
|
||||
//
|
||||
//case 201: {
|
||||
// // Total upload speed;
|
||||
// CL.Message = FormatBytes(vinstance->getAllSpeedUp()) + "/s";
|
||||
// break;
|
||||
//}
|
||||
//
|
||||
//case 202: {
|
||||
// // Total download speed;
|
||||
// CL.Message = FormatBytes(vinstance->getAllSpeedDown()) + "/s";
|
||||
// break;
|
||||
//}
|
||||
//
|
||||
//case 203: {
|
||||
// // Upload speed for tag
|
||||
// CL.Message = FormatBytes(vinstance->getTagSpeedUp(CL.Message)) + "/s";
|
||||
// break;
|
||||
//}
|
||||
//
|
||||
//case 204: {
|
||||
// // Download speed for tag
|
||||
// CL.Message = FormatBytes(vinstance->getTagSpeedDown(CL.Message)) + "/s";
|
||||
// break;
|
||||
//}
|
||||
//
|
||||
//case 301: {
|
||||
// // Total Upload
|
||||
// CL.Message = FormatBytes(vinstance->getAllDataUp());
|
||||
// break;
|
||||
//}
|
||||
//
|
||||
//case 302: {
|
||||
// // Total download
|
||||
// CL.Message = FormatBytes(vinstance->getAllDataDown());
|
||||
// break;
|
||||
//}
|
||||
//
|
||||
//case 303: {
|
||||
// // Upload for tag
|
||||
// CL.Message = FormatBytes(vinstance->getTagDataUp(CL.Message));
|
||||
// break;
|
||||
//}
|
||||
//
|
||||
//case 304: {
|
||||
// // Download for tag
|
||||
// CL.Message = FormatBytes(vinstance->getTagDataDown(CL.Message));
|
||||
// break;
|
||||
//}
|
||||
|
||||
default: {
|
||||
CL.Message = "Not Supported?";
|
||||
|
@ -35,7 +35,7 @@ namespace Qv2ray::components::plugins::Toolbar
|
||||
}
|
||||
}
|
||||
} catch (...) {
|
||||
LOG(PLUGIN, "Closing a broken socket.")
|
||||
LOG(MODULE_PLUGIN, "Closing a broken socket.")
|
||||
}
|
||||
}
|
||||
void DataMessageQThread()
|
||||
@ -55,8 +55,8 @@ namespace Qv2ray::components::plugins::Toolbar
|
||||
|
||||
while (!isExiting) {
|
||||
bool result = server->waitForNewConnection(5000, &timeOut);
|
||||
DEBUG(PLUGIN, "Plugin thread listening failed: " + server->errorString())
|
||||
DEBUG(PLUGIN, "waitForNewConnection: " + QString(result ? "true" : "false") + ", " + QString(timeOut ? "true" : "false"))
|
||||
DEBUG(MODULE_PLUGIN, "Plugin thread listening failed: " + server->errorString())
|
||||
DEBUG(MODULE_PLUGIN, "waitForNewConnection: " + QString(result ? "true" : "false") + ", " + QString(timeOut ? "true" : "false"))
|
||||
}
|
||||
|
||||
server->close();
|
||||
@ -73,7 +73,7 @@ namespace Qv2ray::components::plugins::Toolbar
|
||||
isExiting = true;
|
||||
|
||||
if (linuxWorkerThread->isRunning()) {
|
||||
LOG(PLUGIN, "Waiting for linuxWorkerThread to stop.")
|
||||
LOG(MODULE_PLUGIN, "Waiting for linuxWorkerThread to stop.")
|
||||
linuxWorkerThread->wait();
|
||||
}
|
||||
|
||||
|
@ -44,18 +44,18 @@ namespace Qv2ray::components::plugins::Toolbar
|
||||
hPipe = CreateNamedPipe(lpszPipename.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, BUFSIZE, BUFSIZE, 0, nullptr);
|
||||
|
||||
if (hPipe == INVALID_HANDLE_VALUE) {
|
||||
LOG(PLUGIN, "CreateNamedPipe failed, GLE=" + QSTRN(GetLastError()))
|
||||
LOG(MODULE_PLUGIN, "CreateNamedPipe failed, GLE=" + QSTRN(GetLastError()))
|
||||
return static_cast<DWORD>(-1);
|
||||
}
|
||||
|
||||
fConnected = ConnectNamedPipe(hPipe, nullptr) ? true : (GetLastError() == ERROR_PIPE_CONNECTED);
|
||||
|
||||
if (fConnected) {
|
||||
LOG(PLUGIN, "Client connected, creating a processing thread")
|
||||
LOG(MODULE_PLUGIN, "Client connected, creating a processing thread")
|
||||
ThreadHandle = CreateThread(nullptr, 0, InstanceThread, hPipe, 0, &dwThreadId);
|
||||
|
||||
if (ThreadHandle == nullptr) {
|
||||
LOG(PLUGIN, "CreateThread failed, GLE=" + QSTRN(GetLastError()))
|
||||
LOG(MODULE_PLUGIN, "CreateThread failed, GLE=" + QSTRN(GetLastError()))
|
||||
return static_cast<DWORD>(-1);
|
||||
} else CloseHandle(ThreadHandle);
|
||||
} else CloseHandle(hPipe);
|
||||
@ -76,9 +76,9 @@ namespace Qv2ray::components::plugins::Toolbar
|
||||
|
||||
if (!fSuccess || cbBytesRead == 0) {
|
||||
if (GetLastError() == ERROR_BROKEN_PIPE) {
|
||||
LOG(PLUGIN, "InstanceThread: client disconnected, GLE=" + QSTRN(GetLastError()))
|
||||
LOG(MODULE_PLUGIN, "InstanceThread: client disconnected, GLE=" + QSTRN(GetLastError()))
|
||||
} else {
|
||||
LOG(PLUGIN, "InstanceThread ReadFile failed, GLE=" + QSTRN(GetLastError()))
|
||||
LOG(MODULE_PLUGIN, "InstanceThread ReadFile failed, GLE=" + QSTRN(GetLastError()))
|
||||
}
|
||||
|
||||
break;
|
||||
@ -98,7 +98,7 @@ namespace Qv2ray::components::plugins::Toolbar
|
||||
fSuccess = WriteFile(hPipe, pchReply.c_str(), cbReplyBytes, &cbWritten, nullptr);
|
||||
|
||||
if (!fSuccess || cbReplyBytes != cbWritten) {
|
||||
LOG(PLUGIN, "InstanceThread WriteFile failed, GLE=" + QSTRN(GetLastError()))
|
||||
LOG(MODULE_PLUGIN, "InstanceThread WriteFile failed, GLE=" + QSTRN(GetLastError()))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -174,19 +174,19 @@ namespace Qv2ray::components::proxy
|
||||
bool hasSOCKS = (socksPort != 0);
|
||||
|
||||
if (!(hasHTTP || hasSOCKS || usePAC)) {
|
||||
LOG(PROXY, "Nothing?")
|
||||
LOG(MODULE_PROXY, "Nothing?")
|
||||
return;
|
||||
}
|
||||
|
||||
if (usePAC) {
|
||||
LOG(PROXY, "Qv2ray will set system proxy to use PAC file")
|
||||
LOG(MODULE_PROXY, "Qv2ray will set system proxy to use PAC file")
|
||||
} else {
|
||||
if (hasHTTP) {
|
||||
LOG(PROXY, "Qv2ray will set system proxy to use HTTP")
|
||||
LOG(MODULE_PROXY, "Qv2ray will set system proxy to use HTTP")
|
||||
}
|
||||
|
||||
if (hasSOCKS) {
|
||||
LOG(PROXY, "Qv2ray will set system proxy to use SOCKS")
|
||||
LOG(MODULE_PROXY, "Qv2ray will set system proxy to use SOCKS")
|
||||
}
|
||||
}
|
||||
|
||||
@ -235,13 +235,13 @@ namespace Qv2ray::components::proxy
|
||||
// note: do not use std::all_of / any_of / none_of,
|
||||
// because those are short-circuit and cannot guarantee atomicity.
|
||||
auto result = std::count_if(actions.cbegin(), actions.cend(), [](const QString & action) {
|
||||
DEBUG(PROXY, action)
|
||||
DEBUG(MODULE_PROXY, action)
|
||||
return QProcess::execute(action) == QProcess::NormalExit;
|
||||
}) == actions.size();
|
||||
|
||||
if (!result) {
|
||||
LOG(PROXY, "Something wrong happens when setting system proxy -> Gnome ONLY.")
|
||||
LOG(PROXY, "If you are using KDE Plasma and receiving this message, just simply ignore this.")
|
||||
LOG(MODULE_PROXY, "Something wrong happens when setting system proxy -> Gnome ONLY.")
|
||||
LOG(MODULE_PROXY, "If you are using KDE Plasma and receiving this message, just simply ignore this.")
|
||||
}
|
||||
|
||||
Q_UNUSED(result);
|
||||
|
@ -27,23 +27,23 @@ namespace Qv2ray::components::tcping
|
||||
worker->cancel();
|
||||
}
|
||||
}
|
||||
void QvTCPingModel::StartPing(const ConnectionIdentifier &connectionName, const QString &hostName, int port)
|
||||
void QvTCPingModel::StartPing(const QvConnectionObject &connectionName, const QString &hostName, int port)
|
||||
{
|
||||
QvTCPingData data;
|
||||
data.hostName = hostName;
|
||||
data.port = port;
|
||||
data.connectionIdentifier = connectionName;
|
||||
auto watcher = new QFutureWatcher<QvTCPingData>(this);
|
||||
DEBUG(NETWORK, "Start Ping: " + hostName + ":" + QSTRN(port))
|
||||
DEBUG(MODULE_NETWORK, "Start Ping: " + hostName + ":" + QSTRN(port))
|
||||
watcher->setFuture(QtConcurrent::run(&QvTCPingModel::startTestLatency, data, count));
|
||||
pingWorkingThreads.enqueue(watcher);
|
||||
connect(watcher, &QFutureWatcher<void>::finished, this, [this, watcher]() {
|
||||
this->pingWorkingThreads.removeOne(watcher);
|
||||
auto result = watcher->result();
|
||||
DEBUG(NETWORK, "Ping finished: " + result.hostName + ":" + QSTRN(result.port) + " --> " + QSTRN(result.avg) + "ms")
|
||||
DEBUG(MODULE_NETWORK, "Ping finished: " + result.hostName + ":" + QSTRN(result.port) + " --> " + QSTRN(result.avg) + "ms")
|
||||
|
||||
if (!result.errorMessage.isEmpty()) {
|
||||
LOG(NETWORK, "Ping --> " + result.errorMessage)
|
||||
LOG(MODULE_NETWORK, "Ping --> " + result.errorMessage)
|
||||
}
|
||||
|
||||
emit this->PingFinished(result);
|
||||
@ -78,13 +78,13 @@ namespace Qv2ray::components::tcping
|
||||
|
||||
if ((errcode = testLatency(resolved, &start, &end)) != 0) {
|
||||
if (errcode != -EADDRNOTAVAIL) {
|
||||
LOG(NETWORK, "Error connecting to host: " + data.hostName + ":" + QSTRN(data.port) + " " + strerror(-errcode))
|
||||
LOG(MODULE_NETWORK, "Error connecting to host: " + data.hostName + ":" + QSTRN(data.port) + " " + strerror(-errcode))
|
||||
errorCount++;
|
||||
} else {
|
||||
if (noAddress) {
|
||||
LOG(NETWORK, ".")
|
||||
LOG(MODULE_NETWORK, ".")
|
||||
} else {
|
||||
LOG(NETWORK, "error connecting to host: " + QSTRN(-errcode) + " " + strerror(-errcode))
|
||||
LOG(MODULE_NETWORK, "error connecting to host: " + QSTRN(-errcode) + " " + strerror(-errcode))
|
||||
}
|
||||
|
||||
noAddress = true;
|
||||
|
@ -5,7 +5,7 @@
|
||||
namespace Qv2ray::components::tcping
|
||||
{
|
||||
struct QvTCPingData {
|
||||
ConnectionIdentifier connectionIdentifier;
|
||||
QvConnectionObject connectionIdentifier;
|
||||
QString hostName;
|
||||
int port;
|
||||
QString errorMessage;
|
||||
@ -19,7 +19,7 @@ namespace Qv2ray::components::tcping
|
||||
|
||||
public:
|
||||
explicit QvTCPingModel(int defaultCount = 5, QObject *parent = nullptr);
|
||||
void StartPing(const ConnectionIdentifier &connectionName, const QString &hostName, int port);
|
||||
void StartPing(const QvConnectionObject &connectionName, const QString &hostName, int port);
|
||||
void StopAllPing();
|
||||
signals:
|
||||
void PingFinished(QvTCPingData data);
|
||||
|
43
src/core/CoreSafeTypes.hpp
Normal file
43
src/core/CoreSafeTypes.hpp
Normal file
@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
#include <QHash>
|
||||
#include <QHashFunctions>
|
||||
|
||||
namespace Qv2ray::core
|
||||
{
|
||||
template <typename T>
|
||||
class IDType
|
||||
{
|
||||
public:
|
||||
IDType(const QString &id): m_id(id) {}
|
||||
friend bool operator==(const IDType<T> &lhs, const IDType<T> &rhs)
|
||||
{
|
||||
return lhs.m_id == rhs.m_id;
|
||||
}
|
||||
const QString &toString() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
uint qHash(uint seed) const
|
||||
{
|
||||
return ::qHash(m_id, seed);
|
||||
}
|
||||
private:
|
||||
QString m_id;
|
||||
};
|
||||
|
||||
template <typename T> uint qHash(const IDType<T> &key, uint seed = 0)
|
||||
{
|
||||
return key.qHash(seed);
|
||||
}
|
||||
//
|
||||
class __QvGroup;
|
||||
class __QvConnection;
|
||||
class __QvSubscription;
|
||||
typedef IDType<__QvGroup> GroupId;
|
||||
typedef IDType<__QvConnection> ConnectionId;
|
||||
typedef IDType<__QvSubscription> SubscriptionId;
|
||||
}
|
||||
|
||||
using namespace Qv2ray::core;
|
@ -18,7 +18,7 @@ namespace Qv2ray::core
|
||||
if (validOutboundFound) {
|
||||
return make_tuple(host, port, outboundType);
|
||||
} else {
|
||||
LOG(UI, "Unknown outbound entry: " + outboundType + ", cannot deduce host and port.")
|
||||
LOG(MODULE_UI, "Unknown outbound entry: " + outboundType + ", cannot deduce host and port.")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
namespace Qv2ray::core::config
|
||||
{
|
||||
void SaveGlobalConfig(Qv2rayConfig conf)
|
||||
void SaveGlobalConfig(const Qv2rayConfig &conf)
|
||||
{
|
||||
GlobalConfig = conf;
|
||||
QFile config(QV2RAY_CONFIG_FILE);
|
||||
@ -19,17 +19,6 @@ namespace Qv2ray::core::config
|
||||
Qv2rayConfigPath += "/";
|
||||
}
|
||||
}
|
||||
|
||||
void LoadGlobalConfig()
|
||||
{
|
||||
QFile file(QV2RAY_CONFIG_FILE);
|
||||
file.open(QFile::ReadOnly);
|
||||
QTextStream stream(&file);
|
||||
auto str = stream.readAll();
|
||||
auto config = StructFromJsonString<Qv2rayConfig>(str);
|
||||
SaveGlobalConfig(config);
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
|
||||
using namespace Qv2ray::core::config;
|
||||
|
@ -2,9 +2,8 @@
|
||||
|
||||
namespace Qv2ray::core::config
|
||||
{
|
||||
void SaveGlobalConfig(Qv2rayConfig conf);
|
||||
void SaveGlobalConfig(const Qv2rayConfig &conf);
|
||||
void SetConfigDirPath(const QString &path);
|
||||
void LoadGlobalConfig();
|
||||
}
|
||||
|
||||
using namespace Qv2ray::core;
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include "base/Qv2rayBase.hpp"
|
||||
#include "common/QvHelpers.hpp"
|
||||
|
||||
#define UPDATELOG(msg) LOG(SETTINGS, " [" + QSTRN(fromVersion) + "-" + QSTRN(fromVersion + 1) + "] --> " + msg)
|
||||
#define UPGRADELOG(msg) LOG(MODULE_SETTINGS, " [" + QSTRN(fromVersion) + "-" + QSTRN(fromVersion + 1) + "] --> " + msg)
|
||||
|
||||
namespace Qv2ray
|
||||
{
|
||||
@ -14,45 +14,6 @@ namespace Qv2ray
|
||||
QJsonObject UpgradeConfig_Inc(int fromVersion, QJsonObject root)
|
||||
{
|
||||
switch (fromVersion) {
|
||||
case 1: {
|
||||
auto v1_oldConfigVersion = root["config_version"].toString();
|
||||
// From 1 to 2, we changed the config_version from 'string' to 'int'
|
||||
root.remove("config_version");
|
||||
root["config_version"] = 2;
|
||||
UPDATELOG("Upgrading config_version from old value " + v1_oldConfigVersion + " to 2")
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: {
|
||||
// We copied those files.
|
||||
auto vCoreFilePath = root["v2CorePath"].toString();
|
||||
auto vCoreDestPath = QString(QV2RAY_DEFAULT_VCORE_PATH);
|
||||
// We also need v2ctl
|
||||
auto v2CtlFilePath = QFileInfo(vCoreFilePath).dir().path() + "/v2ctl";
|
||||
auto v2CtlDestPath = QFileInfo(vCoreDestPath).dir().path() + "/v2ctl";
|
||||
#ifdef Q_OS_WIN
|
||||
v2CtlFilePath = v2CtlFilePath.append(".exe");
|
||||
v2CtlDestPath = v2CtlDestPath.append(".exe");
|
||||
#endif
|
||||
QFile::copy(vCoreFilePath, vCoreDestPath);
|
||||
QFile::copy(v2CtlFilePath, v2CtlDestPath);
|
||||
root.remove("v2CorePath");
|
||||
UPDATELOG("v2CorePath value from: " + vCoreFilePath + " to " + vCoreDestPath)
|
||||
UPDATELOG("v2CtlFilePath value from: " + v2CtlFilePath + " to " + v2CtlDestPath)
|
||||
break;
|
||||
}
|
||||
|
||||
case 3: {
|
||||
// We changed a key name in the config file.
|
||||
//proxyDefault
|
||||
auto oldProxyDefault = root["proxyDefault"].toBool();
|
||||
root.remove("proxyDefault");
|
||||
root["enableProxy"] = oldProxyDefault;
|
||||
//enableProxy
|
||||
UPDATELOG("key: proxyDefault->enableProxy, value from: " + QSTRN(oldProxyDefault) + " to " + QSTRN(oldProxyDefault))
|
||||
break;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Below is for Qv2ray version 2
|
||||
case 4: {
|
||||
@ -62,12 +23,12 @@ namespace Qv2ray
|
||||
// From 3 to 4, we changed 'runAsRoot' to 'tProxySupport'
|
||||
auto v3_oldrunAsRoot = root["runAsRoot"].toBool();
|
||||
root.insert("tProxySupport", v3_oldrunAsRoot);
|
||||
UPDATELOG("Upgrading runAsRoot to tProxySupport, the value is not changed: " + QSTRN(v3_oldrunAsRoot))
|
||||
UPGRADELOG("Upgrading runAsRoot to tProxySupport, the value is not changed: " + QSTRN(v3_oldrunAsRoot))
|
||||
//
|
||||
QString path;
|
||||
path = QV2RAY_DEFAULT_VCORE_PATH;
|
||||
root["v2CorePath"] = path;
|
||||
UPDATELOG("Added v2CorePath to the config file.")
|
||||
UPGRADELOG("Added v2CorePath to the config file.")
|
||||
//
|
||||
QJsonObject uiSettings;
|
||||
uiSettings["language"] = root["language"].toString("en-US").replace("-", "_");
|
||||
@ -75,7 +36,7 @@ namespace Qv2ray
|
||||
//
|
||||
root["inboundConfig"] = root["inBoundSettings"];
|
||||
root.remove("inBoundSettings");
|
||||
UPDATELOG("Renamed inBoundSettings to inboundConfig.")
|
||||
UPGRADELOG("Renamed inBoundSettings to inboundConfig.")
|
||||
//
|
||||
//connectionConfig
|
||||
QJsonObject o;
|
||||
@ -85,9 +46,9 @@ namespace Qv2ray
|
||||
o["bypassCN"] = !v2_oldProxyCN;
|
||||
o["enableStats"] = true;
|
||||
o["statsPort"] = 13459;
|
||||
UPDATELOG("Default statistics enabled.")
|
||||
UPGRADELOG("Default statistics enabled.")
|
||||
root["connectionConfig"] = o;
|
||||
UPDATELOG("Renamed some connection configs to connectionConfig.")
|
||||
UPGRADELOG("Renamed some connection configs to connectionConfig.")
|
||||
//
|
||||
// Do we need renaming here?
|
||||
// //auto inbound = root["inboundConfig"].toObject();
|
||||
@ -97,10 +58,10 @@ namespace Qv2ray
|
||||
// //root["inboundConfig"] = inbound;
|
||||
// //UPDATELOG("Renamed usePAC to enablePAC.")
|
||||
//
|
||||
ConnectionIdentifier i;
|
||||
i.connectionName = root["autoStartConfig"].toString();
|
||||
root["autoStartConfig"] = GetRootObject(i);
|
||||
UPDATELOG("Added subscription feature to autoStartConfig.")
|
||||
QJsonObject i;
|
||||
i["connectionName"] = root["autoStartConfig"].toString();
|
||||
root["autoStartConfig"] = i;
|
||||
UPGRADELOG("Added subscription feature to autoStartConfig.")
|
||||
break;
|
||||
}
|
||||
|
||||
@ -113,7 +74,7 @@ namespace Qv2ray
|
||||
|
||||
for (auto item = subs.begin(); item != subs.end(); item++) {
|
||||
auto key = item.key();
|
||||
Qv2raySubscriptionConfig _conf;
|
||||
QvSubscriptionObject _conf;
|
||||
_conf.address = item.value().toString();
|
||||
_conf.lastUpdated = system_clock::to_time_t(system_clock::now());
|
||||
_conf.updateInterval = 5;
|
||||
@ -122,7 +83,7 @@ namespace Qv2ray
|
||||
}
|
||||
|
||||
root["subscriptions"] = newSubscriptions;
|
||||
UPDATELOG("Added subscription renewal options.")
|
||||
UPGRADELOG("Added subscription renewal options.")
|
||||
break;
|
||||
}
|
||||
|
||||
@ -141,9 +102,118 @@ namespace Qv2ray
|
||||
auto uiConfig = root["uiConfig"].toObject();
|
||||
uiConfig["language"] = lang;
|
||||
root["uiConfig"] = uiConfig;
|
||||
UPDATELOG("Changed language: " + lang)
|
||||
UPGRADELOG("Changed language: " + lang)
|
||||
break;
|
||||
}
|
||||
|
||||
// From version 8 to 9, we introduced a lot of new connection metainfo(s)
|
||||
case 8: {
|
||||
// Generate a default group
|
||||
QJsonObject defaultGroup;
|
||||
QStringList defaultGroupConnectionId;
|
||||
defaultGroup["displayName"] = QObject::tr("Default Group");
|
||||
QString defaultGroupId = "000000000000";
|
||||
|
||||
if (!QDir(QV2RAY_CONNECTIONS_DIR + defaultGroupId).exists()) {
|
||||
QDir().mkpath(QV2RAY_CONNECTIONS_DIR + defaultGroupId);
|
||||
}
|
||||
|
||||
QString autoStartId;
|
||||
UPGRADELOG("Upgrading connections...")
|
||||
QJsonObject rootConnections;
|
||||
|
||||
for (auto config : root["configs"].toArray()) {
|
||||
UPGRADELOG("Migrating: " + config.toString())
|
||||
//
|
||||
// MOVE FILES.
|
||||
// OLD PATH is at QV2RAY_CONFIG_DIR
|
||||
auto filePath = QV2RAY_CONFIG_DIR + config.toString() + QV2RAY_CONFIG_FILE_EXTENSION;
|
||||
auto configFile = QFile(filePath);
|
||||
auto newUuid = GenerateUuid();
|
||||
DEBUG(MODULE_SETTINGS, "Generated new UUID: " + newUuid);
|
||||
|
||||
if (configFile.exists()) {
|
||||
auto newPath = QV2RAY_CONNECTIONS_DIR + defaultGroupId + "/" + newUuid + QV2RAY_CONFIG_FILE_EXTENSION;
|
||||
configFile.rename(newPath);
|
||||
UPGRADELOG("Moved: " + filePath + " to " + newPath);
|
||||
} else {
|
||||
UPGRADELOG("WARNING! This file is not found, possible loss of data!")
|
||||
continue;
|
||||
}
|
||||
|
||||
QJsonObject connectionObject;
|
||||
connectionObject["displayName"] = config.toString();
|
||||
defaultGroupConnectionId << newUuid;
|
||||
DEBUG(MODULE_SETTINGS, "Pushed uuid: " + newUuid + " to default group.")
|
||||
rootConnections[newUuid] = connectionObject;
|
||||
}
|
||||
|
||||
// Upgrading subscriptions.
|
||||
QJsonObject rootSubscriptions = root.take("subscriptions").toObject();
|
||||
QJsonObject newSubscriptions;
|
||||
|
||||
for (auto i = 0; i < rootSubscriptions.count(); i++) {
|
||||
auto key = rootSubscriptions.keys()[i];
|
||||
auto value = rootSubscriptions.value(key);
|
||||
//
|
||||
UPGRADELOG("Upgrading subscription: " + key)
|
||||
QString subsUuid = GenerateUuid();
|
||||
QJsonObject subs;
|
||||
QStringList subsConnectionIds;
|
||||
subs["address"] = value["address"].toString();
|
||||
subs["lastUpdated"] = value["lastUpdated"];
|
||||
subs["updateInterval"] = value["updateInterval"];
|
||||
subs["displayName"] = key;
|
||||
//
|
||||
auto baseDirPath = QV2RAY_SUBSCRIPTION_DIR + key;
|
||||
auto newDirPath = QV2RAY_SUBSCRIPTION_DIR + subsUuid;
|
||||
QDir newDir(newDirPath);
|
||||
|
||||
if (!newDir.exists()) {
|
||||
newDir.mkpath(newDirPath);
|
||||
}
|
||||
|
||||
// With extensions
|
||||
auto fileList = GetFileList(baseDirPath);
|
||||
|
||||
// Copy every file within a subscription.
|
||||
for (auto fileName : fileList) {
|
||||
auto subsConnectionId = GenerateUuid();
|
||||
auto baseFilePath = baseDirPath + "/" + fileName;
|
||||
auto newFilePath = newDirPath + "/" + subsConnectionId + QV2RAY_CONFIG_FILE_EXTENSION;
|
||||
//
|
||||
QJsonObject subsConnection;
|
||||
subsConnection["displayName"] = fileName.chopped(QString(QV2RAY_CONFIG_FILE_EXTENSION).count());
|
||||
QFile(baseFilePath).rename(newFilePath);
|
||||
UPGRADELOG("Moved subscription file from: " + baseFilePath + " to: " + newFilePath);
|
||||
subsConnectionIds << subsConnectionId;
|
||||
rootConnections[subsConnectionId] = subsConnection;
|
||||
}
|
||||
|
||||
subs["connections"] = QJsonArray::fromStringList(subsConnectionIds);
|
||||
newSubscriptions[subsUuid] = subs;
|
||||
QDir().rmdir(baseDirPath);
|
||||
}
|
||||
|
||||
defaultGroup["connections"] = QJsonArray::fromStringList(defaultGroupConnectionId);
|
||||
QJsonObject groups;
|
||||
groups[defaultGroupId] = defaultGroup;
|
||||
root["groups"] = groups;
|
||||
root["connections"] = rootConnections;
|
||||
root["subscriptions"] = newSubscriptions;
|
||||
UPGRADELOG("Finished upgrading config, version 8.")
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
// Due to technical issue, we cannot maintain all of those upgrade processes anymore.
|
||||
// Check https://github.com/Qv2ray/Qv2ray/issues/353#issuecomment-586117507 for more information
|
||||
QvMessageBoxWarn(nullptr, QObject::tr("Configuration Upgrade Failed"),
|
||||
QObject::tr("Unsupported config version number: ") + QSTRN(fromVersion) + NEWLINE + NEWLINE +
|
||||
QObject::tr("Please upgrade firstly up to Qv2ray v2.0/v2.1 and try again."));
|
||||
throw new runtime_error("The configuration version of your old Qv2ray installation is out-of-date and that"
|
||||
" version is not supported anymore, please try to update to an intermediate version of Qv2ray first.");
|
||||
}
|
||||
}
|
||||
|
||||
root["config_version"] = root["config_version"].toInt() + 1;
|
||||
@ -153,7 +223,7 @@ namespace Qv2ray
|
||||
// Exported function
|
||||
QJsonObject UpgradeConfig(int fromVersion, int toVersion, QJsonObject root)
|
||||
{
|
||||
LOG(SETTINGS, "Migrating config from version " + QSTRN(fromVersion) + " to " + QSTRN(toVersion))
|
||||
LOG(MODULE_SETTINGS, "Migrating config from version " + QSTRN(fromVersion) + " to " + QSTRN(toVersion))
|
||||
|
||||
for (int i = fromVersion; i < toVersion; i++) {
|
||||
root = UpgradeConfig_Inc(i, root);
|
||||
|
@ -5,170 +5,132 @@ namespace Qv2ray::core::connection
|
||||
{
|
||||
namespace ConnectionIO
|
||||
{
|
||||
CONFIGROOT _ReadConnection(const QString &connection)
|
||||
CONFIGROOT ReadConnectionInternal(const QString &connection)
|
||||
{
|
||||
QString jsonString = StringFromFile(connection);
|
||||
auto conf = CONFIGROOT(JsonFromString(jsonString));
|
||||
|
||||
if (conf.count() == 0) {
|
||||
LOG(SETTINGS, "WARN: Possible file corruption, failed to load file: " + connection + " --> File might be empty.")
|
||||
LOG(MODULE_SETTINGS, "WARN: Possible file corruption, failed to load file: " + connection + " --> File might be empty.")
|
||||
}
|
||||
|
||||
return conf;
|
||||
}
|
||||
|
||||
QMap<QString, CONFIGROOT> GetRegularConnections(QStringList connectionNames)
|
||||
CONFIGROOT GetConnectionRoot(const GroupId &group, const ConnectionId &id)
|
||||
{
|
||||
QMap<QString, CONFIGROOT> list;
|
||||
|
||||
for (auto conn : connectionNames) {
|
||||
list.insert(conn, _ReadConnection(QV2RAY_CONFIG_DIR + conn + QV2RAY_CONFIG_FILE_EXTENSION));
|
||||
}
|
||||
|
||||
return list;
|
||||
return ReadConnectionInternal(QV2RAY_CONNECTIONS_DIR + group.toString() + "/" + id.toString() + QV2RAY_CONFIG_FILE_EXTENSION);
|
||||
}
|
||||
|
||||
QMap<QString, CONFIGROOT> GetSubscriptionConnection(QString subscription)
|
||||
CONFIGROOT GetConnectionRoot(const SubscriptionId &subscription, const ConnectionId &id)
|
||||
{
|
||||
auto _files = GetFileList(QV2RAY_SUBSCRIPTION_DIR + subscription);
|
||||
QMap<QString, CONFIGROOT> _config;
|
||||
|
||||
for (auto _file : _files) {
|
||||
// check if is proper connection file.
|
||||
if (_file.endsWith(QV2RAY_CONFIG_FILE_EXTENSION)) {
|
||||
auto confName = _file;
|
||||
// Remove the extension
|
||||
confName.chop(sizeof(QV2RAY_CONFIG_FILE_EXTENSION) - 1);
|
||||
_config[confName] = _ReadConnection(QV2RAY_SUBSCRIPTION_DIR + subscription + "/" + _file);
|
||||
} else {
|
||||
LOG(SUBSCRIPTION, "Found a file in subscription folder but without proper suffix: " + _file)
|
||||
}
|
||||
}
|
||||
|
||||
if (_config.isEmpty()) {
|
||||
LOG(SUBSCRIPTION, "WARN: Maybe loading an empty subscrption: " + subscription)
|
||||
}
|
||||
|
||||
return _config;
|
||||
}
|
||||
|
||||
QMap<QString, QMap<QString, CONFIGROOT>> GetSubscriptionConnections(QStringList subscriptions)
|
||||
{
|
||||
// SUB-NAME CONN-NAME CONN-ROOT
|
||||
QMap<QString, QMap<QString, CONFIGROOT>> list;
|
||||
|
||||
for (auto singleSub : subscriptions) {
|
||||
LOG(SUBSCRIPTION, "Processing subscription: " + singleSub)
|
||||
list[singleSub] = GetSubscriptionConnection(singleSub);
|
||||
}
|
||||
|
||||
return list;
|
||||
return ReadConnectionInternal(QV2RAY_SUBSCRIPTION_DIR + subscription.toString() + "/" + id.toString() + QV2RAY_CONFIG_FILE_EXTENSION);
|
||||
}
|
||||
|
||||
////
|
||||
//// Save Connection to a place, with checking if there's existing file.
|
||||
//// If so, append "_N" to the name.
|
||||
//bool SaveConnectionConfig(CONFIGROOT obj, QString *alias, bool canOverrideExisting)
|
||||
//{
|
||||
// auto str = JsonToString(obj);
|
||||
// auto fullPath = QV2RAY_CONFIG_DIR + *alias + QV2RAY_CONFIG_FILE_EXTENSION;
|
||||
//
|
||||
// Save Connection to a place, with checking if there's existing file.
|
||||
// If so, append "_N" to the name.
|
||||
bool SaveConnectionConfig(CONFIGROOT obj, QString *alias, bool canOverrideExisting)
|
||||
{
|
||||
auto str = JsonToString(obj);
|
||||
auto fullPath = QV2RAY_CONFIG_DIR + *alias + QV2RAY_CONFIG_FILE_EXTENSION;
|
||||
|
||||
// If there's already a file AND we CANNOT override existing file.
|
||||
if (QFile::exists(fullPath) && !canOverrideExisting) {
|
||||
// Alias is a pointer to a QString.
|
||||
DeducePossibleFileName(QV2RAY_CONFIG_DIR, alias, QV2RAY_CONFIG_FILE_EXTENSION);
|
||||
fullPath = QV2RAY_CONFIG_DIR + *alias + QV2RAY_CONFIG_FILE_EXTENSION;
|
||||
}
|
||||
|
||||
LOG(SETTINGS, "Saving a config named: " + *alias)
|
||||
QFile config(fullPath);
|
||||
return StringToFile(&str, &config);
|
||||
}
|
||||
|
||||
bool SaveSubscriptionConfig(CONFIGROOT obj, const QString &subscription, QString *name)
|
||||
{
|
||||
auto str = JsonToString(obj);
|
||||
auto fName = *name;
|
||||
|
||||
if (!IsValidFileName(fName)) {
|
||||
fName = RemoveInvalidFileName(fName);
|
||||
}
|
||||
|
||||
QFile config(QV2RAY_SUBSCRIPTION_DIR + subscription + "/" + fName + QV2RAY_CONFIG_FILE_EXTENSION);
|
||||
|
||||
// If there's already a file. THIS IS EXTREMELY RARE
|
||||
if (config.exists()) {
|
||||
LOG(FILEIO, "Trying to overrwrite an existing subscription config file. THIS IS RARE")
|
||||
}
|
||||
|
||||
LOG(SETTINGS, "Saving a subscription named: " + fName)
|
||||
bool result = StringToFile(&str, &config);
|
||||
|
||||
if (!result) {
|
||||
LOG(FILEIO, "Failed to save a connection config from subscription: " + subscription + ", name: " + fName)
|
||||
}
|
||||
|
||||
*name = fName;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool RemoveConnection(const QString &alias)
|
||||
{
|
||||
QFile config(QV2RAY_CONFIG_DIR + alias + QV2RAY_CONFIG_FILE_EXTENSION);
|
||||
|
||||
if (!config.exists()) {
|
||||
LOG(FILEIO, "Trying to remove a non-existing file?")
|
||||
return false;
|
||||
} else {
|
||||
return config.remove();
|
||||
}
|
||||
}
|
||||
|
||||
bool RemoveSubscriptionConnection(const QString &subsName, const QString &name)
|
||||
{
|
||||
QFile config(QV2RAY_SUBSCRIPTION_DIR + subsName + "/" + name + QV2RAY_CONFIG_FILE_EXTENSION);
|
||||
|
||||
if (!config.exists()) {
|
||||
LOG(FILEIO, "Trying to remove a non-existing file?")
|
||||
return false;
|
||||
} else {
|
||||
return config.remove();
|
||||
}
|
||||
}
|
||||
|
||||
bool RenameConnection(const QString &originalName, const QString &newName)
|
||||
{
|
||||
LOG(CONNECTION, "[RENAME] --> ORIGINAL: " + originalName + ", NEW: " + newName)
|
||||
return QFile::rename(QV2RAY_CONFIG_DIR + originalName + QV2RAY_CONFIG_FILE_EXTENSION, QV2RAY_CONFIG_DIR + newName + QV2RAY_CONFIG_FILE_EXTENSION);
|
||||
}
|
||||
|
||||
bool RenameSubscription(const QString &originalName, const QString &newName)
|
||||
{
|
||||
LOG(SUBSCRIPTION, "[RENAME] --> ORIGINAL: " + originalName + ", NEW: " + newName)
|
||||
return QDir().rename(QV2RAY_SUBSCRIPTION_DIR + originalName, QV2RAY_SUBSCRIPTION_DIR + newName);
|
||||
}
|
||||
|
||||
CONFIGROOT ConvertConfigFromFile(QString sourceFilePath, bool importComplex)
|
||||
{
|
||||
QFile source(sourceFilePath);
|
||||
|
||||
if (!source.exists()) {
|
||||
LOG(FILEIO, "Trying to import from an non-existing file.")
|
||||
return CONFIGROOT();
|
||||
}
|
||||
|
||||
auto root = CONFIGROOT(JsonFromString(StringFromFile(&source)));
|
||||
|
||||
if (!importComplex) {
|
||||
JSON_ROOT_TRY_REMOVE("inbounds")
|
||||
JSON_ROOT_TRY_REMOVE("routing")
|
||||
}
|
||||
|
||||
JSON_ROOT_TRY_REMOVE("log")
|
||||
JSON_ROOT_TRY_REMOVE("api")
|
||||
JSON_ROOT_TRY_REMOVE("stats")
|
||||
JSON_ROOT_TRY_REMOVE("dns")
|
||||
return root;
|
||||
}
|
||||
// // If there's already a file AND we CANNOT override existing file.
|
||||
// if (QFile::exists(fullPath) && !canOverrideExisting) {
|
||||
// // Alias is a pointer to a QString.
|
||||
// DeducePossibleFileName(QV2RAY_CONFIG_DIR, alias, QV2RAY_CONFIG_FILE_EXTENSION);
|
||||
// fullPath = QV2RAY_CONFIG_DIR + *alias + QV2RAY_CONFIG_FILE_EXTENSION;
|
||||
// }
|
||||
//
|
||||
// LOG(MODULE_SETTINGS, "Saving a config named: " + *alias)
|
||||
// QFile config(fullPath);
|
||||
// return StringToFile(&str, &config);
|
||||
//}
|
||||
//
|
||||
//bool SaveSubscriptionConfig(CONFIGROOT obj, const QString &subscription, QString *name)
|
||||
//{
|
||||
// auto str = JsonToString(obj);
|
||||
// auto fName = *name;
|
||||
//
|
||||
// if (!IsValidFileName(fName)) {
|
||||
// fName = RemoveInvalidFileName(fName);
|
||||
// }
|
||||
//
|
||||
// QFile config(QV2RAY_SUBSCRIPTION_DIR + subscription + "/" + fName + QV2RAY_CONFIG_FILE_EXTENSION);
|
||||
//
|
||||
// // If there's already a file. THIS IS EXTREMELY RARE
|
||||
// if (config.exists()) {
|
||||
// LOG(MODULE_FILEIO, "Trying to overrwrite an existing subscription config file. THIS IS RARE")
|
||||
// }
|
||||
//
|
||||
// LOG(MODULE_SETTINGS, "Saving a subscription named: " + fName)
|
||||
// bool result = StringToFile(&str, &config);
|
||||
//
|
||||
// if (!result) {
|
||||
// LOG(MODULE_FILEIO, "Failed to save a connection config from subscription: " + subscription + ", name: " + fName)
|
||||
// }
|
||||
//
|
||||
// *name = fName;
|
||||
// return result;
|
||||
//}
|
||||
//
|
||||
//bool RemoveConnection(const QString &alias)
|
||||
//{
|
||||
// QFile config(QV2RAY_CONFIG_DIR + alias + QV2RAY_CONFIG_FILE_EXTENSION);
|
||||
//
|
||||
// if (!config.exists()) {
|
||||
// LOG(MODULE_FILEIO, "Trying to remove a non-existing file?")
|
||||
// return false;
|
||||
// } else {
|
||||
// return config.remove();
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//bool RemoveSubscriptionConnection(const QString &subsName, const QString &name)
|
||||
//{
|
||||
// QFile config(QV2RAY_SUBSCRIPTION_DIR + subsName + "/" + name + QV2RAY_CONFIG_FILE_EXTENSION);
|
||||
//
|
||||
// if (!config.exists()) {
|
||||
// LOG(MODULE_FILEIO, "Trying to remove a non-existing file?")
|
||||
// return false;
|
||||
// } else {
|
||||
// return config.remove();
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//bool RenameConnection(const QString &originalName, const QString &newName)
|
||||
//{
|
||||
// LOG(MODULE_CONNECTION, "[RENAME] --> ORIGINAL: " + originalName + ", NEW: " + newName)
|
||||
// return QFile::rename(QV2RAY_CONFIG_DIR + originalName + QV2RAY_CONFIG_FILE_EXTENSION, QV2RAY_CONFIG_DIR + newName + QV2RAY_CONFIG_FILE_EXTENSION);
|
||||
//}
|
||||
//
|
||||
//bool RenameSubscription(const QString &originalName, const QString &newName)
|
||||
//{
|
||||
// LOG(MODULE_SUBSCRIPTION, "[RENAME] --> ORIGINAL: " + originalName + ", NEW: " + newName)
|
||||
// return QDir().rename(QV2RAY_SUBSCRIPTION_DIR + originalName, QV2RAY_SUBSCRIPTION_DIR + newName);
|
||||
//}
|
||||
//
|
||||
//CONFIGROOT ConvertConfigFromFile(QString sourceFilePath, bool importComplex)
|
||||
//{
|
||||
// QFile source(sourceFilePath);
|
||||
//
|
||||
// if (!source.exists()) {
|
||||
// LOG(MODULE_FILEIO, "Trying to import from an non-existing file.")
|
||||
// return CONFIGROOT();
|
||||
// }
|
||||
//
|
||||
// auto root = CONFIGROOT(JsonFromString(StringFromFile(&source)));
|
||||
//
|
||||
// if (!importComplex) {
|
||||
// JSON_ROOT_TRY_REMOVE("inbounds")
|
||||
// JSON_ROOT_TRY_REMOVE("routing")
|
||||
// }
|
||||
//
|
||||
// JSON_ROOT_TRY_REMOVE("log")
|
||||
// JSON_ROOT_TRY_REMOVE("api")
|
||||
// JSON_ROOT_TRY_REMOVE("stats")
|
||||
// JSON_ROOT_TRY_REMOVE("dns")
|
||||
// return root;
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
@ -1,28 +1,27 @@
|
||||
#include "base/Qv2rayBase.hpp"
|
||||
#include "core/CoreSafeTypes.hpp"
|
||||
|
||||
namespace Qv2ray::core::connection
|
||||
{
|
||||
namespace ConnectionIO
|
||||
{
|
||||
QMap<QString, CONFIGROOT> GetRegularConnections(QStringList connections);
|
||||
QMap<QString, CONFIGROOT> GetSubscriptionConnection(QString subscription);
|
||||
QMap<QString, QMap<QString, CONFIGROOT>> GetSubscriptionConnections(QStringList subscriptions);
|
||||
CONFIGROOT GetConnectionRoot(const GroupId &group, const ConnectionId &id);
|
||||
CONFIGROOT GetConnectionRoot(const SubscriptionId &subscription, const ConnectionId &id);
|
||||
//
|
||||
// Save Connection Config
|
||||
bool SaveConnectionConfig(CONFIGROOT obj, QString *alias, bool canOverrideExisting);
|
||||
bool SaveSubscriptionConfig(CONFIGROOT obj, const QString &subscription, QString *name);
|
||||
bool SaveConnectionConfig(CONFIGROOT obj, const ConnectionId &id, bool canOverrideExisting);
|
||||
bool SaveSubscriptionConfig(CONFIGROOT obj, const SubscriptionId &subscription, const ConnectionId &name);
|
||||
//
|
||||
bool RemoveConnection(const QString &alias);
|
||||
bool RemoveSubscriptionConnection(const QString &subsName, const QString &name);
|
||||
bool RemoveConnection(const SubscriptionId &id);
|
||||
bool RemoveSubscriptionConnection(const SubscriptionId &id, const ConnectionId &name);
|
||||
//
|
||||
bool RenameConnection(const QString &originalName, const QString &newName);
|
||||
bool RenameSubscription(const QString &originalName, const QString &newName);
|
||||
bool RenameConnection(const ConnectionId &id, const QString &newName);
|
||||
bool RenameSubscription(const SubscriptionId &id, const QString &newName);
|
||||
|
||||
// File Protocol
|
||||
CONFIGROOT ConvertConfigFromFile(QString sourceFilePath, bool importComplex);
|
||||
}
|
||||
}
|
||||
|
||||
using namespace Qv2ray::core;
|
||||
using namespace Qv2ray::core::connection;
|
||||
using namespace Qv2ray::core::connection::ConnectionIO;
|
||||
|
@ -181,7 +181,7 @@ namespace Qv2ray::core::connection
|
||||
INBOUND GenerateInboundEntry(QString listen, int port, QString protocol, INBOUNDSETTING settings, QString tag, QJsonObject sniffing, QJsonObject allocate)
|
||||
{
|
||||
INBOUND root;
|
||||
LOG(CONNECTION, "allocation is not used here.")
|
||||
LOG(MODULE_CONNECTION, "allocation is not used here.")
|
||||
Q_UNUSED(allocate)
|
||||
JADD(listen, port, protocol, settings, tag, sniffing)
|
||||
RROOT
|
||||
@ -261,7 +261,7 @@ namespace Qv2ray::core::connection
|
||||
}
|
||||
|
||||
root["inbounds"] = inboundsList;
|
||||
DEBUG(CONNECTION, "Added global config inbounds to the config")
|
||||
DEBUG(MODULE_CONNECTION, "Added global config inbounds to the config")
|
||||
}
|
||||
|
||||
// Process every inbounds to make sure a tag is configured, fixed API 0 speed
|
||||
@ -272,7 +272,7 @@ namespace Qv2ray::core::connection
|
||||
auto _inboundItem = newTaggedInbounds[i].toObject();
|
||||
|
||||
if (!_inboundItem.contains("tag") || _inboundItem["tag"].toString().isEmpty()) {
|
||||
LOG(SETTINGS, "Adding a tag to an inbound.")
|
||||
LOG(MODULE_SETTINGS, "Adding a tag to an inbound.")
|
||||
_inboundItem["tag"] = GenerateRandomString(8);
|
||||
newTaggedInbounds[i] = _inboundItem;
|
||||
}
|
||||
@ -294,7 +294,7 @@ namespace Qv2ray::core::connection
|
||||
// And what's more, process (by removing unused items) from a rule object.
|
||||
ROUTING routing = ROUTING(root["routing"].toObject());
|
||||
ROUTERULELIST rules;
|
||||
LOG(CONNECTION, "Processing an existing routing table.")
|
||||
LOG(MODULE_CONNECTION, "Processing an existing routing table.")
|
||||
|
||||
for (auto _rule : routing["rules"].toArray()) {
|
||||
auto _b = _rule.toObject();
|
||||
@ -308,14 +308,14 @@ namespace Qv2ray::core::connection
|
||||
_b.remove("balancerTag");
|
||||
}
|
||||
} else {
|
||||
LOG(SETTINGS, "We found a rule without QV2RAY_RULE_USE_BALANCER, so don't process it.")
|
||||
LOG(MODULE_SETTINGS, "We found a rule without QV2RAY_RULE_USE_BALANCER, so don't process it.")
|
||||
}
|
||||
|
||||
// If this entry has been disabled.
|
||||
if (_b.contains("QV2RAY_RULE_ENABLED") && _b["QV2RAY_RULE_ENABLED"].toBool() == true) {
|
||||
rules.append(_b);
|
||||
} else {
|
||||
LOG(SETTINGS, "Discarded a rule as it's been set DISABLED")
|
||||
LOG(MODULE_SETTINGS, "Discarded a rule as it's been set DISABLED")
|
||||
}
|
||||
}
|
||||
|
||||
@ -323,12 +323,12 @@ namespace Qv2ray::core::connection
|
||||
root["routing"] = routing;
|
||||
} else {
|
||||
//
|
||||
LOG(CONNECTION, "Inserting default values to simple config")
|
||||
LOG(MODULE_CONNECTION, "Inserting default values to simple config")
|
||||
|
||||
if (root["outbounds"].toArray().count() != 1) {
|
||||
// There are no ROUTING but 2 or more outbounds.... This is rare, but possible.
|
||||
LOG(CONNECTION, "WARN: This message usually indicates the config file has logic errors:")
|
||||
LOG(CONNECTION, "WARN: --> The config file has NO routing section, however more than 1 outbounds are detected.")
|
||||
LOG(MODULE_CONNECTION, "WARN: This message usually indicates the config file has logic errors:")
|
||||
LOG(MODULE_CONNECTION, "WARN: --> The config file has NO routing section, however more than 1 outbounds are detected.")
|
||||
}
|
||||
|
||||
auto routeObject = GenerateRoutes(GlobalConfig.connectionConfig.enableProxy, GlobalConfig.connectionConfig.bypassCN);
|
||||
@ -342,7 +342,7 @@ namespace Qv2ray::core::connection
|
||||
auto firstOutbound = outboundArray.first().toObject();
|
||||
|
||||
if (firstOutbound[QV2RAY_USE_FPROXY_KEY].toBool(false)) {
|
||||
LOG(CONNECTION, "Applying forward proxy to current connection.")
|
||||
LOG(MODULE_CONNECTION, "Applying forward proxy to current connection.")
|
||||
auto proxy = PROXYSETTING();
|
||||
proxy["tag"] = OUTBOUND_TAG_FORWARD_PROXY;
|
||||
firstOutbound["proxySettings"] = proxy;
|
||||
@ -353,7 +353,7 @@ namespace Qv2ray::core::connection
|
||||
fpOutbound = GenerateHTTPSOCKSOut(fpConf.serverAddress, fpConf.port, fpConf.useAuth, fpConf.username, fpConf.password);
|
||||
outboundArray.push_back(GenerateOutboundEntry(fpConf.type.toLower(), fpOutbound, QJsonObject(), QJsonObject(), "0.0.0.0", OUTBOUND_TAG_FORWARD_PROXY));
|
||||
} else {
|
||||
LOG(CONNECTION, "WARNING: Unsupported outbound type: " + fpConf.type)
|
||||
LOG(MODULE_CONNECTION, "WARNING: Unsupported outbound type: " + fpConf.type)
|
||||
}
|
||||
} else {
|
||||
// Remove proxySettings from firstOutbound
|
||||
|
@ -38,7 +38,7 @@ namespace Qv2ray::core::connection
|
||||
auto ssServer = StructFromJsonString<ShadowSocksServerObject>(JsonToString(outbound["settings"].toObject()["servers"].toArray().first().toObject()));
|
||||
sharelink = ConvertConfigToSSString(ssServer, alias, isSip002);
|
||||
} else {
|
||||
LOG(CONNECTION, "Unsupported outbound type: " + type)
|
||||
LOG(MODULE_CONNECTION, "Unsupported outbound type: " + type)
|
||||
}
|
||||
|
||||
return sharelink;
|
||||
@ -101,13 +101,13 @@ namespace Qv2ray::core::connection
|
||||
|
||||
//auto ssUri = _ssUri.toStdString();
|
||||
if (ssUri.length() < 5) {
|
||||
LOG(CONNECTION, "ss:// string too short")
|
||||
LOG(MODULE_CONNECTION, "ss:// string too short")
|
||||
*errMessage = QObject::tr("SS URI is too short");
|
||||
}
|
||||
|
||||
auto uri = ssUri.mid(5);
|
||||
auto hashPos = uri.lastIndexOf("#");
|
||||
DEBUG(CONNECTION, "Hash sign position: " + QSTRN(hashPos))
|
||||
DEBUG(MODULE_CONNECTION, "Hash sign position: " + QSTRN(hashPos))
|
||||
|
||||
if (hashPos >= 0) {
|
||||
// Get the name/remark
|
||||
@ -123,13 +123,13 @@ namespace Qv2ray::core::connection
|
||||
// uri.erase(pluginPos);
|
||||
//}
|
||||
auto atPos = uri.indexOf('@');
|
||||
DEBUG(CONNECTION, "At sign position: " + QSTRN(atPos))
|
||||
DEBUG(MODULE_CONNECTION, "At sign position: " + QSTRN(atPos))
|
||||
|
||||
if (atPos < 0) {
|
||||
// Old URI scheme
|
||||
QString decoded = QByteArray::fromBase64(uri.toUtf8(), QByteArray::Base64Option::OmitTrailingEquals);
|
||||
auto colonPos = decoded.indexOf(':');
|
||||
DEBUG(CONNECTION, "Colon position: " + QSTRN(colonPos))
|
||||
DEBUG(MODULE_CONNECTION, "Colon position: " + QSTRN(colonPos))
|
||||
|
||||
if (colonPos < 0) {
|
||||
*errMessage = QObject::tr("Can't find the colon separator between method and password");
|
||||
@ -138,7 +138,7 @@ namespace Qv2ray::core::connection
|
||||
server.method = decoded.left(colonPos);
|
||||
decoded.remove(0, colonPos + 1);
|
||||
atPos = decoded.lastIndexOf('@');
|
||||
DEBUG(CONNECTION, "At sign position: " + QSTRN(atPos))
|
||||
DEBUG(MODULE_CONNECTION, "At sign position: " + QSTRN(atPos))
|
||||
|
||||
if (atPos < 0) {
|
||||
*errMessage = QObject::tr("Can't find the at separator between password and hostname");
|
||||
@ -147,7 +147,7 @@ namespace Qv2ray::core::connection
|
||||
server.password = decoded.mid(0, atPos);
|
||||
decoded.remove(0, atPos + 1);
|
||||
colonPos = decoded.lastIndexOf(':');
|
||||
DEBUG(CONNECTION, "Colon position: " + QSTRN(colonPos))
|
||||
DEBUG(MODULE_CONNECTION, "Colon position: " + QSTRN(colonPos))
|
||||
|
||||
if (colonPos < 0) {
|
||||
*errMessage = QObject::tr("Can't find the colon separator between hostname and port");
|
||||
@ -163,7 +163,7 @@ namespace Qv2ray::core::connection
|
||||
QString userInfo = Base64Decode(x.userName());
|
||||
auto userInfoSp = userInfo.indexOf(':');
|
||||
//
|
||||
DEBUG(CONNECTION, "Userinfo splitter position: " + QSTRN(userInfoSp))
|
||||
DEBUG(MODULE_CONNECTION, "Userinfo splitter position: " + QSTRN(userInfoSp))
|
||||
|
||||
if (userInfoSp < 0) {
|
||||
*errMessage = QObject::tr("Can't find the colon separator between method and password");
|
||||
@ -180,7 +180,7 @@ namespace Qv2ray::core::connection
|
||||
outbounds.append(GenerateOutboundEntry("shadowsocks", GenerateShadowSocksOUT(QList<ShadowSocksServerObject>() << server), QJsonObject()));
|
||||
JADD(outbounds)
|
||||
*alias = alias->isEmpty() ? d_name : *alias + "_" + d_name;
|
||||
LOG(CONNECTION, "Deduced alias: " + *alias)
|
||||
LOG(MODULE_CONNECTION, "Deduced alias: " + *alias)
|
||||
return root;
|
||||
}
|
||||
|
||||
@ -189,12 +189,12 @@ namespace Qv2ray::core::connection
|
||||
auto myAlias = QUrl::toPercentEncoding(alias);
|
||||
|
||||
if (isSip002) {
|
||||
LOG(CONNECTION, "Converting an ss-server config to Sip002 ss:// format")
|
||||
LOG(MODULE_CONNECTION, "Converting an ss-server config to Sip002 ss:// format")
|
||||
QString plainUserInfo = server.method + ":" + server.password;
|
||||
QString userinfo(plainUserInfo.toUtf8().toBase64(QByteArray::Base64Option::Base64UrlEncoding).data());
|
||||
return "ss://" + userinfo + "@" + server.address + ":" + QSTRN(server.port) + "#" + myAlias;
|
||||
} else {
|
||||
LOG(CONNECTION, "Converting an ss-server config to old ss:// string format")
|
||||
LOG(MODULE_CONNECTION, "Converting an ss-server config to old ss:// string format")
|
||||
QString ssUri = server.method + ":" + server.password + "@" + server.address + ":" + QSTRN(server.port);
|
||||
return "ss://" + ssUri.toUtf8().toBase64(QByteArray::Base64Option::OmitTrailingEquals) + "#" + myAlias;
|
||||
}
|
||||
@ -205,11 +205,11 @@ namespace Qv2ray::core::connection
|
||||
CONFIGROOT ConvertConfigFromVMessString(const QString &vmessStr, QString *alias, QString *errMessage)
|
||||
{
|
||||
#define default CONFIGROOT()
|
||||
LOG(SETTINGS, "Trying to convert from a vmess string.")
|
||||
LOG(MODULE_SETTINGS, "Trying to convert from a vmess string.")
|
||||
QString vmess = vmessStr;
|
||||
|
||||
if (vmess.trimmed() != vmess) {
|
||||
LOG(SETTINGS, "VMess string has some prefix/postfix spaces, trimming.")
|
||||
LOG(MODULE_SETTINGS, "VMess string has some prefix/postfix spaces, trimming.")
|
||||
vmess = vmessStr.trimmed();
|
||||
}
|
||||
|
||||
@ -264,7 +264,7 @@ namespace Qv2ray::core::connection
|
||||
//return flag ? 0 : 1;
|
||||
} catch (exception *e) {
|
||||
*errMessage = e->what();
|
||||
LOG(IMPORT, "Failed to decode vmess string: " + *errMessage)
|
||||
LOG(MODULE_IMPORT, "Failed to decode vmess string: " + *errMessage)
|
||||
delete e;
|
||||
return default;
|
||||
}
|
||||
@ -292,15 +292,15 @@ namespace Qv2ray::core::connection
|
||||
if (vmessConf.contains(#key) && !vmessConf[#key].toVariant().toString().trimmed().isEmpty() \
|
||||
&& (val.size() <= 1 || val.contains(vmessConf[#key].toVariant().toString()))) {\
|
||||
key = vmessConf[#key].toVariant().toString();\
|
||||
DEBUG(IMPORT, "Found key \"" #key "\" within the vmess object.")\
|
||||
DEBUG(MODULE_IMPORT, "Found key \"" #key "\" within the vmess object.")\
|
||||
} else if (!val.isEmpty()) {\
|
||||
key = val.first(); \
|
||||
DEBUG(IMPORT, "Using key \"" #key "\" from the first candidate list: " + key)\
|
||||
DEBUG(MODULE_IMPORT, "Using key \"" #key "\" from the first candidate list: " + key)\
|
||||
} else{\
|
||||
*errMessage = QObject::tr(#key " does not exist."); \
|
||||
LOG(IMPORT, "Cannot process \"" #key "\" since it's not included in the json object." ) \
|
||||
LOG(IMPORT, " --> values: " + val.join(";")) \
|
||||
LOG(IMPORT, " --> PS: " + ps) \
|
||||
LOG(MODULE_IMPORT, "Cannot process \"" #key "\" since it's not included in the json object." ) \
|
||||
LOG(MODULE_IMPORT, " --> values: " + val.join(";")) \
|
||||
LOG(MODULE_IMPORT, " --> PS: " + ps) \
|
||||
}\
|
||||
}
|
||||
// Strict check of VMess protocol, to check if the specified value is in the correct range.
|
||||
|
86
src/core/handler/ConnectionHandler.cpp
Normal file
86
src/core/handler/ConnectionHandler.cpp
Normal file
@ -0,0 +1,86 @@
|
||||
#include "ConnectionHandler.hpp"
|
||||
namespace Qv2ray::core::handlers
|
||||
{
|
||||
template<typename IDType>
|
||||
QList<IDType> StringsToIdList(const QList<QString> &strings)
|
||||
{
|
||||
QList<IDType> list;
|
||||
|
||||
for (auto str : strings) {
|
||||
list << IDType(str);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
QvConnectionHandler::QvConnectionHandler()
|
||||
{
|
||||
DEBUG(MODULE_CORE_HANDLER, "ConnectionHandler Constructor.")
|
||||
|
||||
// Do we need to check how many of them are loaded?
|
||||
for (auto i = 0; i < GlobalConfig.connections.count(); i++) {
|
||||
connections[ConnectionId(GlobalConfig.connections.keys()[i])] = GlobalConfig.connections.values()[i];
|
||||
}
|
||||
|
||||
for (auto i = 0; i < GlobalConfig.subscriptions.count(); i++) {
|
||||
subscriptions[SubscriptionId(GlobalConfig.subscriptions.keys()[i])] = GlobalConfig.subscriptions.values()[i];
|
||||
}
|
||||
|
||||
for (auto i = 0; i < GlobalConfig.groups.count(); i++) {
|
||||
groups[GroupId(GlobalConfig.groups.keys()[i])] = GlobalConfig.groups.values()[i];
|
||||
}
|
||||
|
||||
kernelInstance = new V2rayKernelInstance();
|
||||
saveTimerId = startTimer(60000);
|
||||
}
|
||||
|
||||
const QList<GroupId> QvConnectionHandler::Groups() const
|
||||
{
|
||||
return groups.keys();
|
||||
}
|
||||
const QList<SubscriptionId> QvConnectionHandler::Subscriptions() const
|
||||
{
|
||||
return subscriptions.keys();
|
||||
}
|
||||
const QList<ConnectionId> QvConnectionHandler::Connections() const
|
||||
{
|
||||
return connections.keys();
|
||||
}
|
||||
const QList<ConnectionId> QvConnectionHandler::Connections(const GroupId &groupId) const
|
||||
{
|
||||
return StringsToIdList<ConnectionId>(groups[groupId].connections);
|
||||
}
|
||||
const QList<ConnectionId> QvConnectionHandler::Connections(const SubscriptionId &subscriptionId) const
|
||||
{
|
||||
return StringsToIdList<ConnectionId>(subscriptions[subscriptionId].connections);
|
||||
}
|
||||
|
||||
const QvConnectionObject &QvConnectionHandler::GetConnection(const ConnectionId &id)
|
||||
{
|
||||
if (!connections.contains(id)) {
|
||||
LOG(MODULE_CORE_HANDLER, "Cannot find id: " + id.toString());
|
||||
}
|
||||
|
||||
return connections[id];
|
||||
}
|
||||
|
||||
const QvGroupObject &QvConnectionHandler::GetGroup(const GroupId &id)
|
||||
{
|
||||
return groups[id];
|
||||
}
|
||||
|
||||
const QvSubscriptionObject &QvConnectionHandler::GetSubscription(const SubscriptionId &id)
|
||||
{
|
||||
return subscriptions[id];
|
||||
}
|
||||
|
||||
QvConnectionHandler::~QvConnectionHandler()
|
||||
{
|
||||
if (kernelInstance->KernelStarted) {
|
||||
kernelInstance->StopConnection();
|
||||
LOG(MODULE_CORE_HANDLER, "Stopped connection from destructor.")
|
||||
}
|
||||
|
||||
delete kernelInstance;
|
||||
}
|
||||
}
|
104
src/core/handler/ConnectionHandler.hpp
Normal file
104
src/core/handler/ConnectionHandler.hpp
Normal file
@ -0,0 +1,104 @@
|
||||
#pragma once
|
||||
|
||||
#include "base/Qv2rayBase.hpp"
|
||||
#include "core/kernel/KernelInteractions.hpp"
|
||||
#include "core/CoreSafeTypes.hpp"
|
||||
#include "core/connection/ConnectionIO.hpp"
|
||||
|
||||
|
||||
namespace Qv2ray::core::handlers
|
||||
{
|
||||
class QvConnectionHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QvConnectionHandler();
|
||||
~QvConnectionHandler();
|
||||
//
|
||||
const QList<GroupId> Groups() const;
|
||||
const QList<ConnectionId> Connections() const;
|
||||
const QList<SubscriptionId> Subscriptions() const;
|
||||
const QList<ConnectionId> Connections(const GroupId &groupId) const;
|
||||
const QList<ConnectionId> Connections(const SubscriptionId &subscriptionId) const;
|
||||
//
|
||||
optional<QString> StopConnection(const ConnectionId &id);
|
||||
//
|
||||
template<typename T>
|
||||
optional<QString> StartConnection(const T &group, const ConnectionId &id)
|
||||
{
|
||||
if (!connections.contains(id)) {
|
||||
return tr("No connection selected!") + NEWLINE + tr("Please select a config from the list.");
|
||||
}
|
||||
|
||||
auto root = GetConnectionRoot(group, id);
|
||||
return _CHTryStartConnection_p(id, root);
|
||||
}
|
||||
template<typename T> optional<QString> StartConnection(const GroupId &group, const ConnectionId &id);
|
||||
template<typename T> optional<QString> StartConnection(const SubscriptionId &group, const ConnectionId &id);
|
||||
//
|
||||
public:
|
||||
//
|
||||
// Connection Operations.
|
||||
const QvConnectionObject &GetConnection(const ConnectionId &id);
|
||||
const ConnectionId &CreateConnection(const QString &displayName, const GroupId &groupId, const CONFIGROOT &root);
|
||||
optional<QString> DeleteConnection(const ConnectionId &id);
|
||||
optional<QString> UpdateConnection(const ConnectionId &id, const CONFIGROOT &root);
|
||||
optional<QString> RenameConnection(const ConnectionId &id, const QString &newName);
|
||||
optional<QString> DuplicateConnection(const ConnectionId &id);
|
||||
optional<QString> MoveConnectionGroup(const ConnectionId &id, const GroupId &newGroupId);
|
||||
//
|
||||
// Misc Connection Operations
|
||||
optional<QString> TestLatency(const ConnectionId &id);
|
||||
optional<QString> TestLatency(const GroupId &id);
|
||||
optional<QString> TestLatency(const SubscriptionId &id);
|
||||
optional<QString> TestAllLatency();
|
||||
//
|
||||
// Group Operations
|
||||
const QvGroupObject &GetGroup(const GroupId &id);
|
||||
const GroupId CreateGroup(const QString displayName);
|
||||
optional<QString> DeleteGroup(const GroupId &id);
|
||||
optional<QString> DuplicateGroup(const GroupId &id);
|
||||
optional<QString> RenameGroup(const GroupId &id, const QString &newName);
|
||||
//
|
||||
// Subscriptions
|
||||
const QvSubscriptionObject &GetSubscription(const SubscriptionId &id);
|
||||
const SubscriptionId &CreateSubscription(const QString &displayName, const QString &address);
|
||||
optional<QString> RenameSubscription(const SubscriptionId &id, const QString &newName);
|
||||
optional<QString> DeleteSubscription(const SubscriptionId &id);
|
||||
optional<QString> UpdateSubscription(const SubscriptionId &id);
|
||||
optional<QString> UpdateSubscriptionASync(const SubscriptionId &id);
|
||||
|
||||
signals:
|
||||
void OnConnectionCreated(const ConnectionId &id, const QString &displayName);
|
||||
void OnConnectionRenamed(const ConnectionId &id, const QString &originalName, const QString &newName);
|
||||
void OnConnectionChanged(const ConnectionId &id);
|
||||
void OnConnectionGroupChanged(const ConnectionId &id, const QString &originalGroup, const QString &newGroup);
|
||||
//
|
||||
void OnConnectionLatencyTestFinished(const ConnectionId &id);
|
||||
//
|
||||
void OnGroupCreated(const GroupId &id, const QString &displayName);
|
||||
void OnGroupRenamed(const GroupId &id, const QString &oldName, const QString &newName);
|
||||
void OnGroupDeleted(const GroupId &id, const QString &displayName);
|
||||
//
|
||||
void OnSubscriptionCreated(const SubscriptionId &id, const QString &displayName, const QString &address);
|
||||
void OnSubscriptionDeleted(const SubscriptionId &id);
|
||||
void OnSubscriptionRenamed(const SubscriptionId &id, const QString &oldName, const QString &newName);
|
||||
void OnSubscriptionUpdateFinished(const SubscriptionId &id);
|
||||
|
||||
private:
|
||||
int saveTimerId;
|
||||
QHash<GroupId, QvGroupObject> groups;
|
||||
QHash<ConnectionId, QvConnectionObject> connections;
|
||||
QHash<SubscriptionId, QvSubscriptionObject> subscriptions;
|
||||
//
|
||||
// We only support one cuncurrent connection currently.
|
||||
//QHash<ConnectionId, V2rayKernelInstance> kernelInstances;
|
||||
V2rayKernelInstance *kernelInstance = nullptr;
|
||||
//
|
||||
optional<QString> _CHTryStartConnection_p(const ConnectionId &id, const CONFIGROOT &root);
|
||||
};
|
||||
//
|
||||
inline QvConnectionHandler *ConnectionHandler = nullptr;
|
||||
}
|
||||
|
||||
using namespace Qv2ray::core::handlers;
|
1
src/core/handler/SubscriptionHandler.cpp
Normal file
1
src/core/handler/SubscriptionHandler.cpp
Normal file
@ -0,0 +1 @@
|
||||
//
|
56
src/core/handler/V2rayInstanceHandler.cpp
Normal file
56
src/core/handler/V2rayInstanceHandler.cpp
Normal file
@ -0,0 +1,56 @@
|
||||
#include "ConnectionHandler.hpp"
|
||||
#include "core/connection/Generation.hpp"
|
||||
|
||||
optional<QString> QvConnectionHandler::_CHTryStartConnection_p(const ConnectionId &id, const CONFIGROOT &root)
|
||||
{
|
||||
auto &connectionMeta = connections[id];
|
||||
auto fullConfig = GenerateRuntimeConfig(root);
|
||||
return kernelInstance->StartConnection(fullConfig);
|
||||
//if (startFlag) {
|
||||
// bool usePAC = GlobalConfig.inboundConfig.pacConfig.enablePAC;
|
||||
// bool pacUseSocks = GlobalConfig.inboundConfig.pacConfig.useSocksProxy;
|
||||
// bool httpEnabled = GlobalConfig.inboundConfig.useHTTP;
|
||||
// bool socksEnabled = GlobalConfig.inboundConfig.useSocks;
|
||||
//
|
||||
// if (usePAC) {
|
||||
// bool canStartPAC = true;
|
||||
// QString pacProxyString; // Something like this --> SOCKS5 127.0.0.1:1080; SOCKS 127.0.0.1:1080; DIRECT; http://proxy:8080
|
||||
// auto pacIP = GlobalConfig.inboundConfig.pacConfig.localIP;
|
||||
//
|
||||
// if (pacIP.isEmpty()) {
|
||||
// LOG(MODULE_PROXY, "PAC Local IP is empty, default to 127.0.0.1")
|
||||
// pacIP = "127.0.0.1";
|
||||
// }
|
||||
//
|
||||
// if (pacUseSocks) {
|
||||
// if (socksEnabled) {
|
||||
// pacProxyString = "SOCKS5 " + pacIP + ":" + QSTRN(GlobalConfig.inboundConfig.socks_port);
|
||||
// } else {
|
||||
// LOG(MODULE_UI, "PAC is using SOCKS, but it is not enabled")
|
||||
// QvMessageBoxWarn(this, tr("Configuring PAC"), tr("Could not start PAC server as it is configured to use SOCKS, but it is not enabled"));
|
||||
// canStartPAC = false;
|
||||
// }
|
||||
// } else {
|
||||
// if (httpEnabled) {
|
||||
// pacProxyString = "PROXY " + pacIP + ":" + QSTRN(GlobalConfig.inboundConfig.http_port);
|
||||
// } else {
|
||||
// LOG(MODULE_UI, "PAC is using HTTP, but it is not enabled")
|
||||
// QvMessageBoxWarn(this, tr("Configuring PAC"), tr("Could not start PAC server as it is configured to use HTTP, but it is not enabled"));
|
||||
// canStartPAC = false;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (canStartPAC) {
|
||||
// pacServer.SetProxyString(pacProxyString);
|
||||
// pacServer.StartListen();
|
||||
// } else {
|
||||
// LOG(MODULE_PROXY, "Not starting PAC due to previous error.")
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (GlobalConfig.inboundConfig.setSystemProxy) {
|
||||
// MWSetSystemProxy();
|
||||
// }
|
||||
//}
|
||||
return "startFlag";
|
||||
}
|
0
src/core/handler/V2rayInstanceHandler.hpp
Normal file
0
src/core/handler/V2rayInstanceHandler.hpp
Normal file
@ -19,15 +19,15 @@ namespace Qv2ray::core::kernel::api
|
||||
{
|
||||
thread = new QThread();
|
||||
this->moveToThread(thread);
|
||||
DEBUG(VCORE, "API Worker initialised.")
|
||||
DEBUG(MODULE_VCORE, "API Worker initialised.")
|
||||
connect(this, SIGNAL(error(QString)), this, SLOT(errorString(QString)));
|
||||
connect(thread, SIGNAL(started()), this, SLOT(process()));
|
||||
connect(thread, &QThread::finished, []() {
|
||||
LOG(VCORE, "API thread stopped")
|
||||
LOG(MODULE_VCORE, "API thread stopped")
|
||||
});
|
||||
started = true;
|
||||
thread->start();
|
||||
DEBUG(VCORE, "API Worker started.")
|
||||
DEBUG(MODULE_VCORE, "API Worker started.")
|
||||
}
|
||||
|
||||
void APIWorkder::StartAPI(QStringList tags)
|
||||
@ -74,7 +74,7 @@ namespace Qv2ray::core::kernel::api
|
||||
Stub = service.NewStub(Channel);
|
||||
#else
|
||||
auto str = Dial(const_cast<char *>(channelAddress.toStdString().c_str()), 10000);
|
||||
LOG(VCORE, QString(str))
|
||||
LOG(MODULE_VCORE, QString(str))
|
||||
free(str);
|
||||
#endif
|
||||
dialed = true;
|
||||
@ -105,10 +105,10 @@ namespace Qv2ray::core::kernel::api
|
||||
thread->exit();
|
||||
}
|
||||
|
||||
long APIWorkder::CallStatsAPIByName(QString name)
|
||||
qint64 APIWorkder::CallStatsAPIByName(QString name)
|
||||
{
|
||||
if (apiFailedCounter == QV2RAY_API_CALL_FAILEDCHECK_THRESHOLD) {
|
||||
LOG(VCORE, "API call failure threshold reached, cancelling further API aclls.")
|
||||
LOG(MODULE_VCORE, "API call failure threshold reached, cancelling further API aclls.")
|
||||
emit error("Failed to get statistics data, please check if V2ray is running properly");
|
||||
apiFailedCounter++;
|
||||
return 0;
|
||||
@ -129,13 +129,13 @@ namespace Qv2ray::core::kernel::api
|
||||
apiFailedCounter++;
|
||||
}
|
||||
|
||||
auto data = response.stat().value();
|
||||
qint64 data = response.stat().value();
|
||||
#else
|
||||
auto data = GetStats(const_cast<char *>(name.toStdString().c_str()), 1000);
|
||||
qint64 data = GetStats(const_cast<char *>(name.toStdString().c_str()), 1000);
|
||||
#endif
|
||||
|
||||
if (data < 0) {
|
||||
LOG(VCORE, "API call returns: " + QSTRN(data))
|
||||
LOG(MODULE_VCORE, "API call returns: " + QSTRN(data))
|
||||
apiFailedCounter++;
|
||||
return 0;
|
||||
}
|
||||
|
@ -26,11 +26,11 @@ namespace Qv2ray::core::kernel::api
|
||||
void process();
|
||||
|
||||
signals:
|
||||
void OnDataReady(QString tag, long dataUp, long dataDown);
|
||||
void OnDataReady(QString tag, qint64 dataUp, qint64 dataDown);
|
||||
void error(QString err);
|
||||
|
||||
private:
|
||||
long CallStatsAPIByName(QString name);
|
||||
qint64 CallStatsAPIByName(QString name);
|
||||
QStringList inboundTags;
|
||||
QThread *thread;
|
||||
//
|
||||
|
@ -12,14 +12,14 @@ namespace Qv2ray::core::kernel
|
||||
QFile coreFile(vCorePath);
|
||||
|
||||
if (!coreFile.exists()) {
|
||||
DEBUG(VCORE, "V2ray core file cannot be found.")
|
||||
DEBUG(MODULE_VCORE, "V2ray core file cannot be found.")
|
||||
*message = tr("V2ray core executable not found.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Use open() here to prevent `executing` a folder, which may have the same name as the V2ray core.
|
||||
if (!coreFile.open(QFile::ReadOnly)) {
|
||||
DEBUG(VCORE, "V2ray core file cannot be opened, possibly be a folder?")
|
||||
DEBUG(MODULE_VCORE, "V2ray core file cannot be opened, possibly be a folder?")
|
||||
*message = tr("V2ray core file cannot be opened, please ensure there's a file instead of a folder.");
|
||||
return false;
|
||||
}
|
||||
@ -33,19 +33,19 @@ namespace Qv2ray::core::kernel
|
||||
bool hasGeoSite = FileExistsIn(QDir(vAssetsPath), "geosite.dat");
|
||||
|
||||
if (!hasGeoIP && !hasGeoSite) {
|
||||
DEBUG(VCORE, "V2ray assets path contains none of those two files.")
|
||||
DEBUG(MODULE_VCORE, "V2ray assets path contains none of those two files.")
|
||||
*message = tr("V2ray assets path is not valid.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!hasGeoIP) {
|
||||
DEBUG(VCORE, "No geoip.dat in assets path, aborting.")
|
||||
DEBUG(MODULE_VCORE, "No geoip.dat in assets path, aborting.")
|
||||
*message = tr("No geoip.dat in assets path.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!hasGeoSite) {
|
||||
DEBUG(VCORE, "No geosite.dat in assets path, aborting.")
|
||||
DEBUG(MODULE_VCORE, "No geosite.dat in assets path, aborting.")
|
||||
*message = tr("No geosite.dat in assets path.");
|
||||
return false;
|
||||
}
|
||||
@ -66,13 +66,13 @@ namespace Qv2ray::core::kernel
|
||||
auto exitCode = proc.exitCode();
|
||||
|
||||
if (exitCode != 0) {
|
||||
DEBUG(VCORE, "VCore failed with an exit code: " + QSTRN(exitCode))
|
||||
DEBUG(MODULE_VCORE, "VCore failed with an exit code: " + QSTRN(exitCode))
|
||||
*message = tr("V2ray core failed with an exit code: ") + QSTRN(exitCode);
|
||||
return false;
|
||||
}
|
||||
|
||||
QString output = proc.readAllStandardOutput();
|
||||
LOG(VCORE, "V2ray output: " + SplitLines(output).join(";"))
|
||||
LOG(MODULE_VCORE, "V2ray output: " + SplitLines(output).join(";"))
|
||||
|
||||
if (SplitLines(output).isEmpty()) {
|
||||
*message = tr("V2ray core returns empty string.");
|
||||
@ -89,14 +89,14 @@ namespace Qv2ray::core::kernel
|
||||
QString v2rayCheckResult;
|
||||
|
||||
if (ValidateKernel(GlobalConfig.v2CorePath, GlobalConfig.v2AssetsPath, &v2rayCheckResult)) {
|
||||
DEBUG(VCORE, "V2ray version: " + v2rayCheckResult)
|
||||
DEBUG(MODULE_VCORE, "V2ray version: " + v2rayCheckResult)
|
||||
// Append assets location env.
|
||||
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
||||
env.insert("V2RAY_LOCATION_ASSET", GlobalConfig.v2AssetsPath);
|
||||
//
|
||||
QProcess process;
|
||||
process.setProcessEnvironment(env);
|
||||
DEBUG(VCORE, "Starting V2ray core with test options")
|
||||
DEBUG(MODULE_VCORE, "Starting V2ray core with test options")
|
||||
process.start(GlobalConfig.v2CorePath, QStringList() << "-test" << "-config" << path, QIODevice::ReadWrite | QIODevice::Text);
|
||||
process.waitForFinished();
|
||||
|
||||
@ -105,7 +105,7 @@ namespace Qv2ray::core::kernel
|
||||
QvMessageBoxWarn(nullptr, tr("Configuration Error"), output.mid(output.indexOf("anti-censorship.") + 17));
|
||||
return false;
|
||||
} else {
|
||||
DEBUG(VCORE, "Config file check passed.")
|
||||
DEBUG(MODULE_VCORE, "Config file check passed.")
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
@ -123,11 +123,11 @@ namespace Qv2ray::core::kernel
|
||||
emit onProcessOutputReadyRead(vProcess->readAllStandardOutput().trimmed());
|
||||
});
|
||||
connect(vProcess, &QProcess::stateChanged, [this](QProcess::ProcessState state) {
|
||||
DEBUG(VCORE, "V2ray kernel process status changed: " + QVariant::fromValue(state).toString())
|
||||
DEBUG(MODULE_VCORE, "V2ray kernel process status changed: " + QVariant::fromValue(state).toString())
|
||||
|
||||
// If V2ray crashed AFTER we start it.
|
||||
if (KernelStarted && state == QProcess::NotRunning) {
|
||||
LOG(VCORE, "V2ray kernel crashed.")
|
||||
LOG(MODULE_VCORE, "V2ray kernel crashed.")
|
||||
StopConnection();
|
||||
emit onProcessErrored();
|
||||
}
|
||||
@ -137,15 +137,14 @@ namespace Qv2ray::core::kernel
|
||||
KernelStarted = false;
|
||||
}
|
||||
|
||||
bool V2rayKernelInstance::StartConnection(CONFIGROOT root)
|
||||
optional<QString> V2rayKernelInstance::StartConnection(CONFIGROOT root)
|
||||
{
|
||||
if (KernelStarted) {
|
||||
LOG(VCORE, "Status is invalid, expect STOPPED when calling StartConnection")
|
||||
return false;
|
||||
LOG(MODULE_VCORE, "Status is invalid, expect STOPPED when calling StartConnection")
|
||||
return tr("Invalid V2ray Instance Status.");
|
||||
}
|
||||
|
||||
// Write the final configuration to the disk.
|
||||
|
||||
QString json = JsonToString(root);
|
||||
QFile configFile(QV2RAY_GENERATED_FILE_PATH);
|
||||
StringToFile(&json, &configFile);
|
||||
@ -158,7 +157,7 @@ namespace Qv2ray::core::kernel
|
||||
vProcess->setProcessEnvironment(env);
|
||||
vProcess->start(GlobalConfig.v2CorePath, QStringList() << "-config" << filePath, QIODevice::ReadWrite | QIODevice::Text);
|
||||
vProcess->waitForStarted();
|
||||
DEBUG(VCORE, "V2ray core started.")
|
||||
DEBUG(MODULE_VCORE, "V2ray core started.")
|
||||
KernelStarted = true;
|
||||
QStringList inboundTags;
|
||||
|
||||
@ -173,26 +172,26 @@ namespace Qv2ray::core::kernel
|
||||
inboundTags.append(tag);
|
||||
}
|
||||
|
||||
DEBUG(VCORE, "Found inbound tags: " + inboundTags.join(";"))
|
||||
DEBUG(MODULE_VCORE, "Found inbound tags: " + inboundTags.join(";"))
|
||||
apiEnabled = false;
|
||||
|
||||
//
|
||||
if (StartupOption.noAPI) {
|
||||
LOG(VCORE, "API has been disabled by the command line argument \"-noAPI\"")
|
||||
LOG(MODULE_VCORE, "API has been disabled by the command line argument \"-noAPI\"")
|
||||
} else if (!GlobalConfig.apiConfig.enableAPI) {
|
||||
LOG(VCORE, "API has been disabled by the global config option")
|
||||
LOG(MODULE_VCORE, "API has been disabled by the global config option")
|
||||
} else if (inboundTags.isEmpty()) {
|
||||
LOG(VCORE, "API is disabled since no inbound tags configured. This is probably caused by a bad complex config.")
|
||||
LOG(MODULE_VCORE, "API is disabled since no inbound tags configured. This is probably caused by a bad complex config.")
|
||||
} else {
|
||||
apiWorker->StartAPI(inboundTags);
|
||||
apiEnabled = true;
|
||||
DEBUG(VCORE, "Qv2ray API started")
|
||||
DEBUG(MODULE_VCORE, "Qv2ray API started")
|
||||
}
|
||||
|
||||
return true;
|
||||
return {};
|
||||
} else {
|
||||
KernelStarted = false;
|
||||
return false;
|
||||
return tr("V2ray kernel failed to start.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -226,7 +225,7 @@ namespace Qv2ray::core::kernel
|
||||
delete vProcess;
|
||||
}
|
||||
|
||||
void V2rayKernelInstance::onAPIDataReady(QString tag, long totalUp, long totalDown)
|
||||
void V2rayKernelInstance::onAPIDataReady(QString tag, qulonglong totalUp, qulonglong totalDown)
|
||||
{
|
||||
auto dataup = totalUp - transferDataUp[tag];
|
||||
transferDataUp[tag] = totalUp;
|
||||
@ -238,23 +237,23 @@ namespace Qv2ray::core::kernel
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------- API FUNCTIONS --------------------------
|
||||
long V2rayKernelInstance::getTagSpeedUp(const QString &tag)
|
||||
qulonglong V2rayKernelInstance::getTagSpeedUp(const QString &tag)
|
||||
{
|
||||
return transferSpeedUp[tag];
|
||||
}
|
||||
long V2rayKernelInstance::getTagSpeedDown(const QString &tag)
|
||||
qulonglong V2rayKernelInstance::getTagSpeedDown(const QString &tag)
|
||||
{
|
||||
return transferSpeedDown[tag];
|
||||
}
|
||||
long V2rayKernelInstance::getTagDataUp(const QString &tag)
|
||||
qulonglong V2rayKernelInstance::getTagDataUp(const QString &tag)
|
||||
{
|
||||
return transferDataUp[tag];
|
||||
}
|
||||
long V2rayKernelInstance::getTagDataDown(const QString &tag)
|
||||
qulonglong V2rayKernelInstance::getTagDataDown(const QString &tag)
|
||||
{
|
||||
return transferDataDown[tag];
|
||||
}
|
||||
long V2rayKernelInstance::getAllDataUp()
|
||||
qulonglong V2rayKernelInstance::getAllDataUp()
|
||||
{
|
||||
long val = 0;
|
||||
|
||||
@ -264,7 +263,7 @@ namespace Qv2ray::core::kernel
|
||||
|
||||
return val;
|
||||
}
|
||||
long V2rayKernelInstance::getAllDataDown()
|
||||
qulonglong V2rayKernelInstance::getAllDataDown()
|
||||
{
|
||||
long val = 0;
|
||||
|
||||
@ -274,9 +273,9 @@ namespace Qv2ray::core::kernel
|
||||
|
||||
return val;
|
||||
}
|
||||
long V2rayKernelInstance::getAllSpeedUp()
|
||||
qulonglong V2rayKernelInstance::getAllSpeedUp()
|
||||
{
|
||||
long val = 0;
|
||||
qulonglong val = 0;
|
||||
|
||||
for (auto _val : transferSpeedUp.values()) {
|
||||
val += _val;
|
||||
@ -284,9 +283,9 @@ namespace Qv2ray::core::kernel
|
||||
|
||||
return val;
|
||||
}
|
||||
long V2rayKernelInstance::getAllSpeedDown()
|
||||
qulonglong V2rayKernelInstance::getAllSpeedDown()
|
||||
{
|
||||
long val = 0;
|
||||
qulonglong val = 0;
|
||||
|
||||
for (auto _val : transferSpeedDown.values()) {
|
||||
val += _val;
|
||||
|
@ -13,16 +13,16 @@ namespace Qv2ray::core::kernel
|
||||
~V2rayKernelInstance() override;
|
||||
//
|
||||
// Speed
|
||||
long getTagSpeedUp(const QString &tag);
|
||||
long getTagSpeedDown(const QString &tag);
|
||||
long getTagDataUp(const QString &tag);
|
||||
long getTagDataDown(const QString &tag);
|
||||
long getAllDataUp();
|
||||
long getAllDataDown();
|
||||
long getAllSpeedUp();
|
||||
long getAllSpeedDown();
|
||||
qulonglong getTagSpeedUp(const QString &tag);
|
||||
qulonglong getTagSpeedDown(const QString &tag);
|
||||
qulonglong getTagDataUp(const QString &tag);
|
||||
qulonglong getTagDataDown(const QString &tag);
|
||||
qulonglong getAllDataUp();
|
||||
qulonglong getAllDataDown();
|
||||
qulonglong getAllSpeedUp();
|
||||
qulonglong getAllSpeedDown();
|
||||
//
|
||||
bool StartConnection(CONFIGROOT root);
|
||||
optional<QString> StartConnection(CONFIGROOT root);
|
||||
void StopConnection();
|
||||
bool KernelStarted = false;
|
||||
//
|
||||
@ -34,16 +34,16 @@ namespace Qv2ray::core::kernel
|
||||
void onProcessOutputReadyRead(QString);
|
||||
|
||||
public slots:
|
||||
void onAPIDataReady(QString tag, long totalUp, long totalDown);
|
||||
void onAPIDataReady(QString tag, qulonglong totalUp, qulonglong totalDown);
|
||||
|
||||
private:
|
||||
APIWorkder *apiWorker;
|
||||
QProcess *vProcess;
|
||||
bool apiEnabled;
|
||||
QMap<QString, long> transferDataUp;
|
||||
QMap<QString, long> transferDataDown;
|
||||
QMap<QString, long> transferSpeedUp;
|
||||
QMap<QString, long> transferSpeedDown;
|
||||
QMap<QString, qulonglong> transferDataUp;
|
||||
QMap<QString, qulonglong> transferDataDown;
|
||||
QMap<QString, qulonglong> transferSpeedUp;
|
||||
QMap<QString, qulonglong> transferSpeedDown;
|
||||
};
|
||||
}
|
||||
|
||||
|
91
src/main.cpp
91
src/main.cpp
@ -9,6 +9,9 @@
|
||||
#include <singleapplication.h>
|
||||
#include <csignal>
|
||||
#include "ui/w_MainWindow.hpp"
|
||||
|
||||
#include "core/config/ConfigBackend.hpp"
|
||||
#include "core/handler/ConnectionHandler.hpp"
|
||||
#include "common/QvHelpers.hpp"
|
||||
#include "common/CommandArgs.hpp"
|
||||
#include "common/QvTranslator.hpp"
|
||||
@ -21,12 +24,10 @@
|
||||
void signalHandler(int signum)
|
||||
{
|
||||
cout << "Interrupt signal (" << signum << ") received." << endl;
|
||||
|
||||
if (MainWindow::mwInstance && MainWindow::mwInstance->vinstance) {
|
||||
cout << "Trying to stop connection..." << endl;
|
||||
MainWindow::mwInstance->vinstance->StopConnection();
|
||||
}
|
||||
|
||||
//if (MainWindow::mwInstance && MainWindow::mwInstance->vinstance) {
|
||||
// cout << "Trying to stop connection..." << endl;
|
||||
// MainWindow::mwInstance->vinstance->StopConnection();
|
||||
//}
|
||||
qApp->exit(-99);
|
||||
}
|
||||
|
||||
@ -41,8 +42,8 @@ bool verifyConfigAvaliability(QString path, bool checkExistingConfig)
|
||||
bool opened = testFile.open(QFile::OpenModeFlag::ReadWrite);
|
||||
|
||||
if (!opened) {
|
||||
LOG(SETTINGS, "Directory at: " + path + " cannot be used as a valid config file path.")
|
||||
LOG(INIT, "---> Cannot create a new file or openwrite a file.")
|
||||
LOG(MODULE_SETTINGS, "Directory at: " + path + " cannot be used as a valid config file path.")
|
||||
LOG(MODULE_INIT, "---> Cannot create a new file or openwrite a file.")
|
||||
return false;
|
||||
} else {
|
||||
testFile.write("Qv2ray test file, feel free to remove.");
|
||||
@ -52,8 +53,8 @@ bool verifyConfigAvaliability(QString path, bool checkExistingConfig)
|
||||
|
||||
if (!removed) {
|
||||
// This is rare, as we can create a file but failed to remove it.
|
||||
LOG(SETTINGS, "Directory at: " + path + " cannot be used as a valid config file path.")
|
||||
LOG(INIT, "---> Cannot remove a file.")
|
||||
LOG(MODULE_SETTINGS, "Directory at: " + path + " cannot be used as a valid config file path.")
|
||||
LOG(MODULE_INIT, "---> Cannot remove a file.")
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -78,21 +79,21 @@ bool verifyConfigAvaliability(QString path, bool checkExistingConfig)
|
||||
auto err = VerifyJsonString(StringFromFile(&configFile));
|
||||
|
||||
if (!err.isEmpty()) {
|
||||
LOG(INIT, "Json parse returns: " + err)
|
||||
LOG(MODULE_INIT, "Json parse returns: " + err)
|
||||
return false;
|
||||
} else {
|
||||
// If the file format is valid.
|
||||
auto conf = JsonFromString(StringFromFile(&configFile));
|
||||
LOG(SETTINGS, "Path: " + path + " contains a config file, in version " + conf["config_version"].toVariant().toString())
|
||||
LOG(MODULE_SETTINGS, "Path: " + path + " contains a config file, in version " + conf["config_version"].toVariant().toString())
|
||||
configFile.close();
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
LOG(SETTINGS, "File: " + configFile.fileName() + " cannot be opened!")
|
||||
LOG(MODULE_SETTINGS, "File: " + configFile.fileName() + " cannot be opened!")
|
||||
return false;
|
||||
}
|
||||
} catch (...) {
|
||||
LOG(SETTINGS, "Exception raised when checking config: " + configFile.fileName())
|
||||
LOG(MODULE_SETTINGS, "Exception raised when checking config: " + configFile.fileName())
|
||||
//LOG(INIT, e->what())
|
||||
QvMessageBoxWarn(nullptr, QObject::tr("Warning"), QObject::tr("Qv2ray cannot load the config file from here:") + NEWLINE + configFile.fileName());
|
||||
return false;
|
||||
@ -102,7 +103,7 @@ bool verifyConfigAvaliability(QString path, bool checkExistingConfig)
|
||||
|
||||
bool initialiseQv2ray()
|
||||
{
|
||||
LOG(INIT, "Application exec path: " + QApplication::applicationDirPath())
|
||||
LOG(MODULE_INIT, "Application exec path: " + QApplication::applicationDirPath())
|
||||
const QString currentPathConfig = QApplication::applicationDirPath() + "/config" QV2RAY_CONFIG_DIR_SUFFIX;
|
||||
const QString configQv2ray = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + "/qv2ray" QV2RAY_CONFIG_DIR_SUFFIX;
|
||||
const QString homeQv2ray = QDir::homePath() + "/.qv2ray" QV2RAY_CONFIG_DIR_SUFFIX;
|
||||
@ -131,11 +132,11 @@ bool initialiseQv2ray()
|
||||
if (hasExistingConfig) break;
|
||||
|
||||
if (isValidConfigPath) {
|
||||
DEBUG(INIT, "Path: " + path + " is valid.")
|
||||
DEBUG(MODULE_INIT, "Path: " + path + " is valid.")
|
||||
configPath = path;
|
||||
hasExistingConfig = true;
|
||||
} else {
|
||||
LOG(INIT, "Path: " + path + " does not contain a valid config file.")
|
||||
LOG(MODULE_INIT, "Path: " + path + " does not contain a valid config file.")
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,7 +144,7 @@ bool initialiseQv2ray()
|
||||
if (hasExistingConfig) {
|
||||
// Use the config path found by the checks above
|
||||
SetConfigDirPath(configPath);
|
||||
LOG(INIT, "Using " + QV2RAY_CONFIG_DIR + " as the config path.")
|
||||
LOG(MODULE_INIT, "Using " + QV2RAY_CONFIG_DIR + " as the config path.")
|
||||
} else {
|
||||
//
|
||||
// Create new config at these dirs, these are default values for each platform.
|
||||
@ -157,7 +158,7 @@ bool initialiseQv2ray()
|
||||
// Check if the dirs are write-able
|
||||
if (mkpathResult && verifyConfigAvaliability(configPath, false)) {
|
||||
// Found a valid config dir, with write permission, but assume no config is located in it.
|
||||
LOG(INIT, "Set " + configPath + " as the config path.")
|
||||
LOG(MODULE_INIT, "Set " + configPath + " as the config path.")
|
||||
SetConfigDirPath(configPath);
|
||||
|
||||
if (QFile::exists(QV2RAY_CONFIG_FILE)) {
|
||||
@ -167,7 +168,7 @@ bool initialiseQv2ray()
|
||||
// It usually means that QV2RAY_CONFIG_FILE here is corrupted, in JSON format.
|
||||
// Otherwise Qv2ray would have loaded this config already instead of notifying to
|
||||
// create a new config in this folder.
|
||||
LOG(INIT, "This should not occur: Qv2ray config exists but failed to load.")
|
||||
LOG(MODULE_INIT, "This should not occur: Qv2ray config exists but failed to load.")
|
||||
QvMessageBoxWarn(nullptr, QObject::tr("Failed to initialise Qv2ray"),
|
||||
QObject::tr("Failed to determine the location of config file.") + NEWLINE +
|
||||
QObject::tr("Qv2ray will now exit.") + NEWLINE +
|
||||
@ -182,12 +183,12 @@ bool initialiseQv2ray()
|
||||
//
|
||||
// Save initial config.
|
||||
SaveGlobalConfig(conf);
|
||||
LOG(INIT, "Created initial config file.")
|
||||
LOG(MODULE_INIT, "Created initial config file.")
|
||||
} else {
|
||||
// None of the path above can be used as a dir for storing config.
|
||||
// Even the last folder failed to pass the check.
|
||||
LOG(INIT, "FATAL")
|
||||
LOG(INIT, " ---> CANNOT find a proper place to store Qv2ray config files.")
|
||||
LOG(MODULE_INIT, "FATAL")
|
||||
LOG(MODULE_INIT, " ---> CANNOT find a proper place to store Qv2ray config files.")
|
||||
QString searchPath = configFilePaths.join(NEWLINE);
|
||||
QvMessageBoxWarn(nullptr, QObject::tr("Cannot Start Qv2ray"),
|
||||
QObject::tr("Cannot find a place to store config files.") + NEWLINE +
|
||||
@ -201,7 +202,7 @@ bool initialiseQv2ray()
|
||||
if (!QDir(QV2RAY_GENERATED_DIR).exists()) {
|
||||
// The dir used to generate final config file, for V2ray interaction.
|
||||
QDir().mkdir(QV2RAY_GENERATED_DIR);
|
||||
LOG(INIT, "Created config generation dir at: " + QV2RAY_GENERATED_DIR)
|
||||
LOG(MODULE_INIT, "Created config generation dir at: " + QV2RAY_GENERATED_DIR)
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -262,7 +263,7 @@ int main(int argc, char *argv[])
|
||||
// finished: command line parsing
|
||||
LOG("QV2RAY_BUILD_INFO", QV2RAY_BUILD_INFO)
|
||||
LOG("QV2RAY_BUILD_EXTRA_INFO", QV2RAY_BUILD_EXTRA_INFO)
|
||||
LOG(INIT, "Qv2ray " QV2RAY_VERSION_STRING " running on " + QSysInfo::prettyProductName() + " " + QSysInfo::currentCpuArchitecture() + NEWLINE)
|
||||
LOG(MODULE_INIT, "Qv2ray " QV2RAY_VERSION_STRING " running on " + QSysInfo::prettyProductName() + " " + QSysInfo::currentCpuArchitecture() + NEWLINE)
|
||||
//
|
||||
// This line must be called before any other ones, since we are using these values to identify instances.
|
||||
SingleApplication::setApplicationName("Qv2ray");
|
||||
@ -285,7 +286,7 @@ int main(int argc, char *argv[])
|
||||
//
|
||||
// Do not install en-US as it's the default language.
|
||||
bool _result_ = _qApp.installTranslator(Qv2rayTranslator.get());
|
||||
LOG(UI, "Installing a tranlator from OS: " + _lang + " -- " + (_result_ ? "OK" : "Failed"))
|
||||
LOG(MODULE_UI, "Installing a tranlator from OS: " + _lang + " -- " + (_result_ ? "OK" : "Failed"))
|
||||
//
|
||||
LOG("LICENCE", NEWLINE "This program comes with ABSOLUTELY NO WARRANTY." NEWLINE
|
||||
"This is free software, and you are welcome to redistribute it" NEWLINE
|
||||
@ -306,7 +307,7 @@ int main(int argc, char *argv[])
|
||||
"Copyright (c) 2015-2020 qBittorrent (Anton Lashkov) (@qBittorrent): speedplotview (GPLv2)" NEWLINE
|
||||
NEWLINE)
|
||||
//
|
||||
LOG(INIT, "Qv2ray Start Time: " + QSTRN(QTime::currentTime().msecsSinceStartOfDay()))
|
||||
LOG(MODULE_INIT, "Qv2ray Start Time: " + QSTRN(QTime::currentTime().msecsSinceStartOfDay()))
|
||||
//
|
||||
#ifdef QT_DEBUG
|
||||
cout << "WARNING: ============================== This is a debug build, many features are not stable enough. ==============================" << endl;
|
||||
@ -316,11 +317,11 @@ int main(int argc, char *argv[])
|
||||
auto langs = GetFileList(QDir(":/translations"));
|
||||
|
||||
if (langs.empty()) {
|
||||
LOG(INIT, "FAILED to find any translations. THIS IS A BUILD ERROR.")
|
||||
LOG(MODULE_INIT, "FAILED to find any translations. THIS IS A BUILD ERROR.")
|
||||
QvMessageBoxWarn(nullptr, QObject::tr("Cannot load languages"), QObject::tr("Qv2ray will continue running, but you cannot change the UI language."));
|
||||
} else {
|
||||
for (auto lang : langs) {
|
||||
LOG(INIT, "Found Translator: " + lang)
|
||||
LOG(MODULE_INIT, "Found Translator: " + lang)
|
||||
}
|
||||
}
|
||||
|
||||
@ -353,18 +354,18 @@ int main(int argc, char *argv[])
|
||||
auto confObject = StructFromJsonString<Qv2rayConfig>(JsonToString(conf));
|
||||
// Remove system translator, for loading custom translations.
|
||||
qApp->removeTranslator(Qv2rayTranslator.get());
|
||||
LOG(INIT, "Removed system translations")
|
||||
LOG(MODULE_INIT, "Removed system translations")
|
||||
|
||||
if (confObject.uiConfig.language.isEmpty()) {
|
||||
// Prevent empty.
|
||||
LOG(UI, "Setting default UI language to en-US")
|
||||
LOG(MODULE_UI, "Setting default UI language to en-US")
|
||||
confObject.uiConfig.language = "en-US";
|
||||
}
|
||||
|
||||
Qv2rayTranslator = std::move(QvTranslator(confObject.uiConfig.language).pTranslator);
|
||||
|
||||
if (qApp->installTranslator(Qv2rayTranslator.get())) {
|
||||
LOG(INIT, "Successfully installed a translator for " + confObject.uiConfig.language)
|
||||
LOG(MODULE_INIT, "Successfully installed a translator for " + confObject.uiConfig.language)
|
||||
} else {
|
||||
// Do not translate these.....
|
||||
// If a translator fails to load, pop up a message.
|
||||
@ -380,11 +381,11 @@ int main(int argc, char *argv[])
|
||||
// Check OpenSSL version for auto-update and subscriptions
|
||||
auto osslReqVersion = QSslSocket::sslLibraryBuildVersionString();
|
||||
auto osslCurVersion = QSslSocket::sslLibraryVersionString();
|
||||
LOG(NETWORK, "Current OpenSSL version: " + osslCurVersion)
|
||||
LOG(MODULE_NETWORK, "Current OpenSSL version: " + osslCurVersion)
|
||||
|
||||
if (!QSslSocket::supportsSsl()) {
|
||||
LOG(NETWORK, "Required OpenSSL version: " + osslReqVersion)
|
||||
LOG(NETWORK, "OpenSSL library MISSING, Quitting.")
|
||||
LOG(MODULE_NETWORK, "Required OpenSSL version: " + osslReqVersion)
|
||||
LOG(MODULE_NETWORK, "OpenSSL library MISSING, Quitting.")
|
||||
QvMessageBoxWarn(nullptr, QObject::tr("Dependency Missing"),
|
||||
QObject::tr("Cannot find openssl libs") + NEWLINE +
|
||||
QObject::tr("This could be caused by a missing of `openssl` package in your system.") + NEWLINE +
|
||||
@ -406,7 +407,7 @@ int main(int argc, char *argv[])
|
||||
LOG(UI, "Using built-in theme.")
|
||||
|
||||
if (confObject.uiConfig.useDarkTheme) {
|
||||
LOG(UI, " --> Using built-in dark theme.")
|
||||
LOG(MODULE_UI, " --> Using built-in dark theme.")
|
||||
// From https://forum.qt.io/topic/101391/windows-10-dark-theme/4
|
||||
_qApp.setStyle("Fusion");
|
||||
QPalette darkPalette;
|
||||
@ -442,17 +443,20 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (themes.contains(confObject.uiConfig.theme)) {
|
||||
_qApp.setStyle(confObject.uiConfig.theme);
|
||||
LOG(INIT + " " + UI, "Setting Qv2ray UI themes: " + confObject.uiConfig.theme)
|
||||
LOG(MODULE_INIT + " " + MODULE_UI, "Setting Qv2ray UI themes: " + confObject.uiConfig.theme)
|
||||
}
|
||||
|
||||
#endif
|
||||
// Show MainWindow
|
||||
MainWindow w;
|
||||
#ifndef QT_DEBUG
|
||||
|
||||
try {
|
||||
#endif
|
||||
QObject::connect(&_qApp, &SingleApplication::instanceStarted, [&w]() {
|
||||
//_qApp.setAttribute(Qt::AA_DontUseNativeMenuBar);
|
||||
// Initialise Connection Handler
|
||||
ConnectionHandler = new QvConnectionHandler();
|
||||
// Show MainWindow
|
||||
MainWindow w;
|
||||
QObject::connect(&_qApp, &SingleApplication::instanceStarted, [&]() {
|
||||
// When a second instance is connected, show the mainwindow.
|
||||
w.show();
|
||||
w.raise();
|
||||
@ -462,7 +466,7 @@ int main(int argc, char *argv[])
|
||||
// Will not block.
|
||||
QGuiApplication::setFallbackSessionManagementEnabled(false);
|
||||
QObject::connect(&_qApp, &QGuiApplication::commitDataRequest, []() {
|
||||
LOG(INIT, "Quit triggered by session manager.")
|
||||
LOG(MODULE_INIT, "Quit triggered by session manager.")
|
||||
});
|
||||
#ifndef Q_OS_WIN
|
||||
signal(SIGUSR1, [](int) {
|
||||
@ -473,12 +477,13 @@ int main(int argc, char *argv[])
|
||||
});
|
||||
#endif
|
||||
auto rcode = _qApp.exec();
|
||||
LOG(INIT, "Quitting normally")
|
||||
delete ConnectionHandler;
|
||||
LOG(MODULE_INIT, "Quitting normally")
|
||||
return rcode;
|
||||
#ifndef QT_DEBUG
|
||||
} catch (...) {
|
||||
QvMessageBoxWarn(nullptr, "ERROR", "There's something wrong happened and Qv2ray will quit now.");
|
||||
LOG(INIT, "EXCEPTION THROWN: " __FILE__)
|
||||
LOG(MODULE_INIT, "EXCEPTION THROWN: " __FILE__)
|
||||
return -99;
|
||||
}
|
||||
|
||||
|
@ -27,11 +27,11 @@ InboundEditor::InboundEditor(INBOUND root, QWidget *parent) :
|
||||
mtSettings = root["settings"].toObject();
|
||||
} else {
|
||||
if (!root["protocol"].toString().isEmpty()) {
|
||||
LOG(UI, "Unsupported inbound type: " + inboundType)
|
||||
LOG(MODULE_UI, "Unsupported inbound type: " + inboundType)
|
||||
QvMessageBoxWarn(this, tr("Inbound type not supported"), tr("The inbound type is not supported by Qv2ray (yet). Please use JsonEditor to change the settings") + "\r\n" +
|
||||
tr("Inbound: ") + inboundType);
|
||||
} else {
|
||||
LOG(UI, "Creating new inbound config")
|
||||
LOG(MODULE_UI, "Creating new inbound config")
|
||||
root["protocol"] = inboundType = "http";
|
||||
}
|
||||
}
|
||||
@ -201,7 +201,7 @@ void InboundEditor::on_httpRemoveUserBtn_clicked()
|
||||
if (entry == item->text().trimmed()) {
|
||||
list.removeAt(i);
|
||||
httpSettings["accounts"] = list;
|
||||
LOG(UI, "Removed http inbound user " + entry)
|
||||
LOG(MODULE_UI, "Removed http inbound user " + entry)
|
||||
httpAccountListBox->takeItem(httpAccountListBox->currentRow());
|
||||
}
|
||||
}
|
||||
@ -254,7 +254,7 @@ void InboundEditor::on_socksRemoveUserBtn_clicked()
|
||||
if (entry == item->text().trimmed()) {
|
||||
list.removeAt(i);
|
||||
socksSettings["accounts"] = list;
|
||||
LOG(UI, "Removed http inbound user " + entry)
|
||||
LOG(MODULE_UI, "Removed http inbound user " + entry)
|
||||
socksAccountListBox->takeItem(socksAccountListBox->currentRow());
|
||||
return;
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ JsonEditor::JsonEditor(QJsonObject rootObject, QWidget *parent) :
|
||||
QString jsonString = JsonToString(rootObject);
|
||||
|
||||
if (VerifyJsonString(jsonString).isEmpty()) {
|
||||
LOG(UI, "Begin loading Json Model")
|
||||
LOG(MODULE_UI, "Begin loading Json Model")
|
||||
jsonTree->setModel(&model);
|
||||
model.loadJson(QJsonDocument(rootObject).toJson());
|
||||
} else {
|
||||
|
@ -113,13 +113,13 @@ OUTBOUND OutboundEditor::GenerateConnectionJson()
|
||||
settings.insert("vnext", vnext);
|
||||
} else if (OutboundType == "shadowsocks") {
|
||||
streaming = QJsonObject();
|
||||
LOG(CONNECTION, "Shadowsocks outbound does not need StreamSettings.")
|
||||
LOG(MODULE_CONNECTION, "Shadowsocks outbound does not need StreamSettings.")
|
||||
QJsonArray servers;
|
||||
servers.append(GetRootObject(shadowsocks));
|
||||
settings["servers"] = servers;
|
||||
} else if (OutboundType == "socks") {
|
||||
streaming = QJsonObject();
|
||||
LOG(CONNECTION, "Socks outbound does not need StreamSettings.")
|
||||
LOG(MODULE_CONNECTION, "Socks outbound does not need StreamSettings.")
|
||||
QJsonArray servers;
|
||||
servers.append(GetRootObject(socks));
|
||||
settings["servers"] = servers;
|
||||
|
@ -12,9 +12,9 @@
|
||||
#include "ui/w_ImportConfig.hpp"
|
||||
#include "core/CoreUtils.hpp"
|
||||
|
||||
#include "ui/nodemodels/RuleNodeModel.hpp"
|
||||
#include "ui/nodemodels/InboundNodeModel.hpp"
|
||||
#include "ui/nodemodels/OutboundNodeModel.hpp"
|
||||
#include "ui/models/RuleNodeModel.hpp"
|
||||
#include "ui/models/InboundNodeModel.hpp"
|
||||
#include "ui/models/OutboundNodeModel.hpp"
|
||||
|
||||
#include "NodeStyle.hpp"
|
||||
#include "FlowView.hpp"
|
||||
@ -29,7 +29,7 @@ static bool isLoading = false;
|
||||
#define GetFirstNodeData(node, nodeModel, dataModel) (static_cast<dataModel *>(static_cast<nodeModel *>((node).nodeDataModel())->outData(0).get()))
|
||||
|
||||
#define CHECKEMPTYRULES if (this->rules.isEmpty()) { \
|
||||
LOG(UI, "No rules currently, we add one.") \
|
||||
LOG(MODULE_UI, "No rules currently, we add one.") \
|
||||
AddNewRule(); \
|
||||
}
|
||||
|
||||
@ -143,7 +143,7 @@ void RouteEditor::onNodeClicked(Node &n)
|
||||
if (isRule) {
|
||||
// It's a rule object
|
||||
currentRuleTag = GetFirstNodeData(n, QvRuleNodeDataModel, RuleNodeData)->GetRuleTag();
|
||||
DEBUG(GRAPH, "Selecting rule: " + currentRuleTag)
|
||||
DEBUG(MODULE_GRAPH, "Selecting rule: " + currentRuleTag)
|
||||
ShowCurrentRuleDetail();
|
||||
toolBox->setCurrentIndex(1);
|
||||
} else if (isOut || isIn) {
|
||||
@ -171,7 +171,7 @@ void RouteEditor::onNodeClicked(Node &n)
|
||||
portLabel->setNum(port);
|
||||
hostLabel->setText(host);
|
||||
} else {
|
||||
LOG(GRAPH, "Selected an unknown node, RARE.")
|
||||
LOG(MODULE_GRAPH, "Selected an unknown node, RARE.")
|
||||
}
|
||||
}
|
||||
|
||||
@ -190,7 +190,7 @@ void RouteEditor::onConnectionCreated(QtNodes::Connection const &c)
|
||||
// It's a inbound-rule connection
|
||||
onNodeClicked(*sourceNode);
|
||||
onNodeClicked(*targetNode);
|
||||
LOG(GRAPH, "Inbound-rule new connection.")
|
||||
LOG(MODULE_GRAPH, "Inbound-rule new connection.")
|
||||
// Get all connected inbounds to this rule node.
|
||||
// QStringList has an helper to let us remove duplicates, see below.
|
||||
QStringList _inbounds;
|
||||
@ -219,10 +219,10 @@ void RouteEditor::onConnectionCreated(QtNodes::Connection const &c)
|
||||
CurrentRule.QV2RAY_RULE_USE_BALANCER = false;
|
||||
// Update balancer settings.
|
||||
ShowCurrentRuleDetail();
|
||||
LOG(GRAPH, "Updated outbound: " + CurrentRule.outboundTag)
|
||||
LOG(MODULE_GRAPH, "Updated outbound: " + CurrentRule.outboundTag)
|
||||
} else {
|
||||
// It's an impossible connection
|
||||
LOG(GRAPH, "Unrecognized connection, RARE.")
|
||||
LOG(MODULE_GRAPH, "Unrecognized connection, RARE.")
|
||||
}
|
||||
}
|
||||
|
||||
@ -242,7 +242,7 @@ void RouteEditor::onConnectionDeleted(QtNodes::Connection const &c)
|
||||
onNodeClicked(*target);
|
||||
currentRuleTag = GetFirstNodeData(*target, QvRuleNodeDataModel, RuleNodeData)->GetRuleTag();
|
||||
auto _inboundTag = GetFirstNodeData(*source, QvInboundNodeModel, InboundNodeData)->GetInbound();
|
||||
LOG(UI, "Removing inbound: " + _inboundTag + " from rule: " + currentRuleTag)
|
||||
LOG(MODULE_UI, "Removing inbound: " + _inboundTag + " from rule: " + currentRuleTag)
|
||||
CurrentRule.inboundTag.removeAll(_inboundTag);
|
||||
} else if (ruleNodes.values().contains(source) && outboundNodes.values().contains(target)) {
|
||||
// It's a rule-outbound connection
|
||||
@ -255,10 +255,10 @@ void RouteEditor::onConnectionDeleted(QtNodes::Connection const &c)
|
||||
CurrentRule.outboundTag.clear();
|
||||
}
|
||||
|
||||
LOG(GRAPH, "Removing an outbound: " + _outboundTag)
|
||||
LOG(MODULE_GRAPH, "Removing an outbound: " + _outboundTag)
|
||||
} else {
|
||||
// It's an impossible connection
|
||||
LOG(GRAPH, "Selected an unknown node, RARE.")
|
||||
LOG(MODULE_GRAPH, "Selected an unknown node, RARE.")
|
||||
}
|
||||
}
|
||||
|
||||
@ -288,7 +288,7 @@ CONFIGROOT RouteEditor::OpenEditor()
|
||||
|
||||
// Find balancer list
|
||||
if (!balancers.contains(_rule.balancerTag)) {
|
||||
LOG(UI, "Cannot find a balancer for tag: " + _rule.balancerTag)
|
||||
LOG(MODULE_UI, "Cannot find a balancer for tag: " + _rule.balancerTag)
|
||||
} else {
|
||||
auto _balancerList = balancers[_rule.balancerTag];
|
||||
QJsonObject balancerEntry;
|
||||
@ -331,7 +331,7 @@ CONFIGROOT RouteEditor::OpenEditor()
|
||||
continue;
|
||||
|
||||
if (getTag(x) == defaultOutbound) {
|
||||
LOG(CONNECTION, "Pushing default outbound to the front.")
|
||||
LOG(MODULE_CONNECTION, "Pushing default outbound to the front.")
|
||||
// Put the default outbound to the first.
|
||||
_outbounds.push_front(x.raw());
|
||||
} else {
|
||||
@ -363,13 +363,13 @@ void RouteEditor::ShowCurrentRuleDetail()
|
||||
LOADINGCHECK
|
||||
|
||||
if (currentRuleTag.isEmpty()) {
|
||||
LOG(UI, "WARNING, trying to access a non-exist rule entry. return.")
|
||||
LOG(MODULE_UI, "WARNING, trying to access a non-exist rule entry. return.")
|
||||
return;
|
||||
}
|
||||
|
||||
if (!rules.contains(currentRuleTag)) {
|
||||
QvMessageBoxWarn(this, tr("Show rule details"), tr("A rule cannot be found: ") + currentRuleTag);
|
||||
LOG(UI, "WARNING, trying to access a non-exist rule entry. return.")
|
||||
LOG(MODULE_UI, "WARNING, trying to access a non-exist rule entry. return.")
|
||||
return;
|
||||
}
|
||||
|
||||
@ -570,15 +570,15 @@ void RouteEditor::on_enableBalancerCB_stateChanged(int arg1)
|
||||
balancersWidget->setEnabled(useBalancer);
|
||||
|
||||
if (CurrentRule.balancerTag.isEmpty()) {
|
||||
LOG(UI, "Creating a new balancer tag.")
|
||||
LOG(MODULE_UI, "Creating a new balancer tag.")
|
||||
CurrentRule.balancerTag = GenerateRandomString(6);
|
||||
balancers[CurrentRule.balancerTag] = QStringList();
|
||||
}
|
||||
|
||||
DEBUG(UI, "Balancer: " + CurrentRule.balancerTag)
|
||||
DEBUG(MODULE_UI, "Balancer: " + CurrentRule.balancerTag)
|
||||
|
||||
if (useBalancer) {
|
||||
LOG(UI, "A rule has been set to use balancer, disconnect it to any outbound.")
|
||||
LOG(MODULE_UI, "A rule has been set to use balancer, disconnect it to any outbound.")
|
||||
auto ruleNode = ruleNodes[currentRuleTag];
|
||||
|
||||
for (auto conn : Qv2ray::common::Values(nodeScene->connections())) {
|
||||
@ -723,7 +723,7 @@ void RouteEditor::on_delBtn_clicked()
|
||||
//currentRuleTag = rules.firstKey();
|
||||
//ShowCurrentRuleDetail();
|
||||
} else {
|
||||
LOG(UI, "Unknown node selected.")
|
||||
LOG(MODULE_UI, "Unknown node selected.")
|
||||
QvMessageBoxWarn(this, tr("Error"), tr("Qv2ray entered an unknown state."));
|
||||
}
|
||||
}
|
||||
@ -773,9 +773,9 @@ void RouteEditor::on_editBtn_clicked()
|
||||
RenameItemTag(RENAME_INBOUND, getTag(_in), getTag(_result));
|
||||
}
|
||||
|
||||
DEBUG(UI, "Removed old tag: " + getTag(_in))
|
||||
DEBUG(MODULE_UI, "Removed old tag: " + getTag(_in))
|
||||
inbounds.remove(getTag(_in));
|
||||
DEBUG(UI, "Adding new tag: " + getTag(_result))
|
||||
DEBUG(MODULE_UI, "Adding new tag: " + getTag(_result))
|
||||
inbounds[getTag(_result)] = _result;
|
||||
}
|
||||
} else if (isOutbound) {
|
||||
@ -810,18 +810,18 @@ void RouteEditor::on_editBtn_clicked()
|
||||
bool isTagChanged = getTag(_out) != getTag(_result);
|
||||
|
||||
if (isTagChanged) {
|
||||
DEBUG(UI, "Outbound tag is changed: " + QString(isTagChanged))
|
||||
DEBUG(MODULE_UI, "Outbound tag is changed: " + QString(isTagChanged))
|
||||
RenameItemTag(RENAME_OUTBOUND, getTag(_out), getTag(_result));
|
||||
DEBUG(UI, "Removed old tag: " + getTag(_out))
|
||||
DEBUG(MODULE_UI, "Removed old tag: " + getTag(_out))
|
||||
outbounds.remove(getTag(_out));
|
||||
}
|
||||
|
||||
DEBUG(UI, "Adding new tag: " + getTag(_result))
|
||||
DEBUG(MODULE_UI, "Adding new tag: " + getTag(_result))
|
||||
outbounds[getTag(_result)] = _result;
|
||||
statusLabel->setText(tr("OK"));
|
||||
}
|
||||
} else {
|
||||
LOG(UI, "Cannot apply 'edit' operation to non-inbound and non-outbound")
|
||||
LOG(MODULE_UI, "Cannot apply 'edit' operation to non-inbound and non-outbound")
|
||||
}
|
||||
}
|
||||
|
||||
@ -842,13 +842,13 @@ void RouteEditor::on_ruleRenameBtn_clicked()
|
||||
auto newTag = ruleTagLineEdit->text();
|
||||
|
||||
if (newTag.isEmpty()) {
|
||||
LOG(UI, "Tag is empty, this is ILLEGAL!")
|
||||
LOG(MODULE_UI, "Tag is empty, this is ILLEGAL!")
|
||||
QvMessageBoxWarn(this, tr("Renaming a tag"), tr("New tag is empty, please try another."));
|
||||
} else if (newTag == CurrentRule.QV2RAY_RULE_TAG) {
|
||||
LOG(UI, "No tag changed, returning.")
|
||||
LOG(MODULE_UI, "No tag changed, returning.")
|
||||
QvMessageBoxInfo(this, tr("Renaming a tag"), tr("New tag is the same as the original one."));
|
||||
} else if (rules.contains(newTag)) {
|
||||
LOG(UI, "Tag duplicate detected.")
|
||||
LOG(MODULE_UI, "Tag duplicate detected.")
|
||||
QvMessageBoxWarn(this, tr("Renaming a tag"), tr("Duplicate rule tag detected, please try another."));
|
||||
} else {
|
||||
RenameItemTag(RENAME_RULE, CurrentRule.QV2RAY_RULE_TAG, newTag);
|
||||
|
@ -78,7 +78,7 @@ void RouteEditor::AddRule(RuleObject rule)
|
||||
|
||||
for (auto inTag : rule.inboundTag) {
|
||||
if (!inboundNodes.contains(inTag)) {
|
||||
LOG(UI, "No inbound tag found for rule: " + rule.QV2RAY_RULE_TAG + ", inbound tag: " + inTag)
|
||||
LOG(MODULE_UI, "No inbound tag found for rule: " + rule.QV2RAY_RULE_TAG + ", inbound tag: " + inTag)
|
||||
QvMessageBoxWarn(this, tr("No Inbound"), tr("No inbound item found: ") + inTag);
|
||||
rule.inboundTag.removeAll(inTag);
|
||||
} else {
|
||||
@ -90,10 +90,10 @@ void RouteEditor::AddRule(RuleObject rule)
|
||||
// If not using balancers (use outbound tag)
|
||||
if (!rule.QV2RAY_RULE_USE_BALANCER) {
|
||||
if (outboundNodes.contains(rule.outboundTag)) {
|
||||
DEBUG(GRAPH, "Found outbound tag: " + rule.outboundTag + ", for rule: " + rule.QV2RAY_RULE_TAG)
|
||||
DEBUG(MODULE_GRAPH, "Found outbound tag: " + rule.outboundTag + ", for rule: " + rule.QV2RAY_RULE_TAG)
|
||||
nodeScene->createConnection(*outboundNodes[rule.outboundTag], 0, node, 0);
|
||||
} else {
|
||||
LOG(GRAPH, "Outbound tag not found: " + rule.outboundTag + ", for: " + rule.QV2RAY_RULE_TAG)
|
||||
LOG(MODULE_GRAPH, "Outbound tag not found: " + rule.outboundTag + ", for: " + rule.QV2RAY_RULE_TAG)
|
||||
//QvMessageBoxWarn(this, tr("No outbound tag"), tr("Please connect the rule with an outbound."));
|
||||
}
|
||||
}
|
||||
@ -116,7 +116,7 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag,
|
||||
auto node = static_cast<QvRuleNodeDataModel *>(ruleNodes[originalTag]->nodeDataModel());
|
||||
|
||||
if (node == nullptr) {
|
||||
LOG(GRAPH, "EMPTY NODE WARN")
|
||||
LOG(MODULE_GRAPH, "EMPTY NODE WARN")
|
||||
}
|
||||
|
||||
node->setData(newTag);
|
||||
@ -129,7 +129,7 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag,
|
||||
auto items = ruleListWidget->findItems(originalTag, Qt::MatchExactly);
|
||||
|
||||
if (items.isEmpty()) {
|
||||
LOG(UI, "Cannot find a node: " + originalTag)
|
||||
LOG(MODULE_UI, "Cannot find a node: " + originalTag)
|
||||
} else {
|
||||
items.first()->setText(newTag);
|
||||
}
|
||||
@ -138,7 +138,7 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag,
|
||||
currentRuleTag = newTag;
|
||||
}
|
||||
} else {
|
||||
LOG(UI, "There's nothing match " + originalTag + " in the containers.")
|
||||
LOG(MODULE_UI, "There's nothing match " + originalTag + " in the containers.")
|
||||
}
|
||||
|
||||
break;
|
||||
@ -155,7 +155,7 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag,
|
||||
auto node = static_cast<QvOutboundNodeModel *>(outboundNodes[newTag]->nodeDataModel());
|
||||
|
||||
if (node == nullptr) {
|
||||
LOG(GRAPH, "EMPTY NODE WARN")
|
||||
LOG(MODULE_GRAPH, "EMPTY NODE WARN")
|
||||
}
|
||||
|
||||
node->setData(newTag);
|
||||
@ -174,7 +174,7 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag,
|
||||
// Resolve default outbound.
|
||||
ResolveDefaultOutboundTag(originalTag, newTag);
|
||||
} else {
|
||||
LOG(UI, "Failed to rename an outbound --> Item not found.")
|
||||
LOG(MODULE_UI, "Failed to rename an outbound --> Item not found.")
|
||||
}
|
||||
|
||||
break;
|
||||
@ -191,7 +191,7 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag,
|
||||
auto node = static_cast<QvInboundNodeModel *>(inboundNodes[newTag]->nodeDataModel());
|
||||
|
||||
if (node == nullptr) {
|
||||
LOG(GRAPH, "EMPTY NODE WARN")
|
||||
LOG(MODULE_GRAPH, "EMPTY NODE WARN")
|
||||
}
|
||||
|
||||
node->setData(newTag);
|
||||
@ -210,7 +210,7 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOG(UI, "Failed to rename an outbound --> Item not found.")
|
||||
LOG(MODULE_UI, "Failed to rename an outbound --> Item not found.")
|
||||
}
|
||||
|
||||
break;
|
||||
@ -219,17 +219,17 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag,
|
||||
|
||||
void RouteEditor::ResolveDefaultOutboundTag(QString original, QString newTag)
|
||||
{
|
||||
LOG(UI, "Resolving default outbound settings: default=" + defaultOutbound + " original=" + original + " new=" + newTag)
|
||||
LOG(MODULE_UI, "Resolving default outbound settings: default=" + defaultOutbound + " original=" + original + " new=" + newTag)
|
||||
auto isDefaultChanged = original == defaultOutbound;
|
||||
defaultOutboundCombo->clear();
|
||||
defaultOutboundCombo->addItems(outbounds.keys());
|
||||
|
||||
if (!isDefaultChanged) {
|
||||
LOG(UI, "Default outbound is not changed: retaining: " + defaultOutbound)
|
||||
LOG(MODULE_UI, "Default outbound is not changed: retaining: " + defaultOutbound)
|
||||
// Just simply restore the default one.
|
||||
defaultOutboundCombo->setCurrentText(defaultOutbound);
|
||||
} else if (newTag.isEmpty()) {
|
||||
LOG(UI, "Default outbound is removed, using first key from the outbounds as the default one.")
|
||||
LOG(MODULE_UI, "Default outbound is removed, using first key from the outbounds as the default one.")
|
||||
|
||||
// Removed the default one, so set the first one as the default.
|
||||
if (outbounds.isEmpty()) {
|
||||
@ -239,7 +239,7 @@ void RouteEditor::ResolveDefaultOutboundTag(QString original, QString newTag)
|
||||
defaultOutboundCombo->addItem(outbounds.firstKey());
|
||||
}
|
||||
} else {
|
||||
LOG(UI, "Default outbound is renamed, ")
|
||||
LOG(MODULE_UI, "Default outbound is renamed, ")
|
||||
defaultOutboundCombo->setCurrentText(newTag);
|
||||
defaultOutbound = newTag;
|
||||
}
|
||||
|
@ -13,13 +13,13 @@ namespace Qv2ray::ui::messaging
|
||||
void QvMessageBusObject::on_QvMessageReceived(QvMessage msg)
|
||||
{
|
||||
QMetaEnum metaEnum = QMetaEnum::fromType<QvMessage>();
|
||||
DEBUG(MESSAGING, "Signal recieved: " + QString(metaEnum.valueToKey(msg)));
|
||||
DEBUG(MODULE_MESSAGING, "Signal recieved: " + QString(metaEnum.valueToKey(msg)));
|
||||
}
|
||||
|
||||
void QvMessageBusObject::EmitGlobalSignal(QvMessage msg)
|
||||
{
|
||||
QMetaEnum metaEnum = QMetaEnum::fromType<QvMessage>();
|
||||
LOG(MESSAGING, "Emitting signal: " + QString(metaEnum.valueToKey(msg)));
|
||||
LOG(MODULE_MESSAGING, "Emitting signal: " + QString(metaEnum.valueToKey(msg)));
|
||||
emit QvSendMessage(msg);
|
||||
}
|
||||
}
|
||||
|
0
src/ui/models/ConnectionTreeModel.cpp
Normal file
0
src/ui/models/ConnectionTreeModel.cpp
Normal file
0
src/ui/models/ConnectionTreeModel.hpp
Normal file
0
src/ui/models/ConnectionTreeModel.hpp
Normal file
@ -1,4 +1,4 @@
|
||||
#include "ui/nodemodels/InboundNodeModel.hpp"
|
||||
#include "ui/models/InboundNodeModel.hpp"
|
||||
|
||||
QvInboundNodeModel::QvInboundNodeModel(std::shared_ptr<InboundNodeData> data): NodeDataModel()
|
||||
{
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
#include "ui/nodemodels/NodeModelsBase.hpp"
|
||||
#include "ui/models/NodeModelsBase.hpp"
|
||||
|
||||
class QvInboundNodeModel : public NodeDataModel
|
||||
{
|
@ -18,7 +18,7 @@ using QtNodes::NodeValidationState;
|
||||
using QtNodes::NodeDataType;
|
||||
using QtNodes::NodeData;
|
||||
|
||||
#define GRAPH_NODE_LABEL_FONTSIZE_INCREMENT 3
|
||||
const int GRAPH_NODE_LABEL_FONTSIZE_INCREMENT = 3;
|
||||
|
||||
namespace Qv2ray::ui::nodemodels
|
||||
{
|
||||
@ -31,7 +31,7 @@ namespace Qv2ray::ui::nodemodels
|
||||
public:
|
||||
InboundNodeData()
|
||||
{
|
||||
DEBUG(GRAPH, "DANGER: Initialising a data model without value.")
|
||||
DEBUG(MODULE_GRAPH, "DANGER: Initialising a data model without value.")
|
||||
}
|
||||
InboundNodeData(QString in) : _inboundTag(in) { }
|
||||
|
||||
@ -55,7 +55,7 @@ namespace Qv2ray::ui::nodemodels
|
||||
public:
|
||||
OutboundNodeData() : _outboundTag()
|
||||
{
|
||||
DEBUG(GRAPH, "DANGER: Initialising a data model without value.")
|
||||
DEBUG(MODULE_GRAPH, "DANGER: Initialising a data model without value.")
|
||||
}
|
||||
OutboundNodeData(QString out) : _outboundTag(out) { }
|
||||
|
||||
@ -79,7 +79,7 @@ namespace Qv2ray::ui::nodemodels
|
||||
public:
|
||||
RuleNodeData() : _ruleTag()
|
||||
{
|
||||
DEBUG(GRAPH, "DANGER: Initialising a data model without value.")
|
||||
DEBUG(MODULE_GRAPH, "DANGER: Initialising a data model without value.")
|
||||
}
|
||||
RuleNodeData(QString out) : _ruleTag(out) { }
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "ui/nodemodels/OutboundNodeModel.hpp"
|
||||
#include "ui/models/OutboundNodeModel.hpp"
|
||||
|
||||
QvOutboundNodeModel::QvOutboundNodeModel(std::shared_ptr<OutboundNodeData> data): NodeDataModel()
|
||||
{
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include <QtCore/qglobal.h>
|
||||
#include "ui/nodemodels/NodeModelsBase.hpp"
|
||||
#include "ui/models/NodeModelsBase.hpp"
|
||||
|
||||
class QvOutboundNodeModel : public NodeDataModel
|
||||
{
|
@ -1,4 +1,4 @@
|
||||
#include "ui/nodemodels/RuleNodeModel.hpp"
|
||||
#include "ui/models/RuleNodeModel.hpp"
|
||||
|
||||
QvRuleNodeDataModel::QvRuleNodeDataModel(std::shared_ptr<RuleNodeData> data): NodeDataModel()
|
||||
{
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
#include "ui/nodemodels/NodeModelsBase.hpp"
|
||||
#include "ui/models/NodeModelsBase.hpp"
|
||||
|
||||
class QvRuleNodeDataModel : public NodeDataModel
|
||||
{
|
@ -25,16 +25,18 @@ ConfigExporter::~ConfigExporter()
|
||||
{
|
||||
}
|
||||
|
||||
ConfigExporter::ConfigExporter(const CONFIGROOT &root, const ConnectionIdentifier &alias, QWidget *parent) : ConfigExporter(parent)
|
||||
{
|
||||
message = ConvertConfigToString(root, alias.IdentifierString());
|
||||
//
|
||||
QZXingEncoderConfig conf;
|
||||
conf.border = true;
|
||||
conf.imageSize = QSize(400, 400);
|
||||
auto img = qzxing.encodeData(message, conf);
|
||||
image = img.copy();
|
||||
}
|
||||
//ConfigExporter::ConfigExporter(QWidget *parent) : ConfigExporter(parent)
|
||||
//{
|
||||
// // WIP
|
||||
// // /auto &x = connection;
|
||||
// //message = ConvertConfigToString(root, alias.IdentifierString());
|
||||
// //
|
||||
// QZXingEncoderConfig conf;
|
||||
// conf.border = true;
|
||||
// conf.imageSize = QSize(400, 400);
|
||||
// auto img = qzxing.encodeData(message, conf);
|
||||
// image = img.copy();
|
||||
//}
|
||||
|
||||
void ConfigExporter::OpenExport()
|
||||
{
|
||||
@ -73,7 +75,7 @@ void ConfigExporter::on_saveBtn_clicked()
|
||||
auto filePath = QFileDialog().getSaveFileName(this, tr("Save Image"), "", "Images (*.png)");
|
||||
auto result = image.save(filePath);
|
||||
QDesktopServices::openUrl(QUrl::fromUserInput(filePath));
|
||||
LOG(FILEIO, "Saving an image to: " + filePath + " result: " + (result ? "OK" : "Failed"))
|
||||
LOG(MODULE_FILEIO, "Saving an image to: " + filePath + " result: " + (result ? "OK" : "Failed"))
|
||||
}
|
||||
|
||||
void ConfigExporter::on_copyImageBtn_clicked()
|
||||
|
@ -10,7 +10,7 @@ class ConfigExporter : public QDialog, private Ui::ExportConfigWindow
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ConfigExporter(const CONFIGROOT &root, const ConnectionIdentifier &alias, QWidget *parent = nullptr);
|
||||
explicit ConfigExporter(QWidget *parent = nullptr);
|
||||
~ConfigExporter();
|
||||
void OpenExport();
|
||||
public slots:
|
||||
@ -25,9 +25,7 @@ class ConfigExporter : public QDialog, private Ui::ExportConfigWindow
|
||||
void on_copyImageBtn_clicked();
|
||||
|
||||
void on_copyVMessBtn_clicked();
|
||||
|
||||
private:
|
||||
explicit ConfigExporter(QWidget *parent);
|
||||
QZXing qzxing;
|
||||
QImage image;
|
||||
QString message;
|
||||
|
@ -84,7 +84,7 @@ void ImportConfigWindow::on_qrFromScreenBtn_clicked()
|
||||
//auto str = QZXing().decodeImage(pix);
|
||||
|
||||
if (str.trimmed().isEmpty()) {
|
||||
LOG(UI, "Cannot decode QR Code from an image, size: h=" + QSTRN(pix.width()) + ", v=" + QSTRN(pix.height()))
|
||||
LOG(MODULE_UI, "Cannot decode QR Code from an image, size: h=" + QSTRN(pix.width()) + ", v=" + QSTRN(pix.height()))
|
||||
QvMessageBoxWarn(this, tr("Capture QRCode"), tr("Cannot find a valid QRCode from this region."));
|
||||
} else {
|
||||
vmessConnectionStringTxt->appendPlainText(str.trimmed() + NEWLINE);
|
||||
@ -101,19 +101,19 @@ void ImportConfigWindow::on_beginImportBtn_clicked()
|
||||
|
||||
switch (tabWidget->currentIndex()) {
|
||||
case 0: {
|
||||
// From File...
|
||||
bool ImportAsComplex = keepImportedInboundCheckBox->isChecked();
|
||||
QString path = fileLineTxt->text();
|
||||
|
||||
if (!V2rayKernelInstance::ValidateConfig(path)) {
|
||||
QvMessageBoxWarn(this, tr("Import config file"), tr("Failed to check the validity of the config file."));
|
||||
return;
|
||||
}
|
||||
|
||||
aliasPrefix += "_" + QFileInfo(path).fileName();
|
||||
CONFIGROOT config = ConvertConfigFromFile(path, ImportAsComplex);
|
||||
connections[aliasPrefix] = config;
|
||||
break;
|
||||
//// From File...
|
||||
//bool ImportAsComplex = keepImportedInboundCheckBox->isChecked();
|
||||
//QString path = fileLineTxt->text();
|
||||
//
|
||||
//if (!V2rayKernelInstance::ValidateConfig(path)) {
|
||||
// QvMessageBoxWarn(this, tr("Import config file"), tr("Failed to check the validity of the config file."));
|
||||
// return;
|
||||
//}
|
||||
//
|
||||
//aliasPrefix += "_" + QFileInfo(path).fileName();
|
||||
////CONFIGROOT config = ConvertConfigFromFile(path, ImportAsComplex);
|
||||
//connections[aliasPrefix] = config;
|
||||
//break;
|
||||
}
|
||||
|
||||
case 1: {
|
||||
@ -124,7 +124,7 @@ void ImportConfigWindow::on_beginImportBtn_clicked()
|
||||
vmessConnectionStringTxt->clear();
|
||||
errorsList->clear();
|
||||
//
|
||||
LOG(IMPORT, QSTRN(linkList.count()) + " string found in vmess box.")
|
||||
LOG(MODULE_IMPORT, QSTRN(linkList.count()) + " string found in vmess box.")
|
||||
|
||||
while (!linkList.isEmpty()) {
|
||||
aliasPrefix = nameTxt->text();
|
||||
@ -217,12 +217,12 @@ void ImportConfigWindow::on_editFileBtn_clicked()
|
||||
auto jsonCheckingError = VerifyJsonString(jsonString);
|
||||
|
||||
if (!jsonCheckingError.isEmpty()) {
|
||||
LOG(FILEIO, "Currupted JSON file detected")
|
||||
LOG(MODULE_FILEIO, "Currupted JSON file detected")
|
||||
|
||||
if (QvMessageBoxAsk(this, tr("Edit file as JSON"), tr("The file you selected has json syntax error. Continue editing may make you lose data. Would you like to continue?") + NEWLINE + jsonCheckingError) != QMessageBox::Yes) {
|
||||
return;
|
||||
} else {
|
||||
LOG(FILEIO, "Continue editing curruped json file, data loss is expected.")
|
||||
LOG(MODULE_FILEIO, "Continue editing curruped json file, data loss is expected.")
|
||||
}
|
||||
}
|
||||
|
||||
@ -238,7 +238,7 @@ void ImportConfigWindow::on_editFileBtn_clicked()
|
||||
QvMessageBoxWarn(this, tr("Edit file as JSON"), tr("Failed to save file, please check if you have proper permissions"));
|
||||
}
|
||||
} else {
|
||||
LOG(FILEIO, "Canceled saving a file.")
|
||||
LOG(MODULE_FILEIO, "Canceled saving a file.")
|
||||
}
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -7,30 +7,20 @@
|
||||
|
||||
#include "ui_w_MainWindow.h"
|
||||
|
||||
#include "core/CoreUtils.hpp"
|
||||
#include "core/kernel/KernelInteractions.hpp"
|
||||
#include "core/connection/ConnectionIO.hpp"
|
||||
//#include "core/CoreUtils.hpp"
|
||||
//#include "core/kernel/KernelInteractions.hpp"
|
||||
//#include "core/connection/ConnectionIO.hpp"
|
||||
|
||||
#include "common/LogHighlighter.hpp"
|
||||
#include "common/HTTPRequestHelper.hpp"
|
||||
|
||||
#include "components/tcping/QvTCPing.hpp"
|
||||
#include "components/pac/QvPACHandler.hpp"
|
||||
|
||||
//#include "components/tcping/QvTCPing.hpp"
|
||||
//#include "components/pac/QvPACHandler.hpp"
|
||||
#include "components/speedchart/speedwidget.hpp"
|
||||
|
||||
#include "ui/messaging/QvMessageBus.hpp"
|
||||
|
||||
enum QvConnectionType {
|
||||
CONNECTION_REGULAR = 1,
|
||||
CONNECTION_SUBSCRIPTION = 2
|
||||
};
|
||||
//
|
||||
struct ConnectionObject : ConnectionIdentifier {
|
||||
QvConnectionType configType;
|
||||
double latency;
|
||||
CONFIGROOT config;
|
||||
};
|
||||
|
||||
class MainWindow : public QMainWindow, Ui::MainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -43,7 +33,7 @@ class MainWindow : public QMainWindow, Ui::MainWindow
|
||||
void ReConnect() const;
|
||||
public slots:
|
||||
QvMessageBusSlotHeader
|
||||
void onPingFinished(QvTCPingData data);
|
||||
//void onPingFinished(QvTCPingData data);
|
||||
void UpdateVCoreLog(const QString &log);
|
||||
void OnConfigListChanged(bool need_restart);
|
||||
private slots:
|
||||
@ -69,15 +59,12 @@ class MainWindow : public QMainWindow, Ui::MainWindow
|
||||
void on_subsButton_clicked();
|
||||
//
|
||||
void ToggleVisibility();
|
||||
void setMasterLogHBar();
|
||||
void VersionUpdate(QByteArray &data);
|
||||
void quit();
|
||||
|
||||
public:
|
||||
static MainWindow *mwInstance;
|
||||
ConnectionIdentifier CurrentConnectionIdentifier;
|
||||
V2rayKernelInstance *vinstance;
|
||||
QString GetCurrentConnectedConfigName();
|
||||
//QvConnectionObject CurrentConnectionIdentifier;
|
||||
|
||||
protected:
|
||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||
@ -92,20 +79,20 @@ class MainWindow : public QMainWindow, Ui::MainWindow
|
||||
void on_action_RCM_RenameConnection_triggered();
|
||||
void on_connectionListWidget_itemSelectionChanged();
|
||||
|
||||
void on_connectionListWidget_itemDoubleClicked(QTreeWidgetItem *item, int column);
|
||||
|
||||
private:
|
||||
//
|
||||
void SetEditWidgetEnable(bool enabled);
|
||||
void ShowAndSetConnection(ConnectionIdentifier fullIdentifier, bool SetConnection, bool Apply);
|
||||
CONFIGROOT currentFullConfig;
|
||||
//void ShowAndSetConnection(QvConnectionObject fullIdentifier, bool SetConnection, bool Apply);
|
||||
//CONFIGROOT currentFullConfig;
|
||||
//
|
||||
// Charts
|
||||
SpeedWidget *speedChartView;
|
||||
//
|
||||
QMenu *connectionListMenu;
|
||||
|
||||
/// Key --> ListWidget.item.text
|
||||
QMap<ConnectionIdentifier, ConnectionObject> connections;
|
||||
//
|
||||
ConnectionIdentifier renameOriginalIdentifier;
|
||||
//QvConnectionObject renameOriginalIdentifier;
|
||||
bool isRenamingInProgress;
|
||||
//
|
||||
// ID for QTimers
|
||||
@ -117,13 +104,9 @@ class MainWindow : public QMainWindow, Ui::MainWindow
|
||||
//
|
||||
QvHttpRequestHelper *requestHelper;
|
||||
QSystemTrayIcon hTray;
|
||||
PACServer pacServer;
|
||||
QvTCPingModel tcpingHelper;
|
||||
//PACServer pacServer;
|
||||
//QvTCPingModel tcpingHelper;
|
||||
SyntaxHighlighter *vCoreLogHighlighter;
|
||||
SyntaxHighlighter *qvAppLogHighlighter;
|
||||
//
|
||||
QList<QTextBrowser *> logTextBrowsers;
|
||||
int currentLogBrowserId = 0;
|
||||
QTreeWidgetItem *CurrentSelectedItemPtr;
|
||||
//
|
||||
// Actions in the system tray menu
|
||||
@ -144,14 +127,8 @@ class MainWindow : public QMainWindow, Ui::MainWindow
|
||||
// ----------------------------------- Extra Headers For w_MainWindow_extra.cpp Handling V2ray Connectivities.
|
||||
bool systemProxyEnabled;
|
||||
void MWFindAndStartAutoConfig();
|
||||
bool MWtryStartConnection();
|
||||
void MWStopConnection();
|
||||
void MWTryPingConnection(const ConnectionIdentifier &alias);
|
||||
tuple<QString, int, QString> MWGetConnectionInfo(const ConnectionIdentifier &alias);
|
||||
void MWSetSystemProxy();
|
||||
void MWClearSystemProxy(bool);
|
||||
void CheckSubscriptionsUpdate();
|
||||
//
|
||||
|
||||
QTreeWidgetItem *FindItemByIdentifier(ConnectionIdentifier identifier);
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -5,65 +5,65 @@
|
||||
#include "components/proxy/QvProxyConfigurator.hpp"
|
||||
#include "core/connection/Generation.hpp"
|
||||
|
||||
QTreeWidgetItem *MainWindow::FindItemByIdentifier(ConnectionIdentifier identifier)
|
||||
{
|
||||
// First filter out all items with our config name.
|
||||
auto items = connectionListWidget->findItems(identifier.connectionName, Qt::MatchExactly | Qt::MatchRecursive);
|
||||
|
||||
for (auto item : items) {
|
||||
// This connectable prevents the an item with (which is the parent node of a subscription, having the same
|
||||
// -- name as our current connected name)
|
||||
if (!IsConnectableItem(item)) {
|
||||
LOG(UI, "Invalid Item found: " + item->text(0))
|
||||
continue;
|
||||
}
|
||||
|
||||
auto thisIdentifier = ItemConnectionIdentifier(item);
|
||||
DEBUG(UI, "Item Identifier: " + thisIdentifier.IdentifierString())
|
||||
|
||||
if (identifier == thisIdentifier) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
LOG(UI, "Warning: Failed to find an item named: " + identifier.IdentifierString())
|
||||
return nullptr;
|
||||
}
|
||||
//QTreeWidgetItem *MainWindow::FindItemByIdentifier(QvConnectionObject identifier)
|
||||
//{
|
||||
// //// First filter out all items with our config name.
|
||||
// //auto items = connectionListWidget->findItems(identifier.connectionName, Qt::MatchExactly | Qt::MatchRecursive);
|
||||
// //
|
||||
// //for (auto item : items) {
|
||||
// // // This connectable prevents the an item with (which is the parent node of a subscription, having the same
|
||||
// // // -- name as our current connected name)
|
||||
// // if (!IsConnectableItem(item)) {
|
||||
// // LOG(UI, "Invalid Item found: " + item->text(0))
|
||||
// // continue;
|
||||
// // }
|
||||
// //
|
||||
// // auto thisIdentifier = ItemConnectionIdentifier(item);
|
||||
// // DEBUG(UI, "Item Identifier: " + thisIdentifier.IdentifierString())
|
||||
// //
|
||||
// // if (identifier == thisIdentifier) {
|
||||
// // return item;
|
||||
// // }
|
||||
// //}
|
||||
// //
|
||||
// //LOG(UI, "Warning: Failed to find an item named: " + identifier.IdentifierString())
|
||||
// return nullptr;
|
||||
//}
|
||||
|
||||
void MainWindow::MWFindAndStartAutoConfig()
|
||||
{
|
||||
if (!GlobalConfig.autoStartConfig.connectionName.isEmpty()) {
|
||||
// User has auto start configured, we try to find that connection item.
|
||||
auto name = GlobalConfig.autoStartConfig.subscriptionName.isEmpty()
|
||||
? GlobalConfig.autoStartConfig.connectionName
|
||||
: GlobalConfig.autoStartConfig.connectionName + " (" + tr("Subscription:") + " " + GlobalConfig.autoStartConfig.subscriptionName + ")";
|
||||
//
|
||||
LOG(UI, "Found auto start config: " + name)
|
||||
auto item = FindItemByIdentifier(GlobalConfig.autoStartConfig);
|
||||
|
||||
if (item != nullptr) {
|
||||
// We found the item required and start it.
|
||||
connectionListWidget->setCurrentItem(item);
|
||||
on_connectionListWidget_currentItemChanged(item, nullptr);
|
||||
connectionListWidget->scrollToItem(item);
|
||||
tray_RootMenu->actions()[0]->setText(tr("Show"));
|
||||
on_startButton_clicked();
|
||||
} else {
|
||||
QvMessageBoxWarn(this, tr("Autostarting a config"), tr("Could not find a specified config named: ") + NEWLINE +
|
||||
name + NEWLINE + NEWLINE +
|
||||
tr("Please reset the settings in Preference Window"));
|
||||
}
|
||||
} else if (connectionListWidget->topLevelItemCount() > 0) {
|
||||
// Make the first one our default selected item.
|
||||
connectionListWidget->setCurrentItem(connectionListWidget->topLevelItem(0));
|
||||
ShowAndSetConnection(ItemConnectionIdentifier(connectionListWidget->topLevelItem(0)), true, false);
|
||||
}
|
||||
//if (!GlobalConfig.autoStartConfig.connectionName.isEmpty()) {
|
||||
// // User has auto start configured, we try to find that connection item.
|
||||
// auto name = GlobalConfig.autoStartConfig.subscriptionName.isEmpty()
|
||||
// ? GlobalConfig.autoStartConfig.connectionName
|
||||
// : GlobalConfig.autoStartConfig.connectionName + " (" + tr("Subscription:") + " " + GlobalConfig.autoStartConfig.subscriptionName + ")";
|
||||
// //
|
||||
// LOG(UI, "Found auto start config: " + name)
|
||||
// auto item = FindItemByIdentifier(GlobalConfig.autoStartConfig);
|
||||
//
|
||||
// if (item != nullptr) {
|
||||
// // We found the item required and start it.
|
||||
// connectionListWidget->setCurrentItem(item);
|
||||
// on_connectionListWidget_currentItemChanged(item, nullptr);
|
||||
// connectionListWidget->scrollToItem(item);
|
||||
// tray_RootMenu->actions()[0]->setText(tr("Show"));
|
||||
// on_startButton_clicked();
|
||||
// } else {
|
||||
// QvMessageBoxWarn(this, tr("Autostarting a config"), tr("Could not find a specified config named: ") + NEWLINE +
|
||||
// name + NEWLINE + NEWLINE +
|
||||
// tr("Please reset the settings in Preference Window"));
|
||||
// }
|
||||
//} else if (connectionListWidget->topLevelItemCount() > 0) {
|
||||
// // Make the first one our default selected item.
|
||||
// connectionListWidget->setCurrentItem(connectionListWidget->topLevelItem(0));
|
||||
// ShowAndSetConnection(ItemConnectionIdentifier(connectionListWidget->topLevelItem(0)), true, false);
|
||||
//}
|
||||
}
|
||||
|
||||
void MainWindow::MWClearSystemProxy(bool showMessage)
|
||||
{
|
||||
ClearSystemProxy();
|
||||
LOG(UI, "Clearing System Proxy")
|
||||
LOG(MODULE_UI, "Clearing System Proxy")
|
||||
systemProxyEnabled = false;
|
||||
|
||||
if (showMessage) {
|
||||
@ -79,11 +79,12 @@ void MainWindow::MWSetSystemProxy()
|
||||
bool socksEnabled = GlobalConfig.inboundConfig.useSocks;
|
||||
//
|
||||
// Set system proxy if necessary
|
||||
bool isComplex = IsComplexConfig(connections[CurrentConnectionIdentifier].config);
|
||||
//bool isComplex = IsComplexConfig(connections[CurrentConnectionIdentifier].config);
|
||||
bool isComplex = true;
|
||||
|
||||
if (!isComplex) {
|
||||
// Is simple config and we will try to set system proxy.
|
||||
LOG(UI, "Preparing to set system proxy")
|
||||
LOG(MODULE_UI, "Preparing to set system proxy")
|
||||
//
|
||||
QString proxyAddress;
|
||||
bool canSetSystemProxy = true;
|
||||
@ -91,13 +92,13 @@ void MainWindow::MWSetSystemProxy()
|
||||
if (usePAC) {
|
||||
if ((httpEnabled && !pacUseSocks) || (socksEnabled && pacUseSocks)) {
|
||||
// If we use PAC and socks/http are properly configured for PAC
|
||||
LOG(PROXY, "System proxy uses PAC")
|
||||
LOG(MODULE_PROXY, "System proxy uses PAC")
|
||||
proxyAddress = "http://" + GlobalConfig.inboundConfig.listenip + ":" + QSTRN(GlobalConfig.inboundConfig.pacConfig.port) + "/pac";
|
||||
} else {
|
||||
// Not properly configured
|
||||
LOG(PROXY, "Failed to process pac due to following reasons:")
|
||||
LOG(PROXY, " --> PAC is configured to use socks but socks is not enabled.")
|
||||
LOG(PROXY, " --> PAC is configuted to use http but http is not enabled.")
|
||||
LOG(MODULE_PROXY, "Failed to process pac due to following reasons:")
|
||||
LOG(MODULE_PROXY, " --> PAC is configured to use socks but socks is not enabled.")
|
||||
LOG(MODULE_PROXY, " --> PAC is configuted to use http but http is not enabled.")
|
||||
QvMessageBoxWarn(this, tr("PAC Processing Failed"), tr("HTTP or SOCKS inbound is not properly configured for PAC") +
|
||||
NEWLINE + tr("Qv2ray will continue, but will not set system proxy."));
|
||||
canSetSystemProxy = false;
|
||||
@ -106,18 +107,18 @@ void MainWindow::MWSetSystemProxy()
|
||||
// Not using PAC
|
||||
if (httpEnabled || socksEnabled) {
|
||||
// Not use PAC, System proxy should use HTTP or SOCKS
|
||||
LOG(PROXY, "Setting up system proxy.")
|
||||
LOG(MODULE_PROXY, "Setting up system proxy.")
|
||||
// A 'proxy host' should be a host WITHOUT `http://` uri scheme
|
||||
proxyAddress = "localhost";
|
||||
} else {
|
||||
LOG(PROXY, "Neither of HTTP nor SOCKS is enabled, cannot set system proxy.")
|
||||
LOG(MODULE_PROXY, "Neither of HTTP nor SOCKS is enabled, cannot set system proxy.")
|
||||
QvMessageBoxWarn(this, tr("Cannot set system proxy"), tr("Both HTTP and SOCKS inbounds are not enabled"));
|
||||
canSetSystemProxy = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (canSetSystemProxy) {
|
||||
LOG(UI, "Setting system proxy for simple config.")
|
||||
LOG(MODULE_UI, "Setting system proxy for simple config.")
|
||||
auto httpPort = GlobalConfig.inboundConfig.useHTTP ? GlobalConfig.inboundConfig.http_port : 0;
|
||||
auto socksPort = GlobalConfig.inboundConfig.useSocks ? GlobalConfig.inboundConfig.socks_port : 0;
|
||||
//
|
||||
@ -131,96 +132,40 @@ void MainWindow::MWSetSystemProxy()
|
||||
}
|
||||
}
|
||||
|
||||
bool MainWindow::MWtryStartConnection()
|
||||
{
|
||||
auto connectionRoot = connections[CurrentConnectionIdentifier].config;
|
||||
currentFullConfig = GenerateRuntimeConfig(connectionRoot);
|
||||
bool startFlag = this->vinstance->StartConnection(currentFullConfig);
|
||||
|
||||
if (startFlag) {
|
||||
bool usePAC = GlobalConfig.inboundConfig.pacConfig.enablePAC;
|
||||
bool pacUseSocks = GlobalConfig.inboundConfig.pacConfig.useSocksProxy;
|
||||
bool httpEnabled = GlobalConfig.inboundConfig.useHTTP;
|
||||
bool socksEnabled = GlobalConfig.inboundConfig.useSocks;
|
||||
|
||||
if (usePAC) {
|
||||
bool canStartPAC = true;
|
||||
QString pacProxyString; // Something like this --> SOCKS5 127.0.0.1:1080; SOCKS 127.0.0.1:1080; DIRECT; http://proxy:8080
|
||||
auto pacIP = GlobalConfig.inboundConfig.pacConfig.localIP;
|
||||
|
||||
if (pacIP.isEmpty()) {
|
||||
LOG(PROXY, "PAC Local IP is empty, default to 127.0.0.1")
|
||||
pacIP = "127.0.0.1";
|
||||
}
|
||||
|
||||
if (pacUseSocks) {
|
||||
if (socksEnabled) {
|
||||
pacProxyString = "SOCKS5 " + pacIP + ":" + QSTRN(GlobalConfig.inboundConfig.socks_port);
|
||||
} else {
|
||||
LOG(UI, "PAC is using SOCKS, but it is not enabled")
|
||||
QvMessageBoxWarn(this, tr("Configuring PAC"), tr("Could not start PAC server as it is configured to use SOCKS, but it is not enabled"));
|
||||
canStartPAC = false;
|
||||
}
|
||||
} else {
|
||||
if (httpEnabled) {
|
||||
pacProxyString = "PROXY " + pacIP + ":" + QSTRN(GlobalConfig.inboundConfig.http_port);
|
||||
} else {
|
||||
LOG(UI, "PAC is using HTTP, but it is not enabled")
|
||||
QvMessageBoxWarn(this, tr("Configuring PAC"), tr("Could not start PAC server as it is configured to use HTTP, but it is not enabled"));
|
||||
canStartPAC = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (canStartPAC) {
|
||||
pacServer.SetProxyString(pacProxyString);
|
||||
pacServer.StartListen();
|
||||
} else {
|
||||
LOG(PROXY, "Not starting PAC due to previous error.")
|
||||
}
|
||||
}
|
||||
|
||||
if (GlobalConfig.inboundConfig.setSystemProxy) {
|
||||
MWSetSystemProxy();
|
||||
}
|
||||
}
|
||||
|
||||
return startFlag;
|
||||
}
|
||||
|
||||
void MainWindow::MWStopConnection()
|
||||
{
|
||||
if (systemProxyEnabled) {
|
||||
MWClearSystemProxy(false);
|
||||
}
|
||||
|
||||
this->vinstance->StopConnection();
|
||||
QFile(QV2RAY_GENERATED_FILE_PATH).remove();
|
||||
|
||||
if (GlobalConfig.inboundConfig.pacConfig.enablePAC) {
|
||||
pacServer.StopServer();
|
||||
LOG(UI, "Stopping PAC server")
|
||||
}
|
||||
//if (systemProxyEnabled) {
|
||||
// MWClearSystemProxy(false);
|
||||
//}
|
||||
//
|
||||
//this->vinstance->StopConnection();
|
||||
//QFile(QV2RAY_GENERATED_FILE_PATH).remove();
|
||||
//
|
||||
//if (GlobalConfig.inboundConfig.pacConfig.enablePAC) {
|
||||
// pacServer.StopServer();
|
||||
// LOG(UI, "Stopping PAC server")
|
||||
//}
|
||||
}
|
||||
|
||||
void MainWindow::MWTryPingConnection(const ConnectionIdentifier &alias)
|
||||
{
|
||||
try {
|
||||
auto info = MWGetConnectionInfo(alias);
|
||||
QString host = get<0>(info);
|
||||
int port = get<1>(info);
|
||||
tcpingHelper.StartPing(alias, host, port);
|
||||
} catch (...) {
|
||||
QvMessageBoxWarn(this, tr("Latency Test"), tr("Failed to test latency for this connection."));
|
||||
}
|
||||
}
|
||||
|
||||
tuple<QString, int, QString> MainWindow::MWGetConnectionInfo(const ConnectionIdentifier &alias)
|
||||
{
|
||||
if (!connections.contains(alias))
|
||||
return make_tuple(tr("N/A"), 0, tr("N/A"));
|
||||
|
||||
return GetConnectionInfo(connections[alias].config);
|
||||
}
|
||||
//void MainWindow::MWTryPingConnection(const QvConnectionObject &alias)
|
||||
//{
|
||||
// //try {
|
||||
// // auto info = MWGetConnectionInfo(alias);
|
||||
// // QString host = get<0>(info);
|
||||
// // int port = get<1>(info);
|
||||
// // tcpingHelper.StartPing(alias, host, port);
|
||||
// //} catch (...) {
|
||||
// // QvMessageBoxWarn(this, tr("Latency Test"), tr("Failed to test latency for this connection."));
|
||||
// //}
|
||||
//}
|
||||
//
|
||||
//tuple<QString, int, QString> MainWindow::MWGetConnectionInfo(const QvConnectionObject &alias)
|
||||
//{
|
||||
// //if (!connections.contains(alias))
|
||||
// // return make_tuple(tr("N/A"), 0, tr("N/A"));
|
||||
// //
|
||||
// //return GetConnectionInfo(connections[alias].config);
|
||||
//}
|
||||
|
||||
void MainWindow::CheckSubscriptionsUpdate()
|
||||
{
|
||||
@ -232,13 +177,13 @@ void MainWindow::CheckSubscriptionsUpdate()
|
||||
//
|
||||
auto lastRenewDate = QDateTime::fromTime_t(subs.lastUpdated);
|
||||
auto renewTime = lastRenewDate.addSecs(subs.updateInterval * 86400);
|
||||
LOG(SUBSCRIPTION, "Subscription \"" + key + "\": " + NEWLINE +
|
||||
LOG(MODULE_SUBSCRIPTION, "Subscription \"" + key + "\": " + NEWLINE +
|
||||
" --> Last renewal time: " + lastRenewDate.toString() + NEWLINE +
|
||||
" --> Renew interval: " + QSTRN(subs.updateInterval) + NEWLINE +
|
||||
" --> Ideal renew time: " + renewTime.toString())
|
||||
|
||||
if (renewTime <= QDateTime::currentDateTime()) {
|
||||
LOG(SUBSCRIPTION, "Subscription: " + key + " needs to be updated.")
|
||||
LOG(MODULE_SUBSCRIPTION, "Subscription: " + key + " needs to be updated.")
|
||||
updateList.append(key);
|
||||
}
|
||||
}
|
||||
|
@ -147,24 +147,26 @@ PreferencesWindow::PreferencesWindow(QWidget *parent) : QDialog(parent),
|
||||
CurrentBarPageId = 0;
|
||||
//
|
||||
// Empty for global config.
|
||||
auto autoSub = CurrentConfig.autoStartConfig.subscriptionName;
|
||||
auto autoCon = CurrentConfig.autoStartConfig.connectionName;
|
||||
autoStartConnCombo->addItem("");
|
||||
//auto autoSub = CurrentConfig.autoStartConfig.subscriptionName;
|
||||
//auto autoCon = CurrentConfig.autoStartConfig.connectionName;
|
||||
//autoStartConnCombo->addItem("");
|
||||
QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP");
|
||||
|
||||
for (auto item : CurrentConfig.subscriptions.keys()) {
|
||||
autoStartSubsCombo->addItem(item);
|
||||
}
|
||||
|
||||
autoStartSubsCombo->setCurrentText(autoSub);
|
||||
|
||||
if (CurrentConfig.autoStartConfig.subscriptionName.isEmpty()) {
|
||||
autoStartConnCombo->addItems(CurrentConfig.configs);
|
||||
} else {
|
||||
auto list = GetSubscriptionConnection(autoSub);
|
||||
autoStartConnCombo->addItems(list.keys());
|
||||
}
|
||||
|
||||
autoStartConnCombo->setCurrentText(autoCon);
|
||||
// TODO: Now use grouping, subscriptions are the special type of group
|
||||
//autoStartConnCombo->setCurrentText(autoCon);for (auto item : CurrentConfig.subscriptions.keys()) {
|
||||
// autoStartSubsCombo->addItem(item);
|
||||
//}
|
||||
//
|
||||
//autoStartSubsCombo->setCurrentText(autoSub);
|
||||
//
|
||||
//if (CurrentConfig.autoStartConfig.subscriptionName.isEmpty()) {
|
||||
// autoStartConnCombo->addItems(CurrentConfig.configs);
|
||||
//} else {
|
||||
// auto list = GetSubscriptionConnection(autoSub);
|
||||
// autoStartConnCombo->addItems(list.keys());
|
||||
//}
|
||||
//
|
||||
//
|
||||
|
||||
// FP Settings
|
||||
if (CurrentConfig.connectionConfig.forwardProxyConfig.type.trimmed().isEmpty()) {
|
||||
@ -242,7 +244,7 @@ void PreferencesWindow::on_buttonBox_accepted()
|
||||
|
||||
// Install translator
|
||||
if (!qApp->installTranslator(Qv2rayTranslator.get())) {
|
||||
LOG(UI, "Failed to translate UI to: " + CurrentConfig.uiConfig.language)
|
||||
LOG(MODULE_UI, "Failed to translate UI to: " + CurrentConfig.uiConfig.language)
|
||||
} else {
|
||||
messageBus.EmitGlobalSignal(QvMessage::RETRANSLATE);
|
||||
QApplication::processEvents();
|
||||
@ -419,48 +421,48 @@ void PreferencesWindow::on_tProxyCheckBox_stateChanged(int arg1)
|
||||
tr("If anything goes wrong after enabling this, please check issue #57 or the link below:") + NEWLINE +
|
||||
" https://github.com/Qv2ray/Qv2ray/wiki/FAQ ") != QMessageBox::Yes) {
|
||||
tProxyCheckBox->setChecked(false);
|
||||
LOG(UI, "Canceled enabling tProxy feature.")
|
||||
LOG(MODULE_UI, "Canceled enabling tProxy feature.")
|
||||
} else {
|
||||
LOG(VCORE, "ENABLING tProxy Support")
|
||||
LOG(FILEIO, " --> Origin V2ray core file is at: " + CurrentConfig.v2CorePath)
|
||||
LOG(MODULE_VCORE, "ENABLING tProxy Support")
|
||||
LOG(MODULE_FILEIO, " --> Origin V2ray core file is at: " + CurrentConfig.v2CorePath)
|
||||
auto v2ctlPath = QFileInfo(CurrentConfig.v2CorePath).absolutePath() + "/v2ctl";
|
||||
auto newPath = QFileInfo(QV2RAY_TPROXY_VCORE_PATH).absolutePath();
|
||||
QString mkPathResult = QDir().mkpath(newPath) ? "OK" : "FAILED";
|
||||
LOG(FILEIO, " --> mkPath result: " + mkPathResult)
|
||||
LOG(MODULE_FILEIO, " --> mkPath result: " + mkPathResult)
|
||||
//
|
||||
LOG(FILEIO, " --> Origin v2ctl file is at: " + v2ctlPath)
|
||||
LOG(FILEIO, " --> New V2ray files will be placed in: " + newPath)
|
||||
LOG(MODULE_FILEIO, " --> Origin v2ctl file is at: " + v2ctlPath)
|
||||
LOG(MODULE_FILEIO, " --> New V2ray files will be placed in: " + newPath)
|
||||
//
|
||||
LOG(FILEIO, " --> Copying files....")
|
||||
LOG(MODULE_FILEIO, " --> Copying files....")
|
||||
|
||||
if (QFileInfo(CurrentConfig.v2CorePath).absoluteFilePath() != QFileInfo(QV2RAY_TPROXY_VCORE_PATH).absoluteFilePath()) {
|
||||
// Only trying to remove file when they are not in the default dir.
|
||||
// (In other words...) Keep using the current files. <Because we don't know where else we can copy the file from...>
|
||||
//
|
||||
if (QFile(QV2RAY_TPROXY_VCORE_PATH).exists()) {
|
||||
LOG(FILEIO, QString(QV2RAY_TPROXY_VCORE_PATH) + ": File already exists.")
|
||||
LOG(FILEIO, QString(QV2RAY_TPROXY_VCORE_PATH) + ": Deleting file.")
|
||||
LOG(MODULE_FILEIO, QString(QV2RAY_TPROXY_VCORE_PATH) + ": File already exists.")
|
||||
LOG(MODULE_FILEIO, QString(QV2RAY_TPROXY_VCORE_PATH) + ": Deleting file.")
|
||||
QFile(QV2RAY_TPROXY_VCORE_PATH).remove();
|
||||
}
|
||||
|
||||
if (QFile(QV2RAY_TPROXY_VCTL_PATH).exists()) {
|
||||
LOG(FILEIO, QV2RAY_TPROXY_VCTL_PATH + ": File already exists.")
|
||||
LOG(FILEIO, QV2RAY_TPROXY_VCTL_PATH + ": Deleting file.")
|
||||
LOG(MODULE_FILEIO, QV2RAY_TPROXY_VCTL_PATH + ": File already exists.")
|
||||
LOG(MODULE_FILEIO, QV2RAY_TPROXY_VCTL_PATH + ": Deleting file.")
|
||||
QFile(QV2RAY_TPROXY_VCTL_PATH).remove();
|
||||
}
|
||||
|
||||
QString vCoreresult = QFile(CurrentConfig.v2CorePath).copy(QV2RAY_TPROXY_VCORE_PATH) ? "OK" : "FAILED";
|
||||
LOG(FILEIO, " --> V2ray Core: " + vCoreresult)
|
||||
LOG(MODULE_FILEIO, " --> V2ray Core: " + vCoreresult)
|
||||
//
|
||||
QString vCtlresult = QFile(v2ctlPath).copy(QV2RAY_TPROXY_VCTL_PATH) ? "OK" : "FAILED";
|
||||
LOG(FILEIO, " --> V2ray Ctl: " + vCtlresult)
|
||||
LOG(MODULE_FILEIO, " --> V2ray Ctl: " + vCtlresult)
|
||||
//
|
||||
|
||||
if (vCoreresult == "OK" && vCtlresult == "OK") {
|
||||
LOG(VCORE, " --> Done copying files.")
|
||||
LOG(MODULE_VCORE, " --> Done copying files.")
|
||||
on_vCorePathTxt_textEdited(QV2RAY_TPROXY_VCORE_PATH);
|
||||
} else {
|
||||
LOG(VCORE, "FAILED to copy V2ray files. Aborting.")
|
||||
LOG(MODULE_VCORE, "FAILED to copy V2ray files. Aborting.")
|
||||
QvMessageBoxWarn(this, tr("Enable tProxy Support"),
|
||||
tr("Qv2ray cannot copy one or both V2ray files from: ") + NEWLINE + NEWLINE +
|
||||
CurrentConfig.v2CorePath + NEWLINE + v2ctlPath + NEWLINE + NEWLINE +
|
||||
@ -468,15 +470,15 @@ void PreferencesWindow::on_tProxyCheckBox_stateChanged(int arg1)
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
LOG(VCORE, "Skipped removing files since the current V2ray core is in the default path.")
|
||||
LOG(VCORE, " --> Actually because we don't know where else to obtain the files.")
|
||||
LOG(MODULE_VCORE, "Skipped removing files since the current V2ray core is in the default path.")
|
||||
LOG(MODULE_VCORE, " --> Actually because we don't know where else to obtain the files.")
|
||||
}
|
||||
|
||||
LOG(UI, "Calling pkexec and setcap...")
|
||||
LOG(MODULE_UI, "Calling pkexec and setcap...")
|
||||
int ret = QProcess::execute("pkexec setcap CAP_NET_ADMIN,CAP_NET_RAW,CAP_NET_BIND_SERVICE=eip " + CurrentConfig.v2CorePath);
|
||||
|
||||
if (ret != 0) {
|
||||
LOG(UI, "WARN: setcap exits with code: " + QSTRN(ret))
|
||||
LOG(MODULE_UI, "WARN: setcap exits with code: " + QSTRN(ret))
|
||||
QvMessageBoxWarn(this, tr("Preferences"), tr("Failed to setcap onto V2ray executable. You may need to run `setcap` manually."));
|
||||
}
|
||||
|
||||
@ -487,7 +489,7 @@ void PreferencesWindow::on_tProxyCheckBox_stateChanged(int arg1)
|
||||
int ret = QProcess::execute("pkexec setcap -r " + CurrentConfig.v2CorePath);
|
||||
|
||||
if (ret != 0) {
|
||||
LOG(UI, "WARN: setcap exits with code: " + QSTRN(ret))
|
||||
LOG(MODULE_UI, "WARN: setcap exits with code: " + QSTRN(ret))
|
||||
QvMessageBoxWarn(this, tr("Preferences"), tr("Failed to setcap onto V2ray executable. You may need to run `setcap` manually."));
|
||||
}
|
||||
|
||||
@ -564,7 +566,7 @@ void PreferencesWindow::on_nsBarPageAddBTN_clicked()
|
||||
CurrentBarLineId = 0;
|
||||
nsBarPagesList->addItem(QSTRN(CurrentBarPageId));
|
||||
ShowLineParameters(CurrentBarLine);
|
||||
LOG(UI, "Adding new page Id: " + QSTRN(CurrentBarPageId))
|
||||
LOG(MODULE_UI, "Adding new page Id: " + QSTRN(CurrentBarPageId))
|
||||
nsBarPageDelBTN->setEnabled(true);
|
||||
nsBarLineAddBTN->setEnabled(true);
|
||||
nsBarLineDelBTN->setEnabled(true);
|
||||
@ -607,7 +609,7 @@ void PreferencesWindow::on_nsBarLineAddBTN_clicked()
|
||||
nsBarLinesList->addItem(QSTRN(CurrentBarLineId));
|
||||
ShowLineParameters(CurrentBarLine);
|
||||
nsBarLineDelBTN->setEnabled(true);
|
||||
LOG(UI, "Adding new line Id: " + QSTRN(CurrentBarLineId))
|
||||
LOG(MODULE_UI, "Adding new line Id: " + QSTRN(CurrentBarLineId))
|
||||
nsBarLinesList->setCurrentRow(static_cast<int>(CurrentBarPage.Lines.size() - 1));
|
||||
}
|
||||
|
||||
@ -837,7 +839,7 @@ void PreferencesWindow::on_pacGoBtn_clicked()
|
||||
pacGoBtn->setEnabled(false);
|
||||
gfwListCB->setEnabled(false);
|
||||
QvHttpRequestHelper request;
|
||||
LOG(PROXY, "Downloading GFWList file.")
|
||||
LOG(MODULE_PROXY, "Downloading GFWList file.")
|
||||
bool withProxy = getGFWListWithProxyCB->isChecked();
|
||||
|
||||
switch (gfwListCB->currentIndex()) {
|
||||
@ -883,7 +885,7 @@ void PreferencesWindow::on_pacGoBtn_clicked()
|
||||
break;
|
||||
}
|
||||
|
||||
LOG(NETWORK, "Fetched: " + gfwLocation)
|
||||
LOG(MODULE_NETWORK, "Fetched: " + gfwLocation)
|
||||
QvMessageBoxInfo(this, tr("Download GFWList"), tr("Successfully downloaded GFWList."));
|
||||
pacGoBtn->setEnabled(true);
|
||||
gfwListCB->setEnabled(true);
|
||||
@ -936,22 +938,24 @@ void PreferencesWindow::on_pacProxyTxt_textEdited(const QString &arg1)
|
||||
void PreferencesWindow::on_autoStartSubsCombo_currentIndexChanged(const QString &arg1)
|
||||
{
|
||||
LOADINGCHECK
|
||||
CurrentConfig.autoStartConfig.subscriptionName = arg1;
|
||||
autoStartConnCombo->clear();
|
||||
|
||||
if (arg1.isEmpty()) {
|
||||
autoStartConnCombo->addItem("");
|
||||
autoStartConnCombo->addItems(CurrentConfig.configs);
|
||||
} else {
|
||||
auto list = GetSubscriptionConnection(arg1);
|
||||
autoStartConnCombo->addItems(list.keys());
|
||||
}
|
||||
QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP");
|
||||
//CurrentConfig.autoStartConfig.subscriptionName = arg1;
|
||||
//autoStartConnCombo->clear();
|
||||
//
|
||||
//if (arg1.isEmpty()) {
|
||||
// autoStartConnCombo->addItem("");
|
||||
// autoStartConnCombo->addItems(CurrentConfig.configs);
|
||||
//} else {
|
||||
// auto list = GetSubscriptionConnection(arg1);
|
||||
// autoStartConnCombo->addItems(list.keys());
|
||||
//}
|
||||
}
|
||||
|
||||
void PreferencesWindow::on_autoStartConnCombo_currentIndexChanged(const QString &arg1)
|
||||
{
|
||||
LOADINGCHECK
|
||||
CurrentConfig.autoStartConfig.connectionName = arg1;
|
||||
QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP");
|
||||
//CurrentConfig.autoStartConfig.connectionName = arg1;
|
||||
}
|
||||
|
||||
void PreferencesWindow::on_startWithLoginCB_stateChanged(int arg1)
|
||||
|
@ -29,7 +29,7 @@ ScreenShotWindow::ScreenShotWindow() : QDialog(), rubber(new QRubberBand(QRubber
|
||||
|
||||
QImage ScreenShotWindow::DoScreenShot()
|
||||
{
|
||||
LOG(IMPORT, "We currently only support the current screen.")
|
||||
LOG(MODULE_IMPORT, "We currently only support the current screen.")
|
||||
// The msleep is the only solution which prevent capturing our windows again.
|
||||
// It works on KDE, https://www.qtcentre.org/threads/55708-Get-Desktop-Screenshot-Without-Application-Window-Being-Shown?p=248993#post248993
|
||||
QThread::msleep(100);
|
||||
|
@ -34,7 +34,7 @@ QPair<QString, CONFIGROOT> SubscribeEditor::GetSelectedConfig()
|
||||
return currentSelectedConfig;
|
||||
}
|
||||
|
||||
void SubscribeEditor::LoadSubscriptionList(QMap<QString, Qv2raySubscriptionConfig> list)
|
||||
void SubscribeEditor::LoadSubscriptionList(QMap<QString, QvSubscriptionObject> list)
|
||||
{
|
||||
subscriptionList->clear();
|
||||
|
||||
@ -69,7 +69,7 @@ void SubscribeEditor::on_updateButton_clicked()
|
||||
|
||||
if (currentSubName != newName) {
|
||||
// Rename needed.
|
||||
LOG(SUBSCRIPTION, "Renaming a subscription, from " + currentSubName + " to: " + newName)
|
||||
LOG(MODULE_SUBSCRIPTION, "Renaming a subscription, from " + currentSubName + " to: " + newName)
|
||||
bool canGo = true;
|
||||
|
||||
if (newName.isEmpty() || !IsValidFileName(newName)) {
|
||||
@ -87,24 +87,23 @@ void SubscribeEditor::on_updateButton_clicked()
|
||||
return;
|
||||
}
|
||||
|
||||
bool result = RenameSubscription(currentSubName, newName);
|
||||
|
||||
if (!result) {
|
||||
QvMessageBoxWarn(this, tr("Renaming a subscription"), tr("Failed to rename a subscription, this is an unknown error."));
|
||||
return;
|
||||
}
|
||||
|
||||
////bool result = RenameSubscription(currentSubName, newName);
|
||||
//
|
||||
//if (!result) {
|
||||
// QvMessageBoxWarn(this, tr("Renaming a subscription"), tr("Failed to rename a subscription, this is an unknown error."));
|
||||
// return;
|
||||
//}
|
||||
subscriptions[newName] = subscriptions[currentSubName];
|
||||
subscriptions.remove(currentSubName);
|
||||
subNameTxt->setText(newName);
|
||||
//
|
||||
QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP");
|
||||
// Update auto-start config if possible
|
||||
auto ASsetting = GlobalConfig.autoStartConfig.subscriptionName;
|
||||
|
||||
if (ASsetting == currentSubName) {
|
||||
GlobalConfig.autoStartConfig.subscriptionName = newName;
|
||||
}
|
||||
|
||||
//auto ASsetting = GlobalConfig.autoStartConfig.subscriptionName;
|
||||
//
|
||||
//if (ASsetting == currentSubName) {
|
||||
// GlobalConfig.autoStartConfig.subscriptionName = newName;
|
||||
//}
|
||||
SaveGlobalConfig(GlobalConfig);
|
||||
// This will set the name to the new name.
|
||||
LoadSubscriptionList(subscriptions);
|
||||
@ -114,7 +113,7 @@ void SubscribeEditor::on_updateButton_clicked()
|
||||
subscriptions[currentSubName].updateInterval = newUpdateInterval;
|
||||
|
||||
if (subscriptions[currentSubName].address != newAddress) {
|
||||
LOG(SUBSCRIPTION, "Setting new address, from " + subscriptions[currentSubName].address + " to: " + newAddress)
|
||||
LOG(MODULE_SUBSCRIPTION, "Setting new address, from " + subscriptions[currentSubName].address + " to: " + newAddress)
|
||||
subscriptions[currentSubName].address = newAddress;
|
||||
}
|
||||
|
||||
@ -127,92 +126,91 @@ void SubscribeEditor::on_updateButton_clicked()
|
||||
|
||||
void SubscribeEditor::StartUpdateSubscription(const QString &subscriptionName)
|
||||
{
|
||||
this->setEnabled(false);
|
||||
auto data = helper.syncget(subscriptions[subscriptionName].address, withProxyCB->isChecked());
|
||||
auto content = DecodeSubscriptionString(data).trimmed();
|
||||
|
||||
if (!content.isEmpty()) {
|
||||
connectionsList->clear();
|
||||
auto vmessList = SplitLines(content);
|
||||
QDir(QV2RAY_SUBSCRIPTION_DIR + subscriptionName).removeRecursively();
|
||||
QDir().mkpath(QV2RAY_SUBSCRIPTION_DIR + subscriptionName);
|
||||
|
||||
for (auto vmess : vmessList) {
|
||||
QString errMessage;
|
||||
QString _alias;
|
||||
auto config = ConvertConfigFromString(vmess.trimmed(), &_alias, &errMessage);
|
||||
|
||||
if (!errMessage.isEmpty()) {
|
||||
LOG(SUBSCRIPTION, "Processing a subscription with following error: " + errMessage)
|
||||
} else {
|
||||
SaveSubscriptionConfig(config, subscriptionName, &_alias);
|
||||
connectionsList->addItem(_alias);
|
||||
}
|
||||
}
|
||||
|
||||
subscriptions[subscriptionName].lastUpdated = system_clock::to_time_t(system_clock::now());
|
||||
lastUpdatedLabel->setText(timeToString(subscriptions[subscriptionName].lastUpdated));
|
||||
isUpdateInProgress = false;
|
||||
} else {
|
||||
LOG(NETWORK, "We have received an empty string from the URL.")
|
||||
QvMessageBoxWarn(this, tr("Updating subscriptions"), tr("Failed to process the result from the upstream, please check your Url."));
|
||||
}
|
||||
|
||||
this->setEnabled(true);
|
||||
//this->setEnabled(false);
|
||||
//auto data = helper.syncget(subscriptions[subscriptionName].address, withProxyCB->isChecked());
|
||||
//auto content = DecodeSubscriptionString(data).trimmed();
|
||||
//
|
||||
//if (!content.isEmpty()) {
|
||||
// connectionsList->clear();
|
||||
// auto vmessList = SplitLines(content);
|
||||
// QDir(QV2RAY_SUBSCRIPTION_DIR + subscriptionName).removeRecursively();
|
||||
// QDir().mkpath(QV2RAY_SUBSCRIPTION_DIR + subscriptionName);
|
||||
//
|
||||
// for (auto vmess : vmessList) {
|
||||
// QString errMessage;
|
||||
// QString _alias;
|
||||
// auto config = ConvertConfigFromString(vmess.trimmed(), &_alias, &errMessage);
|
||||
//
|
||||
// if (!errMessage.isEmpty()) {
|
||||
// LOG(MODULE_SUBSCRIPTION, "Processing a subscription with following error: " + errMessage)
|
||||
// } else {
|
||||
// //SaveSubscriptionConfig(config, subscriptionName, &_alias);
|
||||
// connectionsList->addItem(_alias);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// subscriptions[subscriptionName].lastUpdated = system_clock::to_time_t(system_clock::now());
|
||||
// lastUpdatedLabel->setText(timeToString(subscriptions[subscriptionName].lastUpdated));
|
||||
// isUpdateInProgress = false;
|
||||
//} else {
|
||||
// LOG(MODULE_NETWORK, "We have received an empty string from the URL.")
|
||||
// QvMessageBoxWarn(this, tr("Updating subscriptions"), tr("Failed to process the result from the upstream, please check your Url."));
|
||||
//}
|
||||
//
|
||||
//this->setEnabled(true);
|
||||
}
|
||||
|
||||
void SubscribeEditor::on_removeSubsButton_clicked()
|
||||
{
|
||||
if (subscriptionList->currentRow() < 0)
|
||||
return;
|
||||
|
||||
auto name = subscriptionList->currentItem()->text();
|
||||
subscriptionList->takeItem(subscriptionList->currentRow());
|
||||
subscriptions.remove(name);
|
||||
|
||||
if (!name.isEmpty()) {
|
||||
QDir(QV2RAY_SUBSCRIPTION_DIR + name).removeRecursively();
|
||||
}
|
||||
|
||||
// If removed a whole subscription...
|
||||
if (GlobalConfig.autoStartConfig.subscriptionName == name) {
|
||||
GlobalConfig.autoStartConfig = ConnectionIdentifier();
|
||||
SaveGlobalConfig(GlobalConfig);
|
||||
}
|
||||
|
||||
groupBox_2->setEnabled(subscriptionList->count() > 0);
|
||||
SaveConfig();
|
||||
//if (subscriptionList->currentRow() < 0)
|
||||
// return;
|
||||
//
|
||||
//auto name = subscriptionList->currentItem()->text();
|
||||
//subscriptionList->takeItem(subscriptionList->currentRow());
|
||||
//subscriptions.remove(name);
|
||||
//
|
||||
//if (!name.isEmpty()) {
|
||||
// QDir(QV2RAY_SUBSCRIPTION_DIR + name).removeRecursively();
|
||||
//}
|
||||
//
|
||||
////// If removed a whole subscription...
|
||||
////if (GlobalConfig.autoStartConfig.subscriptionName == name) {
|
||||
//// GlobalConfig.autoStartConfig = QvConnectionObject();
|
||||
//// SaveGlobalConfig(GlobalConfig);
|
||||
////}
|
||||
//groupBox_2->setEnabled(subscriptionList->count() > 0);
|
||||
//SaveConfig();
|
||||
}
|
||||
|
||||
void SubscribeEditor::on_subscriptionList_currentRowChanged(int currentRow)
|
||||
{
|
||||
if (subscriptionList->count() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentRow < 0 && subscriptionList->count() > 0) {
|
||||
subscriptionList->setCurrentRow(0);
|
||||
}
|
||||
|
||||
currentSubName = subscriptionList->currentItem()->text();
|
||||
LOG(UI, "Subscription row changed, new name: " + currentSubName)
|
||||
//if (subscriptionList->count() == 0) {
|
||||
// return;
|
||||
//}
|
||||
//
|
||||
subNameTxt->setText(currentSubName);
|
||||
subAddrTxt->setText(subscriptions[currentSubName].address);
|
||||
updateIntervalSB->setValue(subscriptions[currentSubName].updateInterval);
|
||||
lastUpdatedLabel->setText(timeToString(subscriptions[currentSubName].lastUpdated));
|
||||
//if (currentRow < 0 && subscriptionList->count() > 0) {
|
||||
// subscriptionList->setCurrentRow(0);
|
||||
//}
|
||||
//
|
||||
connectionsList->clear();
|
||||
auto _list = GetSubscriptionConnection(currentSubName);
|
||||
|
||||
for (auto i = 0; i < _list.count(); i++) {
|
||||
connectionsList->addItem(_list.keys()[i]);
|
||||
}
|
||||
//currentSubName = subscriptionList->currentItem()->text();
|
||||
//LOG(MODULE_UI, "Subscription row changed, new name: " + currentSubName)
|
||||
////
|
||||
//subNameTxt->setText(currentSubName);
|
||||
//subAddrTxt->setText(subscriptions[currentSubName].address);
|
||||
//updateIntervalSB->setValue(subscriptions[currentSubName].updateInterval);
|
||||
//lastUpdatedLabel->setText(timeToString(subscriptions[currentSubName].lastUpdated));
|
||||
////
|
||||
//connectionsList->clear();
|
||||
//auto _list = GetSubscriptionConnection(currentSubName);
|
||||
//
|
||||
//for (auto i = 0; i < _list.count(); i++) {
|
||||
// connectionsList->addItem(_list.keys()[i]);
|
||||
//}
|
||||
}
|
||||
|
||||
void SubscribeEditor::SaveConfig()
|
||||
{
|
||||
QMap<QString, Qv2raySubscriptionConfig> newConf;
|
||||
QMap<QString, QvSubscriptionObject> newConf;
|
||||
|
||||
for (auto _ : subscriptions.toStdMap()) {
|
||||
if (!_.second.address.isEmpty()) {
|
||||
@ -244,6 +242,6 @@ void SubscribeEditor::on_connectionsList_itemClicked(QListWidgetItem *item)
|
||||
if (item != nullptr) {
|
||||
auto name = item->text();
|
||||
currentSelectedConfig.first = name;
|
||||
currentSelectedConfig.second = GetSubscriptionConnection(currentSubName)[name];
|
||||
//currentSelectedConfig.second = GetSubscriptionConnection(currentSubName)[name];
|
||||
}
|
||||
}
|
||||
|
@ -38,11 +38,11 @@ class SubscribeEditor : public QDialog, private Ui::w_SubscribeEditor
|
||||
private:
|
||||
void StartUpdateSubscription(const QString &subscriptionName);
|
||||
void SaveConfig();
|
||||
void LoadSubscriptionList(QMap<QString, Qv2raySubscriptionConfig> list);
|
||||
void LoadSubscriptionList(QMap<QString, QvSubscriptionObject> list);
|
||||
|
||||
bool isUpdateInProgress = false;
|
||||
QvHttpRequestHelper helper;
|
||||
QPair<QString, CONFIGROOT> currentSelectedConfig;
|
||||
QMap<QString, Qv2raySubscriptionConfig> subscriptions;
|
||||
QMap<QString, QvSubscriptionObject> subscriptions;
|
||||
QString currentSubName;
|
||||
};
|
||||
|
1
src/ui/widgets/ConnectionWidget.cpp
Normal file
1
src/ui/widgets/ConnectionWidget.cpp
Normal file
@ -0,0 +1 @@
|
||||
#include "ConnectionWidget.hpp"
|
105
src/ui/widgets/ConnectionWidget.hpp
Normal file
105
src/ui/widgets/ConnectionWidget.hpp
Normal file
@ -0,0 +1,105 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include "ui_ConnectionWidget.h"
|
||||
#include "core/handler/ConnectionHandler.hpp"
|
||||
|
||||
enum CONNECTION_ITEM_TYPE {
|
||||
INVALID,
|
||||
GROUP,
|
||||
SUBSCRIPTION
|
||||
};
|
||||
|
||||
class ConnectionWidget : public QWidget, private Ui::ConnectionWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
//
|
||||
// ======================================= Initialisation for connection nodes.
|
||||
//
|
||||
explicit ConnectionWidget(const GroupId &group, const ConnectionId &id, QWidget *parent = nullptr): ConnectionWidget(parent)
|
||||
{
|
||||
type = GROUP;
|
||||
connectionId = id;
|
||||
groupId = group;
|
||||
InitialiseForConnection(id);
|
||||
}
|
||||
explicit ConnectionWidget(const SubscriptionId &group, const ConnectionId &id, QWidget *parent = nullptr): ConnectionWidget(parent)
|
||||
{
|
||||
type = SUBSCRIPTION;
|
||||
connectionId = id;
|
||||
subscriptionId = group;
|
||||
InitialiseForConnection(id);
|
||||
}
|
||||
//
|
||||
// ======================================= Initialisation for root nodes.
|
||||
//
|
||||
explicit ConnectionWidget(const GroupId &id, QWidget *parent = nullptr) : ConnectionWidget(parent)
|
||||
{
|
||||
type = INVALID;
|
||||
groupId = id;
|
||||
InitialiseForGroup(ConnectionHandler->GetGroup(id).displayName, ConnectionHandler->Connections(id).count());
|
||||
}
|
||||
explicit ConnectionWidget(const SubscriptionId &id, QWidget *parent = nullptr) : ConnectionWidget(parent)
|
||||
{
|
||||
type = INVALID;
|
||||
subscriptionId = id;
|
||||
InitialiseForGroup(ConnectionHandler->GetSubscription(id).displayName, ConnectionHandler->Connections(id).count());
|
||||
}
|
||||
inline bool IsConnection() const
|
||||
{
|
||||
return isConnectionItem;
|
||||
}
|
||||
void BeginConnection()
|
||||
{
|
||||
if (isConnectionItem) {
|
||||
if (type == GROUP) {
|
||||
ConnectionHandler->StartConnection(groupId, connectionId);
|
||||
} else if (type == SUBSCRIPTION) {
|
||||
ConnectionHandler->StartConnection(subscriptionId, connectionId);
|
||||
} else {
|
||||
LOG(MODULE_UI, "Trying to start an INVALID non-connection entry, this call is illegal.")
|
||||
}
|
||||
} else {
|
||||
LOG(MODULE_UI, "Trying to start a non-connection entry, this call is illegal.")
|
||||
}
|
||||
}
|
||||
~ConnectionWidget()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
private:
|
||||
ConnectionWidget(QWidget *parent = nullptr) : QWidget(parent), connectionId("null"), groupId("null"), subscriptionId("null")
|
||||
{
|
||||
setupUi(this);
|
||||
}
|
||||
void InitialiseForConnection(const ConnectionId &id)
|
||||
{
|
||||
isConnectionItem = true;
|
||||
auto connection = ConnectionHandler->GetConnection(id);
|
||||
rawDisplayName = connection.displayName;
|
||||
connNameLabel->setText(rawDisplayName);
|
||||
latencyLabel->setText(tr("Latency: ") + QSTRN(connection.latency) + " " + tr("ms"));
|
||||
}
|
||||
void InitialiseForGroup(const QString &displayName, int connectionCount)
|
||||
{
|
||||
rawDisplayName = displayName;
|
||||
connNameLabel->setText(rawDisplayName);
|
||||
latencyLabel->setText(QSTRN(connectionCount) + " " + (connectionCount < 2 ? tr("connection") : tr("connections")));
|
||||
//
|
||||
layout()->removeWidget(connTypeLabel);
|
||||
delete connTypeLabel;
|
||||
layout()->removeWidget(dataLabel);
|
||||
delete dataLabel;
|
||||
}
|
||||
CONNECTION_ITEM_TYPE type;
|
||||
bool isConnectionItem = false;
|
||||
QString rawDisplayName;
|
||||
//
|
||||
ConnectionId connectionId;
|
||||
GroupId groupId;
|
||||
SubscriptionId subscriptionId;
|
||||
|
||||
Q_DISABLE_COPY_MOVE(ConnectionWidget)
|
||||
};
|
66
src/ui/widgets/ConnectionWidget.ui
Normal file
66
src/ui/widgets/ConnectionWidget.ui
Normal file
@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ConnectionWidget</class>
|
||||
<widget class="QWidget" name="ConnectionWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>283</width>
|
||||
<height>84</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="connNameLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Connection Name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="latencyLabel">
|
||||
<property name="text">
|
||||
<string>Latency: 500ms</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="connTypeLabel">
|
||||
<property name="text">
|
||||
<string>Type: vmess + tls + ws</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="dataLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0KB / 0KB</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
Loading…
Reference in New Issue
Block a user