From 31f6e1389fbf478f34c770bb9191a07044881314 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Sun, 17 May 2020 22:04:03 +0800 Subject: [PATCH] update: several refactors and Import window redesign --- makespec/BUILDVERSION | 2 +- src/common/HTTPRequestHelper.cpp | 4 +- src/common/HTTPRequestHelper.hpp | 6 +- src/core/connection/ConnectionIO.cpp | 33 +- src/core/connection/ConnectionIO.hpp | 1 + src/core/connection/Serialization.cpp | 12 +- src/core/connection/Serialization.hpp | 7 +- src/core/connection/Serialization_vmess.cpp | 1 - src/core/handler/ConfigHandler.cpp | 58 +-- src/core/handler/ConfigHandler.hpp | 5 +- src/ui/windows/w_GroupManager.cpp | 4 +- src/ui/windows/w_GroupManager.ui | 29 +- src/ui/windows/w_ImportConfig.cpp | 94 ++++- src/ui/windows/w_ImportConfig.hpp | 19 +- src/ui/windows/w_ImportConfig.ui | 420 ++++++++++---------- src/ui/windows/w_MainWindow.cpp | 2 +- src/ui/windows/w_MainWindow.ui | 10 +- 17 files changed, 356 insertions(+), 351 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 4bbe0873..d627620c 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -5460 +5461 diff --git a/src/common/HTTPRequestHelper.cpp b/src/common/HTTPRequestHelper.cpp index c814675c..a2e61555 100644 --- a/src/common/HTTPRequestHelper.cpp +++ b/src/common/HTTPRequestHelper.cpp @@ -66,9 +66,9 @@ namespace Qv2ray::common request.setHeader(QNetworkRequest::KnownHeaders::UserAgentHeader, ua); } - QByteArray QvHttpRequestHelper::Get(const QString &url) + QByteArray QvHttpRequestHelper::Get(const QUrl &url) { - request.setUrl({ url }); + request.setUrl(url); setAccessManagerAttributes(accessManager); auto _reply = accessManager.get(request); // diff --git a/src/common/HTTPRequestHelper.hpp b/src/common/HTTPRequestHelper.hpp index ffbb54f5..c1482ce8 100644 --- a/src/common/HTTPRequestHelper.hpp +++ b/src/common/HTTPRequestHelper.hpp @@ -33,7 +33,11 @@ namespace Qv2ray::common ~QvHttpRequestHelper(); // get void AsyncGet(const QString &url); - QByteArray Get(const QString &url); + QByteArray Get(const QUrl &url); + QByteArray Get(const QString &url) + { + return Get(QUrl{ url }); + } signals: void OnRequestFinished(QByteArray &data); diff --git a/src/core/connection/ConnectionIO.cpp b/src/core/connection/ConnectionIO.cpp index 90c00807..e0a201b1 100644 --- a/src/core/connection/ConnectionIO.cpp +++ b/src/core/connection/ConnectionIO.cpp @@ -1,5 +1,7 @@ #include "ConnectionIO.hpp" +#include "Serialization.hpp" +#include "common/HTTPRequestHelper.hpp" #include "common/QvHelpers.hpp" namespace Qv2ray::core::connection @@ -8,14 +10,7 @@ namespace Qv2ray::core::connection { CONFIGROOT ConvertConfigFromFile(const QString &sourceFilePath, bool importComplex) { - QFile source(sourceFilePath); - - if (!source.exists()) - { - LOG(MODULE_FILEIO, "Trying to import from an non-existing file.") return CONFIGROOT(); - } - - auto root = CONFIGROOT(JsonFromString(StringFromFile(source))); + auto root = CONFIGROOT(JsonFromString(StringFromFile(sourceFilePath))); if (!importComplex) { @@ -29,5 +24,27 @@ namespace Qv2ray::core::connection root.remove("dns"); return root; } + QMultiHash GetConnectionConfigFromSubscription(const QUrl &subscriptionUrl, const QString &groupName) + { + QMultiHash subscriptionContent; + QvHttpRequestHelper helper; + const auto data = helper.Get(subscriptionUrl); + auto subscriptionLines = SplitLines(TryDecodeSubscriptionString(data)); + for (const auto &line : subscriptionLines) + { + QString __alias; + QString __errMessage; + // Assign a group name, to pass the name check. + QString __groupName = groupName; + auto connectionConfigMap = ConvertConfigFromString(line.trimmed(), &__alias, &__errMessage, &__groupName); + if (!__errMessage.isEmpty()) + LOG(MODULE_SUBSCRIPTION, "Error: " + __errMessage) + for (const auto &val : connectionConfigMap) + { + subscriptionContent.insert(connectionConfigMap.key(val), val); + } + } + return subscriptionContent; + } } // namespace ConnectionIO } // namespace Qv2ray::core::connection diff --git a/src/core/connection/ConnectionIO.hpp b/src/core/connection/ConnectionIO.hpp index 09e9c866..5c788874 100644 --- a/src/core/connection/ConnectionIO.hpp +++ b/src/core/connection/ConnectionIO.hpp @@ -6,6 +6,7 @@ namespace Qv2ray::core::connection { // File Protocol CONFIGROOT ConvertConfigFromFile(const QString &sourceFilePath, bool importComplex); + QMultiHash GetConnectionConfigFromSubscription(const QUrl &subscriptionUrl, const QString &groupName); } // namespace ConnectionIO } // namespace Qv2ray::core::connection diff --git a/src/core/connection/Serialization.cpp b/src/core/connection/Serialization.cpp index 937cebcb..b25131e8 100644 --- a/src/core/connection/Serialization.cpp +++ b/src/core/connection/Serialization.cpp @@ -1,7 +1,6 @@ #include "Serialization.hpp" #include "Generation.hpp" -#include "common/QvHelpers.hpp" #include "components/plugins/QvPluginHost.hpp" #include "core/CoreUtils.hpp" #include "core/handler/ConfigHandler.hpp" @@ -49,7 +48,7 @@ namespace Qv2ray::core::connection { CONFIGROOT root; auto outbound = GenerateOutboundEntry(val.first, OUTBOUNDSETTING(val.second), {}); - root.insert("outbounds", QJsonArray{ outbound }); + QJsonIO::SetValue(root, outbound, "outbounds", 0); connectionConf.insert(key, root); } } @@ -108,14 +107,5 @@ namespace Qv2ray::core::connection return sharelink; } - QString DecodeSubscriptionString(const QByteArray &arr) - { - // String may start with: vmess:// and ss:// - // We only process vmess:// here - // Some subscription providers may use plain vmess:// saperated by - // lines But others may use base64 of above. - auto result = QString::fromUtf8(arr).trimmed(); - return result.contains("://") ? result : SafeBase64Decode(result); - } } // namespace Serialization } // namespace Qv2ray::core::connection diff --git a/src/core/connection/Serialization.hpp b/src/core/connection/Serialization.hpp index 5803decb..f8b39bee 100644 --- a/src/core/connection/Serialization.hpp +++ b/src/core/connection/Serialization.hpp @@ -1,5 +1,6 @@ #pragma once #include "base/Qv2rayBase.hpp" +#include "common/QvHelpers.hpp" namespace Qv2ray::core::connection { @@ -15,7 +16,11 @@ namespace Qv2ray::core::connection const inline auto QV2RAY_SSD_DEFAULT_NAME_PATTERN = QObject::tr("%1 - %2 (rate %3)"); // // General - QString DecodeSubscriptionString(const QByteArray &arr); + inline const QString TryDecodeSubscriptionString(const QByteArray &arr) + { + auto result = QString::fromUtf8(arr).trimmed(); + return result.contains("://") ? result : SafeBase64Decode(result); + } QMultiHash ConvertConfigFromString(const QString &link, QString *aliasPrefix, QString *errMessage, QString *newGroupName = nullptr); const QString ConvertConfigToString(const ConnectionGroupPair &id, bool isSip002 = false); diff --git a/src/core/connection/Serialization_vmess.cpp b/src/core/connection/Serialization_vmess.cpp index 44785d13..7755e317 100644 --- a/src/core/connection/Serialization_vmess.cpp +++ b/src/core/connection/Serialization_vmess.cpp @@ -66,7 +66,6 @@ namespace Qv2ray::core::connection CONFIGROOT Deserialize(const QString &vmessStr, QString *alias, QString *errMessage) { #define default CONFIGROOT() - LOG(MODULE_SETTINGS, "Trying to convert from a vmess string.") QString vmess = vmessStr; if (vmess.trimmed() != vmess) diff --git a/src/core/handler/ConfigHandler.cpp b/src/core/handler/ConfigHandler.cpp index 3504772b..67288af9 100644 --- a/src/core/handler/ConfigHandler.cpp +++ b/src/core/handler/ConfigHandler.cpp @@ -66,7 +66,6 @@ namespace Qv2ray::core::handlers connect(kernelHandler, &KernelInstanceHandler::OnDisconnected, this, &QvConfigHandler::OnDisconnected); // tcpingHelper = new QvTCPingHelper(5, this); - httpHelper = new QvHttpRequestHelper(this); connect(tcpingHelper, &QvTCPingHelper::OnLatencyTestCompleted, this, &QvConfigHandler::OnLatencyDataArrived_p); // // Save per 1 minutes. @@ -369,7 +368,6 @@ namespace Qv2ray::core::handlers { LOG(MODULE_CORE_HANDLER, "Triggering save settings from destructor") delete kernelHandler; - delete httpHelper; CHSaveConfigData(); } @@ -465,57 +463,33 @@ namespace Qv2ray::core::handlers bool QvConfigHandler::UpdateSubscription(const GroupId &id) { CheckGroupExistanceEx(id, false); - if (isHttpRequestInProgress || !groups[id].isSubscription) + if (!groups[id].isSubscription) { return false; } - isHttpRequestInProgress = true; - auto data = httpHelper->Get(groups[id].subscriptionOption.address); - isHttpRequestInProgress = false; - return CHUpdateSubscription_p(id, data); + return CHUpdateSubscription_p(id, groups[id].subscriptionOption.address); } - bool QvConfigHandler::CHUpdateSubscription_p(const GroupId &id, const QByteArray &subscriptionData) + bool QvConfigHandler::CHUpdateSubscription_p(const GroupId &id, const QString &url) { CheckGroupExistanceEx(id, false); if (!groups.contains(id)) { return false; } - QMultiHash allSubscriptionConnections; - // - // // // ====================================================================================== Begin reading subscription + auto _newConnections = GetConnectionConfigFromSubscription(url, GetDisplayName(id)); + if (_newConnections.count() < 5) { - auto subscriptionLines = SplitLines(DecodeSubscriptionString(subscriptionData)); - for (const auto &line : subscriptionLines) - { - QString __alias; - QString __errMessage; - // Assign a group name, to pass the name check. - QString __groupName = GetDisplayName(id); - auto connectionConfigMap = ConvertConfigFromString(line.trimmed(), &__alias, &__errMessage, &__groupName); - if (!__errMessage.isEmpty()) - LOG(MODULE_SUBSCRIPTION, "Error: " + __errMessage) - for (const auto &val : connectionConfigMap) - { - allSubscriptionConnections.insert(connectionConfigMap.key(val), val); - } - } - if (allSubscriptionConnections.count() < 5) - { - LOG(MODULE_SUBSCRIPTION, "Find a subscription with less than 5 connections.") - if (QvMessageBoxAsk(nullptr, tr("Update Subscription"), - tr("%1 entrie(s) have been found from the subscription source, do you want to continue?") - .arg(allSubscriptionConnections.count())) != QMessageBox::Yes) + LOG(MODULE_SUBSCRIPTION, "Find a subscription with less than 5 connections.") + if (QvMessageBoxAsk( + nullptr, tr("Update Subscription"), + tr("%1 entrie(s) have been found from the subscription source, do you want to continue?").arg(_newConnections.count())) != + QMessageBox::Yes) - return false; - } + return false; } - // ====================================================================================== End reading subscription - // - // // // ====================================================================================== Begin Connection Data Storage // Anyway, we try our best to preserve the connection id. @@ -540,9 +514,9 @@ namespace Qv2ray::core::handlers auto originalConnectionIdList = groups[id].connections; groups[id].connections.clear(); // - for (const auto &config : allSubscriptionConnections) + for (const auto &config : _newConnections) { - const auto _alias = allSubscriptionConnections.key(config); + const auto _alias = _newConnections.key(config); QString errMessage; if (!errMessage.isEmpty()) @@ -562,7 +536,7 @@ namespace Qv2ray::core::handlers LOG(MODULE_CORE_HANDLER, "Reused connection id from name: " + _alias) auto _conn = nameMap.take(_alias); groups[id].connections << _conn; - UpdateConnection(_conn, config); + UpdateConnection(_conn, config, true); // Remove Connection Id from the list. originalConnectionIdList.removeAll(_conn); typeMap.remove(typeMap.key(_conn)); @@ -573,7 +547,7 @@ namespace Qv2ray::core::handlers auto _conn = typeMap.take(outboundData); groups[id].connections << _conn; // Update Connection Properties - UpdateConnection(_conn, config); + UpdateConnection(_conn, config, true); RenameConnection(_conn, _alias); // Remove Connection Id from the list. originalConnectionIdList.removeAll(_conn); @@ -583,7 +557,7 @@ namespace Qv2ray::core::handlers { // New connection id is required since nothing matched found... LOG(MODULE_CORE_HANDLER, "Generated new connection id for connection: " + _alias) - CreateConnection(config, _alias, id); + CreateConnection(config, _alias, id, true); } // ====================================================================================== End guessing new ConnectionId } diff --git a/src/core/handler/ConfigHandler.hpp b/src/core/handler/ConfigHandler.hpp index ddea5cd9..a7f9c104 100644 --- a/src/core/handler/ConfigHandler.hpp +++ b/src/core/handler/ConfigHandler.hpp @@ -1,7 +1,6 @@ #pragma once #include "base/Qv2rayBase.hpp" -#include "common/HTTPRequestHelper.hpp" #include "components/latency/QvTCPing.hpp" #include "core/CoreUtils.hpp" #include "core/connection/ConnectionIO.hpp" @@ -152,7 +151,7 @@ namespace Qv2ray::core::handlers void timerEvent(QTimerEvent *event) override; private: - bool CHUpdateSubscription_p(const GroupId &id, const QByteArray &subscriptionData); + bool CHUpdateSubscription_p(const GroupId &id, const QString &url); private: int saveTimerId; @@ -163,8 +162,6 @@ namespace Qv2ray::core::handlers QHash connectionRootCache; private: - QvHttpRequestHelper *httpHelper; - bool isHttpRequestInProgress = false; QvTCPingHelper *tcpingHelper; KernelInstanceHandler *kernelHandler; }; diff --git a/src/ui/windows/w_GroupManager.cpp b/src/ui/windows/w_GroupManager.cpp index 9c6c5502..23468386 100644 --- a/src/ui/windows/w_GroupManager.cpp +++ b/src/ui/windows/w_GroupManager.cpp @@ -257,7 +257,7 @@ GroupManager::~GroupManager() void GroupManager::on_addGroupButton_clicked() { auto const key = tr("New Group") + " - " + GenerateRandomString(5); - auto id = ConnectionManager->CreateGroup(key, true); + auto id = ConnectionManager->CreateGroup(key, false); // auto item = new QListWidgetItem(key); item->setData(Qt::UserRole, id.toString()); @@ -266,7 +266,7 @@ void GroupManager::on_addGroupButton_clicked() void GroupManager::on_updateButton_clicked() { - if (QvMessageBoxAsk(this, tr("Reload Subscription"), tr("Would you like to reload the subscription?")) == QMessageBox::Yes) + if (QvMessageBoxAsk(this, tr("Update Subscription"), tr("Would you like to update the subscription?")) == QMessageBox::Yes) { this->setEnabled(false); ConnectionManager->UpdateSubscription(currentGroupId); diff --git a/src/ui/windows/w_GroupManager.ui b/src/ui/windows/w_GroupManager.ui index 7033a8af..00726f43 100644 --- a/src/ui/windows/w_GroupManager.ui +++ b/src/ui/windows/w_GroupManager.ui @@ -105,7 +105,7 @@ - + :/assets/icons/ui_light/add.png:/assets/icons/ui_light/add.png @@ -125,7 +125,7 @@ - + :/assets/icons/ui_light/delete.png:/assets/icons/ui_light/delete.png @@ -227,6 +227,9 @@ true + + false + @@ -321,26 +324,6 @@ - - - Connection Settings - - - - - - - - - - Route Settings - - - - - - - @@ -352,7 +335,7 @@ updateIntervalSB - + diff --git a/src/ui/windows/w_ImportConfig.cpp b/src/ui/windows/w_ImportConfig.cpp index 6a75c466..9e245d78 100644 --- a/src/ui/windows/w_ImportConfig.cpp +++ b/src/ui/windows/w_ImportConfig.cpp @@ -20,12 +20,22 @@ #include #include +constexpr auto LINK_PAGE = 0; +constexpr auto QRCODE_PAGE = 1; +constexpr auto MANUAL_PAGE = 2; +constexpr auto ADVANCED_PAGE = 3; + ImportConfigWindow::ImportConfigWindow(QWidget *parent) : QDialog(parent) { setupUi(this); - // nameTxt->setText(tr("My Connection Imported at: ") + QDateTime::currentDateTime().toString("MM-dd hh:mm")); + nameTxt->setText(tr("New Connection") + QDateTime::currentDateTime().toString("MM-dd hh:mm")); QvMessageBusConnect(ImportConfigWindow); RESTORE_RUNTIME_CONFIG(screenShotHideQv2ray, hideQv2rayCB->setChecked) + // + for (const auto &gid : ConnectionManager->AllGroups()) + { + groupCombo->addItem(GetDisplayName(gid), gid.toString()); + } } void ImportConfigWindow::UpdateColorScheme() @@ -54,23 +64,28 @@ QMultiHash ImportConfigWindow::SelectConnection(bool outbou // false and disable the checkbox keepImportedInboundCheckBox->setEnabled(!outboundsOnly); routeEditBtn->setEnabled(!outboundsOnly); + groupCombo->setEnabled(false); this->exec(); QMultiHash conn; - for (const auto &connEntry : connections.values()) + for (const auto &connEntry : connectionsToNewGroup.values()) + { + conn += connEntry; + } + for (const auto &connEntry : connectionsToExistingGroup.values()) { conn += connEntry; } return result() == Accepted ? conn : QMultiHash{}; } -int ImportConfigWindow::ImportConnection() +int ImportConfigWindow::PerformImportConnection() { this->exec(); int count = 0; - for (const auto &groupName : connections.keys()) + for (const auto &groupObject : connectionsToNewGroup) { - GroupId groupId = groupName.isEmpty() ? DefaultGroupId : ConnectionManager->CreateGroup(groupName, false); - const auto groupObject = connections[groupName]; + const auto groupName = connectionsToNewGroup.key(groupObject); + GroupId groupId = ConnectionManager->CreateGroup(groupName, false); for (const auto &connConf : groupObject) { auto connName = groupObject.key(connConf); @@ -84,6 +99,21 @@ int ImportConfigWindow::ImportConnection() } } + for (const auto &groupObject : connectionsToExistingGroup) + { + const auto groupId = connectionsToExistingGroup.key(groupObject); + for (const auto &connConf : groupObject) + { + auto connName = groupObject.key(connConf); + auto [protocol, host, port] = GetConnectionInfo(connConf); + if (connName.isEmpty()) + { + connName = protocol + "/" + host + ":" + QSTRN(port) + "-" + GenerateRandomString(5); + } + ConnectionManager->CreateConnection(connConf, connName, groupId, true); + } + } + return count; } @@ -116,7 +146,7 @@ void ImportConfigWindow::on_qrFromScreenBtn_clicked() if (_r == QDialog::Accepted) { auto str = DecodeQRCode(pix); - + qrImageLabel->setPixmap(QPixmap::fromImage(pix)); if (str.trimmed().isEmpty()) { LOG(MODULE_UI, "Cannot decode QR Code from an image, size: h=" + QSTRN(pix.width()) + ", v=" + QSTRN(pix.height())) @@ -124,7 +154,7 @@ void ImportConfigWindow::on_qrFromScreenBtn_clicked() } else { - vmessConnectionStringTxt->appendPlainText(str.trimmed() + NEWLINE); + qrCodeLinkTxt->setText(str.trimmed()); } } } @@ -135,7 +165,7 @@ void ImportConfigWindow::on_beginImportBtn_clicked() switch (tabWidget->currentIndex()) { - case 0: + case LINK_PAGE: { QStringList linkList = SplitLines(vmessConnectionStringTxt->toPlainText()); // @@ -165,11 +195,19 @@ void ImportConfigWindow::on_beginImportBtn_clicked() linkErrors[link] = QSTRN(linkErrors.count() + 1) + ": " + errMessage; continue; } - else + else if (newGroupName.isEmpty()) { for (const auto &conf : config) { - AddToGroup(newGroupName, config.key(conf), conf); + connectionsToExistingGroup[GroupId{ groupCombo->currentData().toString() }].insert(config.key(conf), conf); + } + } + else + { + + for (const auto &conf : config) + { + connectionsToNewGroup[newGroupName].insert(config.key(conf), conf); } } } @@ -189,7 +227,26 @@ void ImportConfigWindow::on_beginImportBtn_clicked() break; } - case 2: + case QRCODE_PAGE: + { + QString errorMsg; + const auto root = ConvertConfigFromString(qrCodeLinkTxt->text(), &aliasPrefix, &errorMsg); + if (!errorMsg.isEmpty()) + { + QvMessageBoxWarn(this, tr("Failed to import connection"), errorMsg); + break; + } + for (const auto &conf : root) + { + connectionsToExistingGroup[GroupId{ groupCombo->currentData().toString() }].insert(root.key(conf), conf); + } + break; + } + case MANUAL_PAGE: + { + break; + } + case ADVANCED_PAGE: { // From File... bool ImportAsComplex = keepImportedInboundCheckBox->isChecked(); @@ -203,7 +260,7 @@ void ImportConfigWindow::on_beginImportBtn_clicked() aliasPrefix += "_" + QFileInfo(path).fileName(); CONFIGROOT config = ConvertConfigFromFile(path, ImportAsComplex); - AddToGroup("", aliasPrefix, config); + connectionsToExistingGroup[GroupId{ groupCombo->currentData().toString() }].insert(aliasPrefix, config); break; } } @@ -275,7 +332,7 @@ void ImportConfigWindow::on_connectionEditBtn_clicked() CONFIGROOT root; root.insert("outbounds", outboundsList); // - AddToGroup("", alias, root); + connectionsToExistingGroup[GroupId{ groupCombo->currentData().toString() }].insert(alias, root); accept(); } } @@ -291,12 +348,13 @@ void ImportConfigWindow::on_subscriptionButton_clicked() GroupManager w(this); w.exec(); auto importToComplex = !keepImportedInboundCheckBox->isEnabled(); - connections.clear(); + connectionsToNewGroup.clear(); + connectionsToExistingGroup.clear(); if (importToComplex) { auto [alias, conf] = w.GetSelectedConfig(); - AddToGroup("", alias, conf); + connectionsToExistingGroup[GroupId{ groupCombo->currentData().toString() }].insert(alias, conf); } accept(); @@ -311,7 +369,7 @@ void ImportConfigWindow::on_routeEditBtn_clicked() if (isChanged) { - AddToGroup("", alias, result); + connectionsToExistingGroup[GroupId{ groupCombo->currentData().toString() }].insert(alias, result); accept(); } } @@ -331,7 +389,7 @@ void ImportConfigWindow::on_jsonEditBtn_clicked() if (isChanged) { - AddToGroup("", alias, CONFIGROOT(result)); + connectionsToExistingGroup[GroupId{ groupCombo->currentData().toString() }].insert(alias, CONFIGROOT(result)); accept(); } } diff --git a/src/ui/windows/w_ImportConfig.hpp b/src/ui/windows/w_ImportConfig.hpp index e662448c..a87b945d 100644 --- a/src/ui/windows/w_ImportConfig.hpp +++ b/src/ui/windows/w_ImportConfig.hpp @@ -15,7 +15,7 @@ class ImportConfigWindow public: explicit ImportConfigWindow(QWidget *parent = nullptr); ~ImportConfigWindow(); - int ImportConnection(); + int PerformImportConnection(); QMultiHash SelectConnection(bool outboundsOnly); private: @@ -43,19 +43,8 @@ class ImportConfigWindow private: void UpdateColorScheme(); - QMap> connections; QMap linkErrors; - void AddToGroup(const QString &groupName, const QString &alias, const CONFIGROOT &root) - { - if (connections.contains(groupName)) - { - connections[groupName].insert(alias, root); - } - else - { - QMultiHash temp; - temp.insert(alias, root); - connections.insert(groupName, temp); - } - } + // + QHash> connectionsToExistingGroup; + QHash> connectionsToNewGroup; }; diff --git a/src/ui/windows/w_ImportConfig.ui b/src/ui/windows/w_ImportConfig.ui index 103d1396..ed1ae5bf 100644 --- a/src/ui/windows/w_ImportConfig.ui +++ b/src/ui/windows/w_ImportConfig.ui @@ -6,8 +6,8 @@ 0 0 - 522 - 460 + 549 + 482 @@ -42,15 +42,18 @@ + + + + Import To Group + + + + + + - - - - Import Source - - - @@ -58,197 +61,193 @@ - VMess / QRCode + Link - - - + + + - Connection Share Link + Share Link - - - - - - Qt::ScrollBarAlwaysOn - - - QPlainTextEdit::NoWrap - - - Paste share link here, one line for each. - - - - - - - - - - Error List - - - - - - - Share Link - - - - + + + + Error List + + - - - - - - QRCode File - - - - - - - - - - - - true - - - - - - - Select - - - - - - - - - Screenshot - - - - - - - - - secs - - - 5.000000000000000 - - - 0.500000000000000 - - - 0.000000000000000 - - - - - - - Delay - - - - - - - Hide Qv2ray - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - Go - - - - - - + + + + Qt::ScrollBarAlwaysOn + + + QPlainTextEdit::NoWrap + + + Paste share link here, one line for each. + + + + + - + - Subscriptions / Manually Input + QR Code - - - + + + - Open Subscription Manager + QRCode File - - + + + + + + + + + true + + + + + + + Select + + + + + + + + + Screenshot + + + + + + + + + Hide Qv2ray + + + + + + + secs + + + 5.000000000000000 + + + 0.500000000000000 + + + 0.000000000000000 + + + + + + + Delay + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Go + + + + + + + + + Image + + + + + - + 0 0 - - - 0 - 10 - - - - Qt::Horizontal - - - - - - Manually Input Connections + + + + true - + + + + Detected Link + + + + + + + true + + + + + + + + Input Manually + + + - Connection Editor + Simple Editor - + Open Connection Editor @@ -258,51 +257,27 @@ - + - Route Editor + Complex Editor - + - Open Route Editor + Open Route / Complex Connection Editor false - - - - Json Editor - - - - - - - Open JSON Editor - - - false - - - - - - - Subscription Manager - - - - + - Subscription Link + You can manually input connection here. @@ -310,17 +285,24 @@ - Existing File + Advanced - + + + + Manually Input Connections + + + + Path - + @@ -338,13 +320,30 @@ - + Import as Complex Config (Manually edit route rules and inbounds) + + + + Json Editor + + + + + + + Open JSON Editor + + + false + + + @@ -384,21 +383,10 @@ nameTxt - tabWidget vmessConnectionStringTxt errorsList - imageFileEdit - selectImageBtn - doubleSpinBox - hideQv2rayCB - qrFromScreenBtn - subscriptionButton - connectionEditBtn - routeEditBtn - jsonEditBtn fileLineTxt selectFileBtn - keepImportedInboundCheckBox beginImportBtn cancelImportBtn diff --git a/src/ui/windows/w_MainWindow.cpp b/src/ui/windows/w_MainWindow.cpp index f0567a8a..aa9ed876 100644 --- a/src/ui/windows/w_MainWindow.cpp +++ b/src/ui/windows/w_MainWindow.cpp @@ -576,7 +576,7 @@ void MainWindow::on_action_RCM_DeleteThese_triggered() void MainWindow::on_importConfigButton_clicked() { ImportConfigWindow w(this); - w.ImportConnection(); + w.PerformImportConnection(); } void MainWindow::on_action_RCM_EditAsComplex_triggered() diff --git a/src/ui/windows/w_MainWindow.ui b/src/ui/windows/w_MainWindow.ui index 0d75a4e3..714cbe45 100644 --- a/src/ui/windows/w_MainWindow.ui +++ b/src/ui/windows/w_MainWindow.ui @@ -86,7 +86,7 @@ - + :/assets/icons/ui_light/locate.png:/assets/icons/ui_light/locate.png @@ -110,7 +110,7 @@ - + :/assets/icons/ui_light/sort.png:/assets/icons/ui_light/sort.png @@ -291,7 +291,7 @@ - + :/assets/icons/ui_light/delete.png:/assets/icons/ui_light/delete.png @@ -354,7 +354,7 @@ - + :/assets/icons/ui_light/delete.png:/assets/icons/ui_light/delete.png @@ -538,7 +538,7 @@ importConfigButton - +