From b33c76a5564dc14690a9d226873a14f82f10f1a5 Mon Sep 17 00:00:00 2001 From: QxQ <59914293+U-v-U@users.noreply.github.com> Date: Thu, 1 Oct 2020 01:20:33 +0800 Subject: [PATCH] update: use model/view for ConnectionList --- cmake/components/qv2ray-ui-widget.cmake | 3 + makespec/BUILDVERSION | 2 +- src/ui/common/speedchart/speedwidget.cpp | 137 ++++--- src/ui/common/speedchart/speedwidget.hpp | 8 +- .../widgets/models/ConnectionModelHelper.cpp | 163 +++++++++ .../widgets/models/ConnectionModelHelper.hpp | 59 +++ src/ui/widgets/windows/w_MainWindow.cpp | 344 ++++++------------ src/ui/widgets/windows/w_MainWindow.hpp | 42 +-- src/ui/widgets/windows/w_MainWindow.ui | 17 +- 9 files changed, 414 insertions(+), 361 deletions(-) create mode 100644 src/ui/widgets/models/ConnectionModelHelper.cpp create mode 100644 src/ui/widgets/models/ConnectionModelHelper.hpp diff --git a/cmake/components/qv2ray-ui-widget.cmake b/cmake/components/qv2ray-ui-widget.cmake index 8cba339f..104340d5 100644 --- a/cmake/components/qv2ray-ui-widget.cmake +++ b/cmake/components/qv2ray-ui-widget.cmake @@ -68,6 +68,9 @@ set(_QV2RAY_UI_SOURCES ${QV2RAY_QWIDGETS_UI_BASEDIR}/styles/StyleManager.cpp ${QV2RAY_QWIDGETS_UI_BASEDIR}/styles/StyleManager.cpp ${QV2RAY_QWIDGETS_UI_BASEDIR}/styles/StyleManager.hpp + # Models + ${QV2RAY_QWIDGETS_UI_BASEDIR}/models/ConnectionModelHelper.cpp + ${QV2RAY_QWIDGETS_UI_BASEDIR}/models/ConnectionModelHelper.hpp # UI Widgets ${QV2RAY_QWIDGETS_UI_BASEDIR}/widgets/ConnectionInfoWidget.hpp ${QV2RAY_QWIDGETS_UI_BASEDIR}/widgets/ConnectionInfoWidget.cpp diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index d19a85be..dc9413a5 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -5946 +5947 diff --git a/src/ui/common/speedchart/speedwidget.cpp b/src/ui/common/speedchart/speedwidget.cpp index b17cf5e3..0decb7ec 100644 --- a/src/ui/common/speedchart/speedwidget.cpp +++ b/src/ui/common/speedchart/speedwidget.cpp @@ -35,12 +35,15 @@ #define VIEWABLE 120 +// table of supposed nice steps for grid marks to get nice looking quarters of scale +const static double roundingTable[] = { 1.2, 1.6, 2, 2.4, 2.8, 3.2, 4, 6, 8 }; + SpeedWidget::SpeedWidget(QWidget *parent) : QGraphicsView(parent) { UpdateSpeedPlotSettings(); } -void SpeedWidget::AddPointData(QMap data) +void SpeedWidget::AddPointData(QMap data) { SpeedWidget::PointData point; point.x = QDateTime::currentMSecsSinceEpoch() / 1000; @@ -50,11 +53,11 @@ void SpeedWidget::AddPointData(QMap data) point.y[id] = data; } - m_datahalfMin.push_back(point); + dataCollection.push_back(point); - while (m_datahalfMin.length() > VIEWABLE) + while (dataCollection.length() > VIEWABLE) { - m_datahalfMin.removeFirst(); + dataCollection.removeFirst(); } replot(); } @@ -93,73 +96,66 @@ int friendlyUnitPrecision(const SizeUnit unit) default: return 3; } } - -namespace +struct SplittedValue { - // table of supposed nice steps for grid marks to get nice looking quarters - // of scale - const static double roundingTable[] = { 1.2, 1.6, 2, 2.4, 2.8, 3.2, 4, 6, 8 }; - struct SplittedValue + double arg; + SizeUnit unit; + qint64 sizeInBytes() const { - double arg; - SizeUnit unit; - qint64 sizeInBytes() const + auto size = arg; + for (int i = 0; i < static_cast(unit); ++i) { - auto size = arg; - for (int i = 0; i < static_cast(unit); ++i) - { - size *= 1024; - } - return size; + size *= 1024; } - }; + return size; + } +}; - SplittedValue getRoundedYScale(double value) +SplittedValue getRoundedYScale(double value) +{ + if (value == 0.0) + return { 0, SizeUnit::Byte }; + + if (value <= 12.0) + return { 12, SizeUnit::Byte }; + + auto calculatedUnit = SizeUnit::Byte; + + while (value > 1000) { - if (value == 0.0) - return { 0, SizeUnit::Byte }; - - if (value <= 12.0) - return { 12, SizeUnit::Byte }; - - auto calculatedUnit = SizeUnit::Byte; - - while (value > 1000) - { - value /= 1000; - calculatedUnit = static_cast(static_cast(calculatedUnit) + 1); - } - - if (value > 100.0) - { - int roundedValue = static_cast(value / 40) * 40; - while (roundedValue < value) roundedValue += 40; - return { static_cast(roundedValue), calculatedUnit }; - } - - if (value > 10.0) - { - int roundedValue = static_cast(value / 4) * 4; - while (roundedValue < value) roundedValue += 4; - return { static_cast(roundedValue), calculatedUnit }; - } - - for (const auto &roundedValue : roundingTable) - { - if (value <= roundedValue) - return { roundedValue, calculatedUnit }; - } - - return { 10.0, calculatedUnit }; + value /= 1000; + calculatedUnit = static_cast(static_cast(calculatedUnit) + 1); } - QString formatLabel(const double argValue, const SizeUnit unit) + if (value > 100.0) { - // check is there need for digits after decimal separator - const int precision = (argValue < 10) ? friendlyUnitPrecision(unit) : 0; - return QLocale::system().toString(argValue, 'f', precision) + " " + unitString(unit, true); + int roundedValue = static_cast(value / 40) * 40; + while (roundedValue < value) roundedValue += 40; + return { static_cast(roundedValue), calculatedUnit }; } -} // namespace + + if (value > 10.0) + { + int roundedValue = static_cast(value / 4) * 4; + while (roundedValue < value) roundedValue += 4; + return { static_cast(roundedValue), calculatedUnit }; + } + + for (const auto &roundedValue : roundingTable) + { + if (value <= roundedValue) + return { roundedValue, calculatedUnit }; + } + + return { 10.0, calculatedUnit }; +} + +QString formatLabel(const double argValue, const SizeUnit unit) +{ + // check is there need for digits after decimal separator + const int precision = (argValue < 10) ? friendlyUnitPrecision(unit) : 0; + return QLocale::system().toString(argValue, 'f', precision) + " " + unitString(unit, true); +} void SpeedWidget::UpdateSpeedPlotSettings() { @@ -168,9 +164,12 @@ void SpeedWidget::UpdateSpeedPlotSettings() if (!Graph.colorConfig.contains(x)) \ Graph.colorConfig[x] = y; - _X_(API_INBOUND, (QvPair{ { 134, 196, 63, 1.5f, Qt::SolidLine }, { 50, 153, 255, 1.5f, Qt::SolidLine } })); + const static QvPair defaultPen{ { 134, 196, 63, 1.5f, Qt::SolidLine }, { 50, 153, 255, 1.5f, Qt::SolidLine } }; + const static QvPair directPen{ { 0, 210, 240, 1.5f, Qt::DotLine }, { 235, 220, 42, 1.5f, Qt::DotLine } }; + + _X_(API_INBOUND, defaultPen); _X_(API_OUTBOUND_PROXY, Graph.colorConfig[API_INBOUND]); - _X_(API_OUTBOUND_DIRECT, (QvPair{ { 0, 210, 240, 1.5f, Qt::DotLine }, { 235, 220, 42, 1.5f, Qt::DotLine } })); + _X_(API_OUTBOUND_DIRECT, directPen); const auto getPen = [](const QvGraphPenConfig &conf) { QPen p{ { conf.R, conf.G, conf.B } }; @@ -200,7 +199,7 @@ void SpeedWidget::UpdateSpeedPlotSettings() void SpeedWidget::Clear() { - m_datahalfMin.clear(); + dataCollection.clear(); m_properties.clear(); UpdateSpeedPlotSettings(); replot(); @@ -215,9 +214,9 @@ quint64 SpeedWidget::maxYValue() quint64 maxYValue = 0; for (int id = 0; id < NB_GRAPHS; ++id) - for (int i = m_datahalfMin.size() - 1, j = 0; (i >= 0) && (j <= VIEWABLE); --i, ++j) - if (m_datahalfMin[i].y[id] > maxYValue) - maxYValue = m_datahalfMin[i].y[id]; + for (int i = dataCollection.size() - 1, j = 0; (i >= 0) && (j <= VIEWABLE); --i, ++j) + if (dataCollection[i].y[id] > maxYValue) + maxYValue = dataCollection[i].y[id]; return maxYValue; } @@ -288,10 +287,10 @@ void SpeedWidget::paintEvent(QPaintEvent *) { QVector points; - for (int i = static_cast(m_datahalfMin.size()) - 1, j = 0; (i >= 0) && (j <= VIEWABLE); --i, ++j) + for (int i = static_cast(dataCollection.size()) - 1, j = 0; (i >= 0) && (j <= VIEWABLE); --i, ++j) { const int newX = rect.right() - j * xTickSize; - const int newY = rect.bottom() - m_datahalfMin[i].y[id] * yMultiplier; + const int newY = rect.bottom() - dataCollection[i].y[id] * yMultiplier; points.push_back({ newX, newY }); } diff --git a/src/ui/common/speedchart/speedwidget.hpp b/src/ui/common/speedchart/speedwidget.hpp index 0eac6bc9..20d62cf3 100644 --- a/src/ui/common/speedchart/speedwidget.hpp +++ b/src/ui/common/speedchart/speedwidget.hpp @@ -35,7 +35,7 @@ class SpeedWidget : public QGraphicsView { Q_OBJECT public: - enum GraphID + enum GraphType { INBOUND_UP, INBOUND_DOWN, @@ -59,7 +59,7 @@ class SpeedWidget : public QGraphicsView explicit SpeedWidget(QWidget *parent = nullptr); void UpdateSpeedPlotSettings(); - void AddPointData(QMap data); + void AddPointData(QMap data); void Clear(); void replot(); @@ -76,7 +76,7 @@ class SpeedWidget : public QGraphicsView }; quint64 maxYValue(); - QList m_datahalfMin; + QList dataCollection; - QMap m_properties; + QMap m_properties; }; diff --git a/src/ui/widgets/models/ConnectionModelHelper.cpp b/src/ui/widgets/models/ConnectionModelHelper.cpp new file mode 100644 index 00000000..6176f407 --- /dev/null +++ b/src/ui/widgets/models/ConnectionModelHelper.cpp @@ -0,0 +1,163 @@ +#include "ConnectionModelHelper.hpp" + +#include "core/handler/ConfigHandler.hpp" +#include "ui/widgets/widgets/ConnectionItemWidget.hpp" + +#define NumericString(i) (QString("%1").arg(i, 30, 10, QLatin1Char('0'))) + +ConnectionListHelper::ConnectionListHelper(QTreeView *view, QObject *parent) : QObject(parent) +{ + parentView = view; + model = new QStandardItemModel(); + view->setModel(model); + for (const auto &group : ConnectionManager->AllGroups()) + { + addGroupItem(group); + for (const auto &connection : ConnectionManager->Connections(group)) + { + addConnectionItem({ connection, group }); + } + } + const auto renamedLambda = [&](const ConnectionId &id, const QString &, const QString &newName) { + for (const auto &gid : ConnectionManager->GetGroupId(id)) + { + ConnectionGroupPair pair{ id, gid }; + if (pairs.contains(pair)) + pairs[pair]->setData(newName, ROLE_DISPLAYNAME); + } + }; + + const auto latencyLambda = [&](const ConnectionId &id, const int avg) { + for (const auto &gid : ConnectionManager->GetGroupId(id)) + { + ConnectionGroupPair pair{ id, gid }; + if (pairs.contains(pair)) + pairs[pair]->setData(NumericString(avg), ROLE_LATENCY); + } + }; + + const auto statsLambda = [&](const ConnectionGroupPair &id, const QMap &data) { + if (connections.contains(id.connectionId)) + { + for (const auto &index : connections[id.connectionId]) + index->setData(NumericString(GetConnectionTotalData(id.connectionId)), ROLE_DATA_USAGE); + } + }; + + connect(ConnectionManager, &QvConfigHandler::OnConnectionRemovedFromGroup, this, &ConnectionListHelper::OnConnectionDeleted); + connect(ConnectionManager, &QvConfigHandler::OnConnectionCreated, this, &ConnectionListHelper::OnConnectionCreated); + connect(ConnectionManager, &QvConfigHandler::OnConnectionLinkedWithGroup, this, &ConnectionListHelper::OnConnectionLinkedWithGroup); + connect(ConnectionManager, &QvConfigHandler::OnGroupCreated, this, &ConnectionListHelper::OnGroupCreated); + connect(ConnectionManager, &QvConfigHandler::OnGroupDeleted, this, &ConnectionListHelper::OnGroupDeleted); + connect(ConnectionManager, &QvConfigHandler::OnConnectionRenamed, renamedLambda); + connect(ConnectionManager, &QvConfigHandler::OnLatencyTestFinished, latencyLambda); + connect(ConnectionManager, &QvConfigHandler::OnStatsAvailable, statsLambda); +} + +ConnectionListHelper::~ConnectionListHelper() +{ + delete model; +} + +void ConnectionListHelper::Sort(ConnectionInfoRole role, Qt::SortOrder order) +{ + model->setSortRole(role); + model->sort(0, order); +} + +void ConnectionListHelper::Filter(const QString &key) +{ + for (const auto &groupId : ConnectionManager->AllGroups()) + { + const auto groupItem = model->indexFromItem(groups[groupId]); + bool isTotallyHide = true; + for (const auto &connectionId : ConnectionManager->Connections(groupId)) + { + const auto connectionItem = model->indexFromItem(pairs[{ connectionId, groupId }]); + const auto willTotallyHide = static_cast(parentView->indexWidget(connectionItem))->NameMatched(key); + parentView->setRowHidden(connectionItem.row(), connectionItem.parent(), !willTotallyHide); + isTotallyHide &= willTotallyHide; + } + parentView->indexWidget(groupItem)->setHidden(isTotallyHide); + if (!isTotallyHide) + parentView->expand(groupItem); + } +} + +QStandardItem *ConnectionListHelper::addConnectionItem(const ConnectionGroupPair &id) +{ + // Create Standard Item + auto connectionItem = new QStandardItem(); + connectionItem->setData(GetDisplayName(id.connectionId), ConnectionInfoRole::ROLE_DISPLAYNAME); + connectionItem->setData(NumericString(GetConnectionLatency(id.connectionId)), ConnectionInfoRole::ROLE_LATENCY); + connectionItem->setData(NumericString(GetConnectionTotalData(id.connectionId)), ConnectionInfoRole::ROLE_DATA_USAGE); + // + // Find groups + const auto groupIndex = groups.contains(id.groupId) ? groups[id.groupId] : addGroupItem(id.groupId); + // Append into model + groupIndex->appendRow(connectionItem); + const auto connectionIndex = connectionItem->index(); + // + auto widget = new ConnectionItemWidget(id, parentView); + connect(widget, &ConnectionItemWidget::RequestWidgetFocus, [widget, connectionIndex, this]() { + parentView->setCurrentIndex(connectionIndex); + parentView->scrollTo(connectionIndex); + }); + // + parentView->setIndexWidget(connectionIndex, widget); + pairs[id] = connectionItem; + connections[id.connectionId].append(connectionItem); + return connectionItem; +} + +QStandardItem *ConnectionListHelper::addGroupItem(const GroupId &groupId) +{ + // Create Item + const auto item = new QStandardItem(); + // Set item into model + model->appendRow(item); + // Get item index + const auto index = item->index(); + parentView->setIndexWidget(index, new ConnectionItemWidget(groupId, parentView)); + groups[groupId] = item; + return item; +} + +void ConnectionListHelper::OnConnectionCreated(const ConnectionGroupPair &id, const QString &) +{ + addConnectionItem(id); +} + +void ConnectionListHelper::OnConnectionDeleted(const ConnectionGroupPair &id) +{ + auto item = pairs.take(id); + const auto index = model->indexFromItem(item); + if (!index.isValid()) + return; + model->removeRow(index.row(), index.parent()); + connections[id.connectionId].removeAll(item); +} + +void ConnectionListHelper::OnConnectionLinkedWithGroup(const ConnectionGroupPair &pairId) +{ + addConnectionItem(pairId); +} + +void ConnectionListHelper::OnGroupCreated(const GroupId &id, const QString &) +{ + addGroupItem(id); +} + +void ConnectionListHelper::OnGroupDeleted(const GroupId &id, const QList &connections) +{ + for (const auto &conn : connections) + { + const ConnectionGroupPair pair{ conn, id }; + OnConnectionDeleted(pair); + } + const auto item = groups.take(id); + const auto index = model->indexFromItem(item); + if (!index.isValid()) + return; + model->removeRow(index.row(), index.parent()); +} diff --git a/src/ui/widgets/models/ConnectionModelHelper.hpp b/src/ui/widgets/models/ConnectionModelHelper.hpp new file mode 100644 index 00000000..1e65e26d --- /dev/null +++ b/src/ui/widgets/models/ConnectionModelHelper.hpp @@ -0,0 +1,59 @@ +#pragma once +#include "base/Qv2rayBase.hpp" + +#include +#include +#include + +namespace Qv2ray::ui::widgets::models +{ + enum ConnectionInfoRole + { + // 10 -> Magic value. + ROLE_DISPLAYNAME = Qt::UserRole + 10, + ROLE_LATENCY, + ROLE_IMPORTTIME, + ROLE_LAST_CONNECTED_TIME, + ROLE_DATA_USAGE + }; + + class ConnectionListHelper : public QObject + { + Q_OBJECT + public: + ConnectionListHelper(QTreeView *parentView, QObject *parent = nullptr); + ~ConnectionListHelper(); + void Sort(ConnectionInfoRole, Qt::SortOrder); + void Filter(const QString &); + + inline QModelIndex GetConnectionPairIndex(const ConnectionGroupPair &id) const + { + return model->indexFromItem(pairs[id]); + } + + inline QModelIndex GetGroupIndex(const GroupId &id) const + { + return model->indexFromItem(groups[id]); + } + + private: + QStandardItem *addConnectionItem(const ConnectionGroupPair &id); + QStandardItem *addGroupItem(const GroupId &groupId); + void OnGroupCreated(const GroupId &id, const QString &displayName); + void OnGroupDeleted(const GroupId &id, const QList &connections); + void OnConnectionCreated(const ConnectionGroupPair &Id, const QString &displayName); + void OnConnectionDeleted(const ConnectionGroupPair &Id); + void OnConnectionLinkedWithGroup(const ConnectionGroupPair &id); + + private: + QTreeView *parentView; + QStandardItemModel *model; + // + QHash groups; + QHash pairs; + QHash> connections; + }; + +} // namespace Qv2ray::ui::widgets::models + +using namespace Qv2ray::ui::widgets::models; diff --git a/src/ui/widgets/windows/w_MainWindow.cpp b/src/ui/widgets/windows/w_MainWindow.cpp index 79083888..4ce1448d 100644 --- a/src/ui/widgets/windows/w_MainWindow.cpp +++ b/src/ui/widgets/windows/w_MainWindow.cpp @@ -20,12 +20,13 @@ #include #define TRAY_TOOLTIP_PREFIX "Qv2ray " QV2RAY_VERSION_STRING + #define CheckCurrentWidget \ - auto widget = GetItemWidget(connectionListWidget->currentItem()); \ + auto widget = GetIndexWidget(connectionTreeView->currentIndex()); \ if (widget == nullptr) \ return; -#define GetItemWidget(item) (qobject_cast(connectionListWidget->itemWidget(item, 0))) +#define GetIndexWidget(item) (qobject_cast(connectionTreeView->indexWidget(item))) #define NumericString(i) (QString("%1").arg(i, 30, 10, QLatin1Char('0'))) #define PLUGIN_BUTTON_PROPERTY_KEY "plugin_list_index" @@ -46,43 +47,9 @@ QvMessageBusSlotImpl(MainWindow) } } -void MainWindow::MWAddConnectionItem_p(const ConnectionGroupPair &id) +void MainWindow::SortConnectionList(ConnectionInfoRole byCol, bool asending) { - if (!groupNodes.contains(id.groupId)) - { - MWAddGroupItem_p(id.groupId); - } - auto groupItem = groupNodes.value(id.groupId); - auto connectionItem = std::make_shared(QStringList{ - "", // - GetDisplayName(id.connectionId), // - NumericString(GetConnectionLatency(id.connectionId)), // - "IMPORTTIME_NOT_SUPPORTED", // - "LAST_CONNECTED_NOT_SUPPORTED", // - NumericString(GetConnectionTotalData(id.connectionId)) // - }); - connectionNodes.insert(id, connectionItem); - groupItem->addChild(connectionItem.get()); - auto widget = new ConnectionItemWidget(id, connectionListWidget); - connect(widget, &ConnectionItemWidget::RequestWidgetFocus, this, &MainWindow::OnConnectionWidgetFocusRequested); - connectionListWidget->setItemWidget(connectionItem.get(), 0, widget); -} - -void MainWindow::MWAddGroupItem_p(const GroupId &groupId) -{ - auto groupItem = std::make_shared(QStringList{ "", GetDisplayName(groupId) }); - groupNodes.insert(groupId, groupItem); - connectionListWidget->addTopLevelItem(groupItem.get()); - connectionListWidget->setItemWidget(groupItem.get(), 0, new ConnectionItemWidget(groupId, connectionListWidget)); -} - -void MainWindow::SortConnectionList(MW_ITEM_COL byCol, bool asending) -{ - connectionListWidget->sortByColumn(MW_ITEM_COL_NAME, Qt::AscendingOrder); - for (auto i = 0; i < connectionListWidget->topLevelItemCount(); i++) - { - connectionListWidget->topLevelItem(i)->sortChildren(byCol, asending ? Qt::AscendingOrder : Qt::DescendingOrder); - } + modelHelper->Sort(byCol, asending ? Qt::AscendingOrder : Qt::DescendingOrder); on_locateBtn_clicked(); } @@ -108,8 +75,10 @@ void MainWindow::OnRecentConnectionsMenuReadyToShow() for (const auto &conn : GlobalConfig.uiConfig.recentConnections) { if (ConnectionManager->IsValidId(conn)) - tray_RecentConnectionsMenu->addAction(GetDisplayName(conn.connectionId) + " (" + GetDisplayName(conn.groupId) + ")", - [=]() { emit ConnectionManager->StartConnection(conn); }); + { + const auto name = GetDisplayName(conn.connectionId) + " (" + GetDisplayName(conn.groupId) + ")"; + tray_RecentConnectionsMenu->addAction(name, [=]() { emit ConnectionManager->StartConnection(conn); }); + } } } @@ -127,6 +96,8 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) speedChartWidget = new SpeedWidget(this); speedChart->addWidget(speedChartWidget); // + modelHelper = new ConnectionListHelper(connectionTreeView); + // this->setWindowIcon(QIcon(":/assets/icons/qv2ray.png")); updateColorScheme(); UpdateActionTranslations(); @@ -144,34 +115,10 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) connect(ConnectionManager, &QvConfigHandler::OnStatsAvailable, this, &MainWindow::OnStatsAvailable); connect(ConnectionManager, &QvConfigHandler::OnKernelLogAvailable, this, &MainWindow::OnVCoreLogAvailable); // - connect(ConnectionManager, &QvConfigHandler::OnConnectionRemovedFromGroup, this, &MainWindow::OnConnectionDeleted); - connect(ConnectionManager, &QvConfigHandler::OnConnectionCreated, this, &MainWindow::OnConnectionCreated); - connect(ConnectionManager, &QvConfigHandler::OnConnectionLinkedWithGroup, this, &MainWindow::OnConnectionLinkedWithGroup); - // - connect(ConnectionManager, &QvConfigHandler::OnGroupCreated, this, &MainWindow::OnGroupCreated); - connect(ConnectionManager, &QvConfigHandler::OnGroupDeleted, this, &MainWindow::OnGroupDeleted); - // connect(ConnectionManager, &QvConfigHandler::OnSubscriptionAsyncUpdateFinished, [](const GroupId &gid) { QvWidgetApplication->ShowTrayMessage(tr("Subscription \"%1\" has been updated").arg(GetDisplayName(gid))); // }); // - connect(ConnectionManager, &QvConfigHandler::OnConnectionRenamed, [this](const ConnectionId &id, const QString &, const QString &newName) { - for (const auto &gid : ConnectionManager->GetGroupId(id)) - { - ConnectionGroupPair pair{ id, gid }; - if (connectionNodes.contains(pair)) - connectionNodes.value(pair)->setText(MW_ITEM_COL_NAME, newName); - } - }); - connect(ConnectionManager, &QvConfigHandler::OnLatencyTestFinished, [this](const ConnectionId &id, const int avg) { - for (const auto &gid : ConnectionManager->GetGroupId(id)) - { - ConnectionGroupPair pair{ id, gid }; - if (connectionNodes.contains(pair)) - connectionNodes.value(pair)->setText(MW_ITEM_COL_PING, NumericString(avg)); // - } - }); - // connect(infoWidget, &ConnectionInfoWidget::OnEditRequested, this, &MainWindow::OnEditRequested); connect(infoWidget, &ConnectionInfoWidget::OnJsonEditRequested, this, &MainWindow::OnEditJsonRequested); // @@ -209,7 +156,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) // connect(tray_action_ToggleVisibility, &QAction::triggered, this, &MainWindow::MWToggleVisibility); connect(tray_action_Preferences, &QAction::triggered, this, &MainWindow::on_preferencesBtn_clicked); - connect(tray_action_Start, &QAction::triggered, [this] { ConnectionManager->StartConnection(lastConnectedIdentifier); }); + connect(tray_action_Start, &QAction::triggered, [this] { ConnectionManager->StartConnection(lastConnected); }); connect(tray_action_Stop, &QAction::triggered, ConnectionManager, &QvConfigHandler::StopConnection); connect(tray_action_Restart, &QAction::triggered, ConnectionManager, &QvConfigHandler::RestartConnection); connect(tray_action_Quit, &QAction::triggered, this, &MainWindow::Action_Exit); @@ -300,39 +247,38 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) sortMenu->addAction(sortAction_SortByPing_Asc); sortMenu->addAction(sortAction_SortByPing_Dsc); // - connect(sortAction_SortByName_Asc, &QAction::triggered, [this] { SortConnectionList(MW_ITEM_COL_NAME, true); }); - connect(sortAction_SortByName_Dsc, &QAction::triggered, [this] { SortConnectionList(MW_ITEM_COL_NAME, false); }); - connect(sortAction_SortByData_Asc, &QAction::triggered, [this] { SortConnectionList(MW_ITEM_COL_DATA, true); }); - connect(sortAction_SortByData_Dsc, &QAction::triggered, [this] { SortConnectionList(MW_ITEM_COL_DATA, false); }); - connect(sortAction_SortByPing_Asc, &QAction::triggered, [this] { SortConnectionList(MW_ITEM_COL_PING, true); }); - connect(sortAction_SortByPing_Dsc, &QAction::triggered, [this] { SortConnectionList(MW_ITEM_COL_PING, false); }); + connect(sortAction_SortByName_Asc, &QAction::triggered, [this] { SortConnectionList(ROLE_DISPLAYNAME, true); }); + connect(sortAction_SortByName_Dsc, &QAction::triggered, [this] { SortConnectionList(ROLE_DISPLAYNAME, false); }); + connect(sortAction_SortByData_Asc, &QAction::triggered, [this] { SortConnectionList(ROLE_DATA_USAGE, true); }); + connect(sortAction_SortByData_Dsc, &QAction::triggered, [this] { SortConnectionList(ROLE_DATA_USAGE, false); }); + connect(sortAction_SortByPing_Asc, &QAction::triggered, [this] { SortConnectionList(ROLE_LATENCY, true); }); + connect(sortAction_SortByPing_Dsc, &QAction::triggered, [this] { SortConnectionList(ROLE_LATENCY, false); }); // sortBtn->setMenu(sortMenu); // graphWidgetMenu->addAction(action_RCM_CopyGraph); connect(action_RCM_CopyGraph, &QAction::triggered, this, &MainWindow::Action_CopyGraphAsImage); // - LOG(MODULE_UI, "Loading data...") - for (const auto &group : ConnectionManager->AllGroups()) - { - MWAddGroupItem_p(group); - for (const auto &connection : ConnectionManager->Connections(group)) MWAddConnectionItem_p({ connection, group }); - } - // // Find and start if there is an auto-connection const auto connectionStarted = StartAutoConnectionEntry(); - if (!connectionStarted && connectionListWidget->topLevelItemCount() > 0) + + if (!connectionStarted && !ConnectionManager->Connections().isEmpty()) { - ReloadRecentConnectionList(); // Select the first connection. - const auto &topLevelItem = connectionListWidget->topLevelItem(0); - const auto &item = (topLevelItem->childCount() > 0) ? topLevelItem->child(0) : topLevelItem; - connectionListWidget->setCurrentItem(item); - on_connectionListWidget_itemClicked(item, 0); + const auto groups = ConnectionManager->AllGroups(); + if (!groups.isEmpty()) + { + const auto connections = ConnectionManager->Connections(groups.first()); + if (!connections.empty()) + { + const auto index = modelHelper->GetConnectionPairIndex({ connections.first(), groups.first() }); + on_connectionTreeView_clicked(index); + } + } } + ReloadRecentConnectionList(); // // - tray_action_ToggleVisibility->setText(!connectionStarted ? tr("Hide") : tr("Show")); if (!connectionStarted) MWShowWindow(); else @@ -423,7 +369,7 @@ void MainWindow::timerEvent(QTimerEvent *event) void MainWindow::keyPressEvent(QKeyEvent *e) { - if (focusWidget() == connectionListWidget) + if (focusWidget() == connectionTreeView) { CheckCurrentWidget; if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) @@ -435,7 +381,7 @@ void MainWindow::keyPressEvent(QKeyEvent *e) } else { - connectionListWidget->expandItem(connectionListWidget->currentItem()); + connectionTreeView->expand(connectionTreeView->currentIndex()); } } else if (e->key() == Qt::Key_F2) @@ -450,7 +396,7 @@ void MainWindow::keyPressEvent(QKeyEvent *e) if (e->key() == Qt::Key_Escape) { - auto widget = GetItemWidget(connectionListWidget->currentItem()); + auto widget = GetIndexWidget(connectionTreeView->currentIndex()); // Check if this key was accpted by the ConnectionItemWidget if (widget && widget->IsRenaming()) { @@ -481,10 +427,10 @@ void MainWindow::keyReleaseEvent(QKeyEvent *e) // Workaround of QtWidget not grabbing KeyDown and KeyUp in keyPressEvent if (e->key() == Qt::Key_Up || e->key() == Qt::Key_Down) { - if (focusWidget() == connectionListWidget) + if (focusWidget() == connectionTreeView) { CheckCurrentWidget; - on_connectionListWidget_itemClicked(connectionListWidget->currentItem(), 0); + on_connectionTreeView_clicked(connectionTreeView->currentIndex()); } } } @@ -500,6 +446,7 @@ void MainWindow::Action_Start() MainWindow::~MainWindow() { + delete modelHelper; for (auto &widget : pluginWidgets) widget->accept(); } @@ -534,14 +481,14 @@ void MainWindow::on_clearlogButton_clicked() { masterLogBrowser->document()->clear(); } -void MainWindow::on_connectionListWidget_customContextMenuRequested(const QPoint &pos) +void MainWindow::on_connectionTreeView_customContextMenuRequested(const QPoint &pos) { Q_UNUSED(pos) auto _pos = QCursor::pos(); - auto item = connectionListWidget->itemAt(connectionListWidget->mapFromGlobal(_pos)); - if (item != nullptr) + auto item = connectionTreeView->indexAt(connectionTreeView->mapFromGlobal(_pos)); + if (item.isValid()) { - bool isConnection = GetItemWidget(item)->IsConnection(); + bool isConnection = GetIndexWidget(item)->IsConnection(); // Disable connection-specific settings. action_RCM_Start->setEnabled(isConnection); action_RCM_SetAutoConnection->setEnabled(isConnection); @@ -551,7 +498,7 @@ void MainWindow::on_connectionListWidget_customContextMenuRequested(const QPoint action_RCM_RenameConnection->setEnabled(isConnection); action_RCM_DuplicateConnection->setEnabled(isConnection); action_RCM_UpdateSubscription->setEnabled(!isConnection); - action_RCM_RealLatencyTest->setEnabled(isConnection && ConnectionManager->IsConnected(GetItemWidget(item)->Identifier())); + action_RCM_RealLatencyTest->setEnabled(isConnection && ConnectionManager->IsConnected(GetIndexWidget(item)->Identifier())); connectionListRCM_Menu->popup(_pos); } } @@ -560,9 +507,9 @@ void MainWindow::Action_DeleteConnections() { QList connlist; - for (const auto &item : connectionListWidget->selectedItems()) + for (const auto &item : connectionTreeView->selectionModel()->selectedIndexes()) { - auto widget = GetItemWidget(item); + auto widget = GetIndexWidget(item); if (widget) { const auto identifier = widget->Identifier(); @@ -640,18 +587,6 @@ void MainWindow::on_subsButton_clicked() GroupManager().exec(); } -void MainWindow::on_connectionListWidget_itemDoubleClicked(QTreeWidgetItem *item, int column) -{ - Q_UNUSED(column) - auto widget = GetItemWidget(item); - if (widget == nullptr) - return; - if (widget->IsConnection()) - { - widget->BeginConnection(); - } -} - void MainWindow::OnDisconnected(const ConnectionGroupPair &id) { Q_UNUSED(id) @@ -660,7 +595,7 @@ void MainWindow::OnDisconnected(const ConnectionGroupPair &id) tray_action_Stop->setEnabled(false); tray_action_Restart->setEnabled(false); tray_SystemProxyMenu->setEnabled(false); - lastConnectedIdentifier = id; + lastConnected = id; locateBtn->setEnabled(false); if (!GlobalConfig.uiConfig.quietMode) { @@ -684,7 +619,7 @@ void MainWindow::OnConnected(const ConnectionGroupPair &id) tray_action_Stop->setEnabled(true); tray_action_Restart->setEnabled(true); tray_SystemProxyMenu->setEnabled(true); - lastConnectedIdentifier = id; + lastConnected = id; locateBtn->setEnabled(true); on_clearlogButton_clicked(); speedChartWidget->Clear(); @@ -710,68 +645,9 @@ void MainWindow::OnConnected(const ConnectionGroupPair &id) } } -void MainWindow::OnConnectionWidgetFocusRequested(const ConnectionItemWidget *_widget) -{ - if (_widget == nullptr) - { - return; - } - - for (auto _item_ : connectionListWidget->findItems(QString("*"), Qt::MatchWrap | Qt::MatchWildcard | Qt::MatchRecursive)) - { - if (GetItemWidget(_item_) == _widget) - { - LOG(MODULE_UI, "Setting current item.") - connectionListWidget->setCurrentItem(_item_); - connectionListWidget->scrollToItem(_item_); - // Click it to show details. - on_connectionListWidget_itemClicked(_item_, 0); - } - } -} - void MainWindow::on_connectionFilterTxt_textEdited(const QString &arg1) { - // No recursive since we only need top level item - for (auto _top_item_ : connectionListWidget->findItems(QString("*"), Qt::MatchWrap | Qt::MatchWildcard)) - { - // auto topWidget = GetItemWidget(_top_item_); - bool isTotallyHide = true; - - for (auto i = 0; i < _top_item_->childCount(); i++) - { - auto _child_ = _top_item_->child(i); - - if (GetItemWidget(_child_)->NameMatched(arg1)) - { - LOG(MODULE_UI, "Setting current item.") - // Show the child - _child_->setHidden(false); - // If any one of the children matches, the parent should not be hidden. - isTotallyHide = false; - } - else - { - _child_->setHidden(true); - } - } - - _top_item_->setHidden(isTotallyHide); - - if (!isTotallyHide) - { - connectionListWidget->expandItem(_top_item_); - } - } -} - -void MainWindow::on_connectionListWidget_itemClicked(QTreeWidgetItem *item, int column) -{ - Q_UNUSED(column) - auto widget = GetItemWidget(item); - if (widget == nullptr) - return; - infoWidget->ShowDetails(widget->Identifier()); + modelHelper->Filter(arg1); } void MainWindow::OnStatsAvailable(const ConnectionGroupPair &id, const QMap &data) @@ -781,13 +657,13 @@ void MainWindow::OnStatsAvailable(const ConnectionGroupPair &id, const QMap pointData; + QMap pointData; bool isOutbound = GlobalConfig.uiConfig.graphConfig.useOutboundStats; bool hasDirect = isOutbound && GlobalConfig.uiConfig.graphConfig.hasDirectStats; - for (const auto &type : data.keys()) + for (const auto &[type, data] : data.toStdMap()) { - const auto upSpeed = data[type].first.first; - const auto downSpeed = data[type].first.second; + const auto upSpeed = data.first.first; + const auto downSpeed = data.first.second; switch (type) { case API_INBOUND: @@ -829,12 +705,6 @@ void MainWindow::OnStatsAvailable(const ConnectionGroupPair &id, const QMapsetToolTip(TRAY_TOOLTIP_PREFIX NEWLINE + tr("Connected: ") + GetDisplayName(id.connectionId) + // NEWLINE "Up: " + totalSpeedUp + " Down: " + totalSpeedDown); - // - // Set data accordingly - if (connectionNodes.contains(id)) - { - connectionNodes.value(id)->setText(MW_ITEM_COL_DATA, NumericString(GetConnectionTotalData(id.connectionId))); - } } void MainWindow::OnVCoreLogAvailable(const ConnectionGroupPair &id, const QString &log) @@ -903,34 +773,6 @@ void MainWindow::OnEditJsonRequested(const ConnectionId &id) } } -void MainWindow::OnConnectionCreated(const ConnectionGroupPair &id, const QString &displayName) -{ - Q_UNUSED(displayName) - MWAddConnectionItem_p(id); -} -void MainWindow::OnConnectionDeleted(const ConnectionGroupPair &id) -{ - auto child = connectionNodes.take(id); - groupNodes.value(id.groupId)->removeChild(child.get()); -} -void MainWindow::OnConnectionLinkedWithGroup(const ConnectionGroupPair &pairId) -{ - MWAddConnectionItem_p(pairId); -} -void MainWindow::OnGroupCreated(const GroupId &id, const QString &displayName) -{ - Q_UNUSED(displayName) - MWAddGroupItem_p(id); -} -void MainWindow::OnGroupDeleted(const GroupId &id, const QList &connections) -{ - for (const auto &conn : connections) - { - groupNodes.value(id)->removeChild(connectionNodes.value({ conn, id }).get()); - } - groupNodes.remove(id); -} - void MainWindow::OnLogScrollbarValueChanged(int value) { if (masterLogBrowser->verticalScrollBar()->maximum() == value) @@ -944,9 +786,10 @@ void MainWindow::on_locateBtn_clicked() auto id = KernelInstance->CurrentConnection(); if (!id.isEmpty()) { - connectionListWidget->setCurrentItem(connectionNodes.value(id).get()); - connectionListWidget->scrollToItem(connectionNodes.value(id).get()); - on_connectionListWidget_itemClicked(connectionNodes.value(id).get(), 0); + const auto index = modelHelper->GetConnectionPairIndex(id); + connectionTreeView->setCurrentIndex(index); + connectionTreeView->scrollTo(index); + on_connectionTreeView_clicked(index); } } @@ -960,9 +803,9 @@ void MainWindow::Action_DuplicateConnection() { QList connlist; - for (const auto &item : connectionListWidget->selectedItems()) + for (const auto &item : connectionTreeView->selectionModel()->selectedIndexes()) { - auto widget = GetItemWidget(item); + auto widget = GetIndexWidget(item); if (widget->IsConnection()) { connlist.append(widget->Identifier()); @@ -1012,14 +855,14 @@ void MainWindow::on_clearChartBtn_clicked() speedChartWidget->Clear(); } -void MainWindow::on_connectionListWidget_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous) -{ - Q_UNUSED(previous) - if (current != nullptr && !isExiting) - { - on_connectionListWidget_itemClicked(current, 0); - } -} +// void MainWindow::on_connectionListWidget_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous) +//{ +// Q_UNUSED(previous) +// if (current != nullptr && !isExiting) +// { +// on_connectionListWidget_itemClicked(current, 0); +// } +//} void MainWindow::on_masterLogBrowser_textChanged() { @@ -1031,10 +874,10 @@ void MainWindow::on_masterLogBrowser_textChanged() void MainWindow::Action_SetAutoConnection() { - auto current = connectionListWidget->currentItem(); - if (current != nullptr) + auto current = connectionTreeView->currentIndex(); + if (current.isValid()) { - auto widget = GetItemWidget(current); + auto widget = GetIndexWidget(current); const auto identifier = widget->Identifier(); GlobalConfig.autoStartId = identifier; GlobalConfig.autoStartBehavior = AUTO_CONNECTION_FIXED; @@ -1048,10 +891,10 @@ void MainWindow::Action_SetAutoConnection() void MainWindow::Action_ResetStats() { - auto current = connectionListWidget->currentItem(); - if (current != nullptr) + auto current = connectionTreeView->currentIndex(); + if (current.isValid()) { - auto widget = GetItemWidget(current); + auto widget = GetIndexWidget(current); if (widget) { if (widget->IsConnection()) @@ -1064,10 +907,10 @@ void MainWindow::Action_ResetStats() void MainWindow::Action_UpdateSubscription() { - auto current = connectionListWidget->currentItem(); - if (current != nullptr) + auto current = connectionTreeView->currentIndex(); + if (current.isValid()) { - auto widget = GetItemWidget(current); + auto widget = GetIndexWidget(current); if (widget) { if (widget->IsConnection()) @@ -1083,11 +926,11 @@ void MainWindow::Action_UpdateSubscription() void MainWindow::Action_TestLatency() { - for (const auto ¤t : connectionListWidget->selectedItems()) + for (const auto ¤t : connectionTreeView->selectionModel()->selectedIndexes()) { - if (!current) + if (!current.isValid()) continue; - const auto widget = GetItemWidget(current); + const auto widget = GetIndexWidget(current); if (!widget) continue; if (widget->IsConnection()) @@ -1099,11 +942,11 @@ void MainWindow::Action_TestLatency() void MainWindow::Action_TestRealLatency() { - for (const auto ¤t : connectionListWidget->selectedItems()) + for (const auto ¤t : connectionTreeView->selectionModel()->selectedIndexes()) { - if (!current) + if (!current.isValid()) continue; - const auto widget = GetItemWidget(current); + const auto widget = GetIndexWidget(current); if (!widget) continue; if (widget->IsConnection()) @@ -1134,8 +977,8 @@ void MainWindow::on_newConnectionBtn_clicked() outboundsList.push_back(outboundEntry); CONFIGROOT root; root.insert("outbounds", outboundsList); - const auto item = connectionListWidget->currentItem(); - const auto id = item ? DefaultGroupId : GetItemWidget(item)->Identifier().groupId; + const auto item = connectionTreeView->currentIndex(); + const auto id = item.isValid() ? DefaultGroupId : GetIndexWidget(item)->Identifier().groupId; ConnectionManager->CreateConnection(root, alias, id); } } @@ -1147,15 +990,15 @@ void MainWindow::on_newComplexConnectionBtn_clicked() bool isChanged = w.result() == QDialog::Accepted; if (isChanged) { - const auto item = connectionListWidget->currentItem(); - const auto id = item ? DefaultGroupId : GetItemWidget(item)->Identifier().groupId; + const auto item = connectionTreeView->currentIndex(); + const auto id = item.isValid() ? DefaultGroupId : GetIndexWidget(item)->Identifier().groupId; ConnectionManager->CreateConnection(root, QJsonIO::GetValue(root, "outbounds", 0, "tag").toString(), id); } } void MainWindow::on_collapseGroupsBtn_clicked() { - connectionListWidget->collapseAll(); + connectionTreeView->collapseAll(); } void MainWindow::Action_CopyRecentLogs() @@ -1174,3 +1017,20 @@ void MainWindow::Action_CopyRecentLogs() } qApp->clipboard()->setText(result.join(NEWLINE)); } + +void MainWindow::on_connectionTreeView_doubleClicked(const QModelIndex &index) +{ + auto widget = GetIndexWidget(index); + if (widget == nullptr) + return; + if (widget->IsConnection()) + widget->BeginConnection(); +} + +void MainWindow::on_connectionTreeView_clicked(const QModelIndex &index) +{ + auto widget = GetIndexWidget(index); + if (widget == nullptr) + return; + infoWidget->ShowDetails(widget->Identifier()); +} diff --git a/src/ui/widgets/windows/w_MainWindow.hpp b/src/ui/widgets/windows/w_MainWindow.hpp index 22205910..322552af 100644 --- a/src/ui/widgets/windows/w_MainWindow.hpp +++ b/src/ui/widgets/windows/w_MainWindow.hpp @@ -3,6 +3,7 @@ #include "ui/common/QvMessageBus.hpp" #include "ui/common/speedchart/speedwidget.hpp" #include "ui/widgets/common/WidgetUIBase.hpp" +#include "ui/widgets/models/ConnectionModelHelper.hpp" #include "ui/widgets/widgets/ConnectionInfoWidget.hpp" #include "ui/widgets/widgets/ConnectionItemWidget.hpp" #include "ui_w_MainWindow.h" @@ -17,15 +18,6 @@ namespace Qv2rayPlugin class QvPluginMainWindowWidget; } -enum MW_ITEM_COL -{ - MW_ITEM_COL_NAME = 1, - MW_ITEM_COL_PING = 2, - MW_ITEM_COL_IMPORTTIME = 3, - MW_ITEM_COL_LASTCONNETED = 4, - MW_ITEM_COL_DATA = 5 -}; - class MainWindow : public QMainWindow , Ui::MainWindow @@ -47,25 +39,29 @@ class MainWindow void on_activatedTray(QSystemTrayIcon::ActivationReason reason); void on_preferencesBtn_clicked(); void on_clearlogButton_clicked(); - void on_connectionListWidget_customContextMenuRequested(const QPoint &pos); + void on_connectionTreeView_customContextMenuRequested(const QPoint &pos); void on_importConfigButton_clicked(); void on_subsButton_clicked(); // - void on_connectionListWidget_itemDoubleClicked(QTreeWidgetItem *item, int column); void on_connectionFilterTxt_textEdited(const QString &arg1); - void on_connectionListWidget_itemClicked(QTreeWidgetItem *item, int column); void on_locateBtn_clicked(); // void on_chartVisibilityBtn_clicked(); void on_logVisibilityBtn_clicked(); void on_clearChartBtn_clicked(); - void on_connectionListWidget_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous); void on_masterLogBrowser_textChanged(); // void on_pluginsBtn_clicked(); void on_collapseGroupsBtn_clicked(); void on_newConnectionBtn_clicked(); void on_newComplexConnectionBtn_clicked(); + // + // void on_connectionListWidget_itemDoubleClicked(QTreeWidgetItem *item, int column); + // void on_connectionListWidget_itemClicked(QTreeWidgetItem *item, int column); + // void on_connectionListWidget_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous); + + void on_connectionTreeView_doubleClicked(const QModelIndex &index); + void on_connectionTreeView_clicked(const QModelIndex &index); private: // Do not declare as slots, we connect them manually. @@ -86,8 +82,6 @@ class MainWindow void Action_CopyGraphAsImage(); void Action_CopyRecentLogs(); - void OnConnectionWidgetFocusRequested(const ConnectionItemWidget *widget); - private: void MWToggleVisibility(); void OnEditRequested(const ConnectionId &id); @@ -98,14 +92,7 @@ class MainWindow void OnStatsAvailable(const ConnectionGroupPair &id, const QMap &data); void OnVCoreLogAvailable(const ConnectionGroupPair &id, const QString &log); // - void OnConnectionCreated(const ConnectionGroupPair &Id, const QString &displayName); - void OnConnectionDeleted(const ConnectionGroupPair &Id); - void OnConnectionLinkedWithGroup(const ConnectionGroupPair &id); - // - void OnGroupCreated(const GroupId &id, const QString &displayName); - void OnGroupDeleted(const GroupId &id, const QList &connections); - // - void SortConnectionList(MW_ITEM_COL byCol, bool asending); + void SortConnectionList(ConnectionInfoRole byCol, bool asending); // void ReloadRecentConnectionList(); void OnRecentConnectionsMenuReadyToShow(); @@ -122,8 +109,6 @@ class MainWindow void closeEvent(QCloseEvent *) override; private: - QHash> groupNodes; - QHash> connectionNodes; // Charts SpeedWidget *speedChartWidget; SyntaxHighlighter *vCoreLogHighlighter; @@ -179,7 +164,7 @@ class MainWindow int qvLogTimerId = -1; bool qvLogAutoScoll = true; // - ConnectionGroupPair lastConnectedIdentifier; + ConnectionGroupPair lastConnected; void MWSetSystemProxy(); void MWClearSystemProxy(); void MWShowWindow(); @@ -189,8 +174,7 @@ class MainWindow // void updateColorScheme(); // - void MWAddConnectionItem_p(const ConnectionGroupPair &id); - void MWAddGroupItem_p(const GroupId &groupId); - // QList pluginWidgets; + // + Qv2ray::ui::widgets::models::ConnectionListHelper *modelHelper; }; diff --git a/src/ui/widgets/windows/w_MainWindow.ui b/src/ui/widgets/windows/w_MainWindow.ui index 33db3859..44bd380a 100644 --- a/src/ui/widgets/windows/w_MainWindow.ui +++ b/src/ui/widgets/windows/w_MainWindow.ui @@ -135,7 +135,7 @@ - + Qt::CustomContextMenu @@ -154,26 +154,12 @@ true - - true - true true - - true - - - false - - - - 1 - - @@ -568,7 +554,6 @@ - connectionListWidget importConfigButton