diff --git a/tools/chatgui/src/channellist.cpp b/tools/chatgui/src/channellist.cpp index 464ac42b..1ceca021 100644 --- a/tools/chatgui/src/channellist.cpp +++ b/tools/chatgui/src/channellist.cpp @@ -453,6 +453,9 @@ void ChannelList::selectChannel(const QString& channelId) { } void ChannelList::setChannelPeersOnline(const QString& channelId, int count) { + if (count < 0) { + DEBUG_WARN(DEBUG_CATEGORY_CHAT, "ChannelList: invalid online count=%d channel=%s", count, qPrintable(channelId)); return; + } int found = 0; for (int row = 0; row < m_model->rowCount(); row++) { QStandardItem* item = m_model->item(row); @@ -480,6 +483,9 @@ void ChannelList::setAutoConnectActive(bool active) { } void ChannelList::setChannelUnreadCount(const QString& channelId, int count) { + if (count < 0) { + DEBUG_WARN(DEBUG_CATEGORY_CHAT, "ChannelList: invalid unread count=%d channel=%s", count, qPrintable(channelId)); return; + } for (int row = 0; row < m_model->rowCount(); row++) { QStandardItem* item = m_model->item(row); if (item && item->data(ChannelChannelIdRole).toString() == channelId) { diff --git a/tools/chatgui/src/channellist.h b/tools/chatgui/src/channellist.h index ecede828..d82c0a08 100644 --- a/tools/chatgui/src/channellist.h +++ b/tools/chatgui/src/channellist.h @@ -1,5 +1,8 @@ -/* Список каналов и PM с unread/online; загружает данные DbManager и принимает обновления bridge. - * Выбор и действия пользователя передаёт наружу signals; виджет используется в GUI-потоке. */ +/* Список каналов и PM с unread/online; все методы и события используются в GUI-потоке. + * DbManager заимствуется через QPointer; setDb/закрытие SQLite остаются обязанностью владельца БД. + * loadChannels() читает самостоятельные снимки БД, bridge-события передаёт сюда внешний контроллер. + * Собственные дочерние model/view/timer принадлежат виджету. Изменения ядра запрашиваются signals. + * Контекстное меню хранит ID цели и проверяет наличие строки/поколение PM после вложенного event loop. */ #pragma once #include @@ -18,43 +21,64 @@ class CpuLoadIndicator; class ChannelList : public QWidget { Q_OBJECT public: + /* Создаёт виджет с необязательной БД (без неё список пуст); parent владеет виджетом. */ explicit ChannelList(DbManager* db = nullptr, QWidget *parent = nullptr); + /* Перечитывает список/непрочитанные из БД. Сохраняет выбор и онлайн-счётчики существующих групп; + * если выбранная строка исчезла, выбирает первую доступную группу/PM. Выбор испускает channelSelected. */ void loadChannels(); + /* Объединяет запросы в один запуск через 50 мс; таймер не периодический. + * Отправляет owned-команды маршрута для видимых в БД PM; при недоступном ядре сбрасывает их online. */ void refreshDmPresence(); + /* Принимает заимствованный снимок [conv_len:1][UTF-8 conv][peer:8][group:8], числа native-endian. + * Проверяет точную длину; online = ненулевые peer и group, это доступность BGP-маршрута. */ void onDmCallRoute(const uint8_t* data, int len); + /* Останавливает отложенный запрос и сбрасывает кеш/точки доступности PM; не отменяет уже отправленные команды. */ void clearDmPresence(); /* Отмечает ожидающее удаление поколения PM; повторное действие в меню недоступно до результата. */ void setDmDeleting(const QString& convId, quint64 generation, bool deleting); + /* Выбирает существующий ID группы или "dm:"; пустой/неизвестный ID сохраняет текущий выбор. */ void selectChannel(const QString& channelId); + /* Обновляет онлайн-счётчик существующей строки; отрицательное count отклоняется с предупреждением. */ void setChannelPeersOnline(const QString& channelId, int count); + /* Задаёт общий индикатор автоподключения для существующих и последующих строк групп. */ void setAutoConnectActive(bool active); + /* Показывает процент CPU, ограниченный диапазоном 0..100. */ void setCpuLoad(int percent); + /* Задаёт unread существующей строки; отрицательное count отклоняется, изменившаяся роль уведомляется один раз. */ void setChannelUnreadCount(const QString& channelId, int count); + /* Возвращает unread строки либо 0, если ID отсутствует. */ int getChannelUnreadCount(const QString& channelId) const; signals: + /* Выбрана строка (также после loadChannels); ID для PM имеет префикс "dm:". */ void channelSelected(const QString& channelId); + /* Запрос контроллеру подтвердить/удалить поколение PM; convId без префикса. */ void dmDeleteRequested(const QString& convId, quint64 generation, const QString& name); + /* Открыть файлы захваченной меню группы, если она по-прежнему присутствует в списке. */ void filesRequested(const QString& channelId); + /* Приняты локальные пути с CopyAction для выбранной числовой группы при готовом ядре/своём node ID. + * Сигнал отложен до следующей итерации Qt, paths копируются; проверка файлов/загрузка — у получателя. */ void ownFilesDropped(const QString& channelId, const QStringList& paths); + /* Кнопки footer: присоединиться, создать группу, настройки и монитор соединений. */ void joinRequested(); void createGroupRequested(); void settingsRequested(); void connMonitorRequested(); protected: + /* Принимает drag/drop в footer; фильтры устанавливаются на него и его кнопки/подписи. */ bool eventFilter(QObject* target, QEvent* event) override; private: - QListView *m_listView; - QStandardItemModel *m_model; - QPointer m_db; - QWidget *m_footer; - QLabel *m_dropHint; - bool m_autoConnectActive = false; - QHash m_dmOnline; + QListView *m_listView; /* Дочерний view; секции не выбираются мышью. */ + QStandardItemModel *m_model; /* Дочерняя плоская модель, роли из channeldelegate.h. */ + QPointer m_db; /* Не владеет БД; обнуляется при уничтожении QObject. */ + QWidget *m_footer; /* Дочерняя панель действий и приёма файлов. */ + QLabel *m_dropHint; /* Дочерняя footer-подсказка, не перехватывает мышь. */ + bool m_autoConnectActive = false; /* Общее состояние автоподключения групп. */ + QHash m_dmOnline; /* Последние снимки доступности conv_id, сохраняются при reload. */ QHash m_dmDeleting; /* conv_id → поколение ожидающего удаления */ - QTimer* m_dmPresenceTimer; - CpuLoadIndicator* m_cpuLoad; + QTimer* m_dmPresenceTimer; /* Дочерний single-shot, debounce 50 мс. */ + CpuLoadIndicator* m_cpuLoad; /* Дочерний индикатор CPU 0..100. */ };