// // Created by arjun-flowylabs on 1/10/2026. // #include "MainWindow.h" #include "authdialog.h" #include "authmanager.h" #include "settingsdialog.h" #include "ui_mainwindow.h" #include #include #include #include #include #include #include MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), m_trayIcon(nullptr), m_authManager(new AuthManager(this)), m_settingsDialog(nullptr), m_authDialog(nullptr), m_data(nullptr), m_networkStreamModel(nullptr), m_particleListModel(nullptr) { m_authDialog = new AuthDialog(m_authManager, this); ui = new Ui::MainWindow; ui->setupUi(this); // this->setWindowFlags(Qt::FramelessWindowHint); ui->splitter->setStretchFactor(0, 1); ui->splitter->setStretchFactor(1, 1); ui->splitter->setStretchFactor(2, 2); setupModels(); m_authDialog->setModal(true); QTimer::singleShot(3000, this, [this]() { if (!m_authManager->isSignedIn()) { m_authDialog->reset(); m_authDialog->show(); } }); // Connect signal so dialog hides if valid session found, shows and resets on sign out connect(m_authManager, &AuthManager::isSignedInChanged, this, [this]() { if (m_authManager->isSignedIn()) { m_authDialog->hide(); } else { m_authDialog->reset(); m_authDialog->show(); } }); // Check for cached session (async) m_authManager->init(); setupTrayIcon(); } void MainWindow::setupTrayIcon() { m_trayIcon = new QSystemTrayIcon(this); m_trayIcon->setIcon(QIcon(":/assets/logo.png")); m_trayIcon->setToolTip("llink"); QMenu *trayMenu = new QMenu(this); trayMenu->addAction("Show", this, &MainWindow::show); trayMenu->addAction("Quit", qApp, &QApplication::quit); m_trayIcon->setContextMenu(trayMenu); connect(m_trayIcon, &QSystemTrayIcon::activated, this, [this](QSystemTrayIcon::ActivationReason reason) { if (reason == QSystemTrayIcon::Trigger) { isVisible() ? hide() : show(); } }); m_trayIcon->show(); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_exitButton_clicked() { qApp->exit(0); } void MainWindow::on_settingsButton_clicked() { if (!m_settingsDialog) { m_settingsDialog = new SettingsDialog(m_authManager, this); } m_settingsDialog->show(); } void MainWindow::setupModels() { // Create data with fake data m_data = new Data(this); // Create and set tree model m_networkStreamModel = new NetworkStreamModel(m_data, this); ui->topLevelParticlesView->setModel(m_networkStreamModel); ui->topLevelParticlesView->setHeaderHidden(true); ui->topLevelParticlesView->expandAll(); // Configure column behavior: name stretches, unseen count is fixed width ui->topLevelParticlesView->header()->setStretchLastSection(false); ui->topLevelParticlesView->header()->setSectionResizeMode(0, QHeaderView::Stretch); ui->topLevelParticlesView->header()->setSectionResizeMode(1, QHeaderView::Fixed); ui->topLevelParticlesView->setColumnWidth(1, 40); // Create and set list model m_particleListModel = new ParticleListModel(m_data, this); ui->particlesView->setModel(m_particleListModel); // Configure particle list view to use ellipses for long text ui->particlesView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); ui->particlesView->setTextElideMode(Qt::ElideRight); // Connect selection changes connect(ui->topLevelParticlesView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &MainWindow::onTreeSelectionChanged); // Connect particle selection changes connect(ui->particlesView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &MainWindow::onParticleSelectionChanged); } void MainWindow::onTreeSelectionChanged( const QItemSelection &selected, const QItemSelection &deselected) { Q_UNUSED(deselected); if (selected.indexes().isEmpty()) { m_particleListModel->setStreamId(QString()); return; } QModelIndex index = selected.indexes().first(); if (m_networkStreamModel->isStreamItem(index)) { QString streamId = m_networkStreamModel->streamIdFromIndex(index); m_particleListModel->setStreamId(streamId); // Auto-select first unseen particle (or first particle if all seen) int unseenRow = m_particleListModel->firstUnseenRow(); if (unseenRow >= 0) { ui->particlesView->setCurrentIndex(m_particleListModel->index(unseenRow, 0)); ui->particlesView->setFocus(); } else if (m_particleListModel->rowCount() > 0) { ui->particlesView->setCurrentIndex(m_particleListModel->index(0, 0)); ui->particlesView->setFocus(); } } else // network selected { m_particleListModel->setStreamId(QString()); } } void MainWindow::onParticleSelectionChanged( const QItemSelection &selected, const QItemSelection &deselected) { Q_UNUSED(deselected); if (selected.indexes().isEmpty()) { ui->label->setText(""); return; } QModelIndex index = selected.indexes().first(); const Particle *particle = m_particleListModel->particleAtRow(index.row()); if (particle) { ui->label->setText(particle->summary); } }