From b14bfa95c202817545012bcfe755324040fbb9f1 Mon Sep 17 00:00:00 2001 From: evgeny Date: Sat, 10 Oct 2026 11:17:00 +0200 Subject: [PATCH] Collect group actions in the conversation header menu --- tools/chatgui/src/mainwindow.cpp | 7 ++-- tools/chatgui/src/messagelist.cpp | 69 +++++++++++++++++++++++-------- tools/chatgui/src/messagelist.h | 7 +++- 3 files changed, 60 insertions(+), 23 deletions(-) diff --git a/tools/chatgui/src/mainwindow.cpp b/tools/chatgui/src/mainwindow.cpp index c5db101e..c309b346 100644 --- a/tools/chatgui/src/mainwindow.cpp +++ b/tools/chatgui/src/mainwindow.cpp @@ -599,17 +599,18 @@ void MainWindow::setupConnects() { gui_bridge_post_uasync_fn(chat_core_connect_channel_trampoline, arg); } }); - connect(m_channelList, &ChannelList::inviteRequested, this, &MainWindow::showShareInviteDialog); - connect(m_channelList, &ChannelList::inviteByLinkRequested, this, &MainWindow::showInviteByLinkDialog); + connect(m_messageList, &MessageList::shareInviteRequested, this, &MainWindow::showShareInviteDialog); + connect(m_messageList, &MessageList::inviteByLinkRequested, this, &MainWindow::showInviteByLinkDialog); connect(m_channelList, &ChannelList::joinRequested, this, &MainWindow::showJoinDialog); connect(m_channelList, &ChannelList::createGroupRequested, this, &MainWindow::onCreateGroupRequested); connect(m_channelList, &ChannelList::settingsRequested, this, &MainWindow::showSettings); connect(m_channelList, &ChannelList::connMonitorRequested, this, &MainWindow::showConnMonitor); - connect(m_channelList, &ChannelList::channelSettingsRequested, this, &MainWindow::showChannelSettings); + connect(m_messageList, &MessageList::channelSettingsRequested, this, &MainWindow::showChannelSettings); connect(m_accountList, &AccountList::memberRenamed, m_messageList, &MessageList::reloadLocalNicks); connect(m_accountList, &AccountList::filesRequested, this, &MainWindow::showMemberFiles); connect(m_channelList, &ChannelList::filesRequested, this, [this](const QString& channel) { showMemberFiles(channel); }); + connect(m_messageList, &MessageList::filesRequested, this, [this](const QString& channel) { showMemberFiles(channel); }); connect(m_messageList, &MessageList::ownFilesRequested, this, [this](const QString& channel) { quint64 owner = m_db ? m_db->myNodeId() : 0; if (!channel.toULongLong() || !owner) { diff --git a/tools/chatgui/src/messagelist.cpp b/tools/chatgui/src/messagelist.cpp index da57f0f6..0decf11f 100644 --- a/tools/chatgui/src/messagelist.cpp +++ b/tools/chatgui/src/messagelist.cpp @@ -377,27 +377,11 @@ MessageList::MessageList(DbManager* db, AudioRecorder* recorder, QWidget *parent m_channelTitle->setStyleSheet("font-weight: bold; font-size: 14px;"); m_channelTitle->setText(QCoreApplication::translate("ChatGui", "Channel")); hl->addWidget(m_channelTitle, 1); - m_pollBtn = new QPushButton(QCoreApplication::translate("ChatGui", "Create poll"), header); - hl->addWidget(m_pollBtn); - connect(m_pollBtn, &QPushButton::clicked, this, &MessageList::createPoll); - m_talkingLabel = new QLabel(header); m_talkingLabel->setStyleSheet("color: #27ae60; font-size: 12px;"); m_talkingLabel->hide(); hl->addWidget(m_talkingLabel); - m_ownFilesButton = new QPushButton(header); - m_ownFilesButton->setObjectName("ownFilesButton"); - m_ownFilesButton->setIcon(style()->standardIcon(QStyle::SP_DirOpenIcon)); - m_ownFilesButton->setIconSize(QSize(24, 24)); - m_ownFilesButton->setFixedSize(34, 30); - m_ownFilesButton->setCursor(Qt::PointingHandCursor); - m_ownFilesButton->setToolTip(QCoreApplication::translate("ChatGui", "My files in the selected group")); - m_ownFilesButton->setAccessibleName(m_ownFilesButton->toolTip()); - m_ownFilesButton->hide(); - hl->addWidget(m_ownFilesButton); - connect(m_ownFilesButton, &QPushButton::clicked, this, [this] { emit ownFilesRequested(m_currentChannelId); }); - m_inviteBtn = new QPushButton(QStringLiteral("+"), header); m_inviteBtn->setAccessibleName(QCoreApplication::translate("ChatGui", "Invite to group")); m_inviteBtn->setToolTip(QCoreApplication::translate("ChatGui", "Invite to group")); @@ -442,6 +426,56 @@ MessageList::MessageList(DbManager* db, AudioRecorder* recorder, QWidget *parent connect(m_radioBtn, &QPushButton::toggled, this, &MessageList::onRadioToggled); hl->addWidget(m_radioBtn); + m_groupMenuButton = new QPushButton(QStringLiteral("…"), header); + m_groupMenuButton->setObjectName("groupMenuButton"); + m_groupMenuButton->setFixedSize(34, 30); + m_groupMenuButton->setCursor(Qt::PointingHandCursor); + m_groupMenuButton->setToolTip(QCoreApplication::translate("ChatGui", "Options")); + m_groupMenuButton->setAccessibleName(m_groupMenuButton->toolTip()); + m_groupMenuButton->hide(); + hl->addWidget(m_groupMenuButton); + connect(m_groupMenuButton, &QPushButton::clicked, this, [this] { + const QString channel = m_currentChannelId; + if (!channel.toULongLong()) return; + auto text = [](const char* s) { return QCoreApplication::translate("ChatGui", s); }; + QMenu menu(this); + auto* files = menu.addAction(text("Group files")); + auto* ownFiles = menu.addAction(text("My files")); + auto* poll = menu.addAction(text("Create poll")); + menu.addSeparator(); + auto* share = menu.addAction(text("Invite link")); + auto* invite = menu.addAction(text("Invite by node link")); + menu.addSeparator(); + auto* sound = menu.addAction(text("Sound")); sound->setCheckable(true); + sound->setEnabled(m_db && m_db->isOpen() && gui_bridge_is_uasync_ready()); + sound->setChecked(m_db && m_db->getUiStateInt(QStringLiteral("ch_%1_sound_on_message").arg(channel), 1)); + auto* settings = menu.addAction(text("Channel Settings")); + QPointer guard(this); + auto* action = menu.exec(m_groupMenuButton->mapToGlobal(QPoint(0, m_groupMenuButton->height()))); + if (!guard || !action) return; + if (channel != m_currentChannelId) { + DEBUG_WARN(DEBUG_CATEGORY_CHAT, "group menu: channel changed old=%s current=%s", qPrintable(channel), qPrintable(m_currentChannelId)); + return; + } + DEBUG_INFO(DEBUG_CATEGORY_CHAT, "group menu: channel=%s action=%s", qPrintable(channel), qPrintable(action->text())); + if (action == files) emit filesRequested(channel); + else if (action == ownFiles) emit ownFilesRequested(channel); + else if (action == poll) createPoll(); + else if (action == share) emit shareInviteRequested(channel); + else if (action == invite) emit inviteByLinkRequested(channel); + else if (action == settings) emit channelSettingsRequested(channel); + else if (action == sound) { + if (!gui_bridge_is_uasync_ready()) { + DEBUG_WARN(DEBUG_CATEGORY_CHAT, "group menu: sound update unavailable channel=%s", qPrintable(channel)); return; + } + auto* arg = (chat_sound_arg*)u_calloc(1, sizeof(chat_sound_arg)); + if (!arg) { DEBUG_ERROR(DEBUG_CATEGORY_CHAT, "group menu: sound allocation failed"); return; } + arg->inst = gui_bridge_get_inst(); arg->on = sound->isChecked(); + snprintf(arg->ch_id, sizeof(arg->ch_id), "%s", channel.toUtf8().constData()); + gui_bridge_post_uasync_fn(chat_core_set_sound_on_message_trampoline, arg); + } + }); + header->setStyleSheet("background: palette(window);"); layout->addWidget(header); } @@ -715,8 +749,7 @@ void MessageList::loadChannel(const QString& channelId) { m_avatarCache.clear(); if (m_currentChannelId != channelId) { m_feedback.clear(); m_pendingPoll.clear(); } m_currentChannelId = channelId; - m_ownFilesButton->setVisible(channelId.toULongLong() != 0); - m_pollBtn->setVisible(!isDmChannel(channelId)); + m_groupMenuButton->setVisible(channelId.toULongLong() != 0); clearDmCallRoute(); m_callBtn->setVisible(isDmChannel(channelId)); m_inviteBtn->setVisible(isDmChannel(channelId)); diff --git a/tools/chatgui/src/messagelist.h b/tools/chatgui/src/messagelist.h index 432a08b6..deeb1236 100644 --- a/tools/chatgui/src/messagelist.h +++ b/tools/chatgui/src/messagelist.h @@ -54,6 +54,10 @@ signals: void openImageRequested(const QString& filePath); void inviteRequested(const QString& sourceChannel, quint64 peer, const QString& name); void ownFilesRequested(const QString& channelId); + void filesRequested(const QString& channelId); + void shareInviteRequested(const QString& channelId); + void inviteByLinkRequested(const QString& channelId); + void channelSettingsRequested(const QString& channelId); void linkActivated(const QString& link); private: @@ -75,7 +79,7 @@ private: QLabel* m_talkingLabel = nullptr; /* шапка: кто говорит в рации */ QPushButton* m_callBtn = nullptr; QPushButton* m_inviteBtn = nullptr; - QPushButton* m_ownFilesButton = nullptr; + QPushButton* m_groupMenuButton = nullptr; quint64 m_callPeer = 0; quint64 m_callGroup = 0; QPushButton* m_radioBtn = nullptr; /* шапка: переключатель рации */ @@ -83,7 +87,6 @@ private: bool m_radioOn = false; QThreadPool m_thumbnailPool; QSet m_thumbnailJobs; - QPushButton* m_pollBtn = nullptr; QHash m_feedback; QPointer m_pollDialog; QString m_pollDialogMessage, m_pendingPoll;