From 7ae62e96fcba3ba73b394d95c48f80e0a1f57d6c Mon Sep 17 00:00:00 2001 From: "Leroy.H.Y" Date: Mon, 2 Dec 2019 09:50:05 +0800 Subject: [PATCH] [update] Several code refactoring and added qvAppLog --- Build.Counter | 2 +- src/Qv2rayBase.hpp | 14 ++ src/QvCoreConfigOperations.cpp | 11 +- src/QvCoreConfigOperations.hpp | 1 - src/QvCoreConfigOperations_Convertion.cpp | 2 +- src/QvUtils.cpp | 31 ++- src/QvUtils.hpp | 1 + src/components/QvCoreInteractions.cpp | 208 ++++++++++++------- src/components/QvCoreInteractions.hpp | 40 ++-- src/components/QvLogHighlighter.cpp | 11 + src/components/QvLogHighlighter.hpp | 3 + src/components/QvNetSpeedPlugin.hpp | 2 +- src/main.cpp | 10 +- src/ui/NetSpeedBar/QvNetSpeedBar.cpp | 36 ++-- src/ui/NetSpeedBar/QvNetSpeedBar_linux.cpp | 4 +- src/ui/NetSpeedBar/QvNetSpeedBar_win.cpp | 8 +- src/ui/w_MainWindow.cpp | 228 +++++++++++---------- src/ui/w_MainWindow.hpp | 29 +-- src/ui/w_MainWindow.ui | 48 +---- src/ui/w_PrefrencesWindow.cpp | 10 +- src/ui/w_RoutesEditor.cpp | 7 +- src/utils/QvTinyLog.hpp | 9 +- 22 files changed, 407 insertions(+), 308 deletions(-) diff --git a/Build.Counter b/Build.Counter index 336df569..c6523368 100644 --- a/Build.Counter +++ b/Build.Counter @@ -1 +1 @@ -1090 +1282 diff --git a/src/Qv2rayBase.hpp b/src/Qv2rayBase.hpp index 5fb79e39..37b690b7 100644 --- a/src/Qv2rayBase.hpp +++ b/src/Qv2rayBase.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #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 +bool contains(std::list &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 { // diff --git a/src/QvCoreConfigOperations.cpp b/src/QvCoreConfigOperations.cpp index 5f1beac4..1e4c79ea 100644 --- a/src/QvCoreConfigOperations.cpp +++ b/src/QvCoreConfigOperations.cpp @@ -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) { diff --git a/src/QvCoreConfigOperations.hpp b/src/QvCoreConfigOperations.hpp index 4a837021..09d8fc4c 100644 --- a/src/QvCoreConfigOperations.hpp +++ b/src/QvCoreConfigOperations.hpp @@ -19,7 +19,6 @@ namespace Qv2ray QMap GetRegularConnections(list connections); QMap> GetSubscriptionConnections(list subscriptions); bool CheckIsComplexConfig(CONFIGROOT root); - int StartPreparation(CONFIGROOT fullConfig); int FindIndexByTag(INOUTLIST list, const QString &tag); // diff --git a/src/QvCoreConfigOperations_Convertion.cpp b/src/QvCoreConfigOperations_Convertion.cpp index 31be07d0..4421d4df 100644 --- a/src/QvCoreConfigOperations_Convertion.cpp +++ b/src/QvCoreConfigOperations_Convertion.cpp @@ -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(); } diff --git a/src/QvUtils.cpp b/src/QvUtils.cpp index cc769c47..f475b33c 100644 --- a/src/QvUtils.cpp +++ b/src/QvUtils.cpp @@ -1,5 +1,25 @@ #include "QvUtils.hpp" -#include +#include + +// Forwarded from QvTinyLog +static QQueue __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(); + } } } diff --git a/src/QvUtils.hpp b/src/QvUtils.hpp index 9892ee65..8fb3a1c0 100644 --- a/src/QvUtils.hpp +++ b/src/QvUtils.hpp @@ -87,6 +87,7 @@ namespace Qv2ray // // QString ConvertGFWToPAC(const QString &rawContent, const QString &customProxyString); + void QFastAppendTextDocument(const QString &message, QTextDocument *doc); } } diff --git a/src/components/QvCoreInteractions.cpp b/src/components/QvCoreInteractions.cpp index 0c28823a..f55d918b 100644 --- a/src/components/QvCoreInteractions.cpp +++ b/src/components/QvCoreInteractions.cpp @@ -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,107 +20,135 @@ 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; } - - return false; } - ConnectionInstance::ConnectionInstance(QWidget *parent) : apiFailedCounter(0), port(0) + ConnectionInstance::ConnectionInstance() { auto proc = new QProcess(); vProcess = proc; - connect(vProcess, &QProcess::readyReadStandardOutput, static_cast(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(); - QString ConnectionInstance::ReadProcessOutput() - { - return vProcess->readAllStandardOutput(); - } + for (auto item : root["inbounds"].toArray()) { + auto tag = item.toObject()["tag"].toString(""); - 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; - } + if (tag.isEmpty() || tag == QV2RAY_API_TAG_INBOUND) + continue; + + inboundTags.append(tag); + } + + 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::StartV2rayCore() - { if (ConnectionStatus != STOPPED) { LOG(MODULE_VCORE, "Status is invalid, expect STOPPED when calling StartV2rayCore") return false; } ConnectionStatus = STARTING; + auto filePath = QV2RAY_GENERATED_FILE_PATH; - if (ValidateKernal()) { - auto filePath = QV2RAY_GENERATED_FILE_PATH; + if (ValidateConfig(filePath)) { + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + env.insert("V2RAY_LOCATION_ASSET", QSTRING(GetGlobalConfig().v2AssetsPath)); + vProcess->setProcessEnvironment(env); + vProcess->start(QSTRING(GetGlobalConfig().v2CorePath), QStringList() << "-config" << filePath, QIODevice::ReadWrite | QIODevice::Text); + vProcess->waitForStarted(); + ConnectionStatus = STARTED; - if (ValidateConfig(filePath)) { - QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - env.insert("V2RAY_LOCATION_ASSET", QSTRING(GetGlobalConfig().v2AssetsPath)); - vProcess->setProcessEnvironment(env); - vProcess->start(QSTRING(GetGlobalConfig().v2CorePath), QStringList() << "-config" << filePath, QIODevice::ReadWrite | QIODevice::Text); - vProcess->waitForStarted(); - ConnectionStatus = STARTED; - return true; - } else { - ConnectionStatus = STOPPED; - return false; + 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; } } - void ConnectionInstance::StopV2rayCore() + 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::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::getTagLastDownlink(const QString &tag) + long ConnectionInstance::getTagSpeedDown(const QString &tag) { - auto val = CallStatsAPIByName("inbound>>>" + tag + ">>>traffic>>>downlink"); - auto data = val - totalDataTransfered[tag + "_down"]; - totalDataTransfered[tag + "_down"] = val; - dataTransferSpeed[tag + "_down"] = data; - return data; + return transferSpeed[tag + "_down"]; } - - long ConnectionInstance::getTagTotalUplink(const QString &tag) + long ConnectionInstance::getTagDataUp(const QString &tag) { - return totalDataTransfered[tag + "_up"]; + return transferData[tag + "_up"]; } - - long ConnectionInstance::getTagTotalDownlink(const QString &tag) + long ConnectionInstance::getTagDataDown(const QString &tag) { - return totalDataTransfered[tag + "_down"]; + return transferData[tag + "_down"]; + } + long ConnectionInstance::getAllDataUp() + { + long val = 0; + + for (auto tag : inboundTags) { + val += transferData[tag + "_up"]; + } + + return val; + } + long ConnectionInstance::getAllDataDown() + { + long val = 0; + + for (auto tag : inboundTags) { + val += transferData[tag + "_down"]; + } + + return val; + } + long ConnectionInstance::getAllSpeedUp() + { + long val = 0; + + for (auto tag : inboundTags) { + val += transferSpeed[tag + "_up"]; + } + + return val; + } + long ConnectionInstance::getAllSpeedDown() + { + long val = 0; + + for (auto tag : inboundTags) { + val += transferSpeed[tag + "_down"]; + } + + return val; } } } diff --git a/src/components/QvCoreInteractions.hpp b/src/components/QvCoreInteractions.hpp index 3cc3292e..216f12d1 100644 --- a/src/components/QvCoreInteractions.hpp +++ b/src/components/QvCoreInteractions.hpp @@ -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 totalDataTransfered; - QMap 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 transferData; + QMap transferSpeed; + // std::shared_ptr<::grpc::Channel> Channel; std::unique_ptr<::v2ray::core::app::stats::command::StatsService::Stub> Stub; - int port; }; } } diff --git a/src/components/QvLogHighlighter.cpp b/src/components/QvLogHighlighter.cpp index 452b5d9a..1226d482 100644 --- a/src/components/QvLogHighlighter.cpp +++ b/src/components/QvLogHighlighter.cpp @@ -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) diff --git a/src/components/QvLogHighlighter.hpp b/src/components/QvLogHighlighter.hpp index 5ddcb9b8..28b306a9 100644 --- a/src/components/QvLogHighlighter.hpp +++ b/src/components/QvLogHighlighter.hpp @@ -89,6 +89,9 @@ namespace Qv2ray QTextCharFormat timeFormat; QTextCharFormat ipHostFormat; QTextCharFormat x; + // + QTextCharFormat qvAppLogFormat; + QTextCharFormat qvAppDebugLogFormat; }; } } diff --git a/src/components/QvNetSpeedPlugin.hpp b/src/components/QvNetSpeedPlugin.hpp index f4c58fb6..48f80d23 100644 --- a/src/components/QvNetSpeedPlugin.hpp +++ b/src/components/QvNetSpeedPlugin.hpp @@ -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 diff --git a/src/main.cpp b/src/main.cpp index efaebaec..df72ff34 100644 --- a/src/main.cpp +++ b/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__) diff --git a/src/ui/NetSpeedBar/QvNetSpeedBar.cpp b/src/ui/NetSpeedBar/QvNetSpeedBar.cpp index 680ed07f..570910d4 100644 --- a/src/ui/NetSpeedBar/QvNetSpeedBar.cpp +++ b/src/ui/NetSpeedBar/QvNetSpeedBar.cpp @@ -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); 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; } diff --git a/src/ui/NetSpeedBar/QvNetSpeedBar_linux.cpp b/src/ui/NetSpeedBar/QvNetSpeedBar_linux.cpp index 12d375e0..a02aef26 100644 --- a/src/ui/NetSpeedBar/QvNetSpeedBar_linux.cpp +++ b/src/ui/NetSpeedBar/QvNetSpeedBar_linux.cpp @@ -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(); diff --git a/src/ui/NetSpeedBar/QvNetSpeedBar_win.cpp b/src/ui/NetSpeedBar/QvNetSpeedBar_win.cpp index 26fc2ba4..a9a74cf4 100644 --- a/src/ui/NetSpeedBar/QvNetSpeedBar_win.cpp +++ b/src/ui/NetSpeedBar/QvNetSpeedBar_win.cpp @@ -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(-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(-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())) } diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index c7587f62..2ccd4749 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -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,32 +173,25 @@ 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::fromStdList(conf.configs).contains(conf.autoStartConfig)) { - // Has auto start. - CurrentConnectionName = QSTRING(conf.autoStartConfig); - auto item = connectionListWidget->findItems(QSTRING(conf.autoStartConfig), Qt::MatchExactly).front(); - item->setSelected(true); - connectionListWidget->setCurrentItem(item); - on_connectionListWidget_itemClicked(item); - trayMenu->actions()[0]->setText(tr("Show")); - this->hide(); - on_startButton_clicked(); - } else if (connectionListWidget->count() != 0) { - // The first one is default. - connectionListWidget->setCurrentRow(0); - ShowAndSetConnection(connectionListWidget->item(0)->text(), true, false); - this->show(); - } - } else { + 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(); + item->setSelected(true); + connectionListWidget->setCurrentItem(item); + on_connectionListWidget_itemClicked(item); + trayMenu->actions()[0]->setText(tr("Show")); + this->hide(); + on_startButton_clicked(); + } else if (connectionListWidget->count() != 0) { + // The first one is default. + connectionListWidget->setCurrentRow(0); + ShowAndSetConnection(connectionListWidget->item(0)->text(), true, false); 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::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::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,54 +916,52 @@ void MainWindow::timerEvent(QTimerEvent *event) { // Calling base class QMainWindow::timerEvent(event); - // - 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(); + if (event->timerId() == speedTimerId) { + auto _totalSpeedUp = vinstance->getAllSpeedUp(); + auto _totalSpeedDown = vinstance->getAllSpeedDown(); + auto _totalDataUp = vinstance->getAllDataUp(); + auto _totalDataDown = vinstance->getAllDataDown(); + // + double max = 0; + double historyMax = 0; + auto graphVUp = _totalSpeedUp / 1024; + auto graphVDown = _totalSpeedDown / 1024; - // We don't want these two. - if (tag.isEmpty() || tag == QV2RAY_API_TAG_INBOUND) continue; + for (auto i = 0; i < 29; i++) { + historyMax = MAX(historyMax, MAX(uploadList[i + 1], downloadList[i + 1])); + uploadList[i] = uploadList[i + 1]; + downloadList[i] = downloadList[i + 1]; + uploadSerie->replace(i, i, uploadList[i + 1]); + downloadSerie->replace(i, i, downloadList[i + 1]); + } - _totalSpeedUp += vinstance->getTagLastUplink(tag); - _totalSpeedDown += vinstance->getTagLastDownlink(tag); - _totalDataUp += vinstance->getTagTotalUplink(tag); - _totalDataDown += vinstance->getTagTotalDownlink(tag); + uploadList[uploadList.count() - 1] = graphVUp; + downloadList[uploadList.count() - 1] = graphVDown; + uploadSerie->replace(29, 29, graphVUp); + downloadSerie->replace(29, 29, graphVDown); + // + max = MAX(MAX(graphVUp, graphVDown), historyMax); + speedChartObj->axes(Qt::Vertical).first()->setRange(0, max * 1.2); + // + // + auto totalSpeedUp = FormatBytes(_totalSpeedUp) + "/s"; + auto totalSpeedDown = FormatBytes(_totalSpeedDown) + "/s"; + auto totalDataUp = FormatBytes(_totalDataUp); + auto totalDataDown = FormatBytes(_totalDataDown); + // + netspeedLabel->setText(totalSpeedUp + NEWLINE + totalSpeedDown); + dataamountLabel->setText(totalDataUp + NEWLINE + totalDataDown); + // + 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); + } } - - double max = 0; - double historyMax = 0; - auto graphVUp = _totalSpeedUp / 1024; - auto graphVDown = _totalSpeedDown / 1024; - - for (auto i = 0; i < 29; i++) { - historyMax = MAX(historyMax, MAX(uploadList[i + 1], downloadList[i + 1])); - uploadList[i] = uploadList[i + 1]; - downloadList[i] = downloadList[i + 1]; - uploadSerie->replace(i, i, uploadList[i + 1]); - downloadSerie->replace(i, i, downloadList[i + 1]); - } - - uploadList[uploadList.count() - 1] = graphVUp; - downloadList[uploadList.count() - 1] = graphVDown; - uploadSerie->replace(29, 29, graphVUp); - downloadSerie->replace(29, 29, graphVDown); - // - max = MAX(MAX(graphVUp, graphVDown), historyMax); - speedChartObj->axes(Qt::Vertical).first()->setRange(0, max * 1.2); - // - // - totalSpeedUp = FormatBytes(_totalSpeedUp); - totalSpeedDown = FormatBytes(_totalSpeedDown); - totalDataUp = FormatBytes(_totalDataUp); - totalDataDown = FormatBytes(_totalDataDown); - // - netspeedLabel->setText(totalSpeedUp + "/s\r\n" + totalSpeedDown + "/s"); - dataamountLabel->setText(totalDataUp + "\r\n" + totalDataDown); - // - hTray->setToolTip(TRAY_TOOLTIP_PREFIX "\r\n" + tr("Connected To Server: ") + CurrentConnectionName + "\r\nUp: " + totalSpeedUp + "/s Down: " + totalSpeedDown + "/s"); } 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(); +} diff --git a/src/ui/w_MainWindow.hpp b/src/ui/w_MainWindow.hpp index 0c0d1b28..322a51f4 100644 --- a/src/ui/w_MainWindow.hpp +++ b/src/ui/w_MainWindow.hpp @@ -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 logTextBrowsers; + int currentLogBrowserId = 0; }; +static const MainWindow *mwInstance; + #endif // MAINWINDOW_H diff --git a/src/ui/w_MainWindow.ui b/src/ui/w_MainWindow.ui index c1dbfa6e..207364d0 100644 --- a/src/ui/w_MainWindow.ui +++ b/src/ui/w_MainWindow.ui @@ -41,7 +41,7 @@ 530 - + @@ -124,29 +124,11 @@ Qt::CustomContextMenu - - QFrame::StyledPanel - - - QFrame::Sunken - - - 1 - - - 0 - - - Qt::ScrollBarAsNeeded - - - Qt::ScrollBarAsNeeded - QAbstractItemView::NoEditTriggers - - Qt::CopyAction + + QAbstractItemView::ExtendedSelection QAbstractItemView::ScrollPerPixel @@ -419,7 +401,7 @@ - + @@ -440,25 +422,6 @@ - - - - - 8 - false - - - - Qt::ScrollBarAlwaysOn - - - QTextEdit::NoWrap - - - false - - - @@ -466,6 +429,9 @@ + + + diff --git a/src/ui/w_PrefrencesWindow.cpp b/src/ui/w_PrefrencesWindow.cpp index 0331ecf2..8b5d24e4 100644 --- a/src/ui/w_PrefrencesWindow.cpp +++ b/src/ui/w_PrefrencesWindow.cpp @@ -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. 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(); } diff --git a/src/ui/w_RoutesEditor.cpp b/src/ui/w_RoutesEditor.cpp index 07f28b8b..9f401a96 100644 --- a/src/ui/w_RoutesEditor.cpp +++ b/src/ui/w_RoutesEditor.cpp @@ -262,10 +262,9 @@ void RouteEditor::ShowRuleDetail(RuleObject rule) netBothRB->setChecked(network.contains("tcp") && network.contains("udp")); // // Set protocol checkboxes. - auto protocols = QList::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)); diff --git a/src/utils/QvTinyLog.hpp b/src/utils/QvTinyLog.hpp index c568231f..15304f91 100644 --- a/src/utils/QvTinyLog.hpp +++ b/src/utils/QvTinyLog.hpp @@ -3,13 +3,17 @@ #include #include +#include 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"