diff --git a/tools/chatgui/CMakeLists.txt b/tools/chatgui/CMakeLists.txt index 37d10ebd..8f29ef41 100644 --- a/tools/chatgui/CMakeLists.txt +++ b/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}) diff --git a/tools/chatgui/src/emoji.cpp b/tools/chatgui/src/emoji.cpp new file mode 100644 index 00000000..67cdc2a5 --- /dev/null +++ b/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 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 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 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 builtinEmojiSet() { + return { + {"Smileys & People", smileys()}, + {"Gestures", gestures()}, + {"Hearts & Symbols", hearts()}, + }; +} diff --git a/tools/chatgui/src/emoji.h b/tools/chatgui/src/emoji.h new file mode 100644 index 00000000..a7d0358c --- /dev/null +++ b/tools/chatgui/src/emoji.h @@ -0,0 +1,23 @@ +#pragma once + +#include +#include + +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 items; +}; + +QVector builtinEmojiSet(); diff --git a/tools/chatgui/src/emojipanel.cpp b/tools/chatgui/src/emojipanel.cpp new file mode 100644 index 00000000..1cb6a74b --- /dev/null +++ b/tools/chatgui/src/emojipanel.cpp @@ -0,0 +1,86 @@ +#include "emojipanel.h" +#include "emoji.h" +#include "emojitabbar.h" +#include +#include +#include +#include +#include +#include + +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 &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(sender()); + if (btn) { + emit emojiSelected(btn->text()); + } +} diff --git a/tools/chatgui/src/emojipanel.h b/tools/chatgui/src/emojipanel.h new file mode 100644 index 00000000..2a4a0351 --- /dev/null +++ b/tools/chatgui/src/emojipanel.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include + +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 &categories); + QWidget *buildCategoryPage(const EmojiCategory &cat); +}; diff --git a/tools/chatgui/src/emojitabbar.cpp b/tools/chatgui/src/emojitabbar.cpp new file mode 100644 index 00000000..f2040850 --- /dev/null +++ b/tools/chatgui/src/emojitabbar.cpp @@ -0,0 +1,50 @@ +#include "emojitabbar.h" +#include +#include + +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); +} diff --git a/tools/chatgui/src/emojitabbar.h b/tools/chatgui/src/emojitabbar.h new file mode 100644 index 00000000..7489447f --- /dev/null +++ b/tools/chatgui/src/emojitabbar.h @@ -0,0 +1,12 @@ +#pragma once + +#include + +class EmojiTabBar : public QTabBar { + Q_OBJECT +public: + explicit EmojiTabBar(QWidget *parent = nullptr); + +protected: + void paintEvent(QPaintEvent *event) override; +}; diff --git a/tools/chatgui/src/inputbar.cpp b/tools/chatgui/src/inputbar.cpp new file mode 100644 index 00000000..fb40e52a --- /dev/null +++ b/tools/chatgui/src/inputbar.cpp @@ -0,0 +1,125 @@ +#include "inputbar.h" +#include "emojipanel.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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(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(); +} diff --git a/tools/chatgui/src/inputbar.h b/tools/chatgui/src/inputbar.h new file mode 100644 index 00000000..2396c463 --- /dev/null +++ b/tools/chatgui/src/inputbar.h @@ -0,0 +1,28 @@ +#pragma once + +#include + +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; +}; diff --git a/tools/chatgui/src/messagelist.cpp b/tools/chatgui/src/messagelist.cpp index 5c18dc8e..90fa942d 100644 --- a/tools/chatgui/src/messagelist.cpp +++ b/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 #include #include +#include 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); diff --git a/tools/chatgui/src/messagelist.h b/tools/chatgui/src/messagelist.h index cd37eae3..ce441032 100644 --- a/tools/chatgui/src/messagelist.h +++ b/tools/chatgui/src/messagelist.h @@ -4,6 +4,8 @@ #include class ChatView; +class InputBar; +class EmojiPanel; class MessageList : public QWidget { Q_OBJECT @@ -11,7 +13,9 @@ public: explicit MessageList(QWidget *parent = nullptr); private: - ChatView *m_view; + ChatView *m_view; QStandardItemModel *m_model; + InputBar *m_inputBar; + EmojiPanel *m_emojiPanel; void populateStubData(); };