Browse Source

tools/chatgui: input bar with emoji panel, custom tab bar, Ctrl+Enter multiline, scroll fixes

feature/x25519-migration
Evgeny 3 months ago
parent
commit
e50ca9978e
  1. 4
      tools/chatgui/CMakeLists.txt
  2. 118
      tools/chatgui/src/emoji.cpp
  3. 23
      tools/chatgui/src/emoji.h
  4. 86
      tools/chatgui/src/emojipanel.cpp
  5. 26
      tools/chatgui/src/emojipanel.h
  6. 50
      tools/chatgui/src/emojitabbar.cpp
  7. 12
      tools/chatgui/src/emojitabbar.h
  8. 125
      tools/chatgui/src/inputbar.cpp
  9. 28
      tools/chatgui/src/inputbar.h
  10. 64
      tools/chatgui/src/messagelist.cpp
  11. 4
      tools/chatgui/src/messagelist.h

4
tools/chatgui/CMakeLists.txt

@ -22,6 +22,10 @@ add_executable(chatgui
src/messagedelegate.cpp
src/messagelist.cpp
src/accountlist.cpp
src/emoji.cpp
src/emojipanel.cpp
src/emojitabbar.cpp
src/inputbar.cpp
)
target_link_libraries(chatgui PRIVATE ${QT_LIBS})

118
tools/chatgui/src/emoji.cpp

@ -0,0 +1,118 @@
#include "emoji.h"
EmojiData EmojiData::unicodeEmoji(const QString &u, const QString &s) {
EmojiData d;
d.type = EmojiType::Unicode;
d.unicode = u;
d.shortcode = s;
return d;
}
static QVector<EmojiData> smileys() {
return {
EmojiData::unicodeEmoji("\xF0\x9F\x98\x80", ":grinning:"),
EmojiData::unicodeEmoji("\xF0\x9F\x98\x83", ":smiley:"),
EmojiData::unicodeEmoji("\xF0\x9F\x98\x84", ":smile:"),
EmojiData::unicodeEmoji("\xF0\x9F\x98\x81", ":grin:"),
EmojiData::unicodeEmoji("\xF0\x9F\x98\x86", ":laughing:"),
EmojiData::unicodeEmoji("\xF0\x9F\x98\x85", ":sweat_smile:"),
EmojiData::unicodeEmoji("\xF0\x9F\x98\x82", ":joy:"),
EmojiData::unicodeEmoji("\xF0\x9F\xA4\xA3", ":rofl:"),
EmojiData::unicodeEmoji("\xF0\x9F\x98\x8A", ":blush:"),
EmojiData::unicodeEmoji("\xF0\x9F\x98\x87", ":innocent:"),
EmojiData::unicodeEmoji("\xF0\x9F\x99\x82", ":slight_smile:"),
EmojiData::unicodeEmoji("\xF0\x9F\x98\x89", ":wink:"),
EmojiData::unicodeEmoji("\xF0\x9F\x98\x8D", ":heart_eyes:"),
EmojiData::unicodeEmoji("\xF0\x9F\xA5\xB0", ":smiling_face_3_hearts:"),
EmojiData::unicodeEmoji("\xF0\x9F\x98\x98", ":kissing_heart:"),
EmojiData::unicodeEmoji("\xF0\x9F\x98\x97", ":kissing:"),
EmojiData::unicodeEmoji("\xF0\x9F\x98\x99", ":kissing_smiling_eyes:"),
EmojiData::unicodeEmoji("\xF0\x9F\x98\x9B", ":stuck_out_tongue:"),
EmojiData::unicodeEmoji("\xF0\x9F\x98\x9D", ":stuck_out_tongue_closed_eyes:"),
EmojiData::unicodeEmoji("\xF0\x9F\x98\x9C", ":stuck_out_tongue_wink:"),
EmojiData::unicodeEmoji("\xF0\x9F\xA5\xB4", ":face_with_tongue:"),
EmojiData::unicodeEmoji("\xF0\x9F\xA4\xAA", ":zany_face:"),
EmojiData::unicodeEmoji("\xF0\x9F\x98\x8E", ":sunglasses:"),
EmojiData::unicodeEmoji("\xF0\x9F\xA5\xB3", ":star_struck:"),
EmojiData::unicodeEmoji("\xF0\x9F\xA4\xA9", ":hugging:"),
EmojiData::unicodeEmoji("\xF0\x9F\xA4\x94", ":thinking:"),
EmojiData::unicodeEmoji("\xF0\x9F\xA4\xAD", ":shushing:"),
EmojiData::unicodeEmoji("\xF0\x9F\xA4\x90", ":zipper_mouth:"),
EmojiData::unicodeEmoji("\xF0\x9F\x98\x90", ":neutral_face:"),
EmojiData::unicodeEmoji("\xF0\x9F\x98\x91", ":expressionless:"),
EmojiData::unicodeEmoji("\xF0\x9F\x99\x84", ":rolling_eyes:"),
EmojiData::unicodeEmoji("\xF0\x9F\x98\xAF", ":hushed:"),
EmojiData::unicodeEmoji("\xF0\x9F\x98\xB3", ":flushed:"),
EmojiData::unicodeEmoji("\xF0\x9F\xA5\xB5", ":hot_face:"),
EmojiData::unicodeEmoji("\xF0\x9F\xA5\xB6", ":cold_face:"),
EmojiData::unicodeEmoji("\xF0\x9F\x98\xA8", ":fearful:"),
EmojiData::unicodeEmoji("\xF0\x9F\x98\xB1", ":scream:"),
EmojiData::unicodeEmoji("\xF0\x9F\x98\xA2", ":cry:"),
EmojiData::unicodeEmoji("\xF0\x9F\x98\xAD", ":sob:"),
EmojiData::unicodeEmoji("\xF0\x9F\x98\xA4", ":triumph:"),
EmojiData::unicodeEmoji("\xF0\x9F\x98\xA0", ":angry:"),
EmojiData::unicodeEmoji("\xF0\x9F\x92\xA9", ":poop:"),
EmojiData::unicodeEmoji("\xF0\x9F\x91\xBB", ":ghost:"),
EmojiData::unicodeEmoji("\xF0\x9F\x92\x80", ":skull:"),
EmojiData::unicodeEmoji("\xF0\x9F\x91\xBD", ":alien:"),
EmojiData::unicodeEmoji("\xF0\x9F\xA4\x96", ":robot:"),
};
}
static QVector<EmojiData> gestures() {
return {
EmojiData::unicodeEmoji("\xF0\x9F\x91\x8D", ":+1:"),
EmojiData::unicodeEmoji("\xF0\x9F\x91\x8E", ":-1:"),
EmojiData::unicodeEmoji("\xF0\x9F\x91\x8F", ":clap:"),
EmojiData::unicodeEmoji("\xF0\x9F\x99\x8C", ":raised_hands:"),
EmojiData::unicodeEmoji("\xF0\x9F\x99\x8F", ":pray:"),
EmojiData::unicodeEmoji("\xF0\x9F\xA4\x9D", ":handshake:"),
EmojiData::unicodeEmoji("\xF0\x9F\x92\xAA", ":muscle:"),
EmojiData::unicodeEmoji("\xE2\x9C\x8A", ":fist:"),
EmojiData::unicodeEmoji("\xF0\x9F\x91\x8B", ":wave:"),
EmojiData::unicodeEmoji("\xF0\x9F\x96\x90", ":ok_hand:"),
EmojiData::unicodeEmoji("\xE2\x98\x9D\xEF\xB8\x8F", ":point_up:"),
EmojiData::unicodeEmoji("\xF0\x9F\x91\x86", ":point_up_2:"),
EmojiData::unicodeEmoji("\xF0\x9F\x91\x87", ":point_down:"),
EmojiData::unicodeEmoji("\xF0\x9F\x91\x88", ":point_left:"),
EmojiData::unicodeEmoji("\xF0\x9F\x91\x89", ":point_right:"),
EmojiData::unicodeEmoji("\xF0\x9F\xA4\x98", ":metal:"),
EmojiData::unicodeEmoji("\xF0\x9F\xA4\x9E", ":fingers_crossed:"),
EmojiData::unicodeEmoji("\xE2\x9C\x8C\xEF\xB8\x8F", ":v:"),
EmojiData::unicodeEmoji("\xF0\x9F\xA4\x9F", ":love_you_gesture:"),
EmojiData::unicodeEmoji("\xF0\x9F\x91\x8C", ":pinched_fingers:"),
};
}
static QVector<EmojiData> hearts() {
return {
EmojiData::unicodeEmoji("\xE2\x9D\xA4\xEF\xB8\x8F", ":heart:"),
EmojiData::unicodeEmoji("\xF0\x9F\xA7\xA1", ":orange_heart:"),
EmojiData::unicodeEmoji("\xF0\x9F\x92\x9B", ":yellow_heart:"),
EmojiData::unicodeEmoji("\xF0\x9F\x92\x9A", ":green_heart:"),
EmojiData::unicodeEmoji("\xF0\x9F\x92\x99", ":blue_heart:"),
EmojiData::unicodeEmoji("\xF0\x9F\x92\x9C", ":purple_heart:"),
EmojiData::unicodeEmoji("\xF0\x9F\xA4\x8E", ":brown_heart:"),
EmojiData::unicodeEmoji("\xF0\x9F\x96\xA4", ":black_heart:"),
EmojiData::unicodeEmoji("\xF0\x9F\xA4\x8D", ":white_heart:"),
EmojiData::unicodeEmoji("\xF0\x9F\x92\x94", ":broken_heart:"),
EmojiData::unicodeEmoji("\xF0\x9F\x92\x95", ":two_hearts:"),
EmojiData::unicodeEmoji("\xF0\x9F\x92\x98", ":cupid:"),
EmojiData::unicodeEmoji("\xF0\x9F\x92\x97", ":heartbeat:"),
EmojiData::unicodeEmoji("\xF0\x9F\x94\xA5", ":fire:"),
EmojiData::unicodeEmoji("\xF0\x9F\x92\xAF", ":100:"),
EmojiData::unicodeEmoji("\xF0\x9F\x92\xA5", ":boom:"),
EmojiData::unicodeEmoji("\xE2\xAD\x90", ":star:"),
EmojiData::unicodeEmoji("\xF0\x9F\x8C\x9F", ":glowing_star:"),
EmojiData::unicodeEmoji("\xF0\x9F\x92\xAB", ":dizzy:"),
EmojiData::unicodeEmoji("\xF0\x9F\x92\xA4", ":zzz:"),
};
}
QVector<EmojiCategory> builtinEmojiSet() {
return {
{"Smileys & People", smileys()},
{"Gestures", gestures()},
{"Hearts & Symbols", hearts()},
};
}

23
tools/chatgui/src/emoji.h

@ -0,0 +1,23 @@
#pragma once
#include <QString>
#include <QVector>
enum class EmojiType { Unicode, Image, Animation };
struct EmojiData {
EmojiType type = EmojiType::Unicode;
QString unicode;
QString shortcode;
QString imagePath;
QString animPath;
static EmojiData unicodeEmoji(const QString &u, const QString &s);
};
struct EmojiCategory {
QString name;
QVector<EmojiData> items;
};
QVector<EmojiCategory> builtinEmojiSet();

86
tools/chatgui/src/emojipanel.cpp

@ -0,0 +1,86 @@
#include "emojipanel.h"
#include "emoji.h"
#include "emojitabbar.h"
#include <QPushButton>
#include <QScrollArea>
#include <QTabWidget>
#include <QGridLayout>
#include <QHBoxLayout>
#include <QVBoxLayout>
namespace {
class EmojiTabWidget : public QTabWidget {
public:
using QTabWidget::setTabBar;
};
} // namespace
EmojiPanel::EmojiPanel(QWidget *parent)
: QWidget(parent)
{
setStyleSheet("EmojiPanel { background: palette(window); }");
buildPanel(builtinEmojiSet());
hide();
}
void EmojiPanel::showEvent(QShowEvent *event) {
if (parentWidget()) {
setFixedHeight(parentWidget()->height() / 2);
}
QWidget::showEvent(event);
}
void EmojiPanel::buildPanel(const QVector<EmojiCategory> &categories) {
auto *tabs = new EmojiTabWidget();
tabs->setDocumentMode(true);
tabs->setTabBar(new EmojiTabBar(tabs));
tabs->setStyleSheet("QTabWidget::pane { border: none; background: rgba(255,255,255,0.6); }");
for (const auto &cat : categories) {
tabs->addTab(buildCategoryPage(cat), cat.name);
}
auto *layout = new QVBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(0);
layout->addWidget(tabs);
}
QWidget *EmojiPanel::buildCategoryPage(const EmojiCategory &cat) {
auto *scroll = new QScrollArea();
scroll->setWidgetResizable(true);
scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
scroll->setStyleSheet("QScrollArea { border: none; }");
auto *container = new QWidget();
auto *grid = new QGridLayout(container);
grid->setContentsMargins(4, 4, 4, 4);
grid->setSpacing(2);
int cols = 9;
for (int i = 0; i < cat.items.size(); ++i) {
auto *btn = new QPushButton(cat.items[i].unicode, container);
btn->setFixedSize(32, 32);
btn->setCursor(Qt::PointingHandCursor);
btn->setStyleSheet(
"QPushButton { border: none; border-radius: 4px; font-size: 18px; background: transparent; }"
"QPushButton:hover { background: rgba(0,0,0,0.08); }"
);
btn->setToolTip(cat.items[i].shortcode);
connect(btn, &QPushButton::clicked, this, &EmojiPanel::onEmojiClicked);
grid->addWidget(btn, i / cols, i % cols);
}
grid->setRowStretch(grid->rowCount(), 1);
scroll->setWidget(container);
return scroll;
}
void EmojiPanel::onEmojiClicked() {
auto *btn = qobject_cast<QPushButton *>(sender());
if (btn) {
emit emojiSelected(btn->text());
}
}

26
tools/chatgui/src/emojipanel.h

@ -0,0 +1,26 @@
#pragma once
#include <QWidget>
#include <QVector>
class QPushButton;
struct EmojiCategory;
class EmojiPanel : public QWidget {
Q_OBJECT
public:
explicit EmojiPanel(QWidget *parent = nullptr);
signals:
void emojiSelected(const QString &unicode);
protected:
void showEvent(QShowEvent *event) override;
private slots:
void onEmojiClicked();
private:
void buildPanel(const QVector<EmojiCategory> &categories);
QWidget *buildCategoryPage(const EmojiCategory &cat);
};

50
tools/chatgui/src/emojitabbar.cpp

@ -0,0 +1,50 @@
#include "emojitabbar.h"
#include <QPainter>
#include <QStyleOptionTab>
EmojiTabBar::EmojiTabBar(QWidget *parent)
: QTabBar(parent)
{
setDrawBase(false);
setExpanding(false);
setUsesScrollButtons(false);
}
void EmojiTabBar::paintEvent(QPaintEvent *event) {
Q_UNUSED(event);
QPainter p(this);
p.setRenderHint(QPainter::Antialiasing);
int w = width();
int h = height();
static const QColor bgColor(255, 255, 255);
static const QColor activeTextColor(0x33, 0x90, 0xEC);
static const QColor inactiveTextColor(0x8E, 0x8E, 0x93);
static const QColor activeBarColor(0x33, 0x90, 0xEC);
static const QColor separatorColor(0xE0, 0xE0, 0xE0);
p.fillRect(rect(), bgColor);
QFont f = font();
f.setPointSize(f.pointSize() - 1);
p.setFont(f);
int current = currentIndex();
for (int i = 0; i < count(); ++i) {
QRect r = tabRect(i);
if (!r.isValid()) continue;
bool active = (i == current);
p.setPen(active ? activeTextColor : inactiveTextColor);
p.drawText(r, Qt::AlignHCenter | Qt::AlignVCenter, tabText(i));
if (active) {
int barX = r.left() + 4;
int barW = r.width() - 8;
p.fillRect(QRect(barX, h - 3, barW, 3), activeBarColor);
}
}
p.fillRect(QRect(0, h - 1, w, 1), separatorColor);
}

12
tools/chatgui/src/emojitabbar.h

@ -0,0 +1,12 @@
#pragma once
#include <QTabBar>
class EmojiTabBar : public QTabBar {
Q_OBJECT
public:
explicit EmojiTabBar(QWidget *parent = nullptr);
protected:
void paintEvent(QPaintEvent *event) override;
};

125
tools/chatgui/src/inputbar.cpp

@ -0,0 +1,125 @@
#include "inputbar.h"
#include "emojipanel.h"
#include <QTextEdit>
#include <QPushButton>
#include <QHBoxLayout>
#include <QFileDialog>
#include <QDebug>
#include <QKeyEvent>
#include <QFontMetrics>
#include <QScrollBar>
#include <QApplication>
static QPushButton *makeIconBtn(const QString &text, const QString &tooltip, QWidget *parent) {
auto *btn = new QPushButton(text, parent);
btn->setFixedSize(34, 34);
btn->setCursor(Qt::PointingHandCursor);
btn->setToolTip(tooltip);
btn->setStyleSheet(
"QPushButton { border: none; border-radius: 4px; font-size: 18px; background: transparent; }"
"QPushButton:hover { background: palette(light); }"
);
return btn;
}
InputBar::InputBar(EmojiPanel *emojiPanel, QWidget *parent)
: QWidget(parent)
, m_input(new QTextEdit(this))
, m_emojiBtn(nullptr)
, m_emojiPanel(emojiPanel)
{
auto *layout = new QHBoxLayout(this);
layout->setContentsMargins(8, 4, 8, 4);
layout->setSpacing(4);
auto *attachBtn = makeIconBtn(QString::fromUtf8("\xF0\x9F\x93\x8E"),
QString::fromUtf8("Прикрепить"), this);
connect(attachBtn, &QPushButton::clicked, this, [this]() {
QString path = QFileDialog::getOpenFileName(this, QString::fromUtf8("Прикрепить файл"));
if (!path.isEmpty()) {
qDebug() << "Attached:" << path;
}
});
layout->addWidget(attachBtn, 0, Qt::AlignBottom);
m_input->setAcceptRichText(false);
m_input->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_input->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_input->setTabChangesFocus(true);
m_input->setStyleSheet(
"QTextEdit { border: 1px solid palette(mid); border-radius: 6px;"
" padding: 4px 8px; background: palette(base); }"
);
m_input->installEventFilter(this);
QFontMetrics fm(m_input->font());
m_input->setFixedHeight(fm.lineSpacing() + 12);
layout->addWidget(m_input, 1);
m_emojiBtn = makeIconBtn(QString::fromUtf8("\xF0\x9F\x99\x82"),
QString::fromUtf8("Смайлики"), this);
layout->addWidget(m_emojiBtn, 0, Qt::AlignBottom);
auto *sendBtn = makeIconBtn(QString::fromUtf8("\xE2\x9E\xA4"),
QString::fromUtf8("Отправить"), this);
sendBtn->setStyleSheet(sendBtn->styleSheet() +
"QPushButton { color: palette(highlight); font-weight: bold; }");
layout->addWidget(sendBtn, 0, Qt::AlignBottom);
connect(m_input, &QTextEdit::textChanged, this, &InputBar::adjustInputHeight);
connect(sendBtn, &QPushButton::clicked, this, &InputBar::onSendClicked);
if (m_emojiPanel) {
connect(m_emojiBtn, &QPushButton::clicked, this, [this]() {
m_emojiPanel->setVisible(!m_emojiPanel->isVisible());
});
connect(m_emojiPanel, &EmojiPanel::emojiSelected, this, [this](const QString &emoji) {
m_input->insertPlainText(emoji);
m_input->setFocus();
});
}
}
bool InputBar::eventFilter(QObject *obj, QEvent *event) {
if (obj == m_input && event->type() == QEvent::KeyPress) {
auto *ke = static_cast<QKeyEvent *>(event);
if (ke->key() == Qt::Key_Return || ke->key() == Qt::Key_Enter) {
if (ke->modifiers() & Qt::ControlModifier) {
m_input->insertPlainText("\n");
return true;
} else {
onSendClicked();
return true;
}
}
}
return QWidget::eventFilter(obj, event);
}
void InputBar::adjustInputHeight() {
m_input->document()->adjustSize();
int lineSpacing = m_input->fontMetrics().lineSpacing();
int docH = (int)m_input->document()->size().height() + 12;
int maxH = 12 * lineSpacing + 12;
int h = qBound(lineSpacing + 12, docH, maxH);
m_input->setFixedHeight(h);
bool needScroll = docH > maxH;
m_input->setVerticalScrollBarPolicy(needScroll ? Qt::ScrollBarAlwaysOn
: Qt::ScrollBarAlwaysOff);
if (needScroll) {
QTextCursor c = m_input->textCursor();
if (c.atEnd())
m_input->verticalScrollBar()->setValue(m_input->verticalScrollBar()->maximum());
else
m_input->ensureCursorVisible();
}
}
void InputBar::onSendClicked() {
QString text = m_input->toPlainText().trimmed();
if (text.isEmpty()) return;
emit sendMessage(text);
m_input->clear();
if (m_emojiPanel) m_emojiPanel->hide();
}

28
tools/chatgui/src/inputbar.h

@ -0,0 +1,28 @@
#pragma once
#include <QWidget>
class QTextEdit;
class QPushButton;
class EmojiPanel;
class InputBar : public QWidget {
Q_OBJECT
public:
explicit InputBar(EmojiPanel *emojiPanel, QWidget *parent = nullptr);
signals:
void sendMessage(const QString &text);
protected:
bool eventFilter(QObject *obj, QEvent *event) override;
private slots:
void onSendClicked();
void adjustInputHeight();
private:
QTextEdit *m_input;
QPushButton *m_emojiBtn;
EmojiPanel *m_emojiPanel;
};

64
tools/chatgui/src/messagelist.cpp

@ -1,9 +1,12 @@
#include "messagelist.h"
#include "chatview.h"
#include "messagedelegate.h"
#include "inputbar.h"
#include "emojipanel.h"
#include <QVBoxLayout>
#include <QPainter>
#include <QPixmap>
#include <QDateTime>
static QPixmap makeAvatar(const QColor &color, const QString &letter, int size = 36) {
QPixmap pix(size, size);
@ -33,10 +36,31 @@ static QVariant makeReaction(const QString &emoji, int count,
return m;
}
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);
}
MessageList::MessageList(QWidget *parent)
: QWidget(parent)
, m_view(new ChatView(this))
, m_model(new QStandardItemModel(this))
, m_inputBar(nullptr)
, m_emojiPanel(nullptr)
{
auto *layout = new QVBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
@ -50,30 +74,28 @@ MessageList::MessageList(QWidget *parent)
m_view->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
m_view->setFrameShape(QFrame::NoFrame);
m_view->setBackgroundImage("../resources/bg.jpg");
layout->addWidget(m_view);
layout->addWidget(m_view, 1);
m_emojiPanel = new EmojiPanel(this);
layout->addWidget(m_emojiPanel);
m_inputBar = new InputBar(m_emojiPanel, this);
layout->addWidget(m_inputBar);
connect(m_inputBar, &InputBar::sendMessage, this, [this](const QString &text) {
QColor youColor(74, 144, 226);
auto av = makeAvatar(youColor, "Y");
auto *item = new QStandardItem();
setMsg(item,
QString::fromUtf8("You"), text,
QDateTime::currentDateTime().toString("HH:mm"),
av, false, false, QString(), QString(), {});
m_model->appendRow(item);
m_view->scrollToBottom();
});
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);

4
tools/chatgui/src/messagelist.h

@ -4,6 +4,8 @@
#include <QStandardItemModel>
class ChatView;
class InputBar;
class EmojiPanel;
class MessageList : public QWidget {
Q_OBJECT
@ -13,5 +15,7 @@ public:
private:
ChatView *m_view;
QStandardItemModel *m_model;
InputBar *m_inputBar;
EmojiPanel *m_emojiPanel;
void populateStubData();
};

Loading…
Cancel
Save