1
0
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:
TriKriSta 2018-02-10 14:43:03 +02:00
parent 863c46c73d
commit b881d32d1b
7 changed files with 207 additions and 5 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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..."));

View File

@ -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

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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