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