You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

142 lines
5.0 KiB

#include "inputbar.h"
#include "emojipanel.h"
#include "debug_ui.h"
#include <QDebug>
#include <QTextEdit>
#include <QPushButton>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QFileDialog>
#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;
}
static QWidget *wrapBottomBtn(QPushButton *btn, int pad) {
auto *w = new QWidget(btn->parentWidget());
auto *l = new QVBoxLayout(w);
l->setContentsMargins(0, 0, 0, 0);
l->setSpacing(0);
l->addWidget(btn);
l->addSpacing(pad);
return w;
}
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(wrapBottomBtn(attachBtn, 3), 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(wrapBottomBtn(m_emojiBtn, 3), 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();
GUI_INFO("send: len=%d hasLF=%d text='%s'",
text.length(), text.contains('\n'), qPrintable(text));
while (!text.isEmpty() && (text.back() == ' ' || text.back() == '\t'))
text.chop(1);
if (text.isEmpty()) return;
emit sendMessage(text);
m_input->clear();
if (m_emojiPanel) m_emojiPanel->hide();
m_input->setFocus();
}