From 4607a23fa206c101497068c13b4ad357f09350e1 Mon Sep 17 00:00:00 2001 From: talksik Date: Sat, 7 Feb 2026 09:27:36 -0800 Subject: [PATCH] refactor: decouple network detail widget from business logic --- src/MainWindow.cpp | 54 ++++++++++++++++++++------- src/MainWindow.h | 2 +- src/networkdetailwidget.cpp | 74 +++++++++++++------------------------ src/networkdetailwidget.h | 17 +++++---- 4 files changed, 76 insertions(+), 71 deletions(-) diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index b11e75a..9e40f7b 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -108,7 +108,6 @@ MainWindow::MainWindow(QWidget *parent) m_splitter->setStretchFactor(0, 1); m_splitter->setStretchFactor(1, 4); m_splitter->setStretchFactor(2, 1); - m_splitter->setStretchFactor(3, 5); setupModels(); @@ -124,7 +123,6 @@ MainWindow::MainWindow(QWidget *parent) connect(m_authManager, &AuthManager::signedOut, m_authDialog, &AuthDialog::show); connect(m_authManager, &AuthManager::signedIn, this, [this]() { m_store->setCurrentUserEmail(m_authManager->sessionData()->email); - m_networkDetailWidget->setCurrentUserEmail(m_authManager->sessionData()->email); m_store->loadStartupData(); }); connect(m_store, &Store::startupDataLoaded, this, [this]() { @@ -158,9 +156,9 @@ MainWindow::MainWindow(QWidget *parent) // "New stream" button m_createStreamDialog = new CreateStreamDialog(this); connect(m_newStreamButton, &QPushButton::clicked, this, [this]() { - if (m_selectedNetworkName.isEmpty()) + if (m_selectedNetworkId.isEmpty()) return; - const Network *network = m_store->networkById(m_selectedNetworkName); + const Network *network = m_store->networkById(m_selectedNetworkId); if (network) m_createStreamDialog->setNetworkMembers(network->members); m_createStreamDialog->show(); @@ -169,14 +167,14 @@ MainWindow::MainWindow(QWidget *parent) }); connect(m_createStreamDialog, &CreateStreamDialog::streamRequested, this, [this](const QString &name, const QString &visibility, const QStringList &members) { - m_store->createStream(m_selectedNetworkName, name, "", visibility, members); + m_store->createStream(m_selectedNetworkId, name, "", visibility, members); }); // "Add members" toolbar button (ListAdd icon in right sidebar) connect(m_addMembersButton, &QToolButton::clicked, this, [this]() { - if (m_selectedStreamId.isEmpty() || m_selectedNetworkName.isEmpty()) + if (m_selectedStreamId.isEmpty() || m_selectedNetworkId.isEmpty()) return; - const Network *network = m_store->networkById(m_selectedNetworkName); + const Network *network = m_store->networkById(m_selectedNetworkId); const Stream *stream = m_store->streamById(m_selectedStreamId); if (!network || !stream) return; @@ -446,10 +444,32 @@ void MainWindow::setupModels() // Create store (data loaded after sign-in via loadStartupData) m_store = new Store(this); - m_networkDetailWidget = new NetworkDetailWidget(m_store); + m_networkDetailWidget = new NetworkDetailWidget(this); m_splitter->addWidget(m_networkDetailWidget); + m_splitter->setStretchFactor(3, 4); m_networkDetailWidget->hide(); + // Push fresh data when networks change + connect(m_store, &Store::networksChanged, this, [this]() { + if (!m_selectedNetworkId.isEmpty() && m_networkDetailWidget->isVisible()) + { + const Network *network = m_store->networkById(m_selectedNetworkId); + if (network) + m_networkDetailWidget->setNetwork(*network, m_authManager->sessionData() ? m_authManager->sessionData()->email : QString()); + else + m_networkDetailWidget->clear(); + } + }); + + // Handle add-member requests from the widget + connect(m_networkDetailWidget, &NetworkDetailWidget::addMemberRequested, this, + [this](const QString &networkId, const QString &email) { + auto *op = m_store->addNetworkMembers(networkId, {email}); + connect(op, &Operation::success, this, [this, networkId](const QJsonDocument &) { + m_store->fetchNetwork(networkId); + }); + }); + // Create and set tree model m_networkStreamModel = new NetworkStreamModel(m_store, this); m_treeView->setModel(m_networkStreamModel); @@ -514,7 +534,7 @@ void MainWindow::onTreeSelectionChanged(const QItemSelection &selected, const QI // Also track the parent network QModelIndex parentIndex = m_networkStreamModel->parent(index); QString networkId = m_networkStreamModel->networkIdFromIndex(parentIndex); - m_selectedNetworkName = networkId; + m_selectedNetworkId = networkId; // Show stream members m_membersList->clear(); @@ -548,10 +568,18 @@ void MainWindow::onTreeSelectionChanged(const QItemSelection &selected, const QI m_membersList->clear(); QString networkId = m_networkStreamModel->networkIdFromIndex(index); - m_selectedNetworkName = networkId; + m_selectedNetworkId = networkId; // Show network detail widget - m_networkDetailWidget->setNetwork(networkId); + const Network *network = m_store->networkById(networkId); + if (network) + { + m_networkDetailWidget->setNetwork(*network, m_authManager->sessionData() ? m_authManager->sessionData()->email : QString()); + } + else + { + m_networkDetailWidget->clear(); + } m_contentView->hide(); m_rightSidebar->hide(); m_networkDetailWidget->show(); @@ -622,9 +650,9 @@ void MainWindow::updateStatusBar() QStringList pathComponents; // Add network if selected - if (!m_selectedNetworkName.isEmpty()) + if (!m_selectedNetworkId.isEmpty()) { - const Network *network = m_store->networkById(m_selectedNetworkName); + const Network *network = m_store->networkById(m_selectedNetworkId); if (network) { pathComponents << network->name; diff --git a/src/MainWindow.h b/src/MainWindow.h index 32e4d01..5467477 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -99,7 +99,7 @@ private: void showTextInputDialog(); void updateStatusBar(); QString m_selectedParticleId; - QString m_selectedNetworkName; + QString m_selectedNetworkId; QString m_selectedStreamId; int m_selectedParticleRow; QLabel *m_currentPathLabel; diff --git a/src/networkdetailwidget.cpp b/src/networkdetailwidget.cpp index cf27178..8876f72 100644 --- a/src/networkdetailwidget.cpp +++ b/src/networkdetailwidget.cpp @@ -1,5 +1,4 @@ #include "networkdetailwidget.h" -#include "store.h" #include #include #include @@ -8,8 +7,8 @@ #include #include -NetworkDetailWidget::NetworkDetailWidget(Store *store, QWidget *parent) - : QWidget(parent), m_store(store) +NetworkDetailWidget::NetworkDetailWidget(QWidget *parent) + : QWidget(parent) { auto *layout = new QVBoxLayout(this); layout->setContentsMargins(16, 16, 16, 16); @@ -54,7 +53,6 @@ NetworkDetailWidget::NetworkDetailWidget(Store *store, QWidget *parent) buttonRow->addStretch(); layout->addLayout(buttonRow); - // Admin actions connect(m_addMemberBtn, &QPushButton::clicked, this, [this]() { bool ok; QString email = QInputDialog::getText(this, "Add Member", @@ -62,64 +60,42 @@ NetworkDetailWidget::NetworkDetailWidget(Store *store, QWidget *parent) QString(), &ok); if (ok && !email.isEmpty()) { - auto *op = m_store->addNetworkMembers(m_networkId, {email}); - connect(op, &Operation::success, this, [this](const QJsonDocument &) { - m_store->fetchNetwork(m_networkId); - }); + emit addMemberRequested(m_networkId, email); } }); - - // Refresh when networks change - connect(m_store, &Store::networksChanged, this, [this]() { - if (!m_networkId.isEmpty()) - refresh(); - }); } -void NetworkDetailWidget::setNetwork(const QString &networkId) +void NetworkDetailWidget::setNetwork(const Network &network, const QString ¤tUserEmail) { - m_networkId = networkId; - refresh(); -} + m_networkId = network.id; -void NetworkDetailWidget::setCurrentUserEmail(const QString &email) -{ - m_currentUserEmail = email; - if (!m_networkId.isEmpty()) - refresh(); -} + m_nameLabel->setText(network.name); + m_adminLabel->setText("Admin: " + network.admin.emailPrefix); -void NetworkDetailWidget::refresh() -{ - const Network *network = m_store->networkById(m_networkId); - if (!network) - { - m_nameLabel->setText(""); - m_adminLabel->setText(""); - m_streamBar->setValue(0); - m_streamBarLabel->setText(""); - m_membersList->clear(); - m_addMemberBtn->hide(); - return; - } - - m_nameLabel->setText(network->name); - m_adminLabel->setText("Admin: " + network->admin.emailPrefix); - - m_streamBar->setMaximum(network->openStreamCapacity > 0 ? network->openStreamCapacity : 1); - m_streamBar->setValue(network->openStreamCount); + m_streamBar->setMaximum(network.openStreamCapacity > 0 ? network.openStreamCapacity : 1); + m_streamBar->setValue(network.openStreamCount); m_streamBarLabel->setText(QString("%1 / %2 open streams") - .arg(network->openStreamCount) - .arg(network->openStreamCapacity)); + .arg(network.openStreamCount) + .arg(network.openStreamCapacity)); m_membersList->clear(); - for (const auto &member : network->members) + for (const auto &member : network.members) { m_membersList->addItem(member.email); } - // Show admin controls only if current user is admin - bool isAdmin = (!m_currentUserEmail.isEmpty() && - m_currentUserEmail == network->admin.email); + bool isAdmin = (!currentUserEmail.isEmpty() && + currentUserEmail == network.admin.email); m_addMemberBtn->setVisible(isAdmin); } + +void NetworkDetailWidget::clear() +{ + m_networkId.clear(); + m_nameLabel->setText(""); + m_adminLabel->setText(""); + m_streamBar->setValue(0); + m_streamBarLabel->setText(""); + m_membersList->clear(); + m_addMemberBtn->hide(); +} diff --git a/src/networkdetailwidget.h b/src/networkdetailwidget.h index 3c1fd20..c282d4b 100644 --- a/src/networkdetailwidget.h +++ b/src/networkdetailwidget.h @@ -1,30 +1,31 @@ #ifndef NETWORKDETAILWIDGET_H #define NETWORKDETAILWIDGET_H +#include "models.h" #include -class Store; +QT_BEGIN_NAMESPACE class QLabel; class QProgressBar; class QListWidget; class QPushButton; +QT_END_NAMESPACE class NetworkDetailWidget : public QWidget { Q_OBJECT public: - explicit NetworkDetailWidget(Store *store, QWidget *parent = nullptr); + explicit NetworkDetailWidget(QWidget *parent = nullptr); - void setNetwork(const QString &networkId); - void setCurrentUserEmail(const QString &email); + void setNetwork(const Network &network, const QString ¤tUserEmail); + void clear(); + +signals: + void addMemberRequested(const QString &networkId, const QString &email); private: - void refresh(); - - Store *m_store; QString m_networkId; - QString m_currentUserEmail; QLabel *m_nameLabel; QLabel *m_adminLabel;