From 47d9da98cf6811a30d35a1204e5342a4f7f4bf94 Mon Sep 17 00:00:00 2001 From: TriKriSta Date: Sat, 3 Feb 2018 15:02:11 +0200 Subject: [PATCH 01/12] feat: add a button to search --- res.qrc | 4 +- src/widget/chatformheader.cpp | 18 ++++++-- src/widget/chatformheader.h | 3 ++ src/widget/form/chatform.cpp | 6 +++ src/widget/form/chatform.h | 1 + ui/chatForm/buttons.css | 8 ++++ ui/chatForm/searchButton.svg | 86 +++++++++++++++++++++++++++++++++++ 7 files changed, 120 insertions(+), 6 deletions(-) create mode 100644 ui/chatForm/searchButton.svg diff --git a/res.qrc b/res.qrc index bac33714b..934829e45 100644 --- a/res.qrc +++ b/res.qrc @@ -51,18 +51,15 @@ ui/chatArea/scrollBarDownArrow.svg ui/chatArea/scrollBarLeftArrow.svg ui/chatArea/scrollBarRightArrow.svg - ui/chatForm/buttons.css ui/chatForm/callButton.svg ui/chatForm/micButton.svg ui/chatForm/videoButton.svg ui/chatForm/volButton.svg - ui/chatForm/emoteButton.svg ui/chatForm/fileButton.svg ui/chatForm/screenshotButton.svg ui/chatForm/sendButton.svg - ui/emoticonWidget/dot_page.svg ui/emoticonWidget/dot_page_current.svg ui/emoticonWidget/dot_page_hover.svg @@ -98,5 +95,6 @@ img/caps_lock.svg ui/contentDialog/contentDialog.css ui/tooliconsZone/tooliconsZone.css + ui/chatForm/searchButton.svg diff --git a/src/widget/chatformheader.cpp b/src/widget/chatformheader.cpp index 3c55a4658..09c3b1644 100644 --- a/src/widget/chatformheader.cpp +++ b/src/widget/chatformheader.cpp @@ -76,6 +76,12 @@ const QString MIC_TOOL_TIP[] = { ChatFormHeader::tr("Mute microphone"), }; +const QString SEARCH_TOOL_TIP[] = { + ChatFormHeader::tr("Search in text"), + ChatFormHeader::tr("Unmute search"), + ChatFormHeader::tr("Mute search"), +}; + template QPushButton* createButton(const QString& name, T* self, Fun onClickSlot) { @@ -111,6 +117,7 @@ ChatFormHeader::ChatFormHeader(QWidget* parent) , videoState{CallButtonState::Disabled} , volState{ToolButtonState::Disabled} , micState{ToolButtonState::Disabled} + , searchState{ToolButtonState::Off} { QHBoxLayout* headLayout = new QHBoxLayout(); avatar = new MaskablePixmapWidget(this, AVATAR_SIZE, ":/img/avatar_mask.svg"); @@ -132,6 +139,7 @@ ChatFormHeader::ChatFormHeader(QWidget* parent) volButton = createButton("volButton", this, &ChatFormHeader::volMuteToggle); callButton = createButton("callButton", this, &ChatFormHeader::callTriggered); videoButton = createButton("videoButton", this, &ChatFormHeader::videoCallTriggered); + searchButton = createButton("searchButton", this, &ChatFormHeader::searchTriggered); QVBoxLayout* micButtonsLayout = new QVBoxLayout(); micButtonsLayout->setSpacing(MIC_BUTTONS_LAYOUT_SPACING); @@ -139,9 +147,10 @@ ChatFormHeader::ChatFormHeader(QWidget* parent) micButtonsLayout->addWidget(volButton, Qt::AlignTop | Qt::AlignRight); QGridLayout* buttonsLayout = new QGridLayout(); - buttonsLayout->addLayout(micButtonsLayout, 0, 0, 2, 1, Qt::AlignTop | Qt::AlignRight); - buttonsLayout->addWidget(callButton, 0, 1, 2, 1, Qt::AlignTop); - buttonsLayout->addWidget(videoButton, 0, 2, 2, 1, Qt::AlignTop); + buttonsLayout->addWidget(searchButton, 0, 0, 2, 1, Qt::AlignTop); + buttonsLayout->addLayout(micButtonsLayout, 0, 1, 2, 1, Qt::AlignTop | Qt::AlignRight); + buttonsLayout->addWidget(callButton, 0, 2, 2, 1, Qt::AlignTop); + buttonsLayout->addWidget(videoButton, 0, 3, 2, 1, Qt::AlignTop); buttonsLayout->setVerticalSpacing(0); buttonsLayout->setHorizontalSpacing(BUTTONS_LAYOUT_HOR_SPACING); @@ -171,6 +180,7 @@ void ChatFormHeader::setMode(ChatFormHeader::Mode mode) videoButton->hide(); volButton->hide(); micButton->hide(); + searchButton->hide(); } } @@ -180,6 +190,7 @@ void ChatFormHeader::retranslateUi() setStateToolTip(videoButton, videoState, VIDEO_TOOL_TIP); setStateToolTip(micButton, micState, MIC_TOOL_TIP); setStateToolTip(volButton, volState, VOL_TOOL_TIP); + setStateToolTip(searchButton, searchState, SEARCH_TOOL_TIP); } void ChatFormHeader::updateButtonsView() @@ -188,6 +199,7 @@ void ChatFormHeader::updateButtonsView() setStateName(videoButton, videoState); setStateName(micButton, micState); setStateName(volButton, volState); + setStateName(searchButton, searchState); retranslateUi(); Style::repolish(this); } diff --git a/src/widget/chatformheader.h b/src/widget/chatformheader.h index d744cf0d2..0ab7f9200 100644 --- a/src/widget/chatformheader.h +++ b/src/widget/chatformheader.h @@ -81,6 +81,7 @@ signals: void videoCallTriggered(); void micMuteToggle(); void volMuteToggle(); + void searchTriggered(); void nameChanged(const QString& name); @@ -102,11 +103,13 @@ private: QPushButton* videoButton; QPushButton* volButton; QPushButton* micButton; + QPushButton* searchButton; CallButtonState callState; CallButtonState videoState; ToolButtonState volState; ToolButtonState micState; + ToolButtonState searchState; std::unique_ptr callConfirm; }; diff --git a/src/widget/form/chatform.cpp b/src/widget/form/chatform.cpp index 1b54fed94..4b23d4748 100644 --- a/src/widget/form/chatform.cpp +++ b/src/widget/form/chatform.cpp @@ -177,6 +177,7 @@ ChatForm::ChatForm(Friend* chatFriend, History* history) connect(headWidget, &ChatFormHeader::videoCallTriggered, this, &ChatForm::onVideoCallTriggered); connect(headWidget, &ChatFormHeader::micMuteToggle, this, &ChatForm::onMicMuteToggle); connect(headWidget, &ChatFormHeader::volMuteToggle, this, &ChatForm::onVolMuteToggle); + connect(headWidget, &ChatFormHeader::searchTriggered, this, &ChatForm::onSearchTrigered); connect(msgEdit, &ChatTextEdit::enterPressed, this, &ChatForm::onSendTriggered); connect(msgEdit, &ChatTextEdit::textChanged, this, &ChatForm::onTextEditChanged); @@ -488,6 +489,11 @@ void ChatForm::onVolMuteToggle() updateMuteVolButton(); } +void ChatForm::onSearchTrigered() +{ + +} + void ChatForm::onFileSendFailed(uint32_t friendId, const QString& fname) { if (friendId != f->getId()) { diff --git a/src/widget/form/chatform.h b/src/widget/form/chatform.h index bb926533d..87912425a 100644 --- a/src/widget/form/chatform.h +++ b/src/widget/form/chatform.h @@ -87,6 +87,7 @@ private slots: void onRejectCallTriggered(); void onMicMuteToggle(); void onVolMuteToggle(); + void onSearchTrigered(); void onFileSendFailed(uint32_t friendId, const QString& fname); void onFriendStatusChanged(quint32 friendId, Status status); diff --git a/ui/chatForm/buttons.css b/ui/chatForm/buttons.css index 12c33a71c..11f19b32c 100644 --- a/ui/chatForm/buttons.css +++ b/ui/chatForm/buttons.css @@ -67,6 +67,14 @@ QAbstractButton#callButton height: 40px; } +QAbstractButton#searchButton +{ + background-image: url(":/ui/chatForm/searchButton.svg"); + border-radius: 5px; + width: 50px; + height: 40px; +} + /* Common */ QAbstractButton diff --git a/ui/chatForm/searchButton.svg b/ui/chatForm/searchButton.svg new file mode 100644 index 000000000..bebf9b02c --- /dev/null +++ b/ui/chatForm/searchButton.svg @@ -0,0 +1,86 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + From 863c46c73d1a2fc677f9142ba8d7a2e8dc659c2a Mon Sep 17 00:00:00 2001 From: TriKriSta Date: Sun, 4 Feb 2018 16:17:55 +0200 Subject: [PATCH 02/12] feat: add form for search --- CMakeLists.txt | 2 + res.qrc | 2 + src/widget/chatformheader.cpp | 11 ++++ src/widget/chatformheader.h | 1 + src/widget/form/chatform.cpp | 9 +++- src/widget/form/genericchatform.cpp | 4 ++ src/widget/form/genericchatform.h | 2 + src/widget/searchform.cpp | 28 ++++++++++ src/widget/searchform.h | 21 ++++++++ ui/chatForm/buttons.css | 19 +++++++ ui/chatForm/searchDownButton.svg | 82 +++++++++++++++++++++++++++++ ui/chatForm/searchUpButton.svg | 82 +++++++++++++++++++++++++++++ 12 files changed, 262 insertions(+), 1 deletion(-) create mode 100644 src/widget/searchform.cpp create mode 100644 src/widget/searchform.h create mode 100644 ui/chatForm/searchDownButton.svg create mode 100644 ui/chatForm/searchUpButton.svg diff --git a/CMakeLists.txt b/CMakeLists.txt index ef2ba42d0..37ee8aca9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -341,6 +341,8 @@ set(${PROJECT_NAME}_SOURCES src/widget/emoticonswidget.h src/widget/flowlayout.cpp src/widget/flowlayout.h + src/widget/searchform.cpp + src/widget/searchform.h src/widget/form/addfriendform.cpp src/widget/form/addfriendform.h src/widget/form/chatform.cpp diff --git a/res.qrc b/res.qrc index 934829e45..d68c3caf7 100644 --- a/res.qrc +++ b/res.qrc @@ -96,5 +96,7 @@ ui/contentDialog/contentDialog.css ui/tooliconsZone/tooliconsZone.css ui/chatForm/searchButton.svg + ui/chatForm/searchDownButton.svg + ui/chatForm/searchUpButton.svg diff --git a/src/widget/chatformheader.cpp b/src/widget/chatformheader.cpp index 09c3b1644..508df880a 100644 --- a/src/widget/chatformheader.cpp +++ b/src/widget/chatformheader.cpp @@ -281,6 +281,17 @@ void ChatFormHeader::updateMuteVolButton(bool active, bool outputMuted) updateButtonsView(); } +void ChatFormHeader::updateSearchButton(bool active) +{ + if (active) { + searchState = ToolButtonState::On; + } else { + searchState = ToolButtonState::Off; + } + + updateButtonsView(); +} + void ChatFormHeader::setAvatar(const QPixmap &img) { avatar->setPixmap(img); diff --git a/src/widget/chatformheader.h b/src/widget/chatformheader.h index 0ab7f9200..8fbc0d125 100644 --- a/src/widget/chatformheader.h +++ b/src/widget/chatformheader.h @@ -67,6 +67,7 @@ public: void updateCallButtons(bool online, bool audio, bool video = false); void updateMuteMicButton(bool active, bool inputMuted); void updateMuteVolButton(bool active, bool outputMuted); + void updateSearchButton(bool active); void setAvatar(const QPixmap& img); QSize getAvatarSize() const; diff --git a/src/widget/form/chatform.cpp b/src/widget/form/chatform.cpp index 4b23d4748..226217705 100644 --- a/src/widget/form/chatform.cpp +++ b/src/widget/form/chatform.cpp @@ -41,6 +41,7 @@ #include "src/widget/tool/screenshotgrabber.h" #include "src/widget/translator.h" #include "src/widget/widget.h" +#include "src/widget/searchform.h" #include #include @@ -491,7 +492,13 @@ void ChatForm::onVolMuteToggle() void ChatForm::onSearchTrigered() { - + if (searchForm->maximumHeight() == 0) { + searchForm->setMaximumHeight(50); + headWidget->updateSearchButton(true); + } else { + searchForm->setMaximumHeight(0); + headWidget->updateSearchButton(false); + } } void ChatForm::onFileSendFailed(uint32_t friendId, const QString& fname) diff --git a/src/widget/form/genericchatform.cpp b/src/widget/form/genericchatform.cpp index bc079c431..b5a018b2e 100644 --- a/src/widget/form/genericchatform.cpp +++ b/src/widget/form/genericchatform.cpp @@ -39,6 +39,7 @@ #include "src/widget/tool/flyoutoverlaywidget.h" #include "src/widget/translator.h" #include "src/widget/widget.h" +#include "src/widget/searchform.h" #include #include @@ -135,8 +136,10 @@ GenericChatForm::GenericChatForm(QWidget* parent) { curRow = 0; headWidget = new ChatFormHeader(); + searchForm = new SearchForm(); chatWidget = new ChatLog(this); chatWidget->setBusyNotification(ChatMessage::createBusyNotification()); + searchForm->setMaximumHeight(0); // settings const Settings& s = Settings::getInstance(); @@ -190,6 +193,7 @@ GenericChatForm::GenericChatForm(QWidget* parent) mainFootLayout->setSpacing(0); QVBoxLayout* contentLayout = new QVBoxLayout(contentWidget); + contentLayout->addWidget(searchForm); contentLayout->addWidget(chatWidget); contentLayout->addLayout(mainFootLayout); diff --git a/src/widget/form/genericchatform.h b/src/widget/form/genericchatform.h index a3f34d795..d9eb2307b 100644 --- a/src/widget/form/genericchatform.h +++ b/src/widget/form/genericchatform.h @@ -40,6 +40,7 @@ class CroppingLabel; class FlyoutOverlayWidget; class GenericNetCamView; class MaskablePixmapWidget; +class SearchForm; class Widget; class QLabel; @@ -151,6 +152,7 @@ protected: ChatFormHeader* headWidget; + SearchForm *searchForm; ChatLog* chatWidget; ChatTextEdit* msgEdit; FlyoutOverlayWidget* fileFlyout; diff --git a/src/widget/searchform.cpp b/src/widget/searchform.cpp new file mode 100644 index 000000000..79be2701a --- /dev/null +++ b/src/widget/searchform.cpp @@ -0,0 +1,28 @@ +#include "searchform.h" +#include "src/widget/style.h" +#include +#include +#include + +SearchForm::SearchForm(QWidget *parent) : QWidget(parent) +{ + QHBoxLayout *layout = new QHBoxLayout(); + searchLine = new QLineEdit(); + upButton = new QPushButton(); + upButton->setAttribute(Qt::WA_LayoutUsesWidgetRect); + upButton->setObjectName("searchUpButton"); + upButton->setProperty("state", "green"); + upButton->setStyleSheet(Style::getStylesheet(QStringLiteral(":/ui/chatForm/buttons.css"))); + + downButton = new QPushButton(); + downButton->setAttribute(Qt::WA_LayoutUsesWidgetRect); + downButton->setObjectName("searchDownButton"); + downButton->setProperty("state", "green"); + downButton->setStyleSheet(Style::getStylesheet(QStringLiteral(":/ui/chatForm/buttons.css"))); + + layout->addWidget(searchLine); + layout->addWidget(upButton); + layout->addWidget(downButton); + + setLayout(layout); +} diff --git a/src/widget/searchform.h b/src/widget/searchform.h new file mode 100644 index 000000000..7aedfa4b7 --- /dev/null +++ b/src/widget/searchform.h @@ -0,0 +1,21 @@ +#ifndef SEARCHFORM_H +#define SEARCHFORM_H + +#include + +class QPushButton; +class QLineEdit; + +class SearchForm final : public QWidget +{ + Q_OBJECT +public: + explicit SearchForm(QWidget *parent = nullptr); + +private: + QPushButton* upButton; + QPushButton* downButton; + QLineEdit* searchLine; +}; + +#endif // SEARCHFORM_H diff --git a/ui/chatForm/buttons.css b/ui/chatForm/buttons.css index 11f19b32c..759ae87fb 100644 --- a/ui/chatForm/buttons.css +++ b/ui/chatForm/buttons.css @@ -75,6 +75,25 @@ QAbstractButton#searchButton height: 40px; } +/* SearchLine */ + + +QAbstractButton#searchUpButton +{ + background-image: url(":/ui/chatForm/searchUpButton.svg"); + border-radius: 5px; + width: 35px; + height: 35px; +} + +QAbstractButton#searchDownButton +{ + background-image: url(":/ui/chatForm/searchDownButton.svg"); + border-radius: 5px; + width: 35px; + height: 35px; +} + /* Common */ QAbstractButton diff --git a/ui/chatForm/searchDownButton.svg b/ui/chatForm/searchDownButton.svg new file mode 100644 index 000000000..e99f985c5 --- /dev/null +++ b/ui/chatForm/searchDownButton.svg @@ -0,0 +1,82 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/ui/chatForm/searchUpButton.svg b/ui/chatForm/searchUpButton.svg new file mode 100644 index 000000000..20fdf3732 --- /dev/null +++ b/ui/chatForm/searchUpButton.svg @@ -0,0 +1,82 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + From b881d32d1bddb7352b8d24e2442ef6277ff0d583 Mon Sep 17 00:00:00 2001 From: TriKriSta Date: Sat, 10 Feb 2018 14:43:03 +0200 Subject: [PATCH 03/12] feat: add text search --- src/chatlog/content/text.cpp | 31 +++++++ src/chatlog/content/text.h | 2 + src/widget/form/chatform.cpp | 123 ++++++++++++++++++++++++++++ src/widget/form/chatform.h | 6 ++ src/widget/form/genericchatform.cpp | 12 +-- src/widget/searchform.cpp | 25 ++++++ src/widget/searchform.h | 13 +++ 7 files changed, 207 insertions(+), 5 deletions(-) diff --git a/src/chatlog/content/text.cpp b/src/chatlog/content/text.cpp index 560086f0d..b568fa4a9 100644 --- a/src/chatlog/content/text.cpp +++ b/src/chatlog/content/text.cpp @@ -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; diff --git a/src/chatlog/content/text.h b/src/chatlog/content/text.h index d4e18f7aa..961fba609 100644 --- a/src/chatlog/content/text.h +++ b/src/chatlog/content/text.h @@ -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; diff --git a/src/widget/form/chatform.cpp b/src/widget/form/chatform.cpp index 226217705..cb5d1ad30 100644 --- a/src/widget/form/chatform.cpp +++ b/src/widget/form/chatform.cpp @@ -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 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(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 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(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 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(content); + text->deselectText(); + } + } +} + void ChatForm::retranslateUi() { loadHistoryAction->setText(tr("Load chat history...")); diff --git a/src/widget/form/chatform.h b/src/widget/form/chatform.h index 87912425a..f891488d3 100644 --- a/src/widget/form/chatform.h +++ b/src/widget/form/chatform.h @@ -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 ftransWidgets; bool isTyping; bool lastCallIsVideo; + QPoint searchPoint; }; #endif // CHATFORM_H diff --git a/src/widget/form/genericchatform.cpp b/src/widget/form/genericchatform.cpp index b5a018b2e..235912a80 100644 --- a/src/widget/form/genericchatform.cpp +++ b/src/widget/form/genericchatform.cpp @@ -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(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(e); + if ((ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::ShiftModifier) + && !ke->text().isEmpty()) + msgEdit->setFocus(); + } } return QWidget::event(e); } diff --git a/src/widget/searchform.cpp b/src/widget/searchform.cpp index 79be2701a..a67fbf258 100644 --- a/src/widget/searchform.cpp +++ b/src/widget/searchform.cpp @@ -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); } diff --git a/src/widget/searchform.h b/src/widget/searchform.h index 7aedfa4b7..49955bf26 100644 --- a/src/widget/searchform.h +++ b/src/widget/searchform.h @@ -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 From de9c9061175c97a9ee203d18a39e73f77544d5e6 Mon Sep 17 00:00:00 2001 From: TriKriSta Date: Sat, 10 Feb 2018 17:50:48 +0200 Subject: [PATCH 04/12] feat: edit load history for search --- src/chatlog/chatlog.cpp | 2 + src/chatlog/chatlog.h | 1 + src/persistence/history.cpp | 24 ++++++++++ src/persistence/history.h | 1 + src/widget/form/chatform.cpp | 89 +++++++++++++++++++++++++++--------- src/widget/form/chatform.h | 2 + src/widget/searchform.cpp | 26 ++++++++++- src/widget/searchform.h | 22 ++++++++- 8 files changed, 144 insertions(+), 23 deletions(-) diff --git a/src/chatlog/chatlog.cpp b/src/chatlog/chatlog.cpp index b45112bdb..e703ab457 100644 --- a/src/chatlog/chatlog.cpp +++ b/src/chatlog/chatlog.cpp @@ -815,6 +815,8 @@ void ChatLog::onWorkerTimeout() // hidden during busy screen verticalScrollBar()->show(); + + emit workerTimeoutFinished(); } } diff --git a/src/chatlog/chatlog.h b/src/chatlog/chatlog.h index c6d7fdb6a..4eb11a9a8 100644 --- a/src/chatlog/chatlog.h +++ b/src/chatlog/chatlog.h @@ -67,6 +67,7 @@ public: signals: void selectionChanged(); + void workerTimeoutFinished(); public slots: void forceRelayout(); diff --git a/src/persistence/history.cpp b/src/persistence/history.cpp index 445b793fa..c0a10d469 100644 --- a/src/persistence/history.cpp +++ b/src/persistence/history.cpp @@ -326,6 +326,30 @@ QList History::getChatHistoryCounts(const ToxPk& friendPk return counts; } +QDateTime History::getStartDateChatHistory(const QString& friendPk) +{ + QList counts; + auto rowCallback = [&counts](const QVector& row) { + counts.append(QDateTime::fromMSecsSinceEpoch(row[0].toLongLong())); + }; + + QString queryText = + QString("SELECT timestamp " + "FROM history " + "LEFT JOIN faux_offline_pending ON history.id = faux_offline_pending.id " + "JOIN peers chat ON chat_id = chat.id " + "WHERE chat.public_key='%1' ORDER BY timestamp ASC LIMIT 1;") + .arg(friendPk); + + db->execNow({queryText, rowCallback}); + + if (!counts.isEmpty()) { + return counts[0]; + } + + return QDateTime(); +} + /** * @brief Marks a message as sent. * Removing message from the faux-offline pending messages list. diff --git a/src/persistence/history.h b/src/persistence/history.h index c80883083..7ee9dcffd 100644 --- a/src/persistence/history.h +++ b/src/persistence/history.h @@ -82,6 +82,7 @@ public: const QDateTime& to); QList getChatHistoryCounts(const ToxPk& friendPk, const QDate& from, const QDate& to); + QDateTime getStartDateChatHistory(const QString& friendPk); void markAsSent(qint64 messageId); diff --git a/src/widget/form/chatform.cpp b/src/widget/form/chatform.cpp index cb5d1ad30..0c020a7f8 100644 --- a/src/widget/form/chatform.cpp +++ b/src/widget/form/chatform.cpp @@ -208,6 +208,8 @@ ChatForm::ChatForm(Friend* chatFriend, History* history) }); connect(headWidget, &ChatFormHeader::callRejected, this, &ChatForm::onRejectCallTriggered); + connect(chatWidget, &ChatLog::workerTimeoutFinished, this, &ChatForm::onContinueSearch); + updateCallButtons(); if (Nexus::getProfile()->isHistoryEnabled()) { loadHistory(QDateTime::currentDateTime().addDays(-7), true); @@ -500,9 +502,10 @@ void ChatForm::onSearchTrigered() searchForm->setMaximumHeight(50); headWidget->updateSearchButton(true); searchPoint = QPoint(1, -1); + searchAfterLoadHistory = false; } else { searchForm->setMaximumHeight(0); - searchForm->removeText(); + searchForm->removeSearchPhrase(); headWidget->updateSearchButton(false); desibleSearchText(); @@ -529,40 +532,71 @@ void ChatForm::onSearchUp(const QString &phrase) int startLine = numLines - searchPoint.x(); if (startLine == 0) { + QString pk = f->getPublicKey().toString(); + QDateTime startDate = history->getStartDateChatHistory(pk); + + if (startDate == earliestMessage) { + return; + } + + QDateTime newBaseData = earliestMessage.addDays(-1); + + if (startDate > newBaseData) { + newBaseData = startDate; + } + + searchAfterLoadHistory = true; + loadHistory(newBaseData); + 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(content); - QString txt = content->getText(); - if (txt.contains(phrase)) { - int startIndex = -1; - if (searchPoint.y() > -1) { - startIndex = searchPoint.y() - 1; - } + if (searchPoint.y() == 0) { + text->deselectText(); + searchPoint.setY(-1); + } else { + QString txt = content->getText(); - 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); + if (txt.contains(phrase, Qt::CaseInsensitive)) { + int startIndex = -1; + if (searchPoint.y() > -1) { + startIndex = searchPoint.y() - 1; + } - break; + int index = txt.lastIndexOf(phrase, startIndex, Qt::CaseInsensitive); + 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) { + QString pk = f->getPublicKey().toString(); + QDateTime startDate = history->getStartDateChatHistory(pk); + QDateTime newBaseData = earliestMessage.addDays(-1); + + if (startDate > newBaseData) { + newBaseData = startDate; + } + searchPoint.setX(numLines); - loadHistory(historyBaselineDate.addDays(-1)); - onSearchUp(phrase); + searchAfterLoadHistory = true; + loadHistory(newBaseData); } } } @@ -586,13 +620,13 @@ void ChatForm::onSearchDown(const QString &phrase) Text* text = static_cast(content); QString txt = content->getText(); - if (txt.contains(phrase)) { + if (txt.contains(phrase, Qt::CaseInsensitive)) { int startIndex = 0; if (searchPoint.y() > -1) { startIndex = searchPoint.y() + 1; } - int index = txt.indexOf(phrase, startIndex); + int index = txt.indexOf(phrase, startIndex, Qt::CaseInsensitive); if (index == -1 && searchPoint.y() > -1) { text->deselectText(); searchPoint.setY(-1); @@ -609,6 +643,15 @@ void ChatForm::onSearchDown(const QString &phrase) } } +void ChatForm::onContinueSearch() +{ + QString phrase = searchForm->getSearchPhrase(); + if (!phrase.isEmpty() && searchAfterLoadHistory) { + searchAfterLoadHistory = false; + onSearchUp(phrase); + } +} + void ChatForm::onFileSendFailed(uint32_t friendId, const QString& fname) { if (friendId != f->getId()) { @@ -874,6 +917,10 @@ void ChatForm::loadHistory(const QDateTime& since, bool processUndelivered) chatWidget->insertChatlineOnTop(historyMessages); savedSliderPos = verticalBar->maximum() - savedSliderPos; verticalBar->setValue(savedSliderPos); + + if (searchAfterLoadHistory && historyMessages.isEmpty()) { + onContinueSearch(); + } } void ChatForm::onScreenshotClicked() diff --git a/src/widget/form/chatform.h b/src/widget/form/chatform.h index f891488d3..8eb6c78c8 100644 --- a/src/widget/form/chatform.h +++ b/src/widget/form/chatform.h @@ -92,6 +92,7 @@ private slots: void earchInBegin(const QString& phrase); void onSearchUp(const QString& phrase); void onSearchDown(const QString& phrase); + void onContinueSearch(); void onFileSendFailed(uint32_t friendId, const QString& fname); void onFriendStatusChanged(quint32 friendId, Status status); void onFriendTypingChanged(quint32 friendId, bool isTyping); @@ -144,6 +145,7 @@ private: bool isTyping; bool lastCallIsVideo; QPoint searchPoint; + bool searchAfterLoadHistory; }; #endif // CHATFORM_H diff --git a/src/widget/searchform.cpp b/src/widget/searchform.cpp index a67fbf258..94231e2e6 100644 --- a/src/widget/searchform.cpp +++ b/src/widget/searchform.cpp @@ -1,3 +1,22 @@ +/* + Copyright © 2015-2016 by The qTox Project Contributors + + This file is part of qTox, a Qt-based graphical interface for Tox. + + qTox is libre software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + qTox is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with qTox. If not, see . +*/ + #include "searchform.h" #include "src/widget/style.h" #include @@ -31,11 +50,16 @@ SearchForm::SearchForm(QWidget *parent) : QWidget(parent) connect(downButton, &QPushButton::clicked, this, &SearchForm::clickedDown); } -void SearchForm::removeText() +void SearchForm::removeSearchPhrase() { searchLine->setText(""); } +QString SearchForm::getSearchPhrase() const +{ + return searchPhrase; +} + void SearchForm::changedSearchPhrare(const QString &text) { searchPhrase = text; diff --git a/src/widget/searchform.h b/src/widget/searchform.h index 49955bf26..3d0369732 100644 --- a/src/widget/searchform.h +++ b/src/widget/searchform.h @@ -1,3 +1,22 @@ +/* + Copyright © 2015-2016 by The qTox Project Contributors + + This file is part of qTox, a Qt-based graphical interface for Tox. + + qTox is libre software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + qTox is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with qTox. If not, see . +*/ + #ifndef SEARCHFORM_H #define SEARCHFORM_H @@ -11,7 +30,8 @@ class SearchForm final : public QWidget Q_OBJECT public: explicit SearchForm(QWidget *parent = nullptr); - void removeText(); + void removeSearchPhrase(); + QString getSearchPhrase() const; private: QPushButton* upButton; From 8bb80c770c1d21d1bdfc03c3d0569fabe6535e8f Mon Sep 17 00:00:00 2001 From: TriKriSta Date: Sun, 11 Feb 2018 17:38:05 +0200 Subject: [PATCH 05/12] feat: remove search button and add line in context menu --- res.qrc | 2 +- src/widget/chatformheader.cpp | 29 +--------- src/widget/chatformheader.h | 4 -- src/widget/form/chatform.cpp | 24 ++++---- src/widget/form/chatform.h | 2 +- src/widget/form/genericchatform.cpp | 18 +++++- src/widget/form/genericchatform.h | 2 + src/widget/searchform.cpp | 25 ++++++++- src/widget/searchform.h | 8 ++- ui/chatForm/buttons.css | 16 +++--- .../{searchButton.svg => hideButton.svg} | 55 +++++++++---------- 11 files changed, 98 insertions(+), 87 deletions(-) rename ui/chatForm/{searchButton.svg => hideButton.svg} (53%) diff --git a/res.qrc b/res.qrc index d68c3caf7..0c80b7515 100644 --- a/res.qrc +++ b/res.qrc @@ -95,8 +95,8 @@ img/caps_lock.svg ui/contentDialog/contentDialog.css ui/tooliconsZone/tooliconsZone.css - ui/chatForm/searchButton.svg ui/chatForm/searchDownButton.svg ui/chatForm/searchUpButton.svg + ui/chatForm/hideButton.svg diff --git a/src/widget/chatformheader.cpp b/src/widget/chatformheader.cpp index 508df880a..3c55a4658 100644 --- a/src/widget/chatformheader.cpp +++ b/src/widget/chatformheader.cpp @@ -76,12 +76,6 @@ const QString MIC_TOOL_TIP[] = { ChatFormHeader::tr("Mute microphone"), }; -const QString SEARCH_TOOL_TIP[] = { - ChatFormHeader::tr("Search in text"), - ChatFormHeader::tr("Unmute search"), - ChatFormHeader::tr("Mute search"), -}; - template QPushButton* createButton(const QString& name, T* self, Fun onClickSlot) { @@ -117,7 +111,6 @@ ChatFormHeader::ChatFormHeader(QWidget* parent) , videoState{CallButtonState::Disabled} , volState{ToolButtonState::Disabled} , micState{ToolButtonState::Disabled} - , searchState{ToolButtonState::Off} { QHBoxLayout* headLayout = new QHBoxLayout(); avatar = new MaskablePixmapWidget(this, AVATAR_SIZE, ":/img/avatar_mask.svg"); @@ -139,7 +132,6 @@ ChatFormHeader::ChatFormHeader(QWidget* parent) volButton = createButton("volButton", this, &ChatFormHeader::volMuteToggle); callButton = createButton("callButton", this, &ChatFormHeader::callTriggered); videoButton = createButton("videoButton", this, &ChatFormHeader::videoCallTriggered); - searchButton = createButton("searchButton", this, &ChatFormHeader::searchTriggered); QVBoxLayout* micButtonsLayout = new QVBoxLayout(); micButtonsLayout->setSpacing(MIC_BUTTONS_LAYOUT_SPACING); @@ -147,10 +139,9 @@ ChatFormHeader::ChatFormHeader(QWidget* parent) micButtonsLayout->addWidget(volButton, Qt::AlignTop | Qt::AlignRight); QGridLayout* buttonsLayout = new QGridLayout(); - buttonsLayout->addWidget(searchButton, 0, 0, 2, 1, Qt::AlignTop); - buttonsLayout->addLayout(micButtonsLayout, 0, 1, 2, 1, Qt::AlignTop | Qt::AlignRight); - buttonsLayout->addWidget(callButton, 0, 2, 2, 1, Qt::AlignTop); - buttonsLayout->addWidget(videoButton, 0, 3, 2, 1, Qt::AlignTop); + buttonsLayout->addLayout(micButtonsLayout, 0, 0, 2, 1, Qt::AlignTop | Qt::AlignRight); + buttonsLayout->addWidget(callButton, 0, 1, 2, 1, Qt::AlignTop); + buttonsLayout->addWidget(videoButton, 0, 2, 2, 1, Qt::AlignTop); buttonsLayout->setVerticalSpacing(0); buttonsLayout->setHorizontalSpacing(BUTTONS_LAYOUT_HOR_SPACING); @@ -180,7 +171,6 @@ void ChatFormHeader::setMode(ChatFormHeader::Mode mode) videoButton->hide(); volButton->hide(); micButton->hide(); - searchButton->hide(); } } @@ -190,7 +180,6 @@ void ChatFormHeader::retranslateUi() setStateToolTip(videoButton, videoState, VIDEO_TOOL_TIP); setStateToolTip(micButton, micState, MIC_TOOL_TIP); setStateToolTip(volButton, volState, VOL_TOOL_TIP); - setStateToolTip(searchButton, searchState, SEARCH_TOOL_TIP); } void ChatFormHeader::updateButtonsView() @@ -199,7 +188,6 @@ void ChatFormHeader::updateButtonsView() setStateName(videoButton, videoState); setStateName(micButton, micState); setStateName(volButton, volState); - setStateName(searchButton, searchState); retranslateUi(); Style::repolish(this); } @@ -281,17 +269,6 @@ void ChatFormHeader::updateMuteVolButton(bool active, bool outputMuted) updateButtonsView(); } -void ChatFormHeader::updateSearchButton(bool active) -{ - if (active) { - searchState = ToolButtonState::On; - } else { - searchState = ToolButtonState::Off; - } - - updateButtonsView(); -} - void ChatFormHeader::setAvatar(const QPixmap &img) { avatar->setPixmap(img); diff --git a/src/widget/chatformheader.h b/src/widget/chatformheader.h index 8fbc0d125..d744cf0d2 100644 --- a/src/widget/chatformheader.h +++ b/src/widget/chatformheader.h @@ -67,7 +67,6 @@ public: void updateCallButtons(bool online, bool audio, bool video = false); void updateMuteMicButton(bool active, bool inputMuted); void updateMuteVolButton(bool active, bool outputMuted); - void updateSearchButton(bool active); void setAvatar(const QPixmap& img); QSize getAvatarSize() const; @@ -82,7 +81,6 @@ signals: void videoCallTriggered(); void micMuteToggle(); void volMuteToggle(); - void searchTriggered(); void nameChanged(const QString& name); @@ -104,13 +102,11 @@ private: QPushButton* videoButton; QPushButton* volButton; QPushButton* micButton; - QPushButton* searchButton; CallButtonState callState; CallButtonState videoState; ToolButtonState volState; ToolButtonState micState; - ToolButtonState searchState; std::unique_ptr callConfirm; }; diff --git a/src/widget/form/chatform.cpp b/src/widget/form/chatform.cpp index 0c020a7f8..8251eba26 100644 --- a/src/widget/form/chatform.cpp +++ b/src/widget/form/chatform.cpp @@ -178,11 +178,11 @@ ChatForm::ChatForm(Friend* chatFriend, History* history) connect(headWidget, &ChatFormHeader::videoCallTriggered, this, &ChatForm::onVideoCallTriggered); connect(headWidget, &ChatFormHeader::micMuteToggle, this, &ChatForm::onMicMuteToggle); connect(headWidget, &ChatFormHeader::volMuteToggle, this, &ChatForm::onVolMuteToggle); - connect(headWidget, &ChatFormHeader::searchTriggered, this, &ChatForm::onSearchTrigered); - connect(searchForm, &SearchForm::searchInBegin, this, &ChatForm::earchInBegin); + connect(searchForm, &SearchForm::searchInBegin, this, &ChatForm::searchInBegin); connect(searchForm, &SearchForm::searchUp, this, &ChatForm::onSearchUp); connect(searchForm, &SearchForm::searchDown, this, &ChatForm::onSearchDown); + connect(searchForm, &SearchForm::visibleChanged, this, &ChatForm::onSearchTrigered); connect(msgEdit, &ChatTextEdit::enterPressed, this, &ChatForm::onSendTriggered); connect(msgEdit, &ChatTextEdit::textChanged, this, &ChatForm::onTextEditChanged); @@ -498,21 +498,17 @@ void ChatForm::onVolMuteToggle() void ChatForm::onSearchTrigered() { - if (searchForm->maximumHeight() == 0) { - searchForm->setMaximumHeight(50); - headWidget->updateSearchButton(true); - searchPoint = QPoint(1, -1); - searchAfterLoadHistory = false; - } else { - searchForm->setMaximumHeight(0); + if (searchForm->isHidden()) { searchForm->removeSearchPhrase(); - headWidget->updateSearchButton(false); desibleSearchText(); + } else { + searchPoint = QPoint(1, -1); + searchAfterLoadHistory = false; } } -void ChatForm::earchInBegin(const QString &phrase) +void ChatForm::searchInBegin(const QString &phrase) { desibleSearchText(); @@ -609,8 +605,12 @@ void ChatForm::onSearchDown(const QString &phrase) } QVector lines = chatWidget->getLines(); - int numLines = lines.size(); + if (lines.isEmpty()) { + return; + } + + int numLines = lines.size(); int startLine = numLines - searchPoint.x(); for (int i = startLine; i < numLines; ++i) { diff --git a/src/widget/form/chatform.h b/src/widget/form/chatform.h index 8eb6c78c8..9a4f87673 100644 --- a/src/widget/form/chatform.h +++ b/src/widget/form/chatform.h @@ -89,7 +89,7 @@ private slots: void onVolMuteToggle(); void onSearchTrigered(); - void earchInBegin(const QString& phrase); + void searchInBegin(const QString& phrase); void onSearchUp(const QString& phrase); void onSearchDown(const QString& phrase); void onContinueSearch(); diff --git a/src/widget/form/genericchatform.cpp b/src/widget/form/genericchatform.cpp index 235912a80..14e12f26d 100644 --- a/src/widget/form/genericchatform.cpp +++ b/src/widget/form/genericchatform.cpp @@ -139,7 +139,7 @@ GenericChatForm::GenericChatForm(QWidget* parent) searchForm = new SearchForm(); chatWidget = new ChatLog(this); chatWidget->setBusyNotification(ChatMessage::createBusyNotification()); - searchForm->setMaximumHeight(0); + searchForm->hide(); // settings const Settings& s = Settings::getInstance(); @@ -202,6 +202,12 @@ GenericChatForm::GenericChatForm(QWidget* parent) addAction(quoteAction); menu.addSeparator(); + searchAction = menu.addAction(QIcon(), QString(), this, SLOT(searchFormShow()), + QKeySequence(Qt::CTRL + Qt::Key_F)); + addAction(searchAction); + + menu.addSeparator(); + menu.addActions(chatWidget->actions()); menu.addSeparator(); @@ -297,7 +303,7 @@ void GenericChatForm::showEvent(QShowEvent*) bool GenericChatForm::event(QEvent* e) { // If the user accidentally starts typing outside of the msgEdit, focus it automatically - if (searchForm->maximumHeight() == 0) { + if (searchForm->isHidden()) { if (e->type() == QEvent::KeyRelease && !msgEdit->hasFocus()) { QKeyEvent* ke = static_cast(e); if ((ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::ShiftModifier) @@ -668,6 +674,13 @@ void GenericChatForm::copyLink() QApplication::clipboard()->setText(linkText); } +void GenericChatForm::searchFormShow() +{ + if (searchForm->isHidden()) { + searchForm->show(); + } +} + void GenericChatForm::retranslateUi() { sendButton->setToolTip(tr("Send message")); @@ -678,6 +691,7 @@ void GenericChatForm::retranslateUi() clearAction->setText(tr("Clear displayed messages")); quoteAction->setText(tr("Quote selected text")); copyLinkAction->setText(tr("Copy link address")); + searchAction->setText(tr("Search in text")); } void GenericChatForm::showNetcam() diff --git a/src/widget/form/genericchatform.h b/src/widget/form/genericchatform.h index d9eb2307b..b4be7fc74 100644 --- a/src/widget/form/genericchatform.h +++ b/src/widget/form/genericchatform.h @@ -103,6 +103,7 @@ protected slots: void onSplitterMoved(int pos, int index); void quoteSelectedText(); void copyLink(); + void searchFormShow(); private: void retranslateUi(); @@ -134,6 +135,7 @@ protected: QAction* clearAction; QAction* quoteAction; QAction* copyLinkAction; + QAction* searchAction; ToxPk previousId; diff --git a/src/widget/searchform.cpp b/src/widget/searchform.cpp index 94231e2e6..145f11f8b 100644 --- a/src/widget/searchform.cpp +++ b/src/widget/searchform.cpp @@ -39,15 +39,24 @@ SearchForm::SearchForm(QWidget *parent) : QWidget(parent) downButton->setProperty("state", "green"); downButton->setStyleSheet(Style::getStylesheet(QStringLiteral(":/ui/chatForm/buttons.css"))); + hideButton = new QPushButton(); + hideButton->setAttribute(Qt::WA_LayoutUsesWidgetRect); + hideButton->setObjectName("hideButton"); + hideButton->setProperty("state", "red"); + hideButton->setStyleSheet(Style::getStylesheet(QStringLiteral(":/ui/chatForm/buttons.css"))); + + layout->setMargin(0); layout->addWidget(searchLine); layout->addWidget(upButton); layout->addWidget(downButton); + layout->addWidget(hideButton); setLayout(layout); - connect(searchLine, &QLineEdit::textChanged, this, &SearchForm::changedSearchPhrare); + connect(searchLine, &QLineEdit::textChanged, this, &SearchForm::changedSearchPhrase); connect(upButton, &QPushButton::clicked, this, &SearchForm::clickedUp); connect(downButton, &QPushButton::clicked, this, &SearchForm::clickedDown); + connect(hideButton, &QPushButton::clicked, this, &SearchForm::clickedHide); } void SearchForm::removeSearchPhrase() @@ -60,7 +69,13 @@ QString SearchForm::getSearchPhrase() const return searchPhrase; } -void SearchForm::changedSearchPhrare(const QString &text) +void SearchForm::showEvent(QShowEvent *event) +{ + QWidget::showEvent(event); + emit visibleChanged(); +} + +void SearchForm::changedSearchPhrase(const QString &text) { searchPhrase = text; emit searchInBegin(searchPhrase); @@ -75,3 +90,9 @@ void SearchForm::clickedDown() { emit searchDown(searchPhrase); } + +void SearchForm::clickedHide() +{ + hide(); + emit visibleChanged(); +} diff --git a/src/widget/searchform.h b/src/widget/searchform.h index 3d0369732..54faf386a 100644 --- a/src/widget/searchform.h +++ b/src/widget/searchform.h @@ -36,19 +36,25 @@ public: private: QPushButton* upButton; QPushButton* downButton; + QPushButton* hideButton; QLineEdit* searchLine; QString searchPhrase; +protected: + virtual void showEvent(QShowEvent *event); + private slots: - void changedSearchPhrare(const QString &text); + void changedSearchPhrase(const QString &text); void clickedUp(); void clickedDown(); + void clickedHide(); signals: void searchInBegin(const QString &); void searchUp(const QString &); void searchDown(const QString &); + void visibleChanged(); }; #endif // SEARCHFORM_H diff --git a/ui/chatForm/buttons.css b/ui/chatForm/buttons.css index 759ae87fb..4042f362b 100644 --- a/ui/chatForm/buttons.css +++ b/ui/chatForm/buttons.css @@ -67,16 +67,16 @@ QAbstractButton#callButton height: 40px; } -QAbstractButton#searchButton -{ - background-image: url(":/ui/chatForm/searchButton.svg"); - border-radius: 5px; - width: 50px; - height: 40px; -} - /* SearchLine */ +QAbstractButton#hideButton +{ + background-image: url(":/ui/chatForm/hideButton.svg"); + border-radius: 5px; + width: 35px; + height: 35px; +} + QAbstractButton#searchUpButton { diff --git a/ui/chatForm/searchButton.svg b/ui/chatForm/hideButton.svg similarity index 53% rename from ui/chatForm/searchButton.svg rename to ui/chatForm/hideButton.svg index bebf9b02c..a29b2da47 100644 --- a/ui/chatForm/searchButton.svg +++ b/ui/chatForm/hideButton.svg @@ -9,13 +9,13 @@ xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="8.5557709mm" - height="5.0002112mm" - viewBox="0 0 8.555771 5.0002106" + width="5.5071211mm" + height="5.5071211mm" + viewBox="0 0 5.5071209 5.5071212" version="1.1" id="svg8" inkscape:version="0.92.2 5c3e80d, 2017-08-06" - sodipodi:docname="searchButton.svg"> + sodipodi:docname="hideButton.svg"> - - + inkscape:window-maximized="1" /> @@ -61,26 +56,26 @@ inkscape:label="Layer 1" inkscape:groupmode="layer" id="layer1" - transform="translate(340.51327,202.78083)"> + transform="translate(59.891963,-41.449704)"> - + y="41.988605" + x="-43.942345" + height="1.5" + width="11.5" + id="rect11" + style="fill:#ffffff;stroke-width:0.26458332" /> + From 7718734c9ab9705c1a1274b2a447611c1a2e22b4 Mon Sep 17 00:00:00 2001 From: TriKriSta Date: Sun, 11 Feb 2018 23:09:13 +0200 Subject: [PATCH 06/12] feat: add search in text in group chats --- res.qrc | 6 +- src/chatlog/content/text.cpp | 7 +- src/widget/form/chatform.cpp | 159 ++++------------------------ src/widget/form/chatform.h | 13 +-- src/widget/form/genericchatform.cpp | 135 +++++++++++++++++++++++ src/widget/form/genericchatform.h | 12 +++ src/widget/form/groupchatform.cpp | 12 +++ src/widget/form/groupchatform.h | 2 + src/widget/searchform.cpp | 36 +++---- src/widget/searchform.h | 14 +-- 10 files changed, 216 insertions(+), 180 deletions(-) diff --git a/res.qrc b/res.qrc index 0c80b7515..8bba49087 100644 --- a/res.qrc +++ b/res.qrc @@ -53,12 +53,15 @@ ui/chatArea/scrollBarRightArrow.svg ui/chatForm/buttons.css ui/chatForm/callButton.svg + ui/chatForm/hideButton.svg ui/chatForm/micButton.svg ui/chatForm/videoButton.svg ui/chatForm/volButton.svg ui/chatForm/emoteButton.svg ui/chatForm/fileButton.svg ui/chatForm/screenshotButton.svg + ui/chatForm/searchDownButton.svg + ui/chatForm/searchUpButton.svg ui/chatForm/sendButton.svg ui/emoticonWidget/dot_page.svg ui/emoticonWidget/dot_page_current.svg @@ -95,8 +98,5 @@ img/caps_lock.svg ui/contentDialog/contentDialog.css ui/tooliconsZone/tooliconsZone.css - ui/chatForm/searchDownButton.svg - ui/chatForm/searchUpButton.svg - ui/chatForm/hideButton.svg diff --git a/src/chatlog/content/text.cpp b/src/chatlog/content/text.cpp index b568fa4a9..a954e243e 100644 --- a/src/chatlog/content/text.cpp +++ b/src/chatlog/content/text.cpp @@ -62,12 +62,13 @@ void Text::selectText(const QString &txt, const int index) { regenerate(); - if (!doc) + if (!doc) { return; + } - QTextCursor cursor = doc->find(txt, index); + auto cursor = doc->find(txt, index); - if (cursor != QTextCursor()) { + if (!cursor.isNull()) { cursor.beginEditBlock(); cursor.setPosition(index); cursor.setPosition(index + txt.size(), QTextCursor::KeepAnchor); diff --git a/src/widget/form/chatform.cpp b/src/widget/form/chatform.cpp index 8251eba26..5df36c32a 100644 --- a/src/widget/form/chatform.cpp +++ b/src/widget/form/chatform.cpp @@ -179,11 +179,6 @@ ChatForm::ChatForm(Friend* chatFriend, History* history) connect(headWidget, &ChatFormHeader::micMuteToggle, this, &ChatForm::onMicMuteToggle); connect(headWidget, &ChatFormHeader::volMuteToggle, this, &ChatForm::onVolMuteToggle); - connect(searchForm, &SearchForm::searchInBegin, this, &ChatForm::searchInBegin); - connect(searchForm, &SearchForm::searchUp, this, &ChatForm::onSearchUp); - connect(searchForm, &SearchForm::searchDown, this, &ChatForm::onSearchDown); - connect(searchForm, &SearchForm::visibleChanged, this, &ChatForm::onSearchTrigered); - connect(msgEdit, &ChatTextEdit::enterPressed, this, &ChatForm::onSendTriggered); connect(msgEdit, &ChatTextEdit::textChanged, this, &ChatForm::onTextEditChanged); connect(msgEdit, &ChatTextEdit::pasteImage, this, &ChatForm::sendImage); @@ -208,8 +203,6 @@ ChatForm::ChatForm(Friend* chatFriend, History* history) }); connect(headWidget, &ChatFormHeader::callRejected, this, &ChatForm::onRejectCallTriggered); - connect(chatWidget, &ChatLog::workerTimeoutFinished, this, &ChatForm::onContinueSearch); - updateCallButtons(); if (Nexus::getProfile()->isHistoryEnabled()) { loadHistory(QDateTime::currentDateTime().addDays(-7), true); @@ -496,27 +489,7 @@ void ChatForm::onVolMuteToggle() updateMuteVolButton(); } -void ChatForm::onSearchTrigered() -{ - if (searchForm->isHidden()) { - searchForm->removeSearchPhrase(); - - desibleSearchText(); - } else { - searchPoint = QPoint(1, -1); - searchAfterLoadHistory = false; - } -} - -void ChatForm::searchInBegin(const QString &phrase) -{ - desibleSearchText(); - - searchPoint = QPoint(1, -1); - onSearchUp(phrase); -} - -void ChatForm::onSearchUp(const QString &phrase) +void ChatForm::onSearchUp(const QString& phrase) { if (phrase.isEmpty()) { desibleSearchText(); @@ -531,7 +504,7 @@ void ChatForm::onSearchUp(const QString &phrase) QString pk = f->getPublicKey().toString(); QDateTime startDate = history->getStartDateChatHistory(pk); - if (startDate == earliestMessage) { + if (!startDate.isValid() || startDate == earliestMessage) { return; } @@ -547,109 +520,30 @@ void ChatForm::onSearchUp(const QString &phrase) return; } - for (int i = startLine; i >= 0; --i) { - ChatLine::Ptr l = lines[i]; + bool isSearch = searchInText(phrase, true); - if (l->getColumnCount() >= 2) { - ChatLineContent* content = l->getContent(1); - Text* text = static_cast(content); + if (!isSearch) { + QString pk = f->getPublicKey().toString(); + QDateTime startDate = history->getStartDateChatHistory(pk); + QDateTime newBaseData = earliestMessage.addDays(-1); - if (searchPoint.y() == 0) { - text->deselectText(); - searchPoint.setY(-1); - } else { - QString txt = content->getText(); - - if (txt.contains(phrase, Qt::CaseInsensitive)) { - int startIndex = -1; - if (searchPoint.y() > -1) { - startIndex = searchPoint.y() - 1; - } - - int index = txt.lastIndexOf(phrase, startIndex, Qt::CaseInsensitive); - 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) { - QString pk = f->getPublicKey().toString(); - QDateTime startDate = history->getStartDateChatHistory(pk); - QDateTime newBaseData = earliestMessage.addDays(-1); - - if (startDate > newBaseData) { - newBaseData = startDate; - } - - searchPoint.setX(numLines); - searchAfterLoadHistory = true; - loadHistory(newBaseData); - } + if (!startDate.isValid()) { + return; } + + if (startDate > newBaseData) { + newBaseData = startDate; + } + + searchPoint.setX(numLines); + searchAfterLoadHistory = true; + loadHistory(newBaseData); } } -void ChatForm::onSearchDown(const QString &phrase) +void ChatForm::onSearchDown(const QString& phrase) { - if (phrase.isEmpty()) { - desibleSearchText(); - } - - QVector lines = chatWidget->getLines(); - - if (lines.isEmpty()) { - return; - } - - 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(content); - QString txt = content->getText(); - - if (txt.contains(phrase, Qt::CaseInsensitive)) { - int startIndex = 0; - if (searchPoint.y() > -1) { - startIndex = searchPoint.y() + 1; - } - - int index = txt.indexOf(phrase, startIndex, Qt::CaseInsensitive); - 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; - } - } - } - } -} - -void ChatForm::onContinueSearch() -{ - QString phrase = searchForm->getSearchPhrase(); - if (!phrase.isEmpty() && searchAfterLoadHistory) { - searchAfterLoadHistory = false; - onSearchUp(phrase); - } + searchInText(phrase, false); } void ChatForm::onFileSendFailed(uint32_t friendId, const QString& fname) @@ -1124,21 +1018,6 @@ void ChatForm::SendMessageStr(QString msg) } } -void ChatForm::desibleSearchText() -{ - if (searchPoint != QPoint(1, -1)) { - QVector 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(content); - text->deselectText(); - } - } -} - void ChatForm::retranslateUi() { loadHistoryAction->setText(tr("Load chat history...")); diff --git a/src/widget/form/chatform.h b/src/widget/form/chatform.h index 9a4f87673..42dd82d77 100644 --- a/src/widget/form/chatform.h +++ b/src/widget/form/chatform.h @@ -72,6 +72,10 @@ public slots: void onAvatarChange(uint32_t friendId, const QPixmap& pic); void onAvatarRemoved(uint32_t friendId); +protected slots: + void onSearchUp(const QString& phrase) override; + void onSearchDown(const QString& phrase) override; + private slots: void clearChatArea(bool notInForm) override final; void onSendTriggered() override; @@ -87,12 +91,7 @@ private slots: void onRejectCallTriggered(); void onMicMuteToggle(); void onVolMuteToggle(); - void onSearchTrigered(); - void searchInBegin(const QString& phrase); - void onSearchUp(const QString& phrase); - void onSearchDown(const QString& phrase); - void onContinueSearch(); void onFileSendFailed(uint32_t friendId, const QString& fname); void onFriendStatusChanged(quint32 friendId, Status status); void onFriendTypingChanged(quint32 friendId, bool isTyping); @@ -117,8 +116,6 @@ private: void updateCallButtons(); void SendMessageStr(QString msg); - void desibleSearchText(); - protected: GenericNetCamView* createNetcam() final override; void insertChatMessage(ChatMessage::Ptr msg) final override; @@ -144,8 +141,6 @@ private: QHash ftransWidgets; bool isTyping; bool lastCallIsVideo; - QPoint searchPoint; - bool searchAfterLoadHistory; }; #endif // CHATFORM_H diff --git a/src/widget/form/genericchatform.cpp b/src/widget/form/genericchatform.cpp index 14e12f26d..b23494b80 100644 --- a/src/widget/form/genericchatform.cpp +++ b/src/widget/form/genericchatform.cpp @@ -224,6 +224,13 @@ GenericChatForm::GenericChatForm(QWidget* parent) connect(chatWidget, &ChatLog::customContextMenuRequested, this, &GenericChatForm::onChatContextMenuRequested); + connect(searchForm, &SearchForm::searchInBegin, this, &GenericChatForm::searchInBegin); + connect(searchForm, &SearchForm::searchUp, this, &GenericChatForm::onSearchUp); + connect(searchForm, &SearchForm::searchDown, this, &GenericChatForm::onSearchDown); + connect(searchForm, &SearchForm::visibleChanged, this, &GenericChatForm::onSearchTrigered); + + connect(chatWidget, &ChatLog::workerTimeoutFinished, this, &GenericChatForm::onContinueSearch); + chatWidget->setStyleSheet(Style::getStylesheet(":/ui/chatArea/chatArea.css")); headWidget->setStyleSheet(Style::getStylesheet(":/ui/chatArea/chatHead.css")); @@ -241,6 +248,7 @@ GenericChatForm::GenericChatForm(QWidget* parent) GenericChatForm::~GenericChatForm() { Translator::unregister(this); + delete searchForm; } void GenericChatForm::adjustFileMenuPosition() @@ -531,6 +539,104 @@ void GenericChatForm::addSystemDateMessage() insertChatMessage(ChatMessage::createChatInfoMessage(dateText, ChatMessage::INFO, QDateTime())); } +void GenericChatForm::desibleSearchText() +{ + if (searchPoint != QPoint(1, -1)) { + QVector 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(content); + text->deselectText(); + } + } +} + +bool GenericChatForm::searchInText(const QString& phrase, bool searchUp) +{ + bool isSearch = false; + + if (phrase.isEmpty()) { + desibleSearchText(); + } + + QVector lines = chatWidget->getLines(); + + if (lines.isEmpty()) { + return isSearch; + } + + int numLines = lines.size(); + int startLine = numLines - searchPoint.x(); + + if (startLine < 0 || startLine >= numLines) { + return isSearch; + } + + for (int i = startLine; searchUp ? i >= 0 : i < numLines; searchUp ? --i : ++i) { + ChatLine::Ptr l = lines[i]; + + if (l->getColumnCount() < 2) { + continue; + } + + ChatLineContent* content = l->getContent(1); + Text* text = static_cast(content); + + if (searchUp && searchPoint.y() == 0) { + text->deselectText(); + searchPoint.setY(-1); + + continue; + } + + QString txt = content->getText(); + + if (txt.contains(phrase, Qt::CaseInsensitive)) { + int index = indexForSearchInLine(txt, phrase, searchUp); + 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); + isSearch = true; + + break; + } + } + } + + return isSearch; +} + +int GenericChatForm::indexForSearchInLine(const QString& txt, const QString& phrase, bool searchUp) +{ + int index = 0; + + if (searchUp) { + int startIndex = -1; + if (searchPoint.y() > -1) { + startIndex = searchPoint.y() - 1; + } + + index = txt.lastIndexOf(phrase, startIndex, Qt::CaseInsensitive); + } else { + int startIndex = 0; + if (searchPoint.y() > -1) { + startIndex = searchPoint.y() + 1; + } + + index = txt.indexOf(phrase, startIndex, Qt::CaseInsensitive); + } + + return index; +} + void GenericChatForm::clearChatArea() { clearChatArea(true); @@ -681,6 +787,35 @@ void GenericChatForm::searchFormShow() } } +void GenericChatForm::onSearchTrigered() +{ + if (searchForm->isHidden()) { + searchForm->removeSearchPhrase(); + + desibleSearchText(); + } else { + searchPoint = QPoint(1, -1); + searchAfterLoadHistory = false; + } +} + +void GenericChatForm::searchInBegin(const QString& phrase) +{ + desibleSearchText(); + + searchPoint = QPoint(1, -1); + onSearchUp(phrase); +} + +void GenericChatForm::onContinueSearch() +{ + QString phrase = searchForm->getSearchPhrase(); + if (!phrase.isEmpty() && searchAfterLoadHistory) { + searchAfterLoadHistory = false; + onSearchUp(phrase); + } +} + void GenericChatForm::retranslateUi() { sendButton->setToolTip(tr("Send message")); diff --git a/src/widget/form/genericchatform.h b/src/widget/form/genericchatform.h index b4be7fc74..e15008e61 100644 --- a/src/widget/form/genericchatform.h +++ b/src/widget/form/genericchatform.h @@ -104,6 +104,12 @@ protected slots: void quoteSelectedText(); void copyLink(); void searchFormShow(); + void onSearchTrigered(); + + void searchInBegin(const QString& phrase); + virtual void onSearchUp(const QString& phrase) = 0; + virtual void onSearchDown(const QString& phrase) = 0; + void onContinueSearch(); private: void retranslateUi(); @@ -125,6 +131,9 @@ protected: virtual bool event(QEvent*) final override; virtual void resizeEvent(QResizeEvent* event) final override; virtual bool eventFilter(QObject* object, QEvent* event) final override; + void desibleSearchText(); + bool searchInText(const QString& phrase, bool searchUp); + int indexForSearchInLine(const QString& txt, const QString& phrase, bool searchUp); protected: bool audioInputFlag; @@ -160,6 +169,9 @@ protected: FlyoutOverlayWidget* fileFlyout; GenericNetCamView* netcam; Widget* parent; + + QPoint searchPoint; + bool searchAfterLoadHistory; }; #endif // GENERICCHATFORM_H diff --git a/src/widget/form/groupchatform.cpp b/src/widget/form/groupchatform.cpp index 853aac3d2..f76378833 100644 --- a/src/widget/form/groupchatform.cpp +++ b/src/widget/form/groupchatform.cpp @@ -22,6 +22,8 @@ #include "tabcompleter.h" #include "src/core/core.h" #include "src/core/coreav.h" +#include "src/chatlog/chatlog.h" +#include "src/chatlog/content/text.h" #include "src/model/friend.h" #include "src/friendlist.h" #include "src/model/group.h" @@ -189,6 +191,16 @@ void GroupChatForm::onTitleChanged(uint32_t groupId, const QString& author, cons addSystemInfoMessage(message, ChatMessage::INFO, curTime); } +void GroupChatForm::onSearchUp(const QString& phrase) +{ + searchInText(phrase, true); +} + +void GroupChatForm::onSearchDown(const QString& phrase) +{ + searchInText(phrase, false); +} + void GroupChatForm::onScreenshotClicked() { // Unsupported diff --git a/src/widget/form/groupchatform.h b/src/widget/form/groupchatform.h index fd436a761..ac55e075d 100644 --- a/src/widget/form/groupchatform.h +++ b/src/widget/form/groupchatform.h @@ -49,6 +49,8 @@ private slots: void onCallClicked(); void onUserListChanged(); void onTitleChanged(uint32_t groupId, const QString& author, const QString& title); + void onSearchUp(const QString& phrase) override; + void onSearchDown(const QString& phrase) override; protected: virtual GenericNetCamView* createNetcam() final override; diff --git a/src/widget/searchform.cpp b/src/widget/searchform.cpp index 145f11f8b..095ff1ef4 100644 --- a/src/widget/searchform.cpp +++ b/src/widget/searchform.cpp @@ -23,27 +23,14 @@ #include #include -SearchForm::SearchForm(QWidget *parent) : QWidget(parent) +SearchForm::SearchForm(QWidget* parent) : QWidget(parent) { QHBoxLayout *layout = new QHBoxLayout(); searchLine = new QLineEdit(); - upButton = new QPushButton(); - upButton->setAttribute(Qt::WA_LayoutUsesWidgetRect); - upButton->setObjectName("searchUpButton"); - upButton->setProperty("state", "green"); - upButton->setStyleSheet(Style::getStylesheet(QStringLiteral(":/ui/chatForm/buttons.css"))); - downButton = new QPushButton(); - downButton->setAttribute(Qt::WA_LayoutUsesWidgetRect); - downButton->setObjectName("searchDownButton"); - downButton->setProperty("state", "green"); - downButton->setStyleSheet(Style::getStylesheet(QStringLiteral(":/ui/chatForm/buttons.css"))); - - hideButton = new QPushButton(); - hideButton->setAttribute(Qt::WA_LayoutUsesWidgetRect); - hideButton->setObjectName("hideButton"); - hideButton->setProperty("state", "red"); - hideButton->setStyleSheet(Style::getStylesheet(QStringLiteral(":/ui/chatForm/buttons.css"))); + upButton = createButton("searchUpButton", "green"); + downButton = createButton("searchDownButton", "green"); + hideButton = createButton("hideButton","red"); layout->setMargin(0); layout->addWidget(searchLine); @@ -69,13 +56,24 @@ QString SearchForm::getSearchPhrase() const return searchPhrase; } -void SearchForm::showEvent(QShowEvent *event) +QPushButton *SearchForm::createButton(const QString& name, const QString& state) +{ + QPushButton* btn = new QPushButton(); + btn->setAttribute(Qt::WA_LayoutUsesWidgetRect); + btn->setObjectName(name); + btn->setProperty("state", state); + btn->setStyleSheet(Style::getStylesheet(QStringLiteral(":/ui/chatForm/buttons.css"))); + + return btn; +} + +void SearchForm::showEvent(QShowEvent* event) { QWidget::showEvent(event); emit visibleChanged(); } -void SearchForm::changedSearchPhrase(const QString &text) +void SearchForm::changedSearchPhrase(const QString& text) { searchPhrase = text; emit searchInBegin(searchPhrase); diff --git a/src/widget/searchform.h b/src/widget/searchform.h index 54faf386a..70f8ae076 100644 --- a/src/widget/searchform.h +++ b/src/widget/searchform.h @@ -29,11 +29,13 @@ class SearchForm final : public QWidget { Q_OBJECT public: - explicit SearchForm(QWidget *parent = nullptr); + explicit SearchForm(QWidget* parent = nullptr); void removeSearchPhrase(); QString getSearchPhrase() const; private: + QPushButton* createButton(const QString& name, const QString& state); + QPushButton* upButton; QPushButton* downButton; QPushButton* hideButton; @@ -42,18 +44,18 @@ private: QString searchPhrase; protected: - virtual void showEvent(QShowEvent *event); + virtual void showEvent(QShowEvent* event); private slots: - void changedSearchPhrase(const QString &text); + void changedSearchPhrase(const QString& text); void clickedUp(); void clickedDown(); void clickedHide(); signals: - void searchInBegin(const QString &); - void searchUp(const QString &); - void searchDown(const QString &); + void searchInBegin(const QString& phrase); + void searchUp(const QString& phrase); + void searchDown(const QString& phrase); void visibleChanged(); }; From 18fa8a745bdafddc00ba2f577c36451f40edfd61 Mon Sep 17 00:00:00 2001 From: TriKriSta Date: Mon, 12 Feb 2018 01:02:28 +0200 Subject: [PATCH 07/12] feat: optimise search in history --- src/persistence/history.cpp | 11 ++++++++--- src/persistence/history.h | 2 +- src/widget/form/chatform.cpp | 19 ++++--------------- 3 files changed, 13 insertions(+), 19 deletions(-) diff --git a/src/persistence/history.cpp b/src/persistence/history.cpp index c0a10d469..5aaa18ce3 100644 --- a/src/persistence/history.cpp +++ b/src/persistence/history.cpp @@ -326,7 +326,7 @@ QList History::getChatHistoryCounts(const ToxPk& friendPk return counts; } -QDateTime History::getStartDateChatHistory(const QString& friendPk) +QDateTime History::getDateWhereFindPhrase(const QString& friendPk, const QDateTime& from, const QString& phrase) { QList counts; auto rowCallback = [&counts](const QVector& row) { @@ -338,8 +338,13 @@ QDateTime History::getStartDateChatHistory(const QString& friendPk) "FROM history " "LEFT JOIN faux_offline_pending ON history.id = faux_offline_pending.id " "JOIN peers chat ON chat_id = chat.id " - "WHERE chat.public_key='%1' ORDER BY timestamp ASC LIMIT 1;") - .arg(friendPk); + "WHERE chat.public_key='%1' " + "AND message LIKE '%%2%' " + "AND timestamp < '%3' ORDER BY timestamp DESC LIMIT 1;") + .arg(friendPk) + .arg(phrase) + .arg(from.toMSecsSinceEpoch()); + db->execNow({queryText, rowCallback}); diff --git a/src/persistence/history.h b/src/persistence/history.h index 7ee9dcffd..956129dbc 100644 --- a/src/persistence/history.h +++ b/src/persistence/history.h @@ -82,7 +82,7 @@ public: const QDateTime& to); QList getChatHistoryCounts(const ToxPk& friendPk, const QDate& from, const QDate& to); - QDateTime getStartDateChatHistory(const QString& friendPk); + QDateTime getDateWhereFindPhrase(const QString& friendPk, const QDateTime& from, const QString& phrase); void markAsSent(qint64 messageId); diff --git a/src/widget/form/chatform.cpp b/src/widget/form/chatform.cpp index 5df36c32a..c370bdf4a 100644 --- a/src/widget/form/chatform.cpp +++ b/src/widget/form/chatform.cpp @@ -502,18 +502,12 @@ void ChatForm::onSearchUp(const QString& phrase) if (startLine == 0) { QString pk = f->getPublicKey().toString(); - QDateTime startDate = history->getStartDateChatHistory(pk); + QDateTime newBaseData = history->getDateWhereFindPhrase(pk, earliestMessage, phrase); - if (!startDate.isValid() || startDate == earliestMessage) { + if (!newBaseData.isValid()) { return; } - QDateTime newBaseData = earliestMessage.addDays(-1); - - if (startDate > newBaseData) { - newBaseData = startDate; - } - searchAfterLoadHistory = true; loadHistory(newBaseData); @@ -524,17 +518,12 @@ void ChatForm::onSearchUp(const QString& phrase) if (!isSearch) { QString pk = f->getPublicKey().toString(); - QDateTime startDate = history->getStartDateChatHistory(pk); - QDateTime newBaseData = earliestMessage.addDays(-1); + QDateTime newBaseData = history->getDateWhereFindPhrase(pk, earliestMessage, phrase); - if (!startDate.isValid()) { + if (!newBaseData.isValid()) { return; } - if (startDate > newBaseData) { - newBaseData = startDate; - } - searchPoint.setX(numLines); searchAfterLoadHistory = true; loadHistory(newBaseData); From ffb51e8a0ea7dc3fb01f1f7650edc80b779a9be2 Mon Sep 17 00:00:00 2001 From: TriKriSta Date: Mon, 12 Feb 2018 19:24:22 +0200 Subject: [PATCH 08/12] feat: add hot keys for search --- src/widget/form/genericchatform.cpp | 21 ++++++------ src/widget/form/genericchatform.h | 2 +- src/widget/searchform.cpp | 50 +++++++++++++++++++++++------ src/widget/searchform.h | 28 +++++++++++++--- 4 files changed, 77 insertions(+), 24 deletions(-) diff --git a/src/widget/form/genericchatform.cpp b/src/widget/form/genericchatform.cpp index b23494b80..bed679b30 100644 --- a/src/widget/form/genericchatform.cpp +++ b/src/widget/form/genericchatform.cpp @@ -227,7 +227,7 @@ GenericChatForm::GenericChatForm(QWidget* parent) connect(searchForm, &SearchForm::searchInBegin, this, &GenericChatForm::searchInBegin); connect(searchForm, &SearchForm::searchUp, this, &GenericChatForm::onSearchUp); connect(searchForm, &SearchForm::searchDown, this, &GenericChatForm::onSearchDown); - connect(searchForm, &SearchForm::visibleChanged, this, &GenericChatForm::onSearchTrigered); + connect(searchForm, &SearchForm::visibleChanged, this, &GenericChatForm::onSearchTriggered); connect(chatWidget, &ChatLog::workerTimeoutFinished, this, &GenericChatForm::onContinueSearch); @@ -311,14 +311,18 @@ void GenericChatForm::showEvent(QShowEvent*) bool GenericChatForm::event(QEvent* e) { // If the user accidentally starts typing outside of the msgEdit, focus it automatically - if (searchForm->isHidden()) { + if (e->type() == QEvent::KeyRelease && !msgEdit->hasFocus()) { QKeyEvent* ke = static_cast(e); if ((ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::ShiftModifier) - && !ke->text().isEmpty()) - msgEdit->setFocus(); + && !ke->text().isEmpty()) { + if (searchForm->isHidden()) { + msgEdit->setFocus(); + } else { + searchForm->setFocusEditor(); + } + } } - } return QWidget::event(e); } @@ -578,9 +582,7 @@ bool GenericChatForm::searchInText(const QString& phrase, bool searchUp) for (int i = startLine; searchUp ? i >= 0 : i < numLines; searchUp ? --i : ++i) { ChatLine::Ptr l = lines[i]; - if (l->getColumnCount() < 2) { - continue; - } + if (l->getColumnCount() < 2) { continue; } ChatLineContent* content = l->getContent(1); Text* text = static_cast(content); @@ -784,10 +786,11 @@ void GenericChatForm::searchFormShow() { if (searchForm->isHidden()) { searchForm->show(); + searchForm->setFocusEditor(); } } -void GenericChatForm::onSearchTrigered() +void GenericChatForm::onSearchTriggered() { if (searchForm->isHidden()) { searchForm->removeSearchPhrase(); diff --git a/src/widget/form/genericchatform.h b/src/widget/form/genericchatform.h index e15008e61..0789d00c2 100644 --- a/src/widget/form/genericchatform.h +++ b/src/widget/form/genericchatform.h @@ -104,7 +104,7 @@ protected slots: void quoteSelectedText(); void copyLink(); void searchFormShow(); - void onSearchTrigered(); + void onSearchTriggered(); void searchInBegin(const QString& phrase); virtual void onSearchUp(const QString& phrase) = 0; diff --git a/src/widget/searchform.cpp b/src/widget/searchform.cpp index 095ff1ef4..e8a405118 100644 --- a/src/widget/searchform.cpp +++ b/src/widget/searchform.cpp @@ -20,13 +20,13 @@ #include "searchform.h" #include "src/widget/style.h" #include -#include #include +#include SearchForm::SearchForm(QWidget* parent) : QWidget(parent) { QHBoxLayout *layout = new QHBoxLayout(); - searchLine = new QLineEdit(); + searchLine = new LineEdit(); upButton = createButton("searchUpButton", "green"); downButton = createButton("searchDownButton", "green"); @@ -40,7 +40,11 @@ SearchForm::SearchForm(QWidget* parent) : QWidget(parent) setLayout(layout); - connect(searchLine, &QLineEdit::textChanged, this, &SearchForm::changedSearchPhrase); + connect(searchLine, &LineEdit::textChanged, this, &SearchForm::changedSearchPhrase); + connect(searchLine, &LineEdit::clickEnter, this, &SearchForm::clickedUp); + connect(searchLine, &LineEdit::clickShiftEnter, this, &SearchForm::clickedDown); + connect(searchLine, &LineEdit::clickEsc, this, &SearchForm::clickedHide); + connect(upButton, &QPushButton::clicked, this, &SearchForm::clickedUp); connect(downButton, &QPushButton::clicked, this, &SearchForm::clickedDown); connect(hideButton, &QPushButton::clicked, this, &SearchForm::clickedHide); @@ -56,6 +60,17 @@ QString SearchForm::getSearchPhrase() const return searchPhrase; } +void SearchForm::setFocusEditor() +{ + searchLine->setFocus(); +} + +void SearchForm::showEvent(QShowEvent* event) +{ + QWidget::showEvent(event); + emit visibleChanged(); +} + QPushButton *SearchForm::createButton(const QString& name, const QString& state) { QPushButton* btn = new QPushButton(); @@ -67,12 +82,6 @@ QPushButton *SearchForm::createButton(const QString& name, const QString& state) return btn; } -void SearchForm::showEvent(QShowEvent* event) -{ - QWidget::showEvent(event); - emit visibleChanged(); -} - void SearchForm::changedSearchPhrase(const QString& text) { searchPhrase = text; @@ -94,3 +103,26 @@ void SearchForm::clickedHide() hide(); emit visibleChanged(); } + +LineEdit::LineEdit(QWidget* parent) : QLineEdit(parent) +{ +} + +void LineEdit::keyPressEvent(QKeyEvent* event) +{ + int key = event->key(); + + if ((key == Qt::Key_Enter || key == Qt::Key_Return)) { + if ((event->modifiers() & Qt::ShiftModifier)) { + emit clickShiftEnter(); + } else { + emit clickEnter(); + } + } else if (key == Qt::Key_Escape) { + emit clickEsc(); + } + + QLineEdit::keyPressEvent(event); +} + + diff --git a/src/widget/searchform.h b/src/widget/searchform.h index 70f8ae076..d7a522c85 100644 --- a/src/widget/searchform.h +++ b/src/widget/searchform.h @@ -21,9 +21,10 @@ #define SEARCHFORM_H #include +#include class QPushButton; -class QLineEdit; +class LineEdit; class SearchForm final : public QWidget { @@ -32,6 +33,10 @@ public: explicit SearchForm(QWidget* parent = nullptr); void removeSearchPhrase(); QString getSearchPhrase() const; + void setFocusEditor(); + +protected: + virtual void showEvent(QShowEvent* event) final override; private: QPushButton* createButton(const QString& name, const QString& state); @@ -39,13 +44,10 @@ private: QPushButton* upButton; QPushButton* downButton; QPushButton* hideButton; - QLineEdit* searchLine; + LineEdit* searchLine; QString searchPhrase; -protected: - virtual void showEvent(QShowEvent* event); - private slots: void changedSearchPhrase(const QString& text); void clickedUp(); @@ -59,4 +61,20 @@ signals: void visibleChanged(); }; +class LineEdit : public QLineEdit +{ + Q_OBJECT + +public: + LineEdit(QWidget* parent = nullptr); + +protected: + virtual void keyPressEvent(QKeyEvent* event) final override; + +signals: + void clickEnter(); + void clickShiftEnter(); + void clickEsc(); +}; + #endif // SEARCHFORM_H From f73021c37679bddf3da90820520a34e2ddee214d Mon Sep 17 00:00:00 2001 From: TriKriSta Date: Mon, 12 Feb 2018 19:35:50 +0200 Subject: [PATCH 09/12] style: change code in searchInText --- src/widget/form/genericchatform.cpp | 32 ++++++++++++++++------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/widget/form/genericchatform.cpp b/src/widget/form/genericchatform.cpp index bed679b30..d92e70276 100644 --- a/src/widget/form/genericchatform.cpp +++ b/src/widget/form/genericchatform.cpp @@ -582,7 +582,9 @@ bool GenericChatForm::searchInText(const QString& phrase, bool searchUp) for (int i = startLine; searchUp ? i >= 0 : i < numLines; searchUp ? --i : ++i) { ChatLine::Ptr l = lines[i]; - if (l->getColumnCount() < 2) { continue; } + if (l->getColumnCount() < 2) { + continue; + } ChatLineContent* content = l->getContent(1); Text* text = static_cast(content); @@ -596,20 +598,22 @@ bool GenericChatForm::searchInText(const QString& phrase, bool searchUp) QString txt = content->getText(); - if (txt.contains(phrase, Qt::CaseInsensitive)) { - int index = indexForSearchInLine(txt, phrase, searchUp); - 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); - isSearch = true; + if (!txt.contains(phrase, Qt::CaseInsensitive)) { + continue; + } - break; - } + int index = indexForSearchInLine(txt, phrase, searchUp); + 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); + isSearch = true; + + break; } } From 3e05279c097b33b09cedcebae4150c839a23af35 Mon Sep 17 00:00:00 2001 From: TriKriSta Date: Wed, 14 Feb 2018 11:30:38 +0200 Subject: [PATCH 10/12] fix: add search symbol ' in history --- src/persistence/history.cpp | 6 +++++- src/persistence/history.h | 2 +- src/widget/form/chatform.cpp | 2 +- src/widget/form/genericchatform.cpp | 8 ++++---- src/widget/form/genericchatform.h | 2 +- src/widget/searchform.cpp | 2 +- src/widget/searchform.h | 1 + 7 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/persistence/history.cpp b/src/persistence/history.cpp index 5aaa18ce3..23a52a43e 100644 --- a/src/persistence/history.cpp +++ b/src/persistence/history.cpp @@ -326,13 +326,17 @@ QList History::getChatHistoryCounts(const ToxPk& friendPk return counts; } -QDateTime History::getDateWhereFindPhrase(const QString& friendPk, const QDateTime& from, const QString& phrase) +QDateTime History::getDateWhereFindPhrase(const QString& friendPk, const QDateTime& from, QString phrase) { QList counts; auto rowCallback = [&counts](const QVector& row) { counts.append(QDateTime::fromMSecsSinceEpoch(row[0].toLongLong())); }; + if (phrase.contains("'")) { + phrase.replace("'", "''"); + } + QString queryText = QString("SELECT timestamp " "FROM history " diff --git a/src/persistence/history.h b/src/persistence/history.h index 956129dbc..6fefd0931 100644 --- a/src/persistence/history.h +++ b/src/persistence/history.h @@ -82,7 +82,7 @@ public: const QDateTime& to); QList getChatHistoryCounts(const ToxPk& friendPk, const QDate& from, const QDate& to); - QDateTime getDateWhereFindPhrase(const QString& friendPk, const QDateTime& from, const QString& phrase); + QDateTime getDateWhereFindPhrase(const QString& friendPk, const QDateTime& from, QString phrase); void markAsSent(qint64 messageId); diff --git a/src/widget/form/chatform.cpp b/src/widget/form/chatform.cpp index c370bdf4a..9a172358f 100644 --- a/src/widget/form/chatform.cpp +++ b/src/widget/form/chatform.cpp @@ -492,7 +492,7 @@ void ChatForm::onVolMuteToggle() void ChatForm::onSearchUp(const QString& phrase) { if (phrase.isEmpty()) { - desibleSearchText(); + disableSearchText(); } QVector lines = chatWidget->getLines(); diff --git a/src/widget/form/genericchatform.cpp b/src/widget/form/genericchatform.cpp index d92e70276..cda76b5c9 100644 --- a/src/widget/form/genericchatform.cpp +++ b/src/widget/form/genericchatform.cpp @@ -543,7 +543,7 @@ void GenericChatForm::addSystemDateMessage() insertChatMessage(ChatMessage::createChatInfoMessage(dateText, ChatMessage::INFO, QDateTime())); } -void GenericChatForm::desibleSearchText() +void GenericChatForm::disableSearchText() { if (searchPoint != QPoint(1, -1)) { QVector lines = chatWidget->getLines(); @@ -563,7 +563,7 @@ bool GenericChatForm::searchInText(const QString& phrase, bool searchUp) bool isSearch = false; if (phrase.isEmpty()) { - desibleSearchText(); + disableSearchText(); } QVector lines = chatWidget->getLines(); @@ -799,7 +799,7 @@ void GenericChatForm::onSearchTriggered() if (searchForm->isHidden()) { searchForm->removeSearchPhrase(); - desibleSearchText(); + disableSearchText(); } else { searchPoint = QPoint(1, -1); searchAfterLoadHistory = false; @@ -808,7 +808,7 @@ void GenericChatForm::onSearchTriggered() void GenericChatForm::searchInBegin(const QString& phrase) { - desibleSearchText(); + disableSearchText(); searchPoint = QPoint(1, -1); onSearchUp(phrase); diff --git a/src/widget/form/genericchatform.h b/src/widget/form/genericchatform.h index 0789d00c2..aebd684a0 100644 --- a/src/widget/form/genericchatform.h +++ b/src/widget/form/genericchatform.h @@ -131,7 +131,7 @@ protected: virtual bool event(QEvent*) final override; virtual void resizeEvent(QResizeEvent* event) final override; virtual bool eventFilter(QObject* object, QEvent* event) final override; - void desibleSearchText(); + void disableSearchText(); bool searchInText(const QString& phrase, bool searchUp); int indexForSearchInLine(const QString& txt, const QString& phrase, bool searchUp); diff --git a/src/widget/searchform.cpp b/src/widget/searchform.cpp index e8a405118..69092e61c 100644 --- a/src/widget/searchform.cpp +++ b/src/widget/searchform.cpp @@ -30,7 +30,7 @@ SearchForm::SearchForm(QWidget* parent) : QWidget(parent) upButton = createButton("searchUpButton", "green"); downButton = createButton("searchDownButton", "green"); - hideButton = createButton("hideButton","red"); + hideButton = createButton("hideButton", "red"); layout->setMargin(0); layout->addWidget(searchLine); diff --git a/src/widget/searchform.h b/src/widget/searchform.h index d7a522c85..988d6763d 100644 --- a/src/widget/searchform.h +++ b/src/widget/searchform.h @@ -39,6 +39,7 @@ protected: virtual void showEvent(QShowEvent* event) final override; private: + // TODO: Merge with 'createButton' from chatformheader.cpp QPushButton* createButton(const QString& name, const QString& state); QPushButton* upButton; From 40cebd421bd49ee8795bd5caccac421bfb961880 Mon Sep 17 00:00:00 2001 From: TriKriSta Date: Wed, 14 Feb 2018 19:41:59 +0200 Subject: [PATCH 11/12] refactor: rename hideButton to searchHideButton --- res.qrc | 2 +- src/widget/searchform.cpp | 2 +- ui/chatForm/buttons.css | 4 ++-- ui/chatForm/{hideButton.svg => searchHideButton.svg} | 0 4 files changed, 4 insertions(+), 4 deletions(-) rename ui/chatForm/{hideButton.svg => searchHideButton.svg} (100%) diff --git a/res.qrc b/res.qrc index 8bba49087..24c48d855 100644 --- a/res.qrc +++ b/res.qrc @@ -53,7 +53,6 @@ ui/chatArea/scrollBarRightArrow.svg ui/chatForm/buttons.css ui/chatForm/callButton.svg - ui/chatForm/hideButton.svg ui/chatForm/micButton.svg ui/chatForm/videoButton.svg ui/chatForm/volButton.svg @@ -61,6 +60,7 @@ ui/chatForm/fileButton.svg ui/chatForm/screenshotButton.svg ui/chatForm/searchDownButton.svg + ui/chatForm/searchHideButton.svg ui/chatForm/searchUpButton.svg ui/chatForm/sendButton.svg ui/emoticonWidget/dot_page.svg diff --git a/src/widget/searchform.cpp b/src/widget/searchform.cpp index 69092e61c..de8c95eab 100644 --- a/src/widget/searchform.cpp +++ b/src/widget/searchform.cpp @@ -30,7 +30,7 @@ SearchForm::SearchForm(QWidget* parent) : QWidget(parent) upButton = createButton("searchUpButton", "green"); downButton = createButton("searchDownButton", "green"); - hideButton = createButton("hideButton", "red"); + hideButton = createButton("searchHideButton", "red"); layout->setMargin(0); layout->addWidget(searchLine); diff --git a/ui/chatForm/buttons.css b/ui/chatForm/buttons.css index 4042f362b..a43e32458 100644 --- a/ui/chatForm/buttons.css +++ b/ui/chatForm/buttons.css @@ -69,9 +69,9 @@ QAbstractButton#callButton /* SearchLine */ -QAbstractButton#hideButton +QAbstractButton#searchHideButton { - background-image: url(":/ui/chatForm/hideButton.svg"); + background-image: url(":/ui/chatForm/searchHideButton.svg"); border-radius: 5px; width: 35px; height: 35px; diff --git a/ui/chatForm/hideButton.svg b/ui/chatForm/searchHideButton.svg similarity index 100% rename from ui/chatForm/hideButton.svg rename to ui/chatForm/searchHideButton.svg From fe4dd83d10459673ae3b2a23d0dec306ba91ea4b Mon Sep 17 00:00:00 2001 From: TriKriSta Date: Thu, 15 Feb 2018 13:21:05 +0200 Subject: [PATCH 12/12] refactor: add/delete checks in search code --- src/persistence/history.cpp | 4 +--- src/widget/form/genericchatform.cpp | 29 +++++++++++++++-------------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/persistence/history.cpp b/src/persistence/history.cpp index 23a52a43e..0bcf30083 100644 --- a/src/persistence/history.cpp +++ b/src/persistence/history.cpp @@ -333,9 +333,7 @@ QDateTime History::getDateWhereFindPhrase(const QString& friendPk, const QDateTi counts.append(QDateTime::fromMSecsSinceEpoch(row[0].toLongLong())); }; - if (phrase.contains("'")) { - phrase.replace("'", "''"); - } + phrase.replace("'", "''"); QString queryText = QString("SELECT timestamp " diff --git a/src/widget/form/genericchatform.cpp b/src/widget/form/genericchatform.cpp index cda76b5c9..f1fff0a1d 100644 --- a/src/widget/form/genericchatform.cpp +++ b/src/widget/form/genericchatform.cpp @@ -311,18 +311,17 @@ 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(e); - if ((ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::ShiftModifier) - && !ke->text().isEmpty()) { - if (searchForm->isHidden()) { - msgEdit->setFocus(); - } else { - searchForm->setFocusEditor(); - } + if (e->type() == QEvent::KeyRelease && !msgEdit->hasFocus()) { + QKeyEvent* ke = static_cast(e); + if ((ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::ShiftModifier) + && !ke->text().isEmpty()) { + if (searchForm->isHidden()) { + msgEdit->setFocus(); + } else { + searchForm->setFocusEditor(); } } + } return QWidget::event(e); } @@ -549,11 +548,13 @@ void GenericChatForm::disableSearchText() QVector lines = chatWidget->getLines(); int numLines = lines.size(); int index = numLines - searchPoint.x(); - if (numLines > index) { + if (index >= 0 && numLines > index) { ChatLine::Ptr l = lines[index]; - ChatLineContent* content = l->getContent(1); - Text* text = static_cast(content); - text->deselectText(); + if (l->getColumnCount() >= 2) { + ChatLineContent* content = l->getContent(1); + Text* text = static_cast(content); + text->deselectText(); + } } } }