Browse Source

chatgui: add SIGINT/SIGTERM handler (as in utun.c), save scroll pos on every debounce

Signal handler via g_shutdown + uasync_wakeup ensures clean uasync poll exit.
updateReadPosition() now saves both lastReadMsgId and lastPosMsgId on every
scroll stop (300ms debounce), not just when read position changes.
connect(stopped, quit) triggers graceful Qt shutdown after uasync cleanup.
topo_upd
Evgeny 2 months ago
parent
commit
6cafff200b
  1. 8
      tools/chatgui/src/mainwindow.cpp
  2. 19
      tools/chatgui/src/messagelist.cpp
  3. 20
      tools/chatgui/transport/utun_node.cpp

8
tools/chatgui/src/mainwindow.cpp

@ -84,6 +84,8 @@ MainWindow::MainWindow(QWidget *parent, DbManager* db, const QString& cfgPath,
} }
MainWindow::~MainWindow() { MainWindow::~MainWindow() {
DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "MainWindow: ~MainWindow — saving channel state");
if (m_messageList) m_messageList->saveChannelState();
DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "MainWindow: ~MainWindow — stopping utun node"); DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "MainWindow: ~MainWindow — stopping utun node");
if (m_node) { m_node->stop(); delete m_node; m_node = nullptr; } if (m_node) { m_node->stop(); delete m_node; m_node = nullptr; }
DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "MainWindow: ~MainWindow done"); DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "MainWindow: ~MainWindow done");
@ -120,6 +122,7 @@ void MainWindow::setupNode() {
connect(m_node, &UtunNode::stopped, this, []() { connect(m_node, &UtunNode::stopped, this, []() {
qDebug("UtunNode stopped"); qDebug("UtunNode stopped");
}); });
connect(m_node, &UtunNode::stopped, qApp, &QApplication::quit);
if (!m_cfgDebugFile.isEmpty()) if (!m_cfgDebugFile.isEmpty())
m_node->setDebugFile(m_cfgDebugFile); m_node->setDebugFile(m_cfgDebugFile);
@ -230,11 +233,6 @@ void MainWindow::setupConnects() {
m_channelList->setChannelUnreadCount(channelId, m_channelList->setChannelUnreadCount(channelId,
m_db->getUnreadCount(channelId, lastReadMsgId)); m_db->getUnreadCount(channelId, lastReadMsgId));
}); });
connect(qApp, &QApplication::aboutToQuit, this, [this]() {
DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "MainWindow: aboutToQuit — saving channel state");
if (m_messageList) m_messageList->saveChannelState();
});
} }
void MainWindow::setupTray() { void MainWindow::setupTray() {

19
tools/chatgui/src/messagelist.cpp

@ -352,19 +352,28 @@ void MessageList::updateReadPosition() {
newReadMsgId = msgId; newReadMsgId = msgId;
} }
QModelIndex topIdx = m_view->indexAt(QPoint(0, 0));
qint64 lastPosMsgId = topIdx.isValid() ? topIdx.data(MsgIdRole).toLongLong() : 0;
DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG,
"MessageList::updateReadPosition ch=%s oldRead=%lld newRead=%lld lastVisRow=%d/%d", "MessageList::updateReadPosition ch=%s oldRead=%lld newRead=%lld pos=%lld lastVisRow=%d/%d",
qPrintable(m_currentChannelId), (long long)m_lastReadMsgId, qPrintable(m_currentChannelId), (long long)m_lastReadMsgId,
(long long)newReadMsgId, lastFullyVisibleRow, m_model->rowCount()); (long long)newReadMsgId, (long long)lastPosMsgId,
lastFullyVisibleRow, m_model->rowCount());
QByteArray cid = m_currentChannelId.toUtf8();
if (newReadMsgId > m_lastReadMsgId) { if (newReadMsgId > m_lastReadMsgId) {
m_lastReadMsgId = newReadMsgId; m_lastReadMsgId = newReadMsgId;
QByteArray cid = m_currentChannelId.toUtf8();
QByteArray key = "ch_" + cid + "_last_read"; QByteArray key = "ch_" + cid + "_last_read";
QByteArray valStr = QByteArray::number(m_lastReadMsgId); QByteArray valStr = QByteArray::number(m_lastReadMsgId);
chat_core_save_ui_state(key.constData(), valStr.constData()); chat_core_save_ui_state(key.constData(), valStr.constData());
emit readPositionChanged(m_currentChannelId, m_lastReadMsgId); emit readPositionChanged(m_currentChannelId, m_lastReadMsgId);
} }
if (lastPosMsgId > 0) {
QByteArray posKey = "ch_" + cid + "_last_pos";
QByteArray posVal = QByteArray::number(lastPosMsgId);
chat_core_save_ui_state(posKey.constData(), posVal.constData());
}
} }

20
tools/chatgui/transport/utun_node.cpp

@ -2,6 +2,7 @@
#include "utun_node.h" #include "utun_node.h"
#include <cinttypes> #include <cinttypes>
#include <QDir> #include <QDir>
#include <csignal>
#include "../../lib/socket_compat.h" #include "../../lib/socket_compat.h"
#include "../db/db_manager.h" #include "../db/db_manager.h"
@ -34,6 +35,15 @@ extern "C" {
static thread_local UtunNode* g_currentNode = nullptr; static thread_local UtunNode* g_currentNode = nullptr;
static volatile sig_atomic_t g_shutdown = 0;
static struct UASYNC* g_signal_ua = nullptr;
static void signal_handler(int sig) {
(void)sig;
g_shutdown = 1;
if (g_signal_ua) uasync_wakeup(g_signal_ua);
}
UtunNode::UtunNode(QObject* parent) : QObject(parent) {} UtunNode::UtunNode(QObject* parent) : QObject(parent) {}
UtunNode::~UtunNode() { UtunNode::~UtunNode() {
@ -321,10 +331,18 @@ void UtunNode::runLoop() {
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "chat_core + chat_sync initialized"); DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "chat_core + chat_sync initialized");
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "utun_node: entering poll loop"); DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "utun_node: entering poll loop");
while (!m_stop) { g_signal_ua = ua;
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
while (!m_stop && !g_shutdown) {
uasync_poll(ua, 100); uasync_poll(ua, 100);
} }
signal(SIGINT, SIG_DFL);
signal(SIGTERM, SIG_DFL);
g_signal_ua = nullptr;
etcp_router_bind(m_instance, ETCP_RT_ID_CHAT, nullptr); etcp_router_bind(m_instance, ETCP_RT_ID_CHAT, nullptr);
chat_sync_destroy(m_instance); chat_sync_destroy(m_instance);
chat_core_destroy(m_instance); chat_core_destroy(m_instance);

Loading…
Cancel
Save