From 7fb8cd3d94f36c3d336decd9e73b4e987ef9b3d1 Mon Sep 17 00:00:00 2001 From: Qv2ray-dev <59914293+Qv2ray-dev@users.noreply.github.com> Date: Mon, 2 Mar 2020 00:03:07 +0800 Subject: [PATCH] add: added more ui functionalities - 2 --- makespec/BUILDVERSION | 2 +- src/core/kernel/APIBackend.cpp | 13 +- src/ui/w_MainWindow.cpp | 101 +++-------- src/ui/w_MainWindow.hpp | 2 +- src/ui/w_MainWindow.ui | 226 ------------------------ src/ui/w_PreferencesWindow.cpp | 7 +- src/ui/w_SubscriptionManager.cpp | 4 + src/ui/widgets/ConnectionInfoWidget.cpp | 7 +- src/ui/widgets/ConnectionInfoWidget.ui | 12 ++ src/ui/widgets/ConnectionItemWidget.cpp | 40 ++++- src/ui/widgets/ConnectionItemWidget.hpp | 11 +- src/ui/widgets/ConnectionItemWidget.ui | 173 ++++++++++++------ 12 files changed, 221 insertions(+), 377 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 87ca4f07..7174ebd1 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -4284 +4326 diff --git a/src/core/kernel/APIBackend.cpp b/src/core/kernel/APIBackend.cpp index bd7b403a..3f7b0823 100644 --- a/src/core/kernel/APIBackend.cpp +++ b/src/core/kernel/APIBackend.cpp @@ -13,6 +13,15 @@ namespace Qv2ray::core::kernel { // To all contributors: // + // You may feel it difficult to understand this part of API backend. + // It's been expected that you will take hours to fully understand the tricks and hacks lying deeply in this class. + // + // The API Worker runs as a daemon together with Qv2ray, on a single thread. + // They use a flag, running, to indicate if the API worker should go and fetch the statistics from V2ray Core. + // + // The flag, running, will be set to true, immediately after the V2ray core reported that it's been started. + // and will be set to false right before we stopping V2ray Core. + // // --- CONSTRUCTOR --- APIWorker::APIWorker() @@ -20,9 +29,9 @@ namespace Qv2ray::core::kernel thread = new QThread(); this->moveToThread(thread); DEBUG(MODULE_VCORE, "API Worker initialised.") - connect(this, SIGNAL(error(QString)), this, SLOT(errorString(QString))); + // connect(this, SIGNAL(error(QString)), this, SLOT(errorString(QString))); connect(thread, SIGNAL(started()), this, SLOT(process())); - connect(thread, &QThread::finished, []() { LOG(MODULE_VCORE, "API thread stopped") }); + connect(thread, &QThread::finished, [] { LOG(MODULE_VCORE, "API thread stopped") }); started = true; thread->start(); DEBUG(MODULE_VCORE, "API Worker started.") diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index 9c1a9ed6..b633eb71 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -162,10 +162,12 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), h // Actions for right click the connection list // QAction *action_RCM_StartThis = new QAction(tr("Connect to this"), this); + QAction *action_RCM_RenameThis = new QAction(tr("Rename"), this); QAction *action_RCM_ConvToComplex = new QAction(QICON_R("edit.png"), tr("Edit as Complex Config"), this); // connect(action_RCM_StartThis, &QAction::triggered, this, &MainWindow::on_action_StartThis_triggered); connect(action_RCM_ConvToComplex, &QAction::triggered, this, &MainWindow::on_action_RCM_ConvToComplex_triggered); + connect(action_RCM_RenameThis, &QAction::triggered, this, &MainWindow::on_action_RCM_RenameThis_triggered); // // Globally invokable signals. connect(this, &MainWindow::Connect, [&] { ConnectionManager->StartConnection(lastConnectedId); }); @@ -177,6 +179,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), h // connectionListMenu = new QMenu(this); connectionListMenu->addAction(action_RCM_StartThis); + connectionListMenu->addAction(action_RCM_RenameThis); connectionListMenu->addAction(action_RCM_ConvToComplex); // LOG(MODULE_UI, "Loading data...") @@ -189,7 +192,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //, vinstance(), h for (auto connection : connections) { - MWAddConnectionItem_p(connection, group); // + MWAddConnectionItem_p(connection, group); } } // @@ -368,6 +371,7 @@ void MainWindow::ToggleVisibility() void MainWindow::on_actionExit_triggered() { + ConnectionManager->StopConnection(); if (StartupOption.enableToolbarPlguin) { StopProcessingPlugins(); @@ -396,85 +400,6 @@ void MainWindow::on_connectionListWidget_customContextMenuRequested(const QPoint } } -void MainWindow::on_connectionListWidget_itemChanged(QTreeWidgetItem *item, int) -{ - // DEBUG(UI, "A connection ListViewItem is changed. This should ONLY occur - // when renaming an connection.") - // - // if (!isRenamingInProgress) { - // return; - //} - // - // isRenamingInProgress = false; - //// In this case it's after we entered the name. - //// and tell user you should not rename a config from subscription. - // auto newIdentifier = renameOriginalIdentifier; - // newIdentifier.connectionName = item->text(0); - // LOG(CONNECTION, "RENAME: " + renameOriginalIdentifier.IdentifierString() - // + " -> " + newIdentifier.IdentifierString()) - // - //// If I really did some changes. - // if (renameOriginalIdentifier != newIdentifier) { - // bool canContinueRename = true; - // - // if (newIdentifier.connectionName.trimmed().isEmpty()) { - // QvMessageBoxWarn(this, tr("Rename a Connection"), tr("The name - // cannot be empty")); canContinueRename = false; - // } - // - // QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP"); - // //if (GlobalConfig.configs.contains(newIdentifier.connectionName)) { - // // QvMessageBoxWarn(this, tr("Rename a Connection"), tr("The name - // has been used already, Please choose another.")); - // // canContinueRename = false; - // //} - // - // if (!IsValidFileName(newIdentifier.connectionName + - // QV2RAY_CONFIG_FILE_EXTENSION)) { - // QvMessageBoxWarn(this, tr("Rename a Connection"), tr("The name you - // suggested is not valid, please try another.")); canContinueRename - // = false; - // } - // - // if (!canContinueRename) { - // // Set the item text back - // assert(item != nullptr); // Let's say the item should not be null - // item->setText(0, renameOriginalIdentifier.connectionName); - // return; - // } - // - // // Change auto start config. - // // |--------------=== In case it's not in a subscription --| - // if (GlobalConfig.autoStartConfig == renameOriginalIdentifier) { - // GlobalConfig.autoStartConfig = newIdentifier; - // } - // - // QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP"); - // //// Replace the items in the current loaded config list and settings. - // //// Note: This original name should only be a reguular. - // //GlobalConfig.configs.removeOne(renameOriginalIdentifier.connectionName); - // //GlobalConfig.configs.push_back(newIdentifier.connectionName); - // // - // //connections[newIdentifier] = - // connections.take(renameOriginalIdentifier); - // //RenameConnection(renameOriginalIdentifier.connectionName, - // newIdentifier.connectionName); - // //LOG(UI, "Saving a global config") - // //SaveGlobalConfig(GlobalConfig); - // //// - // //item->setData(0, Qt::UserRole, QVariant::fromValue(newIdentifier)); - // // - // //if (CurrentConnectionIdentifier == renameOriginalIdentifier) { - // // CurrentConnectionIdentifier = newIdentifier; - // // - // // if (vinstance->KernelStarted) { - // // on_reconnectButton_clicked(); - // // } - // //} - // //OnConfigListChanged(CurrentConnectionIdentifier.connectionName == - // renameOriginalName); - //} -} void MainWindow::on_removeConfigButton_clicked() { QvMessageBoxInfo(this, "NOT SUPPORTED", "WIP"); @@ -622,6 +547,10 @@ void MainWindow::on_connectionListWidget_itemDoubleClicked(QTreeWidgetItem *item void MainWindow::OnDisconnected(const ConnectionId &id) { Q_UNUSED(id) + action_Tray_Start->setEnabled(true); + action_Tray_Stop->setEnabled(false); + action_Tray_Reconnect->setEnabled(false); + tray_SystemProxyMenu->setEnabled(false); lastConnectedId = id; locateBtn->setEnabled(false); this->hTray.showMessage("Qv2ray", tr("Disconnected from: ") + ConnectionManager->GetDisplayName(id), this->windowIcon()); @@ -642,6 +571,10 @@ void MainWindow::OnDisconnected(const ConnectionId &id) void MainWindow::OnConnected(const ConnectionId &id) { Q_UNUSED(id) + action_Tray_Start->setEnabled(false); + action_Tray_Stop->setEnabled(true); + action_Tray_Reconnect->setEnabled(true); + tray_SystemProxyMenu->setEnabled(true); lastConnectedId = id; locateBtn->setEnabled(true); on_clearlogButton_clicked(); @@ -907,5 +840,13 @@ void MainWindow::on_locateBtn_clicked() if (id != NullConnectionId) { connectionListWidget->setCurrentItem(connectionNodes[id].get()); + connectionListWidget->scrollToItem(connectionNodes[id].get()); + on_connectionListWidget_itemClicked(connectionNodes[id].get(), 0); } } + +void MainWindow::on_action_RCM_RenameThis_triggered() +{ + CheckCurrentWidget; + widget->BeginRename(); +} diff --git a/src/ui/w_MainWindow.hpp b/src/ui/w_MainWindow.hpp index f10d9cce..90e46ed6 100644 --- a/src/ui/w_MainWindow.hpp +++ b/src/ui/w_MainWindow.hpp @@ -37,7 +37,6 @@ class MainWindow void on_preferencesBtn_clicked(); void on_clearlogButton_clicked(); void on_connectionListWidget_customContextMenuRequested(const QPoint &pos); - void on_connectionListWidget_itemChanged(QTreeWidgetItem *item, int column); void on_removeConfigButton_clicked(); void on_importConfigButton_clicked(); void on_subsButton_clicked(); @@ -77,6 +76,7 @@ class MainWindow // void on_action_StartThis_triggered(); void on_action_RCM_ConvToComplex_triggered(); + void on_action_RCM_RenameThis_triggered(); // void on_connectionListWidget_itemDoubleClicked(QTreeWidgetItem *item, int column); void on_connectionFilterTxt_textEdited(const QString &arg1); diff --git a/src/ui/w_MainWindow.ui b/src/ui/w_MainWindow.ui index f2a3cf76..c369cdaf 100644 --- a/src/ui/w_MainWindow.ui +++ b/src/ui/w_MainWindow.ui @@ -494,232 +494,6 @@ - - - - 0 - 0 - 900 - 26 - - - - - File - - - - Import Connection - - - - - - - - - - - - - - - - - - Subscriptions - - - - Update Subscriptions - - - - - - - - - - - - Tools - - - - - - - - Help - - - - - - - - - - - - - - - - #ManuallyCreateConnection - - - - - #ImportConnection - - - - - #Exit - - - - - #Preferences - - - - - #Start - - - - - #Stop - - - - - #Restart - - - - - Import from vmess:// - - - - - Import from QRCode File - - - - - Import from ScreenShot - - - - - Open Configuration Folder - - - - - Exit - - - - - From File - - - - - From Connection Link - - - - - From QRCode File - - - - - Take ScreenShot - - - - - Open Connection Editor - - - - - Manually Create Connection - - - - - Manually Create Complex Connection - - - - - Copy Connection Link - - - - - Copy QRCode - - - - - Save QRCode to File - - - - - Open Subscription Manager - - - - - Update All Subscriptions - - - - - Update All Subscriptions with System Proxy - - - - - Options - - - - - About Qt - - - - - About Qv2ray - - - - - Help - - - - - Save Qv2ray Log - - - - - Json Editor - - diff --git a/src/ui/w_PreferencesWindow.cpp b/src/ui/w_PreferencesWindow.cpp index eca5af3b..4cc72f03 100644 --- a/src/ui/w_PreferencesWindow.cpp +++ b/src/ui/w_PreferencesWindow.cpp @@ -1,4 +1,5 @@ #include "w_PreferencesWindow.hpp" + #include "common/HTTPRequestHelper.hpp" #include "common/QvHelpers.hpp" #include "common/QvTranslator.hpp" @@ -1029,7 +1030,11 @@ void PreferencesWindow::on_autoStartSubsCombo_currentIndexChanged(const QString void PreferencesWindow::on_autoStartConnCombo_currentIndexChanged(const QString &arg1) { LOADINGCHECK - CurrentConfig.autoStartId = ConnectionManager->GetConnectionIdByDisplayName(arg1).toString(); + // Fully qualify the connection item. + // Will not work when duplicated names are in the same group. + CurrentConfig.autoStartId = + ConnectionManager->GetConnectionIdByDisplayName(arg1, ConnectionManager->GetGroupIdByDisplayName(autoStartSubsCombo->currentText())) + .toString(); } void PreferencesWindow::on_startWithLoginCB_stateChanged(int arg1) diff --git a/src/ui/w_SubscriptionManager.cpp b/src/ui/w_SubscriptionManager.cpp index 20cc75bc..a1277a09 100644 --- a/src/ui/w_SubscriptionManager.cpp +++ b/src/ui/w_SubscriptionManager.cpp @@ -15,6 +15,10 @@ SubscribeEditor::SubscribeEditor(QWidget *parent) : QDialog(parent) { subscriptionList->addTopLevelItem(new QTreeWidgetItem(QStringList{ ConnectionManager->GetDisplayName(subs), subs.toString() })); } + if (subscriptionList->topLevelItemCount() > 0) + { + subscriptionList->setCurrentItem(subscriptionList->topLevelItem(0)); + } } QvMessageBusSlotImpl(SubscribeEditor) diff --git a/src/ui/widgets/ConnectionInfoWidget.cpp b/src/ui/widgets/ConnectionInfoWidget.cpp index aa4e3400..61245060 100644 --- a/src/ui/widgets/ConnectionInfoWidget.cpp +++ b/src/ui/widgets/ConnectionInfoWidget.cpp @@ -14,8 +14,6 @@ ConnectionInfoWidget::ConnectionInfoWidget(QWidget *parent) : QWidget(parent) editJsonBtn->setIcon(QICON_R("json.png")); // shareLinkTxt->setAutoFillBackground(true); - shareLinkTxt->setStyleSheet("border-bottom: 1px solid gray; border-radius: 0px; padding: 2px; background-color: " + - this->palette().color(this->backgroundRole()).name(QColor::HexRgb)); shareLinkTxt->setCursor(QCursor(Qt::CursorShape::IBeamCursor)); shareLinkTxt->installEventFilter(this); // @@ -25,7 +23,10 @@ ConnectionInfoWidget::ConnectionInfoWidget(QWidget *parent) : QWidget(parent) void ConnectionInfoWidget::ShowDetails(const tuple &_identifier) { - auto [groupId, connectionId] = _identifier; + shareLinkTxt->setStyleSheet("border-bottom: 1px solid gray; border-radius: 0px; padding: 2px; background-color: " + + this->palette().color(this->backgroundRole()).name(QColor::HexRgb)); + this->groupId = get<0>(_identifier); + this->connectionId = get<1>(_identifier); bool isConnection = connectionId != NullConnectionId; // editBtn->setEnabled(isConnection); diff --git a/src/ui/widgets/ConnectionInfoWidget.ui b/src/ui/widgets/ConnectionInfoWidget.ui index bc813740..6b5083f9 100644 --- a/src/ui/widgets/ConnectionInfoWidget.ui +++ b/src/ui/widgets/ConnectionInfoWidget.ui @@ -381,9 +381,15 @@ + + IBeamCursor + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + @@ -395,9 +401,15 @@ + + IBeamCursor + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + diff --git a/src/ui/widgets/ConnectionItemWidget.cpp b/src/ui/widgets/ConnectionItemWidget.cpp index afaf031b..71b30510 100644 --- a/src/ui/widgets/ConnectionItemWidget.cpp +++ b/src/ui/widgets/ConnectionItemWidget.cpp @@ -2,6 +2,8 @@ #include "common/QvHelpers.hpp" +#include + ConnectionItemWidget::ConnectionItemWidget(QWidget *parent) : QWidget(parent), connectionId("null"), groupId("null") { setupUi(this); @@ -16,7 +18,7 @@ ConnectionItemWidget::ConnectionItemWidget(const ConnectionId &id, QWidget *pare { connectionId = id; groupId = ConnectionManager->GetConnectionGroupId(id); - originalConnectionName = ConnectionManager->GetDisplayName(id); + originalItemName = ConnectionManager->GetDisplayName(id); itemType = NODE_ITEM; auto latency = ConnectionManager->GetConnectionLatency(id); @@ -39,7 +41,7 @@ ConnectionItemWidget::ConnectionItemWidget(const ConnectionId &id, QWidget *pare { emit RequestWidgetFocus(this); } - OnConnectionItemRenamed(id, "", originalConnectionName); + OnConnectionItemRenamed(id, "", originalItemName); connect(ConnectionManager, &QvConnectionHandler::OnConnectionRenamed, this, &ConnectionItemWidget::OnConnectionItemRenamed); } @@ -48,7 +50,7 @@ ConnectionItemWidget::ConnectionItemWidget(const GroupId &id, QWidget *parent) : { groupId = id; itemType = GROUP_HEADER_ITEM; - originalConnectionName = ConnectionManager->GetDisplayName(id); + originalItemName = ConnectionManager->GetDisplayName(id); RecalculateConnectionsCount(); // layout()->removeWidget(connTypeLabel); @@ -60,7 +62,7 @@ ConnectionItemWidget::ConnectionItemWidget(const GroupId &id, QWidget *parent) : font.setBold(true); connNameLabel->setFont(font); // - OnGroupItemRenamed(id, "", originalConnectionName); + OnGroupItemRenamed(id, "", originalItemName); connect(ConnectionManager, &QvConnectionHandler::OnConnectionCreated, this, &ConnectionItemWidget::RecalculateConnectionsCount); connect(ConnectionManager, &QvConnectionHandler::OnConnectionDeleted, this, &ConnectionItemWidget::RecalculateConnectionsCount); connect(ConnectionManager, &QvConnectionHandler::OnConnectionChanged, this, &ConnectionItemWidget::RecalculateConnectionsCount); @@ -86,7 +88,7 @@ void ConnectionItemWidget::OnConnected(const ConnectionId &id) { if (id == connectionId) { - connNameLabel->setText("• " + originalConnectionName); + connNameLabel->setText("• " + originalItemName); LOG(MODULE_UI, "OnConnected signal received for: " + id.toString()) emit RequestWidgetFocus(this); } @@ -96,7 +98,7 @@ void ConnectionItemWidget::OnDisConnected(const ConnectionId &id) { if (id == connectionId) { - connNameLabel->setText(originalConnectionName); + connNameLabel->setText(originalItemName); } } @@ -126,17 +128,37 @@ void ConnectionItemWidget::OnLatencyTestFinished(const ConnectionId &id, const u if (average == 0) { latencyLabel->setText(tr("Error")); - RED(latencyLabel) } else { latencyLabel->setText(QSTRN(average) + tr("ms")); - BLACK(latencyLabel) } } } +void ConnectionItemWidget::BeginRename() +{ + stackedWidget->setCurrentIndex(1); + renameTxt->setStyle(QStyleFactory::create("Fusion")); + renameTxt->setStyleSheet("background-color: " + this->palette().color(this->backgroundRole()).name(QColor::HexRgb)); + renameTxt->setText(originalItemName); +} + ConnectionItemWidget::~ConnectionItemWidget() { - // +} + +void ConnectionItemWidget::on_doRenameBtn_clicked() +{ + if (renameTxt->text().isEmpty()) + return; + if (connectionId == NullConnectionId) + { + ConnectionManager->RenameGroup(groupId, renameTxt->text()); + } + else + { + ConnectionManager->RenameConnection(connectionId, renameTxt->text()); + } + stackedWidget->setCurrentIndex(0); } diff --git a/src/ui/widgets/ConnectionItemWidget.hpp b/src/ui/widgets/ConnectionItemWidget.hpp index 63f061f4..5267e82e 100644 --- a/src/ui/widgets/ConnectionItemWidget.hpp +++ b/src/ui/widgets/ConnectionItemWidget.hpp @@ -23,6 +23,7 @@ class ConnectionItemWidget void BeginConnection(); ~ConnectionItemWidget(); // + void BeginRename(); inline bool NameMatched(const QString &arg) { auto searchString = arg.toLower(); @@ -65,13 +66,13 @@ class ConnectionItemWidget { if (ConnectionManager->IsConnected(id)) { - connNameLabel->setText("• " + originalConnectionName); + connNameLabel->setText("• " + newName); } else { connNameLabel->setText(newName); } - originalConnectionName = newName; + originalItemName = newName; this->setToolTip(newName); } } @@ -79,14 +80,16 @@ class ConnectionItemWidget { if (id == groupId) { - originalConnectionName = newName; + originalItemName = newName; connNameLabel->setText(newName); this->setToolTip(newName); } } + void on_doRenameBtn_clicked(); + private: - QString originalConnectionName; + QString originalItemName; explicit ConnectionItemWidget(QWidget *parent = nullptr); ITEM_TYPE itemType; ConnectionId connectionId; diff --git a/src/ui/widgets/ConnectionItemWidget.ui b/src/ui/widgets/ConnectionItemWidget.ui index 2acc24d4..51f3a80d 100644 --- a/src/ui/widgets/ConnectionItemWidget.ui +++ b/src/ui/widgets/ConnectionItemWidget.ui @@ -6,14 +6,26 @@ 0 0 - 277 - 66 + 203 + 58 Form + + 0 + + + 0 + + + 0 + + + 0 + @@ -31,63 +43,124 @@ - - - 5 + + + 0 - - + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 6 + + + 6 + + + 6 + + + 6 + + + 6 + + + + + + + + 11 + + + + Connection Name + + + + + + + 500ms + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + Type: vmess + tls + ws + + + + + + + + 8 + + + + 0KB / 0KB + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + - - - - 11 - - - - Connection Name - - + - + - 500ms - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + OK - - - - - - - Type: vmess + tls + ws - - - - - - - - 8 - - - - 0KB / 0KB - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - + +