mirror of
https://github.com/Qv2ray/Qv2ray.git
synced 2025-05-20 02:40:20 +08:00
[update] Several code refactoring and added qvAppLog
Former-commit-id: 7ae62e96fc
This commit is contained in:
parent
73113bf26f
commit
5d94d99f1a
@ -1 +1 @@
|
||||
1090
|
||||
1282
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <QtGui>
|
||||
#include <QMap>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include "QvTinyLog.hpp"
|
||||
#include "QvCoreConfigObjects.hpp"
|
||||
#include "QObjectMessageProxy.hpp"
|
||||
@ -73,6 +74,19 @@
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Generic function to find if an element of any type exists in list
|
||||
*/
|
||||
template<typename T>
|
||||
bool contains(std::list<T> &listOfElements, const T &element)
|
||||
{
|
||||
// Find the iterator if element in list
|
||||
auto it = std::find(listOfElements.begin(), listOfElements.end(), element);
|
||||
//return if iterator points to end or not. It points to end then it means element
|
||||
// does not exists in list
|
||||
return it != listOfElements.end();
|
||||
}
|
||||
|
||||
namespace Qv2ray
|
||||
{
|
||||
//
|
||||
|
@ -10,7 +10,7 @@ namespace Qv2ray
|
||||
auto conf = CONFIGROOT(JsonFromString(jsonString));
|
||||
|
||||
if (conf.count() == 0) {
|
||||
LOG(MODULE_CONFIG, "WARN: Possible file corruption, failed to load file: " << connection.toStdString())
|
||||
LOG(MODULE_CONFIG, "WARN: Possible file corruption, failed to load file: " + connection.toStdString())
|
||||
}
|
||||
|
||||
return conf;
|
||||
@ -43,7 +43,7 @@ namespace Qv2ray
|
||||
confName.chop(sizeof(QV2RAY_CONFIG_FILE_EXTENSION) - 1);
|
||||
_config[confName] = _ReadConnection(QV2RAY_SUBSCRIPTION_DIR + QSTRING(singleSub) + "/" + _file);
|
||||
} else {
|
||||
LOG(MODULE_SUBSCRIPTION, "Found a file in subscription folder but without proper suffix: " << _file.toStdString())
|
||||
LOG(MODULE_SUBSCRIPTION, "Found a file in subscription folder but without proper suffix: " + _file.toStdString())
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,13 +63,6 @@ namespace Qv2ray
|
||||
bool cRules = cRule && root["routing"].toObject()["rules"].toArray().count() > 0;
|
||||
return cRules;
|
||||
}
|
||||
int StartPreparation(CONFIGROOT fullConfig)
|
||||
{
|
||||
// Writes the final configuration to the disk.
|
||||
QString json = JsonToString(fullConfig);
|
||||
StringToFile(&json, new QFile(QV2RAY_GENERATED_FILE_PATH));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FindIndexByTag(INOUTLIST list, const QString &tag)
|
||||
{
|
||||
|
@ -19,7 +19,6 @@ namespace Qv2ray
|
||||
QMap<QString, CONFIGROOT> GetRegularConnections(list<string> connections);
|
||||
QMap<QString, QMap<QString, CONFIGROOT>> GetSubscriptionConnections(list<string> subscriptions);
|
||||
bool CheckIsComplexConfig(CONFIGROOT root);
|
||||
int StartPreparation(CONFIGROOT fullConfig);
|
||||
int FindIndexByTag(INOUTLIST list, const QString &tag);
|
||||
|
||||
//
|
||||
|
@ -150,7 +150,7 @@ namespace Qv2ray
|
||||
#undef C
|
||||
//return flag ? 0 : 1;
|
||||
} catch (exception *e) {
|
||||
LOG(MODULE_CONNECTION_VMESS, "Failed to decode vmess string: " << e->what())
|
||||
LOG(MODULE_CONNECTION_VMESS, "Failed to decode vmess string: " + string(e->what()))
|
||||
*errMessage = QSTRING(e->what());
|
||||
return CONFIGROOT();
|
||||
}
|
||||
|
@ -1,5 +1,25 @@
|
||||
#include "QvUtils.hpp"
|
||||
#include <QTextStream>
|
||||
#include <QQueue>
|
||||
|
||||
// Forwarded from QvTinyLog
|
||||
static QQueue<QString> __loggerBuffer;
|
||||
void _LOG(const std::string &module, const std::string &log)
|
||||
{
|
||||
string logString = "[" + module + "]: " + log + NEWLINE;
|
||||
cout << logString;
|
||||
__loggerBuffer.enqueue(logString.c_str());
|
||||
}
|
||||
|
||||
const QString readLastLog()
|
||||
{
|
||||
QString result;
|
||||
|
||||
while (!__loggerBuffer.isEmpty()) {
|
||||
result += __loggerBuffer.dequeue();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
namespace Qv2ray
|
||||
{
|
||||
@ -241,5 +261,14 @@ namespace Qv2ray
|
||||
}
|
||||
}
|
||||
|
||||
void QFastAppendTextDocument(const QString &message, QTextDocument *doc)
|
||||
{
|
||||
QTextCursor cursor(doc);
|
||||
cursor.movePosition(QTextCursor::End);
|
||||
cursor.beginEditBlock();
|
||||
cursor.insertBlock();
|
||||
cursor.insertHtml(message);
|
||||
cursor.endEditBlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -87,6 +87,7 @@ namespace Qv2ray
|
||||
//
|
||||
//
|
||||
QString ConvertGFWToPAC(const QString &rawContent, const QString &customProxyString);
|
||||
void QFastAppendTextDocument(const QString &message, QTextDocument *doc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,14 +5,13 @@
|
||||
#include "QvCoreConfigOperations.hpp"
|
||||
|
||||
#include "QvTinyLog.hpp"
|
||||
#include "w_MainWindow.hpp"
|
||||
|
||||
using namespace v2ray::core::app::stats::command;
|
||||
using grpc::Channel;
|
||||
using grpc::ClientContext;
|
||||
using grpc::Status;
|
||||
|
||||
// Check 20 times before telling user that API has failed.
|
||||
// Check 10 times before telling user that API has failed.
|
||||
#define QV2RAY_API_CALL_FAILEDCHECK_THRESHOLD 10
|
||||
|
||||
namespace Qv2ray
|
||||
@ -21,75 +20,75 @@ namespace Qv2ray
|
||||
{
|
||||
bool ConnectionInstance::ValidateConfig(const QString &path)
|
||||
{
|
||||
if (ValidateKernal()) {
|
||||
auto conf = GetGlobalConfig();
|
||||
|
||||
if (QFile::exists(QSTRING(conf.v2CorePath))) {
|
||||
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
||||
env.insert("V2RAY_LOCATION_ASSET", QString::fromStdString(GetGlobalConfig().v2AssetsPath));
|
||||
env.insert("V2RAY_LOCATION_ASSET", QSTRING(conf.v2AssetsPath));
|
||||
QProcess process;
|
||||
process.setProcessEnvironment(env);
|
||||
process.start(QSTRING(GetGlobalConfig().v2CorePath), QStringList() << "-test" << "-config" << path, QIODevice::ReadWrite | QIODevice::Text);
|
||||
process.start(QSTRING(conf.v2CorePath), QStringList() << "-test" << "-config" << path, QIODevice::ReadWrite | QIODevice::Text);
|
||||
|
||||
if (!process.waitForFinished()) {
|
||||
LOG(MODULE_VCORE, "v2ray core failed with exitcode: " << process.exitCode())
|
||||
if (!process.waitForFinished(1000)) {
|
||||
LOG(MODULE_VCORE, "v2ray core failed with exitcode: " + process.exitCode())
|
||||
QvMessageBox(nullptr, tr("Cannot start v2ray"), tr("v2ray core failed with errcode:") + QString::number(process.exitCode()));
|
||||
return false;
|
||||
}
|
||||
|
||||
QString output = QString(process.readAllStandardOutput());
|
||||
|
||||
if (process.exitCode() != 0) {
|
||||
Utils::QvMessageBox(nullptr, tr("Configuration Error"), output.mid(output.indexOf("anti-censorship.") + 17));
|
||||
QvMessageBox(nullptr, tr("Configuration Error"), output.mid(output.indexOf("anti-censorship.") + 17));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} else {
|
||||
QvMessageBox(nullptr, tr("Cannot start v2ray"),
|
||||
tr("v2ray core file cannot be found at:") + NEWLINE +
|
||||
QSTRING(conf.v2CorePath) + NEWLINE + NEWLINE +
|
||||
tr("Please go to Prefrence Window to change the location.") + NEWLINE +
|
||||
tr("Or place your v2ray core file in the location above."));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ConnectionInstance::ConnectionInstance(QWidget *parent) : apiFailedCounter(0), port(0)
|
||||
ConnectionInstance::ConnectionInstance()
|
||||
{
|
||||
auto proc = new QProcess();
|
||||
vProcess = proc;
|
||||
connect(vProcess, &QProcess::readyReadStandardOutput, static_cast<MainWindow *>(parent), &MainWindow::UpdateLog);
|
||||
connect(vProcess, &QProcess::readyReadStandardOutput, this, [this]() {
|
||||
emit onProcessOutputReadyRead(vProcess->readAllStandardOutput().trimmed());
|
||||
});
|
||||
ConnectionStatus = STOPPED;
|
||||
}
|
||||
|
||||
void ConnectionInstance::SetAPIPort(int port)
|
||||
bool ConnectionInstance::StartConnection(CONFIGROOT root, bool useAPI, int apiPort)
|
||||
{
|
||||
// Config API
|
||||
this->port = port;
|
||||
Channel = grpc::CreateChannel("127.0.0.1:" + to_string(port), grpc::InsecureChannelCredentials());
|
||||
StatsService service;
|
||||
Stub = service.NewStub(Channel);
|
||||
inboundTags.clear();
|
||||
|
||||
for (auto item : root["inbounds"].toArray()) {
|
||||
auto tag = item.toObject()["tag"].toString("");
|
||||
|
||||
if (tag.isEmpty() || tag == QV2RAY_API_TAG_INBOUND)
|
||||
continue;
|
||||
|
||||
inboundTags.append(tag);
|
||||
}
|
||||
|
||||
QString ConnectionInstance::ReadProcessOutput()
|
||||
{
|
||||
return vProcess->readAllStandardOutput();
|
||||
}
|
||||
LOG(MODULE_VCORE, "Found Inbound Tags: " + Stringify(inboundTags).toStdString())
|
||||
QString json = JsonToString(root);
|
||||
// Write the final configuration to the disk.
|
||||
StringToFile(&json, new QFile(QV2RAY_GENERATED_FILE_PATH));
|
||||
//
|
||||
enableAPI = useAPI;
|
||||
|
||||
bool ConnectionInstance::ValidateKernal()
|
||||
{
|
||||
if (!QFile::exists(QSTRING(GetGlobalConfig().v2CorePath))) {
|
||||
Utils::QvMessageBox(nullptr, tr("Cannot start v2ray"),
|
||||
tr("v2ray core file cannot be found at:") + NEWLINE +
|
||||
QSTRING(GetGlobalConfig().v2CorePath) + NEWLINE + NEWLINE +
|
||||
tr("Please go to prefrence window to change the location.") + NEWLINE +
|
||||
tr("Or put v2ray core file in the location above."));
|
||||
return false;
|
||||
} else return true;
|
||||
}
|
||||
|
||||
bool ConnectionInstance::StartV2rayCore()
|
||||
{
|
||||
if (ConnectionStatus != STOPPED) {
|
||||
LOG(MODULE_VCORE, "Status is invalid, expect STOPPED when calling StartV2rayCore")
|
||||
return false;
|
||||
}
|
||||
|
||||
ConnectionStatus = STARTING;
|
||||
|
||||
if (ValidateKernal()) {
|
||||
auto filePath = QV2RAY_GENERATED_FILE_PATH;
|
||||
|
||||
if (ValidateConfig(filePath)) {
|
||||
@ -99,29 +98,57 @@ namespace Qv2ray
|
||||
vProcess->start(QSTRING(GetGlobalConfig().v2CorePath), QStringList() << "-config" << filePath, QIODevice::ReadWrite | QIODevice::Text);
|
||||
vProcess->waitForStarted();
|
||||
ConnectionStatus = STARTED;
|
||||
|
||||
if (enableAPI) {
|
||||
// Config API
|
||||
this->apiPort = apiPort;
|
||||
Channel = grpc::CreateChannel("127.0.0.1:" + to_string(apiPort), grpc::InsecureChannelCredentials());
|
||||
StatsService service;
|
||||
Stub = service.NewStub(Channel);
|
||||
apiTimerId = startTimer(1000);
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
ConnectionStatus = STOPPED;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
ConnectionStatus = STOPPED;
|
||||
return false;
|
||||
}
|
||||
|
||||
void ConnectionInstance::timerEvent(QTimerEvent *event)
|
||||
{
|
||||
QObject::timerEvent(event);
|
||||
|
||||
if (event->timerId() == apiTimerId) {
|
||||
// Call API
|
||||
for (auto tag : inboundTags) {
|
||||
// Upload
|
||||
auto valup = CallStatsAPIByName("inbound>>>" + tag + ">>>traffic>>>uplink");
|
||||
auto dataup = valup - transferData[tag + "_up"];
|
||||
transferData[tag + "_up"] = valup;
|
||||
transferSpeed[tag + "_up"] = dataup;
|
||||
// Download
|
||||
auto valdown = CallStatsAPIByName("inbound>>>" + tag + ">>>traffic>>>downlink");
|
||||
auto datadown = valdown - transferData[tag + "_down"];
|
||||
transferData[tag + "_down"] = valdown;
|
||||
transferSpeed[tag + "_down"] = datadown;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectionInstance::StopV2rayCore()
|
||||
void ConnectionInstance::StopConnection()
|
||||
{
|
||||
vProcess->close();
|
||||
killTimer(apiTimerId);
|
||||
apiFailedCounter = 0;
|
||||
totalDataTransfered.clear();
|
||||
dataTransferSpeed.clear();
|
||||
transferData.clear();
|
||||
transferSpeed.clear();
|
||||
ConnectionStatus = STOPPED;
|
||||
}
|
||||
|
||||
ConnectionInstance::~ConnectionInstance()
|
||||
{
|
||||
StopV2rayCore();
|
||||
StopConnection();
|
||||
delete vProcess;
|
||||
}
|
||||
|
||||
@ -135,8 +162,8 @@ namespace Qv2ray
|
||||
if (apiFailedCounter == QV2RAY_API_CALL_FAILEDCHECK_THRESHOLD) {
|
||||
LOG(MODULE_VCORE, "API call failure threshold reached, cancelling further API aclls.")
|
||||
QvMessageBox(nullptr, tr("API Call Failed"), tr("Failed to get statistics data, please check if v2ray is running properly"));
|
||||
totalDataTransfered.clear();
|
||||
dataTransferSpeed.clear();
|
||||
transferData.clear();
|
||||
transferSpeed.clear();
|
||||
apiFailedCounter++;
|
||||
return 0;
|
||||
} else if (apiFailedCounter > QV2RAY_API_CALL_FAILEDCHECK_THRESHOLD) {
|
||||
@ -151,39 +178,68 @@ namespace Qv2ray
|
||||
Status status = Stub->GetStats(&context, request, &response);
|
||||
|
||||
if (!status.ok()) {
|
||||
LOG(MODULE_VCORE, "API call returns: " << status.error_code() << " (" << status.error_message() << ")")
|
||||
LOG(MODULE_VCORE, "API call returns: " + to_string(status.error_code()) + " (" + status.error_message() + ")")
|
||||
apiFailedCounter++;
|
||||
}
|
||||
|
||||
return response.stat().value();
|
||||
}
|
||||
|
||||
long ConnectionInstance::getTagLastUplink(const QString &tag)
|
||||
// ------------------------------------------------------------- API FUNCTIONS --------------------------
|
||||
long ConnectionInstance::getTagSpeedUp(const QString &tag)
|
||||
{
|
||||
auto val = CallStatsAPIByName("inbound>>>" + tag + ">>>traffic>>>uplink");
|
||||
auto data = val - totalDataTransfered[tag + "_up"];
|
||||
totalDataTransfered[tag + "_up"] = val;
|
||||
dataTransferSpeed[tag + "_up"] = data;
|
||||
return data;
|
||||
return transferSpeed[tag + "_up"];
|
||||
}
|
||||
long ConnectionInstance::getTagSpeedDown(const QString &tag)
|
||||
{
|
||||
return transferSpeed[tag + "_down"];
|
||||
}
|
||||
long ConnectionInstance::getTagDataUp(const QString &tag)
|
||||
{
|
||||
return transferData[tag + "_up"];
|
||||
}
|
||||
long ConnectionInstance::getTagDataDown(const QString &tag)
|
||||
{
|
||||
return transferData[tag + "_down"];
|
||||
}
|
||||
long ConnectionInstance::getAllDataUp()
|
||||
{
|
||||
long val = 0;
|
||||
|
||||
for (auto tag : inboundTags) {
|
||||
val += transferData[tag + "_up"];
|
||||
}
|
||||
|
||||
long ConnectionInstance::getTagLastDownlink(const QString &tag)
|
||||
return val;
|
||||
}
|
||||
long ConnectionInstance::getAllDataDown()
|
||||
{
|
||||
auto val = CallStatsAPIByName("inbound>>>" + tag + ">>>traffic>>>downlink");
|
||||
auto data = val - totalDataTransfered[tag + "_down"];
|
||||
totalDataTransfered[tag + "_down"] = val;
|
||||
dataTransferSpeed[tag + "_down"] = data;
|
||||
return data;
|
||||
long val = 0;
|
||||
|
||||
for (auto tag : inboundTags) {
|
||||
val += transferData[tag + "_down"];
|
||||
}
|
||||
|
||||
long ConnectionInstance::getTagTotalUplink(const QString &tag)
|
||||
return val;
|
||||
}
|
||||
long ConnectionInstance::getAllSpeedUp()
|
||||
{
|
||||
return totalDataTransfered[tag + "_up"];
|
||||
long val = 0;
|
||||
|
||||
for (auto tag : inboundTags) {
|
||||
val += transferSpeed[tag + "_up"];
|
||||
}
|
||||
|
||||
long ConnectionInstance::getTagTotalDownlink(const QString &tag)
|
||||
return val;
|
||||
}
|
||||
long ConnectionInstance::getAllSpeedDown()
|
||||
{
|
||||
return totalDataTransfered[tag + "_down"];
|
||||
long val = 0;
|
||||
|
||||
for (auto tag : inboundTags) {
|
||||
val += transferSpeed[tag + "_down"];
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,32 +22,44 @@ namespace Qv2ray
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ConnectionInstance(QWidget *parent = nullptr);
|
||||
void SetAPIPort(int port);
|
||||
explicit ConnectionInstance();
|
||||
~ConnectionInstance() override;
|
||||
//
|
||||
long getTagTotalDownlink(const QString &tag);
|
||||
long getTagTotalUplink(const QString &tag);
|
||||
long getTagLastDownlink(const QString &tag);
|
||||
long getTagLastUplink(const QString &tag);
|
||||
// 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();
|
||||
//
|
||||
bool StartV2rayCore();
|
||||
void StopV2rayCore();
|
||||
bool StartConnection(CONFIGROOT root, bool useAPI, int apiPort);
|
||||
void StopConnection();
|
||||
QvInstanceStatus ConnectionStatus;
|
||||
QString ReadProcessOutput();
|
||||
//
|
||||
static bool ValidateConfig(const QString &path);
|
||||
static bool ValidateKernal();
|
||||
|
||||
~ConnectionInstance();
|
||||
QMap<QString, long> totalDataTransfered;
|
||||
QMap<QString, long> dataTransferSpeed;
|
||||
signals:
|
||||
void onProcessOutputReadyRead(QString);
|
||||
|
||||
private:
|
||||
void timerEvent(QTimerEvent *event) override;
|
||||
QStringList inboundTags;
|
||||
bool enableAPI;
|
||||
int apiTimerId;
|
||||
int apiPort;
|
||||
//
|
||||
int apiFailedCounter;
|
||||
long CallStatsAPIByName(QString name);
|
||||
QProcess *vProcess;
|
||||
//
|
||||
QMap<QString, long> transferData;
|
||||
QMap<QString, long> transferSpeed;
|
||||
//
|
||||
std::shared_ptr<::grpc::Channel> Channel;
|
||||
std::unique_ptr<::v2ray::core::app::stats::command::StatsService::Stub> Stub;
|
||||
int port;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -106,6 +106,17 @@ namespace Qv2ray
|
||||
rule.format = failedFormat;
|
||||
highlightingRules.append(rule);
|
||||
//
|
||||
qvAppLogFormat.setFontWeight(QFont::Bold);
|
||||
qvAppLogFormat.setForeground(darkMode ? Qt::cyan : Qt::darkCyan);
|
||||
rule.pattern = QRegularExpression("\\[[A-Z]*\\]:");
|
||||
rule.format = qvAppLogFormat;
|
||||
highlightingRules.append(rule);
|
||||
//
|
||||
qvAppDebugLogFormat.setFontWeight(QFont::Bold);
|
||||
qvAppDebugLogFormat.setForeground(darkMode ? Qt::yellow : Qt::darkYellow);
|
||||
rule.pattern = QRegularExpression("\\[\\[DEBUG\\] - [A-Z]*\\]:");
|
||||
rule.format = qvAppDebugLogFormat;
|
||||
highlightingRules.append(rule);
|
||||
}
|
||||
|
||||
void Highlighter::highlightBlock(const QString &text)
|
||||
|
@ -89,6 +89,9 @@ namespace Qv2ray
|
||||
QTextCharFormat timeFormat;
|
||||
QTextCharFormat ipHostFormat;
|
||||
QTextCharFormat x;
|
||||
//
|
||||
QTextCharFormat qvAppLogFormat;
|
||||
QTextCharFormat qvAppDebugLogFormat;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ namespace Qv2ray
|
||||
{ 303, QObject::tr("Uploaded Data for Specific Tag") },
|
||||
{ 304, QObject::tr("Downloaded Data for Specific Tag") }
|
||||
};
|
||||
void StartProcessingPlugins(QWidget *mainWindow);
|
||||
void StartProcessingPlugins();
|
||||
void StopProcessingPlugins();
|
||||
#ifdef Q_OS_WIN
|
||||
namespace _win
|
||||
|
10
src/main.cpp
10
src/main.cpp
@ -74,11 +74,11 @@ bool initialiseQv2ray()
|
||||
bool avail = verifyConfigAvaliability(path, true);
|
||||
|
||||
if (avail) {
|
||||
DEBUG(MODULE_INIT, "Path: " << path.toStdString() << " is valid.")
|
||||
DEBUG(MODULE_INIT, "Path: " + path.toStdString() + " is valid.")
|
||||
configPath = path;
|
||||
hasExistingConfig = true;
|
||||
} else {
|
||||
DEBUG(MODULE_INIT, "Path: " << path.toStdString() << " does not contain a valid config file.")
|
||||
DEBUG(MODULE_INIT, "Path: " + path.toStdString() + " does not contain a valid config file.")
|
||||
}
|
||||
}
|
||||
|
||||
@ -304,7 +304,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (themes.contains(QSTRING(confObject.uiConfig.theme))) {
|
||||
_qApp.setStyle(QSTRING(confObject.uiConfig.theme));
|
||||
LOG(MODULE_INIT " " MODULE_UI, "Setting Qv2ray UI themes.")
|
||||
LOG(MODULE_INIT " " MODULE_UI, "Setting Qv2ray UI themes: " + confObject.uiConfig.theme)
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -312,7 +312,9 @@ int main(int argc, char *argv[])
|
||||
try {
|
||||
// Show MainWindow
|
||||
MainWindow w;
|
||||
return _qApp.exec();
|
||||
auto rcode = _qApp.exec();
|
||||
LOG(MODULE_INIT, "Quitting normally")
|
||||
return rcode;
|
||||
} catch (...) {
|
||||
QvMessageBox(nullptr, "ERROR", "There's something wrong happened and Qv2ray will quit now.");
|
||||
LOG(MODULE_INIT, "EXCEPTION THROWN: " __FILE__)
|
||||
|
@ -9,7 +9,6 @@ namespace Qv2ray
|
||||
{
|
||||
namespace NetSpeedPlugin
|
||||
{
|
||||
static MainWindow *mainWindow;
|
||||
static Qv2rayConfig config;
|
||||
void StopProcessingPlugins()
|
||||
{
|
||||
@ -23,9 +22,8 @@ namespace Qv2ray
|
||||
|
||||
/// Public Function - CALL ONLY ONCE -
|
||||
/// To start processing plugins' command.
|
||||
void StartProcessingPlugins(QWidget *_mainWindow)
|
||||
void StartProcessingPlugins()
|
||||
{
|
||||
mainWindow = static_cast<MainWindow *>(_mainWindow);
|
||||
config = GetGlobalConfig();
|
||||
#ifdef Q_OS_LINUX
|
||||
_linux::StartMessageQThread();
|
||||
@ -36,16 +34,18 @@ namespace Qv2ray
|
||||
}
|
||||
QString GetAnswerToRequest(const QString &pchRequest)
|
||||
{
|
||||
auto vinstance = mwInstance->vinstance;
|
||||
//
|
||||
auto req = pchRequest.trimmed();
|
||||
config = GetGlobalConfig();
|
||||
QString reply = "{}";
|
||||
|
||||
if (req == "START") {
|
||||
emit mainWindow->Connect();
|
||||
emit mwInstance->Connect();
|
||||
} else if (req == "STOP") {
|
||||
emit mainWindow->DisConnect();
|
||||
emit mwInstance->DisConnect();
|
||||
} else if (req == "RESTART") {
|
||||
emit mainWindow->ReConnect();
|
||||
emit mwInstance->ReConnect();
|
||||
}
|
||||
|
||||
auto BarConfig = config.toolBarConfig;
|
||||
@ -82,13 +82,13 @@ namespace Qv2ray
|
||||
|
||||
case 104: {
|
||||
// Current Connection Name
|
||||
CL.Message = mainWindow->CurrentConnectionName.toStdString();
|
||||
CL.Message = mwInstance->CurrentConnectionName.toStdString();
|
||||
break;
|
||||
}
|
||||
|
||||
case 105: {
|
||||
// Current Connection Status
|
||||
switch (mainWindow->vinstance->ConnectionStatus) {
|
||||
switch (mwInstance->vinstance->ConnectionStatus) {
|
||||
case STARTED: {
|
||||
CL.Message = QObject::tr("Connected").toStdString();
|
||||
break;
|
||||
@ -111,60 +111,56 @@ namespace Qv2ray
|
||||
case 201: {
|
||||
// Total upload speed;
|
||||
STATS_ENABLE_CHECK
|
||||
CL.Message = (mainWindow->totalSpeedUp + "/s").toStdString();
|
||||
CL.Message = FormatBytes(vinstance->getAllSpeedUp()).toStdString() + "/s";
|
||||
break;
|
||||
}
|
||||
|
||||
case 202: {
|
||||
// Total download speed;
|
||||
STATS_ENABLE_CHECK
|
||||
CL.Message = (mainWindow->totalSpeedDown + "/s").toStdString();
|
||||
CL.Message = (FormatBytes(vinstance->getAllSpeedDown()) + "/s").toStdString();
|
||||
break;
|
||||
}
|
||||
|
||||
case 203: {
|
||||
// Upload speed for tag
|
||||
STATS_ENABLE_CHECK
|
||||
auto data = mainWindow->vinstance->dataTransferSpeed[QSTRING(CL.Message) + "_up"];
|
||||
CL.Message = FormatBytes(data).toStdString() + "/s";
|
||||
CL.Message = FormatBytes(vinstance->getTagSpeedUp(QSTRING(CL.Message))).toStdString() + "/s";
|
||||
break;
|
||||
}
|
||||
|
||||
case 204: {
|
||||
STATS_ENABLE_CHECK
|
||||
// Download speed for tag
|
||||
auto data = mainWindow->vinstance->dataTransferSpeed[QSTRING(CL.Message) + "_down"];
|
||||
CL.Message = FormatBytes(data).toStdString() + "/s";
|
||||
CL.Message = FormatBytes(vinstance->getTagSpeedDown(QSTRING(CL.Message))).toStdString() + "/s";
|
||||
break;
|
||||
}
|
||||
|
||||
case 301: {
|
||||
// Total Upload
|
||||
STATS_ENABLE_CHECK
|
||||
CL.Message = (mainWindow->totalDataUp).toStdString();
|
||||
CL.Message = FormatBytes(vinstance->getAllDataUp()).toStdString();
|
||||
break;
|
||||
}
|
||||
|
||||
case 302: {
|
||||
// Total download
|
||||
STATS_ENABLE_CHECK
|
||||
CL.Message = (mainWindow->totalDataDown).toStdString();
|
||||
CL.Message = FormatBytes(vinstance->getAllDataDown()).toStdString();
|
||||
break;
|
||||
}
|
||||
|
||||
case 303: {
|
||||
// Upload for tag
|
||||
STATS_ENABLE_CHECK
|
||||
auto data = mainWindow->vinstance->totalDataTransfered[QSTRING(CL.Message) + "_up"];
|
||||
CL.Message = FormatBytes(data).toStdString();
|
||||
CL.Message = FormatBytes(vinstance->getTagDataUp(QSTRING(CL.Message))).toStdString();
|
||||
break;
|
||||
}
|
||||
|
||||
case 304: {
|
||||
// Download for tag
|
||||
STATS_ENABLE_CHECK
|
||||
auto data = mainWindow->vinstance->totalDataTransfered[QSTRING(CL.Message) + "_down"];
|
||||
CL.Message = FormatBytes(data).toStdString();
|
||||
CL.Message = FormatBytes(vinstance->getTagDataDown(QSTRING(CL.Message))).toStdString();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -61,8 +61,8 @@ namespace Qv2ray
|
||||
|
||||
while (!isExiting) {
|
||||
bool result = server->waitForNewConnection(200, &timeOut);
|
||||
LOG(MODULE_PLUGIN, "Plugin thread listening failed: " << server->errorString().toStdString())
|
||||
LOG(MODULE_PLUGIN, "waitForNewConnection: " << (result ? "true" : "false") << ", " << (timeOut ? "true" : "false"))
|
||||
LOG(MODULE_PLUGIN, "Plugin thread listening failed: " + server->errorString().toStdString())
|
||||
LOG(MODULE_PLUGIN, "waitForNewConnection: " + string(result ? "true" : "false") + ", " + string(timeOut ? "true" : "false"))
|
||||
}
|
||||
|
||||
server->close();
|
||||
|
@ -29,7 +29,7 @@ namespace Qv2ray
|
||||
auto hThread = CreateThread(nullptr, 0, NamedPipeMasterThread, nullptr, 0, nullptr);
|
||||
|
||||
if (hThread == nullptr) {
|
||||
LOG(MODULE_PLUGIN, "CreateThread failed, GLE=" << GetLastError())
|
||||
LOG(MODULE_PLUGIN, "CreateThread failed, GLE=" + to_string(GetLastError()))
|
||||
return;
|
||||
} else CloseHandle(hThread);
|
||||
}
|
||||
@ -47,7 +47,7 @@ namespace Qv2ray
|
||||
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(MODULE_PLUGIN, "CreateNamedPipe failed, GLE=" << GetLastError())
|
||||
LOG(MODULE_PLUGIN, "CreateNamedPipe failed, GLE=" + to_string(GetLastError()))
|
||||
return static_cast<DWORD>(-1);
|
||||
}
|
||||
|
||||
@ -58,7 +58,7 @@ namespace Qv2ray
|
||||
ThreadHandle = CreateThread(nullptr, 0, InstanceThread, hPipe, 0, &dwThreadId);
|
||||
|
||||
if (ThreadHandle == nullptr) {
|
||||
LOG(MODULE_PLUGIN, "CreateThread failed, GLE=%d.\n" << GetLastError())
|
||||
LOG(MODULE_PLUGIN, "CreateThread failed, GLE=" + to_string(GetLastError()))
|
||||
return static_cast<DWORD>(-1);
|
||||
} else CloseHandle(ThreadHandle);
|
||||
} else CloseHandle(hPipe);
|
||||
@ -79,7 +79,7 @@ namespace Qv2ray
|
||||
|
||||
if (!fSuccess || cbBytesRead == 0) {
|
||||
if (GetLastError() == ERROR_BROKEN_PIPE) {
|
||||
LOG(MODULE_PLUGIN, "InstanceThread: client disconnected.\n" + to_string(GetLastError()))
|
||||
LOG(MODULE_PLUGIN, "InstanceThread: client disconnected, GLE=" + to_string(GetLastError()))
|
||||
} else {
|
||||
LOG(MODULE_PLUGIN, "InstanceThread ReadFile failed, GLE=" + to_string(GetLastError()))
|
||||
}
|
||||
|
@ -27,6 +27,9 @@
|
||||
#include "QvSystemProxyConfigurator.hpp"
|
||||
|
||||
#define TRAY_TOOLTIP_PREFIX "Qv2ray " QV2RAY_VERSION_STRING
|
||||
#define vCoreLogBrowser this->logTextBrowsers[0]
|
||||
#define qvAppLogBrowser this->logTextBrowsers[1]
|
||||
#define currentLogBrowser this->logTextBrowsers[currentLogBrowserId]
|
||||
#define SUBSCRIPTION_CONFIG_MODIFY_ASK(varName) \
|
||||
if (!connections[varName].isRegularConnection) { \
|
||||
if (QvMessageBoxAsk(this, tr("Editing a subscription config"), tr("You are trying to edit a config loaded from subscription.") + \
|
||||
@ -36,27 +39,36 @@
|
||||
} \
|
||||
} \
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent)
|
||||
:
|
||||
QMainWindow(parent),
|
||||
vinstance(),
|
||||
uploadList(),
|
||||
downloadList(),
|
||||
HTTPRequestHelper(),
|
||||
hTray(new QSystemTrayIcon(this)),
|
||||
highlighter()
|
||||
MainWindow::MainWindow(QWidget *parent):
|
||||
QMainWindow(parent), vinstance(), uploadList(), downloadList(), HTTPRequestHelper(),
|
||||
hTray(new QSystemTrayIcon(this)), vCoreLogHighlighter(), qvAppLogHighlighter()
|
||||
{
|
||||
mwInstance = this;
|
||||
auto conf = GetGlobalConfig();
|
||||
vinstance = new ConnectionInstance(this);
|
||||
vinstance = new ConnectionInstance();
|
||||
connect(vinstance, &ConnectionInstance::onProcessOutputReadyRead, this, &MainWindow::UpdateVCoreLog);
|
||||
setupUi(this);
|
||||
//
|
||||
highlighter = new Highlighter(conf.uiConfig.useDarkTheme, vcoreLog.document());
|
||||
logText->setDocument(vcoreLog.document());
|
||||
logText->setFontPointSize(8);
|
||||
vcoreLog.setFontPointSize(8);
|
||||
qvAppLog.setFontPointSize(8);
|
||||
// Two browsers
|
||||
logTextBrowsers.append(new QTextBrowser());
|
||||
logTextBrowsers.append(new QTextBrowser());
|
||||
vCoreLogBrowser->setFontPointSize(8);
|
||||
vCoreLogBrowser->setReadOnly(true);
|
||||
vCoreLogBrowser->setLineWrapMode(QTextBrowser::LineWrapMode::NoWrap);
|
||||
qvAppLogBrowser->setFontPointSize(8);
|
||||
qvAppLogBrowser->setReadOnly(true);
|
||||
qvAppLogBrowser->setLineWrapMode(QTextBrowser::LineWrapMode::NoWrap);
|
||||
//
|
||||
vCoreLogHighlighter = new Highlighter(conf.uiConfig.useDarkTheme, vCoreLogBrowser->document());
|
||||
qvAppLogHighlighter = new Highlighter(conf.uiConfig.useDarkTheme, qvAppLogBrowser->document());
|
||||
pacServer = new PACHandler();
|
||||
currentLogBrowserId = 0;
|
||||
masterLogBrowser->setDocument(currentLogBrowser->document());
|
||||
masterLogBrowser->document()->setDocumentMargin(0);
|
||||
masterLogBrowser->document()->adjustSize();
|
||||
masterLogBrowser->setLineWrapMode(QTextBrowser::LineWrapMode::NoWrap);
|
||||
//
|
||||
logTimerId = startTimer(500);
|
||||
//
|
||||
this->setWindowIcon(QIcon(":/icons/qv2ray.png"));
|
||||
hTray->setIcon(QIcon(conf.uiConfig.useDarkTrayIcon ? ":/icons/ui_dark/tray.png" : ":/icons/ui_light/tray.png"));
|
||||
@ -103,7 +115,6 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
connect(action_Tray_Reconnect, &QAction::triggered, this, &MainWindow::on_reconnectButton_clicked);
|
||||
connect(action_Tray_Quit, &QAction::triggered, this, &MainWindow::quit);
|
||||
connect(hTray, &QSystemTrayIcon::activated, this, &MainWindow::on_activatedTray);
|
||||
connect(logText, &QTextBrowser::textChanged, this, &MainWindow::QTextScrollToBottom);
|
||||
connect(action_RCM_RenameConnection, &QAction::triggered, this, &MainWindow::on_action_RenameConnection_triggered);
|
||||
connect(action_RCM_StartThis, &QAction::triggered, this, &MainWindow::on_action_StartThis_triggered);
|
||||
connect(action_RCM_EditJson, &QAction::triggered, this, &MainWindow::on_action_RCM_EditJson_triggered);
|
||||
@ -162,12 +173,8 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
auto layout = new QHBoxLayout(speedChart);
|
||||
layout->addWidget(speedChartView);
|
||||
speedChart->setLayout(layout);
|
||||
//
|
||||
bool hasAutoStart = vinstance->ValidateKernal();
|
||||
|
||||
if (hasAutoStart) {
|
||||
// At least kernal is ready.
|
||||
if (!conf.autoStartConfig.empty() && QList<string>::fromStdList(conf.configs).contains(conf.autoStartConfig)) {
|
||||
if (!conf.autoStartConfig.empty() && contains(conf.configs, conf.autoStartConfig)) {
|
||||
// Has auto start.
|
||||
CurrentConnectionName = QSTRING(conf.autoStartConfig);
|
||||
auto item = connectionListWidget->findItems(QSTRING(conf.autoStartConfig), Qt::MatchExactly).front();
|
||||
@ -183,11 +190,8 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
ShowAndSetConnection(connectionListWidget->item(0)->text(), true, false);
|
||||
this->show();
|
||||
}
|
||||
} else {
|
||||
this->show();
|
||||
}
|
||||
|
||||
StartProcessingPlugins(this);
|
||||
StartProcessingPlugins();
|
||||
}
|
||||
|
||||
void MainWindow::mouseReleaseEvent(QMouseEvent *e)
|
||||
@ -195,7 +199,14 @@ void MainWindow::mouseReleaseEvent(QMouseEvent *e)
|
||||
Q_UNUSED(e)
|
||||
|
||||
if (logLabel->underMouse()) {
|
||||
logText->setDocument(logSourceId++ % 2 == 0 ? vcoreLog.document() : qvAppLog.document());
|
||||
//auto layout = masterLogBrowser->document()->setDocumentLayout()
|
||||
currentLogBrowserId = (currentLogBrowserId + 1) % logTextBrowsers.count();
|
||||
masterLogBrowser->setDocument(currentLogBrowser->document());
|
||||
masterLogBrowser->document()->setDocumentMargin(4);
|
||||
masterLogBrowser->document()->adjustSize();
|
||||
masterLogBrowser->setLineWrapMode(QTextBrowser::LineWrapMode::NoWrap);
|
||||
auto bar = masterLogBrowser->verticalScrollBar();
|
||||
bar->setValue(bar->maximum());
|
||||
}
|
||||
}
|
||||
|
||||
@ -250,7 +261,6 @@ void MainWindow::VersionUpdate(QByteArray &data)
|
||||
tr("Download Link: ") + link, QMessageBox::Ignore);
|
||||
|
||||
if (result == QMessageBox::Yes) {
|
||||
CLOG(result)
|
||||
QDesktopServices::openUrl(QUrl::fromUserInput(link));
|
||||
} else if (result == QMessageBox::Ignore) {
|
||||
conf.ignoredVersion = newversion.toString().toStdString();
|
||||
@ -330,9 +340,20 @@ MainWindow::~MainWindow()
|
||||
delete this->hTray;
|
||||
delete this->vinstance;
|
||||
}
|
||||
void MainWindow::UpdateLog()
|
||||
void MainWindow::UpdateVCoreLog(const QString &log)
|
||||
{
|
||||
vcoreLog.append(vinstance->ReadProcessOutput().trimmed());
|
||||
vCoreLogBrowser->append(log);
|
||||
setMasterLogHBar();
|
||||
}
|
||||
void MainWindow::setMasterLogHBar()
|
||||
{
|
||||
auto bar = masterLogBrowser->verticalScrollBar();
|
||||
//LOG(bar->maximum(), bar->value())
|
||||
auto max = bar->maximum();
|
||||
auto val = bar->value();
|
||||
|
||||
if (val >= max * 0.8 || val >= max - 20)
|
||||
bar->setValue(max);
|
||||
}
|
||||
void MainWindow::on_startButton_clicked()
|
||||
{
|
||||
@ -352,26 +373,23 @@ void MainWindow::on_startButton_clicked()
|
||||
}
|
||||
|
||||
LOG(MODULE_VCORE, ("Connecting to: " + CurrentConnectionName).toStdString())
|
||||
logText->clear();
|
||||
vCoreLogBrowser->clear();
|
||||
//
|
||||
auto connectionRoot = connections[CurrentConnectionName].config;
|
||||
//
|
||||
auto conf = GetGlobalConfig();
|
||||
CurrentFullConfig = GenerateRuntimeConfig(connectionRoot);
|
||||
StartPreparation(CurrentFullConfig);
|
||||
bool startFlag = this->vinstance->StartV2rayCore();
|
||||
bool startFlag = this->vinstance->StartConnection(CurrentFullConfig, conf.connectionConfig.enableStats, conf.connectionConfig.statsPort);
|
||||
|
||||
if (startFlag) {
|
||||
if (conf.connectionConfig.enableStats) {
|
||||
speedTimerId = startTimer(1000);
|
||||
}
|
||||
|
||||
this->hTray->showMessage("Qv2ray", tr("Connected To Server: ") + CurrentConnectionName);
|
||||
hTray->setToolTip(TRAY_TOOLTIP_PREFIX "\r\n" + tr("Connected To Server: ") + CurrentConnectionName);
|
||||
statusLabel->setText(tr("Connected") + ": " + CurrentConnectionName);
|
||||
//
|
||||
auto conf = GetGlobalConfig();
|
||||
|
||||
if (conf.connectionConfig.enableStats) {
|
||||
vinstance->SetAPIPort(conf.connectionConfig.statsPort);
|
||||
speedTimerId = startTimer(1000);
|
||||
}
|
||||
|
||||
bool usePAC = conf.inboundConfig.pacConfig.enablePAC;
|
||||
bool pacUseSocks = conf.inboundConfig.pacConfig.useSocksProxy;
|
||||
bool httpEnabled = conf.inboundConfig.useHTTP;
|
||||
@ -469,12 +487,12 @@ void MainWindow::on_stopButton_clicked()
|
||||
{
|
||||
if (vinstance->ConnectionStatus != STOPPED) {
|
||||
// Is running or starting
|
||||
this->vinstance->StopV2rayCore();
|
||||
this->vinstance->StopConnection();
|
||||
killTimer(speedTimerId);
|
||||
hTray->setToolTip(TRAY_TOOLTIP_PREFIX);
|
||||
QFile(QV2RAY_GENERATED_FILE_PATH).remove();
|
||||
statusLabel->setText(tr("Disconnected"));
|
||||
logText->setPlainText("");
|
||||
vCoreLogBrowser->clear();
|
||||
trayMenu->actions()[2]->setEnabled(true);
|
||||
trayMenu->actions()[3]->setEnabled(false);
|
||||
trayMenu->actions()[4]->setEnabled(false);
|
||||
@ -554,12 +572,6 @@ void MainWindow::on_actionExit_triggered()
|
||||
{
|
||||
quit();
|
||||
}
|
||||
void MainWindow::QTextScrollToBottom()
|
||||
{
|
||||
auto bar = logText->verticalScrollBar();
|
||||
|
||||
if (bar->value() >= bar->maximum() - 10) bar->setValue(bar->maximum());
|
||||
}
|
||||
void MainWindow::ShowAndSetConnection(QString guiConnectionName, bool SetConnection, bool ApplyConnection)
|
||||
{
|
||||
// Check empty again...
|
||||
@ -644,7 +656,7 @@ void MainWindow::on_connectionListWidget_doubleClicked(const QModelIndex &index)
|
||||
}
|
||||
void MainWindow::on_clearlogButton_clicked()
|
||||
{
|
||||
logText->clear();
|
||||
vCoreLogBrowser->clear();
|
||||
}
|
||||
void MainWindow::on_connectionListWidget_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)
|
||||
{
|
||||
@ -675,7 +687,6 @@ void MainWindow::on_connectionListWidget_itemChanged(QListWidgetItem *item)
|
||||
LOG(MODULE_CONNECTION, "RENAME: " + originalName.toStdString() + " -> " + item->text().toStdString())
|
||||
auto newName = item->text();
|
||||
auto config = GetGlobalConfig();
|
||||
auto configList = QList<string>::fromStdList(config.configs);
|
||||
|
||||
if (newName.trimmed().isEmpty()) {
|
||||
QvMessageBox(this, tr("Rename a Connection"), tr("The name cannot be empty"));
|
||||
@ -683,6 +694,8 @@ void MainWindow::on_connectionListWidget_itemChanged(QListWidgetItem *item)
|
||||
}
|
||||
|
||||
// If I really did some changes.
|
||||
auto configList = QList<string>::fromStdList(config.configs);
|
||||
|
||||
if (originalName != newName) {
|
||||
if (configList.contains(newName.toStdString())) {
|
||||
QvMessageBox(this, tr("Rename a Connection"), tr("The name has been used already, Please choose another."));
|
||||
@ -903,23 +916,13 @@ void MainWindow::timerEvent(QTimerEvent *event)
|
||||
{
|
||||
// Calling base class
|
||||
QMainWindow::timerEvent(event);
|
||||
|
||||
if (event->timerId() == speedTimerId) {
|
||||
auto _totalSpeedUp = vinstance->getAllSpeedUp();
|
||||
auto _totalSpeedDown = vinstance->getAllSpeedDown();
|
||||
auto _totalDataUp = vinstance->getAllDataUp();
|
||||
auto _totalDataDown = vinstance->getAllDataDown();
|
||||
//
|
||||
Q_UNUSED(event)
|
||||
auto inbounds = CurrentFullConfig["inbounds"].toArray();
|
||||
long _totalSpeedUp = 0, _totalSpeedDown = 0, _totalDataUp = 0, _totalDataDown = 0;
|
||||
|
||||
foreach (auto inbound, inbounds) {
|
||||
auto tag = inbound.toObject()["tag"].toString();
|
||||
|
||||
// We don't want these two.
|
||||
if (tag.isEmpty() || tag == QV2RAY_API_TAG_INBOUND) continue;
|
||||
|
||||
_totalSpeedUp += vinstance->getTagLastUplink(tag);
|
||||
_totalSpeedDown += vinstance->getTagLastDownlink(tag);
|
||||
_totalDataUp += vinstance->getTagTotalUplink(tag);
|
||||
_totalDataDown += vinstance->getTagTotalDownlink(tag);
|
||||
}
|
||||
|
||||
double max = 0;
|
||||
double historyMax = 0;
|
||||
auto graphVUp = _totalSpeedUp / 1024;
|
||||
@ -942,15 +945,23 @@ void MainWindow::timerEvent(QTimerEvent *event)
|
||||
speedChartObj->axes(Qt::Vertical).first()->setRange(0, max * 1.2);
|
||||
//
|
||||
//
|
||||
totalSpeedUp = FormatBytes(_totalSpeedUp);
|
||||
totalSpeedDown = FormatBytes(_totalSpeedDown);
|
||||
totalDataUp = FormatBytes(_totalDataUp);
|
||||
totalDataDown = FormatBytes(_totalDataDown);
|
||||
auto totalSpeedUp = FormatBytes(_totalSpeedUp) + "/s";
|
||||
auto totalSpeedDown = FormatBytes(_totalSpeedDown) + "/s";
|
||||
auto totalDataUp = FormatBytes(_totalDataUp);
|
||||
auto totalDataDown = FormatBytes(_totalDataDown);
|
||||
//
|
||||
netspeedLabel->setText(totalSpeedUp + "/s\r\n" + totalSpeedDown + "/s");
|
||||
dataamountLabel->setText(totalDataUp + "\r\n" + totalDataDown);
|
||||
netspeedLabel->setText(totalSpeedUp + NEWLINE + totalSpeedDown);
|
||||
dataamountLabel->setText(totalDataUp + NEWLINE + totalDataDown);
|
||||
//
|
||||
hTray->setToolTip(TRAY_TOOLTIP_PREFIX "\r\n" + tr("Connected To Server: ") + CurrentConnectionName + "\r\nUp: " + totalSpeedUp + "/s Down: " + totalSpeedDown + "/s");
|
||||
hTray->setToolTip(TRAY_TOOLTIP_PREFIX NEWLINE + tr("Connected To Server: ") + CurrentConnectionName + NEWLINE
|
||||
"Up: " + totalSpeedUp + " Down: " + totalSpeedDown);
|
||||
} else if (event->timerId() == logTimerId) {
|
||||
QString lastLog = readLastLog();
|
||||
|
||||
if (!lastLog.isEmpty()) {
|
||||
qvAppLogBrowser->append(lastLog);
|
||||
}
|
||||
}
|
||||
}
|
||||
void MainWindow::on_duplicateBtn_clicked()
|
||||
{
|
||||
@ -977,3 +988,8 @@ void MainWindow::on_duplicateBtn_clicked()
|
||||
SetGlobalConfig(config);
|
||||
this->OnConfigListChanged(false);
|
||||
}
|
||||
|
||||
void MainWindow::on_masterLogBrowser_textChanged()
|
||||
{
|
||||
//setMasterLogHBar();
|
||||
}
|
||||
|
@ -29,13 +29,14 @@ class MainWindow : public QMainWindow, Ui::MainWindow
|
||||
explicit MainWindow(QWidget *parent = nullptr);
|
||||
~MainWindow() override;
|
||||
signals:
|
||||
void Connect();
|
||||
void DisConnect();
|
||||
void ReConnect();
|
||||
void Connect() const;
|
||||
void DisConnect() const;
|
||||
void ReConnect() const;
|
||||
public slots:
|
||||
void UpdateLog();
|
||||
void UpdateVCoreLog(const QString &log);
|
||||
void OnConfigListChanged(bool need_restart);
|
||||
private slots:
|
||||
void setMasterLogHBar();
|
||||
void on_action_RCM_ShareQR_triggered(bool checked = false);
|
||||
void on_startButton_clicked();
|
||||
void on_stopButton_clicked();
|
||||
@ -45,7 +46,6 @@ class MainWindow : public QMainWindow, Ui::MainWindow
|
||||
void ToggleVisibility();
|
||||
void quit();
|
||||
void on_actionExit_triggered();
|
||||
void QTextScrollToBottom();
|
||||
|
||||
void on_connectionListWidget_itemClicked(QListWidgetItem *item);
|
||||
|
||||
@ -75,14 +75,12 @@ class MainWindow : public QMainWindow, Ui::MainWindow
|
||||
|
||||
void on_duplicateBtn_clicked();
|
||||
|
||||
void on_masterLogBrowser_textChanged();
|
||||
|
||||
public:
|
||||
CONFIGROOT CurrentFullConfig;
|
||||
QString CurrentConnectionName = "";
|
||||
ConnectionInstance *vinstance;
|
||||
QString totalDataUp;
|
||||
QString totalDataDown;
|
||||
QString totalSpeedUp;
|
||||
QString totalSpeedDown;
|
||||
|
||||
protected:
|
||||
|
||||
@ -114,17 +112,20 @@ class MainWindow : public QMainWindow, Ui::MainWindow
|
||||
QString originalName;
|
||||
bool isRenamingInProgress;
|
||||
//
|
||||
int logTimerId;
|
||||
int speedTimerId;
|
||||
//
|
||||
void ShowAndSetConnection(QString currentText, bool SetConnection, bool Apply);
|
||||
void LoadConnections();
|
||||
//
|
||||
PACHandler *pacServer;
|
||||
Highlighter *highlighter;
|
||||
//
|
||||
QTextEdit vcoreLog;
|
||||
QTextEdit qvAppLog;
|
||||
int logSourceId = 0;
|
||||
Highlighter *vCoreLogHighlighter;
|
||||
Highlighter *qvAppLogHighlighter;
|
||||
|
||||
QList<QTextBrowser *> logTextBrowsers;
|
||||
int currentLogBrowserId = 0;
|
||||
};
|
||||
|
||||
static const MainWindow *mwInstance;
|
||||
|
||||
#endif // MAINWINDOW_H
|
||||
|
@ -41,7 +41,7 @@
|
||||
<height>530</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2" rowstretch="0,6,4,0" columnstretch="6,4">
|
||||
<layout class="QGridLayout" name="gridLayout_4" rowstretch="0,5,4,0" columnstretch="6,5">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,1,0,1,0,0,0">
|
||||
<property name="spacing">
|
||||
@ -124,29 +124,11 @@
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Sunken</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="midLineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAsNeeded</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAsNeeded</enum>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="defaultDropAction">
|
||||
<enum>Qt::CopyAction</enum>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="verticalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
@ -419,7 +401,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<layout class="QGridLayout" name="gridLayout" columnstretch="5,0">
|
||||
<layout class="QGridLayout" name="gridLayout_3" rowstretch="0,1" columnstretch="7,0">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="logLabel">
|
||||
<property name="text">
|
||||
@ -440,25 +422,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QTextBrowser" name="logText">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>8</pointsize>
|
||||
<italic>false</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOn</enum>
|
||||
</property>
|
||||
<property name="lineWrapMode">
|
||||
<enum>QTextEdit::NoWrap</enum>
|
||||
</property>
|
||||
<property name="openLinks">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
@ -466,6 +429,9 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QTextBrowser" name="masterLogBrowser"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
|
@ -356,7 +356,7 @@ void PrefrencesWindow::on_tProxyCheckBox_stateChanged(int arg1)
|
||||
auto newPath = QFileInfo(QV2RAY_DEFAULT_VCORE_PATH).path();
|
||||
//
|
||||
LOG(MODULE_FILE, " --> Origin v2ctl file is at: " + v2ctlPath.toStdString())
|
||||
LOG(MODULE_FILE, " --> New v2ray files will be placed in: " << newPath.toStdString())
|
||||
LOG(MODULE_FILE, " --> New v2ray files will be placed in: " + newPath.toStdString())
|
||||
//
|
||||
LOG(MODULE_FILE, " --> Copying files....")
|
||||
|
||||
@ -364,14 +364,14 @@ void PrefrencesWindow::on_tProxyCheckBox_stateChanged(int arg1)
|
||||
// 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_DEFAULT_VCORE_PATH).exists()) {
|
||||
LOG(MODULE_FILE, QV2RAY_DEFAULT_VCORE_PATH.toStdString() << ": File already exists.")
|
||||
LOG(MODULE_FILE, QV2RAY_DEFAULT_VCORE_PATH.toStdString() << ": Deleting file.")
|
||||
LOG(MODULE_FILE, QV2RAY_DEFAULT_VCORE_PATH.toStdString() + ": File already exists.")
|
||||
LOG(MODULE_FILE, QV2RAY_DEFAULT_VCORE_PATH.toStdString() + ": Deleting file.")
|
||||
QFile(QV2RAY_DEFAULT_VCORE_PATH).remove();
|
||||
}
|
||||
|
||||
if (QFile(newPath + "/v2ctl").exists()) {
|
||||
LOG(MODULE_FILE, newPath.toStdString() << "/v2ctl" << ": File already exists.")
|
||||
LOG(MODULE_FILE, newPath.toStdString() << "/v2ctl" << ": Deleting file.")
|
||||
LOG(MODULE_FILE, newPath.toStdString() + "/v2ctl : File already exists.")
|
||||
LOG(MODULE_FILE, newPath.toStdString() + "/v2ctl : Deleting file.")
|
||||
QFile(newPath + "/v2ctl").remove();
|
||||
}
|
||||
|
||||
|
@ -262,10 +262,9 @@ void RouteEditor::ShowRuleDetail(RuleObject rule)
|
||||
netBothRB->setChecked(network.contains("tcp") && network.contains("udp"));
|
||||
//
|
||||
// Set protocol checkboxes.
|
||||
auto protocols = QList<string>::fromStdList(CurrentRule.protocol);
|
||||
routeProtocolHTTPCB->setChecked(protocols.contains("http"));
|
||||
routeProtocolTLSCB->setChecked(protocols.contains("tls"));
|
||||
routeProtocolBTCB->setChecked(protocols.contains("bittorrent"));
|
||||
routeProtocolHTTPCB->setChecked(contains(CurrentRule.protocol, string("http")));
|
||||
routeProtocolTLSCB->setChecked(contains(CurrentRule.protocol, string("tls")));
|
||||
routeProtocolBTCB->setChecked(contains(CurrentRule.protocol, string("bittorrent")));
|
||||
//
|
||||
// Port
|
||||
routePortTxt->setText(QSTRING(CurrentRule.port));
|
||||
|
@ -3,13 +3,17 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <QtDebug>
|
||||
#include <QBuffer>
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
* Tiny log module.
|
||||
*/
|
||||
|
||||
#define LOG(module, msg) cout << "[" << module << "]: " << msg << endl;
|
||||
void _LOG(const std::string &module, const std::string &log);
|
||||
const QString readLastLog();
|
||||
|
||||
#define LOG(module, msg) _LOG(module, msg);
|
||||
|
||||
#ifdef QT_DEBUG
|
||||
#define DEBUG(module, msg) LOG("[DEBUG] - " module, msg)
|
||||
@ -17,9 +21,6 @@ using namespace std;
|
||||
#define DEBUG(module, msg)
|
||||
#endif
|
||||
|
||||
#define CLOG(value) DEBUG("[CONTENT-LOG]", #value << ":" << value)
|
||||
#define XLOG(module, level, msg) LOG(module, level << msg)
|
||||
|
||||
#define MODULE_INIT "INIT"
|
||||
#define MODULE_UPDATE "UPDATE"
|
||||
#define MODULE_VCORE "VCORE"
|
||||
|
Loading…
Reference in New Issue
Block a user