mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
feat: add text search
This commit is contained in:
parent
863c46c73d
commit
b881d32d1b
|
@ -58,6 +58,37 @@ void Text::setText(const QString& txt)
|
|||
dirty = true;
|
||||
}
|
||||
|
||||
void Text::selectText(const QString &txt, const int index)
|
||||
{
|
||||
regenerate();
|
||||
|
||||
if (!doc)
|
||||
return;
|
||||
|
||||
QTextCursor cursor = doc->find(txt, index);
|
||||
|
||||
if (cursor != QTextCursor()) {
|
||||
cursor.beginEditBlock();
|
||||
cursor.setPosition(index);
|
||||
cursor.setPosition(index + txt.size(), QTextCursor::KeepAnchor);
|
||||
cursor.endEditBlock();
|
||||
|
||||
QTextCharFormat format;
|
||||
format.setBackground(QBrush(QColor("#ff7626")));
|
||||
cursor.mergeCharFormat(format);
|
||||
|
||||
regenerate();
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void Text::deselectText()
|
||||
{
|
||||
dirty = true;
|
||||
regenerate();
|
||||
update();
|
||||
}
|
||||
|
||||
void Text::setWidth(qreal w)
|
||||
{
|
||||
width = w;
|
||||
|
|
|
@ -36,6 +36,8 @@ public:
|
|||
virtual ~Text();
|
||||
|
||||
void setText(const QString& txt);
|
||||
void selectText(const QString& txt, const int index);
|
||||
void deselectText();
|
||||
|
||||
virtual void setWidth(qreal width) final;
|
||||
|
||||
|
|
|
@ -180,6 +180,10 @@ ChatForm::ChatForm(Friend* chatFriend, History* history)
|
|||
connect(headWidget, &ChatFormHeader::volMuteToggle, this, &ChatForm::onVolMuteToggle);
|
||||
connect(headWidget, &ChatFormHeader::searchTriggered, this, &ChatForm::onSearchTrigered);
|
||||
|
||||
connect(searchForm, &SearchForm::searchInBegin, this, &ChatForm::earchInBegin);
|
||||
connect(searchForm, &SearchForm::searchUp, this, &ChatForm::onSearchUp);
|
||||
connect(searchForm, &SearchForm::searchDown, this, &ChatForm::onSearchDown);
|
||||
|
||||
connect(msgEdit, &ChatTextEdit::enterPressed, this, &ChatForm::onSendTriggered);
|
||||
connect(msgEdit, &ChatTextEdit::textChanged, this, &ChatForm::onTextEditChanged);
|
||||
connect(msgEdit, &ChatTextEdit::pasteImage, this, &ChatForm::sendImage);
|
||||
|
@ -495,9 +499,113 @@ void ChatForm::onSearchTrigered()
|
|||
if (searchForm->maximumHeight() == 0) {
|
||||
searchForm->setMaximumHeight(50);
|
||||
headWidget->updateSearchButton(true);
|
||||
searchPoint = QPoint(1, -1);
|
||||
} else {
|
||||
searchForm->setMaximumHeight(0);
|
||||
searchForm->removeText();
|
||||
headWidget->updateSearchButton(false);
|
||||
|
||||
desibleSearchText();
|
||||
}
|
||||
}
|
||||
|
||||
void ChatForm::earchInBegin(const QString &phrase)
|
||||
{
|
||||
desibleSearchText();
|
||||
|
||||
searchPoint = QPoint(1, -1);
|
||||
onSearchUp(phrase);
|
||||
}
|
||||
|
||||
void ChatForm::onSearchUp(const QString &phrase)
|
||||
{
|
||||
if (phrase.isEmpty()) {
|
||||
desibleSearchText();
|
||||
}
|
||||
|
||||
QVector<ChatLine::Ptr> lines = chatWidget->getLines();
|
||||
int numLines = lines.size();
|
||||
|
||||
int startLine = numLines - searchPoint.x();
|
||||
|
||||
if (startLine == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = startLine; i >= 0; --i) {
|
||||
ChatLine::Ptr l = lines[i];
|
||||
if (l->getColumnCount() >= 2) {
|
||||
ChatLineContent* content = l->getContent(1);
|
||||
Text* text = static_cast<Text*>(content);
|
||||
QString txt = content->getText();
|
||||
|
||||
if (txt.contains(phrase)) {
|
||||
int startIndex = -1;
|
||||
if (searchPoint.y() > -1) {
|
||||
startIndex = searchPoint.y() - 1;
|
||||
}
|
||||
|
||||
int index = txt.lastIndexOf(phrase, startIndex);
|
||||
if (index == -1 && searchPoint.y() > -1) {
|
||||
text->deselectText();
|
||||
searchPoint.setY(-1);
|
||||
} else {
|
||||
chatWidget->scrollToLine(l);
|
||||
text->deselectText();
|
||||
text->selectText(phrase, index);
|
||||
searchPoint = QPoint(numLines - i, index);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
searchPoint.setX(numLines);
|
||||
loadHistory(historyBaselineDate.addDays(-1));
|
||||
onSearchUp(phrase);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ChatForm::onSearchDown(const QString &phrase)
|
||||
{
|
||||
if (phrase.isEmpty()) {
|
||||
desibleSearchText();
|
||||
}
|
||||
|
||||
QVector<ChatLine::Ptr> lines = chatWidget->getLines();
|
||||
int numLines = lines.size();
|
||||
|
||||
int startLine = numLines - searchPoint.x();
|
||||
|
||||
for (int i = startLine; i < numLines; ++i) {
|
||||
ChatLine::Ptr l = lines[i];
|
||||
if (l->getColumnCount() >= 2) {
|
||||
ChatLineContent* content = l->getContent(1);
|
||||
Text* text = static_cast<Text*>(content);
|
||||
QString txt = content->getText();
|
||||
|
||||
if (txt.contains(phrase)) {
|
||||
int startIndex = 0;
|
||||
if (searchPoint.y() > -1) {
|
||||
startIndex = searchPoint.y() + 1;
|
||||
}
|
||||
|
||||
int index = txt.indexOf(phrase, startIndex);
|
||||
if (index == -1 && searchPoint.y() > -1) {
|
||||
text->deselectText();
|
||||
searchPoint.setY(-1);
|
||||
} else {
|
||||
chatWidget->scrollToLine(l);
|
||||
text->deselectText();
|
||||
text->selectText(phrase, index);
|
||||
searchPoint = QPoint(numLines - i, index);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -969,6 +1077,21 @@ void ChatForm::SendMessageStr(QString msg)
|
|||
}
|
||||
}
|
||||
|
||||
void ChatForm::desibleSearchText()
|
||||
{
|
||||
if (searchPoint != QPoint(1, -1)) {
|
||||
QVector<ChatLine::Ptr> lines = chatWidget->getLines();
|
||||
int numLines = lines.size();
|
||||
int index = numLines - searchPoint.x();
|
||||
if (numLines > index) {
|
||||
ChatLine::Ptr l = lines[index];
|
||||
ChatLineContent* content = l->getContent(1);
|
||||
Text* text = static_cast<Text*>(content);
|
||||
text->deselectText();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ChatForm::retranslateUi()
|
||||
{
|
||||
loadHistoryAction->setText(tr("Load chat history..."));
|
||||
|
|
|
@ -89,6 +89,9 @@ private slots:
|
|||
void onVolMuteToggle();
|
||||
void onSearchTrigered();
|
||||
|
||||
void earchInBegin(const QString& phrase);
|
||||
void onSearchUp(const QString& phrase);
|
||||
void onSearchDown(const QString& phrase);
|
||||
void onFileSendFailed(uint32_t friendId, const QString& fname);
|
||||
void onFriendStatusChanged(quint32 friendId, Status status);
|
||||
void onFriendTypingChanged(quint32 friendId, bool isTyping);
|
||||
|
@ -113,6 +116,8 @@ private:
|
|||
void updateCallButtons();
|
||||
void SendMessageStr(QString msg);
|
||||
|
||||
void desibleSearchText();
|
||||
|
||||
protected:
|
||||
GenericNetCamView* createNetcam() final override;
|
||||
void insertChatMessage(ChatMessage::Ptr msg) final override;
|
||||
|
@ -138,6 +143,7 @@ private:
|
|||
QHash<uint, FileTransferInstance*> ftransWidgets;
|
||||
bool isTyping;
|
||||
bool lastCallIsVideo;
|
||||
QPoint searchPoint;
|
||||
};
|
||||
|
||||
#endif // CHATFORM_H
|
||||
|
|
|
@ -297,11 +297,13 @@ void GenericChatForm::showEvent(QShowEvent*)
|
|||
bool GenericChatForm::event(QEvent* e)
|
||||
{
|
||||
// If the user accidentally starts typing outside of the msgEdit, focus it automatically
|
||||
if (e->type() == QEvent::KeyRelease && !msgEdit->hasFocus()) {
|
||||
QKeyEvent* ke = static_cast<QKeyEvent*>(e);
|
||||
if ((ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::ShiftModifier)
|
||||
&& !ke->text().isEmpty())
|
||||
msgEdit->setFocus();
|
||||
if (searchForm->maximumHeight() == 0) {
|
||||
if (e->type() == QEvent::KeyRelease && !msgEdit->hasFocus()) {
|
||||
QKeyEvent* ke = static_cast<QKeyEvent*>(e);
|
||||
if ((ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::ShiftModifier)
|
||||
&& !ke->text().isEmpty())
|
||||
msgEdit->setFocus();
|
||||
}
|
||||
}
|
||||
return QWidget::event(e);
|
||||
}
|
||||
|
|
|
@ -25,4 +25,29 @@ SearchForm::SearchForm(QWidget *parent) : QWidget(parent)
|
|||
layout->addWidget(downButton);
|
||||
|
||||
setLayout(layout);
|
||||
|
||||
connect(searchLine, &QLineEdit::textChanged, this, &SearchForm::changedSearchPhrare);
|
||||
connect(upButton, &QPushButton::clicked, this, &SearchForm::clickedUp);
|
||||
connect(downButton, &QPushButton::clicked, this, &SearchForm::clickedDown);
|
||||
}
|
||||
|
||||
void SearchForm::removeText()
|
||||
{
|
||||
searchLine->setText("");
|
||||
}
|
||||
|
||||
void SearchForm::changedSearchPhrare(const QString &text)
|
||||
{
|
||||
searchPhrase = text;
|
||||
emit searchInBegin(searchPhrase);
|
||||
}
|
||||
|
||||
void SearchForm::clickedUp()
|
||||
{
|
||||
emit searchUp(searchPhrase);
|
||||
}
|
||||
|
||||
void SearchForm::clickedDown()
|
||||
{
|
||||
emit searchDown(searchPhrase);
|
||||
}
|
||||
|
|
|
@ -11,11 +11,24 @@ class SearchForm final : public QWidget
|
|||
Q_OBJECT
|
||||
public:
|
||||
explicit SearchForm(QWidget *parent = nullptr);
|
||||
void removeText();
|
||||
|
||||
private:
|
||||
QPushButton* upButton;
|
||||
QPushButton* downButton;
|
||||
QLineEdit* searchLine;
|
||||
|
||||
QString searchPhrase;
|
||||
|
||||
private slots:
|
||||
void changedSearchPhrare(const QString &text);
|
||||
void clickedUp();
|
||||
void clickedDown();
|
||||
|
||||
signals:
|
||||
void searchInBegin(const QString &);
|
||||
void searchUp(const QString &);
|
||||
void searchDown(const QString &);
|
||||
};
|
||||
|
||||
#endif // SEARCHFORM_H
|
||||
|
|
Loading…
Reference in New Issue
Block a user