tools/chatgui: Qt5 GUI chat app stub with tray, channel list, message bubbles

This commit is contained in:
Evgeny committed 2026-06-22 22:48:27 +03:00
1 parent 6717c863e7
commit b667d6f352
20 files changed
+1089

No files matched your search

+179
View File
@@ -0,0 +1,179 @@
#include "messagelist.h"
#include "chatview.h"
#include "messagedelegate.h"
#include <QVBoxLayout>
#include <QPainter>
#include <QPixmap>
static QPixmap makeAvatar(const QColor &color, const QString &letter, int size = 36) {
QPixmap pix(size, size);
pix.fill(Qt::transparent);
QPainter p(&pix);
p.setRenderHint(QPainter::Antialiasing);
p.setBrush(color);
p.setPen(Qt::NoPen);
p.drawEllipse(0, 0, size, size);
p.setPen(Qt::white);
QFont f = p.font();
f.setBold(true);
f.setPointSize(size / 3);
p.setFont(f);
p.drawText(QRect(0, 0, size, size), Qt::AlignCenter, letter);
p.end();
return pix;
}
static QVariant makeReaction(const QString &emoji, int count,
const QList<QColor> &colors = {}) {
QVariantMap m;
m["emoji"] = emoji;
m["count"] = count;
if (!colors.isEmpty())
m["colors"] = QVariant::fromValue(colors);
return m;
}
MessageList::MessageList(QWidget *parent)
: QWidget(parent)
, m_view(new ChatView(this))
, m_model(new QStandardItemModel(this))
{
auto *layout = new QVBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(0);
m_view->setModel(m_model);
m_view->setItemDelegate(new MessageDelegate(this));
m_view->setEditTriggers(QAbstractItemView::NoEditTriggers);
m_view->setSelectionMode(QAbstractItemView::NoSelection);
m_view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_view->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
m_view->setFrameShape(QFrame::NoFrame);
m_view->setBackgroundImage("../resources/bg.jpg");
layout->addWidget(m_view);
populateStubData();
}
static void setMsg(QStandardItem *item,
const QString &author, const QString &text, const QString &time,
const QPixmap &avatar, bool edited,
bool hasQuote, const QString &qAuthor, const QString &qText,
const QVariantList &reactions) {
item->setData(author, MsgAuthorRole);
item->setData(text, MsgTextRole);
item->setData(time, MsgTimeRole);
item->setData(edited, MsgEditedRole);
item->setData(QVariant::fromValue(avatar), MsgAvatarRole);
item->setData(hasQuote, MsgHasQuoteRole);
if (hasQuote) {
item->setData(qAuthor, MsgQuoteAuthorRole);
item->setData(qText, MsgQuoteTextRole);
}
if (!reactions.isEmpty())
item->setData(reactions, MsgReactionsRole);
}
void MessageList::populateStubData() {
QColor cAlice(74, 144, 226), cBob(126, 211, 33), cCarol(245, 166, 35);
QColor cDave(144, 19, 254), cEve(0, 184, 148);
auto avAlice = makeAvatar(cAlice, "A");
auto avBob = makeAvatar(cBob, "B");
auto avCarol = makeAvatar(cCarol, "C");
auto avDave = makeAvatar(cDave, "D");
auto *m0 = new QStandardItem();
setMsg(m0,
QString::fromUtf8("Alice"),
QString::fromUtf8("Hey team! How's the deployment going?"),
"10:15", avAlice, false,
false, QString(), QString(),
{});
m_model->appendRow(m0);
auto *m1 = new QStandardItem();
setMsg(m1,
QString::fromUtf8("Bob"),
QString::fromUtf8("All green on staging. Running the final integration tests now."),
"10:17", avBob, false,
false, QString(), QString(),
QVariantList{makeReaction(QString::fromUtf8("\xF0\x9F\x91\x8D"), 2,
{cAlice, cCarol})});
m_model->appendRow(m1);
auto *m2 = new QStandardItem();
setMsg(m2,
QString::fromUtf8("Carol"),
QString::fromUtf8("I've pushed the ETCP-42 fix to staging. BGP handshake should be stable now. Please review the patch when you get a chance."),
"10:22", avCarol, true,
false, QString(), QString(),
QVariantList{
makeReaction(QString::fromUtf8("\xF0\x9F\x91\x8D"), 3,
{cAlice, cBob, cDave}),
makeReaction(QString::fromUtf8("\xE2\x9D\xA4\xEF\xB8\x8F"), 1,
{cAlice})
});
m_model->appendRow(m2);
auto *m3 = new QStandardItem();
setMsg(m3,
QString::fromUtf8("Dave"),
QString::fromUtf8("Wait — the BGP session is still flapping after the handshake. I'm seeing the keepalive timer fire but no route updates come through. Logs attached."),
"10:25", avDave, false,
true,
QString::fromUtf8("Carol"),
QString::fromUtf8("BGP handshake should be stable now"),
QVariantList{
makeReaction(QString::fromUtf8("\xF0\x9F\x98\xAE"), 1,
{cBob})
});
m_model->appendRow(m3);
auto *m4 = new QStandardItem();
setMsg(m4,
QString::fromUtf8("Alice"),
QString::fromUtf8("Reviewed the patch. LGTM. Let's merge and deploy to production tomorrow morning."),
"10:28", avAlice, false,
false, QString(), QString(),
QVariantList{
makeReaction(QString::fromUtf8("\xF0\x9F\x91\x8D"), 5),
makeReaction(QString::fromUtf8("\xF0\x9F\x8E\x89"), 2,
{cBob, cEve})
});
m_model->appendRow(m4);
auto *m5 = new QStandardItem();
setMsg(m5,
QString::fromUtf8("Bob"),
QString::fromUtf8("Can you share the full logs for the BGP session? I'll dig into the keepalive timer logic."),
"10:30", avBob, false,
true,
QString::fromUtf8("Dave"),
QString::fromUtf8("keepalive timer fire but no route updates"),
{});
m_model->appendRow(m5);
auto *m6 = new QStandardItem();
setMsg(m6,
QString::fromUtf8("Carol"),
QString::fromUtf8("Sounds good. Let's coordinate in #dev-team. I'll prepare the release notes."),
"10:33", avCarol, false,
false, QString(), QString(),
{});
m_model->appendRow(m6);
auto *m7 = new QStandardItem();
setMsg(m7,
QString::fromUtf8("Alice"),
QString::fromUtf8("Deploy scheduled for tomorrow 10:00 UTC. All features are frozen — no more merges to main."),
"10:35", avAlice, false,
false, QString(), QString(),
QVariantList{
makeReaction(QString::fromUtf8("\xF0\x9F\x9A\x80"), 3,
{cBob, cCarol, cDave}),
makeReaction(QString::fromUtf8("\xE2\x9D\xA4\xEF\xB8\x8F"), 7)
});
m_model->appendRow(m7);
m_view->scrollToBottom();
}