You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

181 lines
5.1 KiB

#include "mainwindow.h"
#include "channellist.h"
#include "messagelist.h"
#include "accountlist.h"
#include "invitedialog.h"
#include "invite_link.h"
#include "../db/db_manager.h"
#include "../transport/utun_node.h"
#include "../transport/node_config.h"
#include "../transport/chat_propagator.h"
#include <QSplitter>
#include <QCloseEvent>
#include <QApplication>
#include <QStyle>
#include <QMessageBox>
#include <QStandardPaths>
#include <QDir>
MainWindow::MainWindow(QWidget *parent, DbManager* db)
: QMainWindow(parent)
, m_channelList(nullptr)
, m_messageList(nullptr)
, m_accountList(nullptr)
, m_trayIcon(nullptr)
, m_trayMenu(nullptr)
, m_db(db)
{
setWindowTitle("Chat");
resize(900, 600);
setupUi();
setupTray();
if (m_db && m_db->isOpen()) {
setupNode();
setupMessaging();
connect(m_channelList, &ChannelList::channelSelected,
this, [this](const QString& channelId) {
m_db->setUiState("last_channel_id", channelId);
m_messageList->loadChannel(channelId);
});
connect(m_channelList, &ChannelList::inviteRequested,
this, &MainWindow::showInviteDialog);
m_channelList->loadChannels();
m_accountList->loadAccounts();
QString lastCid = m_db->getUiState("last_channel_id");
if (!lastCid.isEmpty())
m_channelList->selectChannel(lastCid);
}
}
MainWindow::~MainWindow() {
if (m_node) { m_node->stop(); delete m_node; m_node = nullptr; }
delete m_config;
}
void MainWindow::setupUi() {
auto *splitter = new QSplitter(Qt::Horizontal, this);
m_channelList = new ChannelList(m_db, splitter);
m_messageList = new MessageList(m_db, splitter);
m_accountList = new AccountList(m_db, splitter);
splitter->addWidget(m_channelList);
splitter->addWidget(m_messageList);
splitter->addWidget(m_accountList);
splitter->setStretchFactor(0, 2);
splitter->setStretchFactor(1, 5);
splitter->setStretchFactor(2, 1);
splitter->setSizes({220, 480, 180});
setCentralWidget(splitter);
}
void MainWindow::setupNode() {
QString configDir = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
QDir().mkpath(configDir);
QString configPath = configDir + "/node.conf";
m_config = new NodeConfig(configPath);
if (!m_config->exists()) {
if (!m_config->create("chatgui", 1333)) {
qWarning("Failed to create node config");
return;
}
} else {
m_config->load();
}
m_node = new UtunNode(this);
connect(m_node, &UtunNode::error, this, [](const QString& msg) {
qWarning("UtunNode error: %s", qPrintable(msg));
});
connect(m_node, &UtunNode::started, this, []() {
qDebug("UtunNode started");
});
connect(m_node, &UtunNode::stopped, this, []() {
qDebug("UtunNode stopped");
});
if (!m_node->start(configPath))
qWarning("Failed to start UtunNode");
}
void MainWindow::setupMessaging() {
if (!m_node || !m_node->isRunning()) return;
m_propagator = new ChatPropagator(m_node, m_db, this);
m_messageList->setPropagator(m_propagator);
connect(m_propagator, &ChatPropagator::messageReceived,
m_messageList, &MessageList::addMessage);
}
void MainWindow::setupTray() {
m_trayIcon = new QSystemTrayIcon(this);
m_trayIcon->setIcon(style()->standardIcon(QStyle::SP_ComputerIcon));
m_trayIcon->setToolTip("Chat");
m_trayMenu = new QMenu(this);
QAction *showAction = m_trayMenu->addAction("Show");
connect(showAction, &QAction::triggered, this, [this]() {
show();
raise();
activateWindow();
});
QAction *quitAction = m_trayMenu->addAction("Quit");
connect(quitAction, &QAction::triggered, qApp, &QApplication::quit);
m_trayIcon->setContextMenu(m_trayMenu);
connect(m_trayIcon, &QSystemTrayIcon::activated,
this, &MainWindow::onTrayActivated);
m_trayIcon->show();
}
void MainWindow::closeEvent(QCloseEvent *event) {
hide();
m_trayIcon->showMessage("Chat", "Application minimized to tray.",
QSystemTrayIcon::Information, 2000);
event->ignore();
}
void MainWindow::onTrayActivated(QSystemTrayIcon::ActivationReason reason) {
if (reason == QSystemTrayIcon::Trigger ||
reason == QSystemTrayIcon::DoubleClick) {
show();
raise();
activateWindow();
}
}
void MainWindow::showInviteDialog(const QString& channelId) {
if (!m_db || !m_db->isOpen()) return;
QByteArray pubkey;
if (m_config && !m_config->pubKey().isEmpty())
pubkey = QByteArray::fromHex(m_config->pubKey().toLatin1());
if (pubkey.size() != 32) {
QMessageBox::warning(this, "Error", "Failed to get node public key.");
return;
}
QList<NodeAddr> addrs = m_db->getOnlinePeerAddresses(m_db->myNodeId());
QString link = encodeInviteLink(channelId, pubkey, addrs);
if (link.isEmpty()) {
QMessageBox::warning(this, "Error", "Failed to create invite link.");
return;
}
InviteDialog dlg(link, this);
dlg.exec();
}