add: added more ui functionalities - 2

This commit is contained in:
Qv2ray-dev 2020-03-02 00:03:07 +08:00
parent 44e9a550d2
commit 7fb8cd3d94
12 changed files with 221 additions and 377 deletions

View File

@ -1 +1 @@
4284
4326

View File

@ -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.")

View File

@ -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();
}

View File

@ -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);

View File

@ -494,232 +494,6 @@
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>900</width>
<height>26</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>File</string>
</property>
<widget class="QMenu" name="menuImport_Connection">
<property name="title">
<string>Import Connection</string>
</property>
<addaction name="actionFrom_File"/>
<addaction name="actionFrom_Connection_Link"/>
<addaction name="actionFrom_QRCode_File"/>
<addaction name="actionTake_ScreenShot"/>
<addaction name="separator"/>
<addaction name="actionManually_Create_Connection"/>
<addaction name="actionManually_Create_Complex_Connection"/>
</widget>
<addaction name="menuImport_Connection"/>
<addaction name="separator"/>
<addaction name="actionOpen_Qv2ray_Configuration_Folder"/>
<addaction name="separator"/>
<addaction name="actionExit_2"/>
</widget>
<widget class="QMenu" name="menuSubscriptions">
<property name="title">
<string>Subscriptions</string>
</property>
<widget class="QMenu" name="menuUpdate_Subscriptions">
<property name="title">
<string>Update Subscriptions</string>
</property>
<addaction name="actionUpdate_All_Subscriptions"/>
<addaction name="actionUpdate_All_Subscriptions_with_System_Proxy"/>
<addaction name="separator"/>
</widget>
<addaction name="actionSubscription_Manager"/>
<addaction name="separator"/>
<addaction name="menuUpdate_Subscriptions"/>
</widget>
<widget class="QMenu" name="menuTools">
<property name="title">
<string>Tools</string>
</property>
<addaction name="actionJson_Editor"/>
<addaction name="separator"/>
<addaction name="actionOptions"/>
</widget>
<widget class="QMenu" name="menuHelp">
<property name="title">
<string>Help</string>
</property>
<addaction name="actionSave_Qv2ray_Log"/>
<addaction name="separator"/>
<addaction name="actionAbout_Qt"/>
<addaction name="actionAbout_Qv2ray"/>
<addaction name="separator"/>
<addaction name="actionHelp"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuSubscriptions"/>
<addaction name="menuTools"/>
<addaction name="menuHelp"/>
</widget>
<action name="actionEdit">
<property name="text">
<string>#ManuallyCreateConnection</string>
</property>
</action>
<action name="actionExisting_config">
<property name="text">
<string>#ImportConnection</string>
</property>
</action>
<action name="actionExit">
<property name="text">
<string>#Exit</string>
</property>
</action>
<action name="actionPreferences">
<property name="text">
<string>#Preferences</string>
</property>
</action>
<action name="action_Start">
<property name="text">
<string>#Start</string>
</property>
</action>
<action name="action_Stop">
<property name="text">
<string>#Stop</string>
</property>
</action>
<action name="action_Restart">
<property name="text">
<string>#Restart</string>
</property>
</action>
<action name="actionImport_from_vmess">
<property name="text">
<string>Import from vmess://</string>
</property>
</action>
<action name="actionImport_from_QRCode_File">
<property name="text">
<string>Import from QRCode File</string>
</property>
</action>
<action name="actionImport_from_ScreenShot">
<property name="text">
<string>Import from ScreenShot</string>
</property>
</action>
<action name="actionOpen_Qv2ray_Configuration_Folder">
<property name="text">
<string>Open Configuration Folder</string>
</property>
</action>
<action name="actionExit_2">
<property name="text">
<string>Exit</string>
</property>
</action>
<action name="actionFrom_File">
<property name="text">
<string>From File</string>
</property>
</action>
<action name="actionFrom_Connection_Link">
<property name="text">
<string>From Connection Link</string>
</property>
</action>
<action name="actionFrom_QRCode_File">
<property name="text">
<string>From QRCode File</string>
</property>
</action>
<action name="actionTake_ScreenShot">
<property name="text">
<string>Take ScreenShot</string>
</property>
</action>
<action name="actionOpen_Connection_Editor">
<property name="text">
<string>Open Connection Editor</string>
</property>
</action>
<action name="actionManually_Create_Connection">
<property name="text">
<string>Manually Create Connection</string>
</property>
</action>
<action name="actionManually_Create_Complex_Connection">
<property name="text">
<string>Manually Create Complex Connection</string>
</property>
</action>
<action name="actionCopy_Connection_Link">
<property name="text">
<string>Copy Connection Link</string>
</property>
</action>
<action name="actionCopy_QRCode">
<property name="text">
<string>Copy QRCode</string>
</property>
</action>
<action name="actionSave_QRCode">
<property name="text">
<string>Save QRCode to File</string>
</property>
</action>
<action name="actionSubscription_Manager">
<property name="text">
<string>Open Subscription Manager</string>
</property>
</action>
<action name="actionUpdate_All_Subscriptions">
<property name="text">
<string>Update All Subscriptions</string>
</property>
</action>
<action name="actionUpdate_All_Subscriptions_with_System_Proxy">
<property name="text">
<string>Update All Subscriptions with System Proxy</string>
</property>
</action>
<action name="actionOptions">
<property name="text">
<string>Options</string>
</property>
</action>
<action name="actionAbout_Qt">
<property name="text">
<string>About Qt</string>
</property>
</action>
<action name="actionAbout_Qv2ray">
<property name="text">
<string>About Qv2ray</string>
</property>
</action>
<action name="actionHelp">
<property name="text">
<string>Help</string>
</property>
</action>
<action name="actionSave_Qv2ray_Log">
<property name="text">
<string>Save Qv2ray Log</string>
</property>
</action>
<action name="actionJson_Editor">
<property name="text">
<string>Json Editor</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<tabstops>

View File

@ -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)

View File

@ -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)

View File

@ -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<GroupId, ConnectionId> &_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);

View File

@ -381,9 +381,15 @@
</item>
<item row="0" column="1">
<widget class="QLabel" name="groupNameLabel">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
</property>
<property name="text">
<string/>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="1" column="0">
@ -395,9 +401,15 @@
</item>
<item row="1" column="1">
<widget class="QLabel" name="groupSubsLinkLabel">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
</property>
<property name="text">
<string/>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="2" column="0">

View File

@ -2,6 +2,8 @@
#include "common/QvHelpers.hpp"
#include <QStyleFactory>
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);
}

View File

@ -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;

View File

@ -6,14 +6,26 @@
<rect>
<x>0</x>
<y>0</y>
<width>277</width>
<height>66</height>
<width>203</width>
<height>58</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<spacer name="indentSpacer">
<property name="orientation">
@ -31,63 +43,124 @@
</spacer>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>5</number>
<widget class="QStackedWidget" name="stackedWidget">
<property name="currentIndex">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0">
<widget class="QWidget" name="page">
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0">
<item>
<widget class="QLabel" name="connNameLabel">
<property name="font">
<font>
<pointsize>11</pointsize>
</font>
</property>
<property name="text">
<string>Connection Name</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="latencyLabel">
<property name="text">
<string>500ms</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="1,0">
<item>
<widget class="QLabel" name="connTypeLabel">
<property name="text">
<string>Type: vmess + tls + ws</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="dataLabel">
<property name="font">
<font>
<pointsize>8</pointsize>
</font>
</property>
<property name="text">
<string>0KB / 0KB</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_2">
<layout class="QHBoxLayout" name="horizontalLayout_4" stretch="1,0">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="connNameLabel">
<property name="font">
<font>
<pointsize>11</pointsize>
</font>
</property>
<property name="text">
<string>Connection Name</string>
</property>
</widget>
<widget class="QLineEdit" name="renameTxt"/>
</item>
<item>
<widget class="QLabel" name="latencyLabel">
<widget class="QToolButton" name="doRenameBtn">
<property name="text">
<string>500ms</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
<string>OK</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="1,0">
<item>
<widget class="QLabel" name="connTypeLabel">
<property name="text">
<string>Type: vmess + tls + ws</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="dataLabel">
<property name="font">
<font>
<pointsize>8</pointsize>
</font>
</property>
<property name="text">
<string>0KB / 0KB</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>