From 87b340f4a14b3544cdc2ea50c1256bca974ac967 Mon Sep 17 00:00:00 2001 From: TriKriSta Date: Sat, 16 Jun 2018 13:41:31 +0300 Subject: [PATCH 01/19] feat: create widget for search settings --- CMakeLists.txt | 3 + res.qrc | 1 + src/widget/form/searchsettingsform.cpp | 73 ++++++++++++ src/widget/form/searchsettingsform.h | 28 +++++ src/widget/form/searchsettingsform.ui | 152 +++++++++++++++++++++++++ src/widget/searchform.cpp | 39 ++++++- src/widget/searchform.h | 6 + ui/chatForm/buttons.css | 17 ++- ui/chatForm/searchSettingsButton.svg | 53 +++++++++ ui/chatForm/searchUpButton.svg | 6 +- 10 files changed, 368 insertions(+), 10 deletions(-) create mode 100644 src/widget/form/searchsettingsform.cpp create mode 100644 src/widget/form/searchsettingsform.h create mode 100644 src/widget/form/searchsettingsform.ui create mode 100644 ui/chatForm/searchSettingsButton.svg diff --git a/CMakeLists.txt b/CMakeLists.txt index 92b128ff6..250ee9915 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -102,6 +102,7 @@ qt5_wrap_ui(${PROJECT_NAME}_FORMS src/widget/form/loadhistorydialog.ui src/widget/form/profileform.ui src/widget/form/removefrienddialog.ui + src/widget/form/searchsettingsform.ui src/widget/form/setpassworddialog.ui src/widget/form/settings/aboutsettings.ui src/widget/form/settings/advancedsettings.ui @@ -368,6 +369,8 @@ set(${PROJECT_NAME}_SOURCES src/widget/form/loadhistorydialog.h src/widget/form/profileform.cpp src/widget/form/profileform.h + src/widget/form/searchsettingsform.cpp + src/widget/form/searchsettingsform.h src/widget/form/setpassworddialog.cpp src/widget/form/setpassworddialog.h src/widget/form/settings/aboutform.cpp diff --git a/res.qrc b/res.qrc index da45a6b57..5edb06960 100644 --- a/res.qrc +++ b/res.qrc @@ -68,6 +68,7 @@ ui/chatForm/screenshotButton.svg ui/chatForm/searchDownButton.svg ui/chatForm/searchHideButton.svg + ui/chatForm/searchSettingsButton.svg ui/chatForm/searchUpButton.svg ui/chatForm/sendButton.svg ui/chatForm/exitFullScreenButton.svg diff --git a/src/widget/form/searchsettingsform.cpp b/src/widget/form/searchsettingsform.cpp new file mode 100644 index 000000000..574d4e0c3 --- /dev/null +++ b/src/widget/form/searchsettingsform.cpp @@ -0,0 +1,73 @@ +#include "searchsettingsform.h" +#include "ui_searchsettingsform.h" +#include "src/widget/style.h" + +SearchSettingsForm::SearchSettingsForm(QWidget *parent) : + QWidget(parent), + ui(new Ui::SearchSettingsForm) +{ + ui->setupUi(this); + + ui->choiceDateButton->setEnabled(false); + ui->startDateLabel->setEnabled(false); + + ui->choiceDateButton->setAttribute(Qt::WA_LayoutUsesWidgetRect); + ui->choiceDateButton->setObjectName("choiceDateButton"); + ui->choiceDateButton->setStyleSheet(Style::getStylesheet(QStringLiteral(":/ui/chatForm/buttons.css"))); + + ui->startDateLabel->setStyleSheet("QLabel{color: #ddd;}"); + + connect(ui->startSearchComboBox, static_cast(&QComboBox::currentIndexChanged), + this, &SearchSettingsForm::onStartSearchSelected); + connect(ui->registerCheckBox, &QCheckBox::clicked, this, &SearchSettingsForm::onRegisterClicked); + connect(ui->wordsOnlyCheckBox, &QCheckBox::clicked, this, &SearchSettingsForm::onWordsOnlyClicked); + connect(ui->regularCheckBox, &QCheckBox::clicked, this, &SearchSettingsForm::onRegularClicked); +} + +SearchSettingsForm::~SearchSettingsForm() +{ + delete ui; +} + +void SearchSettingsForm::onStartSearchSelected(const int index) +{ + if (index > 1) { + ui->choiceDateButton->setEnabled(true); + ui->startDateLabel->setEnabled(true); + + ui->choiceDateButton->setProperty("state", "green"); + ui->choiceDateButton->setStyleSheet(Style::getStylesheet(QStringLiteral(":/ui/chatForm/buttons.css"))); + + ui->startDateLabel->setStyleSheet("QLabel{color: #000;}"); + } else { + ui->choiceDateButton->setEnabled(false); + ui->startDateLabel->setEnabled(false); + + ui->choiceDateButton->setProperty("state", ""); + ui->choiceDateButton->setStyleSheet(Style::getStylesheet(QStringLiteral(":/ui/chatForm/buttons.css"))); + + ui->startDateLabel->setStyleSheet("QLabel{color: #ddd;}"); + } +} + +void SearchSettingsForm::onRegisterClicked(const bool checked) +{ + if (checked) { + ui->regularCheckBox->setChecked(false); + } +} + +void SearchSettingsForm::onWordsOnlyClicked(const bool checked) +{ + if (checked) { + ui->regularCheckBox->setChecked(false); + } +} + +void SearchSettingsForm::onRegularClicked(const bool checked) +{ + if (checked) { + ui->registerCheckBox->setChecked(false); + ui->wordsOnlyCheckBox->setChecked(false); + } +} diff --git a/src/widget/form/searchsettingsform.h b/src/widget/form/searchsettingsform.h new file mode 100644 index 000000000..b1f878427 --- /dev/null +++ b/src/widget/form/searchsettingsform.h @@ -0,0 +1,28 @@ +#ifndef SEARCHSETTINGSFORM_H +#define SEARCHSETTINGSFORM_H + +#include + +namespace Ui { +class SearchSettingsForm; +} + +class SearchSettingsForm : public QWidget +{ + Q_OBJECT + +public: + explicit SearchSettingsForm(QWidget *parent = nullptr); + ~SearchSettingsForm(); + +private: + Ui::SearchSettingsForm *ui; + +private slots: + void onStartSearchSelected(const int index); + void onRegisterClicked(const bool checked); + void onWordsOnlyClicked(const bool checked); + void onRegularClicked(const bool checked); +}; + +#endif // SEARCHSETTINGSFORM_H diff --git a/src/widget/form/searchsettingsform.ui b/src/widget/form/searchsettingsform.ui new file mode 100644 index 000000000..864f212cf --- /dev/null +++ b/src/widget/form/searchsettingsform.ui @@ -0,0 +1,152 @@ + + + SearchSettingsForm + + + + 0 + 0 + 473 + 78 + + + + + 0 + 0 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::Plain + + + Qt::Horizontal + + + + + + + + + Start searching: + + + + + + + + 1 + 0 + + + + + with the end + + + + + with the first + + + + + after date + + + + + before date + + + + + + + + 00.00.0000 + + + + + + + Choice + + + + + + + + + + + Case sensitive + + + + + + + Whole words only + + + + + + + Use regular expressions + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + QFrame::Plain + + + Qt::Horizontal + + + + + + + + diff --git a/src/widget/searchform.cpp b/src/widget/searchform.cpp index 5c55215ba..1bd8d9351 100644 --- a/src/widget/searchform.cpp +++ b/src/widget/searchform.cpp @@ -18,25 +18,37 @@ */ #include "searchform.h" +#include "form/searchsettingsform.h" #include "src/widget/style.h" +#include #include #include #include SearchForm::SearchForm(QWidget* parent) : QWidget(parent) { - QHBoxLayout *layout = new QHBoxLayout(); + QVBoxLayout* layout = new QVBoxLayout(); + QHBoxLayout* layoutNavigation = new QHBoxLayout(); searchLine = new LineEdit(); + settings = new SearchSettingsForm(); + settings->setVisible(false); + isActiveSettings = false; + + settingsButton = createButton("searchSettingsButton", "green"); upButton = createButton("searchUpButton", "green"); downButton = createButton("searchDownButton", "green"); hideButton = createButton("searchHideButton", "red"); - layout->setMargin(0); - layout->addWidget(searchLine); - layout->addWidget(upButton); - layout->addWidget(downButton); - layout->addWidget(hideButton); + layoutNavigation->setMargin(0); + layoutNavigation->addWidget(settingsButton); + layoutNavigation->addWidget(searchLine); + layoutNavigation->addWidget(upButton); + layoutNavigation->addWidget(downButton); + layoutNavigation->addWidget(hideButton); + + layout->addLayout(layoutNavigation); + layout->addWidget(settings); setLayout(layout); @@ -48,6 +60,7 @@ SearchForm::SearchForm(QWidget* parent) : QWidget(parent) connect(upButton, &QPushButton::clicked, this, &SearchForm::clickedUp); connect(downButton, &QPushButton::clicked, this, &SearchForm::clickedDown); connect(hideButton, &QPushButton::clicked, this, &SearchForm::clickedHide); + connect(settingsButton, &QPushButton::clicked, this, &SearchForm::clickedSearch); } void SearchForm::removeSearchPhrase() @@ -109,6 +122,20 @@ void SearchForm::clickedHide() emit visibleChanged(); } +void SearchForm::clickedSearch() +{ + isActiveSettings = !isActiveSettings; + settings->setVisible(isActiveSettings); + + if (isActiveSettings) { + settingsButton->setProperty("state", "red"); + } else { + settingsButton->setProperty("state", "green"); + } + settingsButton->setStyleSheet(Style::getStylesheet(QStringLiteral(":/ui/chatForm/buttons.css"))); + settingsButton->update(); +} + LineEdit::LineEdit(QWidget* parent) : QLineEdit(parent) { } diff --git a/src/widget/searchform.h b/src/widget/searchform.h index 4f5cdad83..127a11acc 100644 --- a/src/widget/searchform.h +++ b/src/widget/searchform.h @@ -25,6 +25,7 @@ class QPushButton; class LineEdit; +class SearchSettingsForm; class SearchForm final : public QWidget { @@ -43,18 +44,23 @@ private: // TODO: Merge with 'createButton' from chatformheader.cpp QPushButton* createButton(const QString& name, const QString& state); + QPushButton* settingsButton; QPushButton* upButton; QPushButton* downButton; QPushButton* hideButton; LineEdit* searchLine; + SearchSettingsForm* settings; QString searchPhrase; + bool isActiveSettings; + private slots: void changedSearchPhrase(const QString& text); void clickedUp(); void clickedDown(); void clickedHide(); + void clickedSearch(); signals: void searchInBegin(const QString& phrase); diff --git a/ui/chatForm/buttons.css b/ui/chatForm/buttons.css index a43e32458..3c1b2f454 100644 --- a/ui/chatForm/buttons.css +++ b/ui/chatForm/buttons.css @@ -69,6 +69,14 @@ QAbstractButton#callButton /* SearchLine */ +QAbstractButton#searchSettingsButton +{ + background-image: url(":/ui/chatForm/searchSettingsButton.svg"); + border-radius: 5px; + width: 35px; + height: 35px; +} + QAbstractButton#searchHideButton { background-image: url(":/ui/chatForm/searchHideButton.svg"); @@ -77,7 +85,6 @@ QAbstractButton#searchHideButton height: 35px; } - QAbstractButton#searchUpButton { background-image: url(":/ui/chatForm/searchUpButton.svg"); @@ -94,6 +101,14 @@ QAbstractButton#searchDownButton height: 35px; } +QAbstractButton#choiceDateButton +{ + border-radius: 5px; + width: 55px; + height: 25px; + color: #fff +} + /* Common */ QAbstractButton diff --git a/ui/chatForm/searchSettingsButton.svg b/ui/chatForm/searchSettingsButton.svg new file mode 100644 index 000000000..0f69d1d1a --- /dev/null +++ b/ui/chatForm/searchSettingsButton.svg @@ -0,0 +1,53 @@ + + + +image/svg+xml + + \ No newline at end of file diff --git a/ui/chatForm/searchUpButton.svg b/ui/chatForm/searchUpButton.svg index 20fdf3732..d579c81fc 100644 --- a/ui/chatForm/searchUpButton.svg +++ b/ui/chatForm/searchUpButton.svg @@ -14,7 +14,7 @@ viewBox="0 0 7.0183304 4.1245209" version="1.1" id="svg8" - inkscape:version="0.92.2 5c3e80d, 2017-08-06" + inkscape:version="0.92.2 2405546, 2018-03-11" sodipodi:docname="searchUpButton.svg"> @@ -38,7 +38,7 @@ inkscape:window-width="1920" inkscape:window-height="1015" inkscape:window-x="0" - inkscape:window-y="876" + inkscape:window-y="36" inkscape:window-maximized="1" /> @@ -48,7 +48,7 @@ image/svg+xml - + From 610e04aa2698deb24af2f04db5cf3e049101a54d Mon Sep 17 00:00:00 2001 From: TriKriSta Date: Sun, 24 Jun 2018 21:11:20 +0300 Subject: [PATCH 02/19] feat: use search settings --- CMakeLists.txt | 1 + src/chatlog/chatlog.cpp | 8 ++ src/chatlog/chatlog.h | 1 + src/chatlog/content/text.cpp | 42 ++++-- src/chatlog/content/text.h | 5 +- src/persistence/db/rawdatabase.cpp | 40 ++++++ src/persistence/db/rawdatabase.h | 5 + src/persistence/history.cpp | 77 +++++++++- src/persistence/history.h | 4 +- src/widget/form/chatform.cpp | 73 ++++++++-- src/widget/form/chatform.h | 6 +- src/widget/form/genericchatform.cpp | 185 ++++++++++++++++++++----- src/widget/form/genericchatform.h | 13 +- src/widget/form/groupchatform.cpp | 21 ++- src/widget/form/groupchatform.h | 5 +- src/widget/form/loadhistorydialog.cpp | 7 + src/widget/form/loadhistorydialog.h | 1 + src/widget/form/searchsettingsform.cpp | 83 +++++++++-- src/widget/form/searchsettingsform.h | 8 ++ src/widget/form/searchsettingsform.ui | 38 +++-- src/widget/searchform.cpp | 38 ++++- src/widget/searchform.h | 11 +- src/widget/searchtypes.h | 50 +++++++ ui/settings/mainContent.css | 6 + 24 files changed, 625 insertions(+), 103 deletions(-) create mode 100644 src/widget/searchtypes.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 250ee9915..f087f2c1a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -351,6 +351,7 @@ set(${PROJECT_NAME}_SOURCES src/widget/flowlayout.h src/widget/searchform.cpp src/widget/searchform.h + src/widget/searchtypes.h src/widget/form/addfriendform.cpp src/widget/form/addfriendform.h src/widget/form/chatform.cpp diff --git a/src/chatlog/chatlog.cpp b/src/chatlog/chatlog.cpp index 50ff2a6ae..ff26e85f7 100644 --- a/src/chatlog/chatlog.cpp +++ b/src/chatlog/chatlog.cpp @@ -541,6 +541,14 @@ ChatLine::Ptr ChatLog::getLatestLine() const return nullptr; } +ChatLine::Ptr ChatLog::getFirstLine() const +{ + if (!lines.empty()) { + return lines.first(); + } + return nullptr; +} + /** * @brief Finds the chat line object at a position on screen * @param pos Position on screen in global coordinates diff --git a/src/chatlog/chatlog.h b/src/chatlog/chatlog.h index dfaba6390..56d0dda54 100644 --- a/src/chatlog/chatlog.h +++ b/src/chatlog/chatlog.h @@ -62,6 +62,7 @@ public: ChatLine::Ptr getTypingNotification() const; QVector getLines(); ChatLine::Ptr getLatestLine() const; + ChatLine::Ptr getFirstLine() const; ChatLineContent* getContentFromGlobalPos(QPoint pos) const; const uint repNameAfter = 5 * 60; diff --git a/src/chatlog/content/text.cpp b/src/chatlog/content/text.cpp index 9ed8e99d3..b25d97c0c 100644 --- a/src/chatlog/content/text.cpp +++ b/src/chatlog/content/text.cpp @@ -58,7 +58,7 @@ void Text::setText(const QString& txt) dirty = true; } -void Text::selectText(const QString &txt, const int index) +void Text::selectText(const QString& txt, const std::pair& point) { regenerate(); @@ -66,21 +66,22 @@ void Text::selectText(const QString &txt, const int index) return; } - auto cursor = doc->find(txt, index); + auto cursor = doc->find(txt, point.first); - if (!cursor.isNull()) { - cursor.beginEditBlock(); - cursor.setPosition(index); - cursor.setPosition(index + txt.size(), QTextCursor::KeepAnchor); - cursor.endEditBlock(); + selectText(cursor, point); +} - QTextCharFormat format; - format.setBackground(QBrush(QColor("#ff7626"))); - cursor.mergeCharFormat(format); +void Text::selectText(const QRegExp &exp, const std::pair& point) +{ + regenerate(); - regenerate(); - update(); + if (!doc) { + return; } + + auto cursor = doc->find(exp, point.first); + + selectText(cursor, point); } void Text::deselectText() @@ -439,3 +440,20 @@ QString Text::extractImgTooltip(int pos) const return QString(); } + +void Text::selectText(QTextCursor& cursor, const std::pair& point) +{ + if (!cursor.isNull()) { + cursor.beginEditBlock(); + cursor.setPosition(point.first); + cursor.setPosition(point.first + point.second, QTextCursor::KeepAnchor); + cursor.endEditBlock(); + + QTextCharFormat format; + format.setBackground(QBrush(QColor("#ff7626"))); + cursor.mergeCharFormat(format); + + regenerate(); + update(); + } +} diff --git a/src/chatlog/content/text.h b/src/chatlog/content/text.h index 75fc11979..15e1f7f77 100644 --- a/src/chatlog/content/text.h +++ b/src/chatlog/content/text.h @@ -36,7 +36,8 @@ public: virtual ~Text(); void setText(const QString& txt); - void selectText(const QString& txt, const int index); + void selectText(const QString& txt, const std::pair& point); + void selectText(const QRegExp& exp, const std::pair& point); void deselectText(); virtual void setWidth(qreal width) final; @@ -78,6 +79,8 @@ protected: QString extractImgTooltip(int pos) const; private: + void selectText(QTextCursor& cursor, const std::pair& point); + QTextDocument* doc = nullptr; QString text; QString rawText; diff --git a/src/persistence/db/rawdatabase.cpp b/src/persistence/db/rawdatabase.cpp index a86b8590c..6085d3a34 100644 --- a/src/persistence/db/rawdatabase.cpp +++ b/src/persistence/db/rawdatabase.cpp @@ -171,6 +171,18 @@ bool RawDatabase::open(const QString& path, const QString& hexKey) return false; } + if (sqlite3_create_function(sqlite, "regexp", 2, SQLITE_UTF8, NULL, &RawDatabase::regexpInsensitive, NULL, NULL)) { + qWarning() << "Failed to create function regexp"; + close(); + return false; + } + + if (sqlite3_create_function(sqlite, "regexpsensitive", 2, SQLITE_UTF8, NULL, &RawDatabase::regexpSensitive, NULL, NULL)) { + qWarning() << "Failed to create function regexpsensitive"; + close(); + return false; + } + if (!hexKey.isEmpty()) { if (!execNow("PRAGMA key = \"x'" + hexKey + "'\"")) { qWarning() << "Failed to set encryption key"; @@ -705,3 +717,31 @@ QVariant RawDatabase::extractData(sqlite3_stmt* stmt, int col) return QByteArray::fromRawData(data, len); } } + +void RawDatabase::regexpInsensitive(sqlite3_context* ctx, int argc, sqlite3_value** argv) +{ + regexp(ctx, argc, argv, Qt::CaseInsensitive); +} + +void RawDatabase::regexpSensitive(sqlite3_context* ctx, int argc, sqlite3_value** argv) +{ + regexp(ctx, argc, argv, Qt::CaseSensitive); +} + +void RawDatabase::regexp(sqlite3_context* ctx, int argc, sqlite3_value** argv, const Qt::CaseSensitivity cs) +{ + QRegExp regex; + QString str1((const char*)sqlite3_value_text(argv[0])); + QString str2((const char*)sqlite3_value_text(argv[1])); + + regex.setPattern(str1); + regex.setCaseSensitivity(cs); + + bool b = str2.contains(regex); + + if (b) { + sqlite3_result_int(ctx, 1); + } else { + sqlite3_result_int(ctx, 0); + } +} diff --git a/src/persistence/db/rawdatabase.h b/src/persistence/db/rawdatabase.h index d3374e850..e2ca9d5a3 100644 --- a/src/persistence/db/rawdatabase.h +++ b/src/persistence/db/rawdatabase.h @@ -15,6 +15,8 @@ struct sqlite3; struct sqlite3_stmt; +struct sqlite3_context; +struct sqlite3_value; class RawDatabase : QObject { @@ -85,6 +87,9 @@ protected: static QString deriveKey(const QString& password, const QByteArray& salt); static QString deriveKey(const QString& password); static QVariant extractData(sqlite3_stmt* stmt, int col); + static void regexpInsensitive(sqlite3_context* ctx, int argc, sqlite3_value** argv); + static void regexpSensitive(sqlite3_context* ctx, int argc, sqlite3_value** argv); + static void regexp(sqlite3_context* ctx, int argc, sqlite3_value** argv, const Qt::CaseSensitivity cs); private: struct Transaction diff --git a/src/persistence/history.cpp b/src/persistence/history.cpp index 44ce96f52..024609efc 100644 --- a/src/persistence/history.cpp +++ b/src/persistence/history.cpp @@ -315,7 +315,7 @@ QList History::getChatHistoryCounts(const ToxPk& friendPk return counts; } -QDateTime History::getDateWhereFindPhrase(const QString& friendPk, const QDateTime& from, QString phrase) +QDateTime History::getDateWhereFindPhrase(const QString& friendPk, const QDateTime& from, QString phrase, const ParameterSearch& parameter) { QList counts; auto rowCallback = [&counts](const QVector& row) { @@ -324,19 +324,86 @@ QDateTime History::getDateWhereFindPhrase(const QString& friendPk, const QDateTi phrase.replace("'", "''"); + QString message; + + switch (parameter.filter) { + case FilterSearch::Register: + message = QString("message LIKE '%%1%'").arg(phrase); + break; + case FilterSearch::WordsOnly: + message = QString("message REGEXP '\\b%1\\b'").arg(phrase.toLower()); + break; + case FilterSearch::RegisterAndWordsOnly: + message = QString("REGEXPSENSITIVE(message, '\\b%1\\b')").arg(phrase); + break; + case FilterSearch::Regular: + message = QString("message REGEXP '%1'").arg(phrase); + break; + case FilterSearch::RegisterAndRegular: + message = QString("REGEXPSENSITIVE(message '%1')").arg(phrase); + break; + default: + message = QString("LOWER(message) LIKE '%%1%'").arg(phrase.toLower()); + break; + } + + QDateTime date = from; + if (parameter.period != PeriodSearch::None) { + date = QDateTime(parameter.date); + } + + QString period; + switch (parameter.period) { + case PeriodSearch::WithTheFirst: + period = QString("ORDER BY timestamp ASC LIMIT 1;"); + break; + case PeriodSearch::AfterDate: + period = QString("AND timestamp > '%1' ORDER BY timestamp ASC LIMIT 1;").arg(date.toMSecsSinceEpoch()); + break; + case PeriodSearch::BeforeDate: + period = QString("AND timestamp < '%1' ORDER BY timestamp DESC LIMIT 1;").arg(date.toMSecsSinceEpoch()); + break; + default: + period = QString("AND timestamp < '%1' ORDER BY timestamp DESC LIMIT 1;").arg(date.toMSecsSinceEpoch()); + break; + } + 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' " - "AND message LIKE '%%2%' " - "AND timestamp < '%3' ORDER BY timestamp DESC LIMIT 1;") + "AND %2 " + "%3") .arg(friendPk) - .arg(phrase) - .arg(from.toMSecsSinceEpoch()); + .arg(message) + .arg(period); + db->execNow({queryText, rowCallback}); + if (!counts.isEmpty()) { + return counts[0]; + } + + return QDateTime(); +} + +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()) { diff --git a/src/persistence/history.h b/src/persistence/history.h index c749b3774..bca46daa2 100644 --- a/src/persistence/history.h +++ b/src/persistence/history.h @@ -29,6 +29,7 @@ #include "src/core/toxpk.h" #include "src/persistence/db/rawdatabase.h" +#include "src/widget/searchtypes.h" class Profile; class HistoryKeeper; @@ -82,7 +83,8 @@ public: const QDateTime& to); QList getChatHistoryDefaultNum(const QString& friendPk); QList getChatHistoryCounts(const ToxPk& friendPk, const QDate& from, const QDate& to); - QDateTime getDateWhereFindPhrase(const QString& friendPk, const QDateTime& from, QString phrase); + QDateTime getDateWhereFindPhrase(const QString& friendPk, const QDateTime& from, QString phrase, const ParameterSearch ¶meter); + QDateTime getStartDateChatHistory(const QString& friendPk); void markAsSent(qint64 messageId); diff --git a/src/widget/form/chatform.cpp b/src/widget/form/chatform.cpp index 1230814d0..e897e2685 100644 --- a/src/widget/form/chatform.cpp +++ b/src/widget/form/chatform.cpp @@ -497,7 +497,38 @@ void ChatForm::onVolMuteToggle() updateMuteVolButton(); } -void ChatForm::onSearchUp(const QString& phrase) +void ChatForm::searchInBegin(const QString& phrase, const ParameterSearch& parameter) +{ + disableSearchText(); + + searchPoint = QPoint(1, -1); + + bool b = (parameter.period == PeriodSearch::WithTheFirst); + bool b1 = (parameter.period == PeriodSearch::AfterDate); + if (b || b1) { + if (b || (b1 && parameter.date < getFirstDate())) { + QString pk = f->getPublicKey().toString(); + if ((b || parameter.date >= history->getStartDateChatHistory(pk).date()) && + loadHistory(phrase, parameter)) { + + return; + } + } + + onSearchDown(phrase, parameter); + } else { + if (parameter.period == PeriodSearch::BeforeDate && parameter.date < getFirstDate()) { + QString pk = f->getPublicKey().toString(); + if (parameter.date >= history->getStartDateChatHistory(pk).date() && loadHistory(phrase, parameter)) { + return; + } + } + + onSearchUp(phrase, parameter); + } +} + +void ChatForm::onSearchUp(const QString& phrase, const ParameterSearch& parameter) { if (phrase.isEmpty()) { disableSearchText(); @@ -508,25 +539,26 @@ void ChatForm::onSearchUp(const QString& phrase) int startLine = numLines - searchPoint.x(); - if (startLine == 0) { - QString pk = f->getPublicKey().toString(); - QDateTime newBaseDate = history->getDateWhereFindPhrase(pk, earliestMessage, phrase); + if (startLine == 0 && loadHistory(phrase, parameter)) { +// QString pk = f->getPublicKey().toString(); +// QDateTime newBaseDate = history->getDateWhereFindPhrase(pk, earliestMessage, phrase, parameter); - if (!newBaseDate.isValid()) { - return; - } +// if (!newBaseDate.isValid()) { +// return; +// } - searchAfterLoadHistory = true; - loadHistoryByDateRange(newBaseDate); +// searchAfterLoadHistory = true; +// loadHistoryByDateRange(newBaseDate); +// return; return; } - bool isSearch = searchInText(phrase, true); + bool isSearch = searchInText(phrase, parameter, true); if (!isSearch) { QString pk = f->getPublicKey().toString(); - QDateTime newBaseDate = history->getDateWhereFindPhrase(pk, earliestMessage, phrase); + QDateTime newBaseDate = history->getDateWhereFindPhrase(pk, earliestMessage, phrase, parameter); if (!newBaseDate.isValid()) { return; @@ -538,9 +570,9 @@ void ChatForm::onSearchUp(const QString& phrase) } } -void ChatForm::onSearchDown(const QString& phrase) +void ChatForm::onSearchDown(const QString& phrase, const ParameterSearch& parameter) { - searchInText(phrase, false); + searchInText(phrase, parameter, false); } void ChatForm::onFileSendFailed(uint32_t friendId, const QString& fname) @@ -1045,6 +1077,21 @@ void ChatForm::SendMessageStr(QString msg) } } +bool ChatForm::loadHistory(const QString& phrase, const ParameterSearch& parameter) +{ + QString pk = f->getPublicKey().toString(); + QDateTime newBaseDate = history->getDateWhereFindPhrase(pk, earliestMessage, phrase, parameter); + + if (newBaseDate.isValid() && getFirstDate().isValid() && newBaseDate.date() < getFirstDate()) { + searchAfterLoadHistory = true; + loadHistoryByDateRange(newBaseDate); + + return true; + } + + return false; +} + void ChatForm::retranslateUi() { loadHistoryAction->setText(tr("Load chat history...")); diff --git a/src/widget/form/chatform.h b/src/widget/form/chatform.h index 84790abd0..e948d2351 100644 --- a/src/widget/form/chatform.h +++ b/src/widget/form/chatform.h @@ -77,8 +77,9 @@ public slots: void onFileNameChanged(); protected slots: - void onSearchUp(const QString& phrase) override; - void onSearchDown(const QString& phrase) override; + void searchInBegin(const QString& phrase, const ParameterSearch& parameter) override; + void onSearchUp(const QString& phrase, const ParameterSearch& parameter) override; + void onSearchDown(const QString& phrase, const ParameterSearch& parameter) override; private slots: void clearChatArea(bool notInForm) override final; @@ -138,6 +139,7 @@ private: void stopCounter(bool error = false); void updateCallButtons(); void SendMessageStr(QString msg); + bool loadHistory(const QString& phrase, const ParameterSearch& parameter); protected: GenericNetCamView* createNetcam() final override; diff --git a/src/widget/form/genericchatform.cpp b/src/widget/form/genericchatform.cpp index b8f0fab2f..e67749ccb 100644 --- a/src/widget/form/genericchatform.cpp +++ b/src/widget/form/genericchatform.cpp @@ -45,6 +45,7 @@ #include #include #include +#include /** * @class GenericChatForm @@ -273,18 +274,12 @@ void GenericChatForm::hideFileMenu() QDate GenericChatForm::getLatestDate() const { - ChatLine::Ptr chatLine = chatWidget->getLatestLine(); + return getDate(chatWidget->getLatestLine()); +} - if (chatLine) { - Timestamp* timestamp = qobject_cast(chatLine->getContent(2)); - - if (timestamp) - return timestamp->getTime().date(); - else - return QDate::currentDate(); - } - - return QDate(); +QDate GenericChatForm::getFirstDate() const +{ + return getDate(chatWidget->getFirstLine()); } void GenericChatForm::setName(const QString& newName) @@ -542,6 +537,21 @@ void GenericChatForm::addSystemDateMessage() insertChatMessage(ChatMessage::createChatInfoMessage(dateText, ChatMessage::INFO, QDateTime())); } +QDate GenericChatForm::getDate(const ChatLine::Ptr &chatLine) const +{ + if (chatLine) { + Timestamp* timestamp = qobject_cast(chatLine->getContent(2)); + + if (timestamp) { + return timestamp->getTime().date(); + } else { + return QDate::currentDate(); + } + } + + return QDate(); +} + void GenericChatForm::disableSearchText() { if (searchPoint != QPoint(1, -1)) { @@ -559,7 +569,7 @@ void GenericChatForm::disableSearchText() } } -bool GenericChatForm::searchInText(const QString& phrase, bool searchUp) +bool GenericChatForm::searchInText(const QString& phrase, const ParameterSearch& parameter, bool searchUp) { bool isSearch = false; @@ -567,14 +577,36 @@ bool GenericChatForm::searchInText(const QString& phrase, bool searchUp) disableSearchText(); } - QVector lines = chatWidget->getLines(); + auto lines = chatWidget->getLines(); if (lines.isEmpty()) { return isSearch; } int numLines = lines.size(); + + auto d = QDate::currentDate(); + int startLine = numLines - searchPoint.x(); + if (parameter.period == PeriodSearch::WithTheFirst) { + startLine = 0; + } else if (parameter.period == PeriodSearch::AfterDate) { + for (int i = 0; i < lines.size(); ++i) { + auto d = getDate(lines[i]); + if (d.isValid() && parameter.date <= d) { + startLine = i; + break; + } + } + } else if (parameter.period == PeriodSearch::BeforeDate) { + for (int i = lines.size() - 1; i >= 0; --i) { + auto d = getDate(lines[i]); + if (d.isValid() && parameter.date >= d) { + startLine = i; + break; + } + } + } if (startLine < 0 || startLine >= numLines) { return isSearch; @@ -599,19 +631,52 @@ bool GenericChatForm::searchInText(const QString& phrase, bool searchUp) QString txt = content->getText(); - if (!txt.contains(phrase, Qt::CaseInsensitive)) { + bool find = false; + QRegExp exp; + switch (parameter.filter) { + case FilterSearch::Register: + find = txt.contains(phrase, Qt::CaseSensitive); + break; + case FilterSearch::WordsOnly: + exp = QRegExp(QString("\\b%1\\b").arg(phrase), Qt::CaseInsensitive); + find = txt.contains(exp); + break; + case FilterSearch::RegisterAndWordsOnly: + exp = QRegExp(QString("\\b%1\\b").arg(phrase)); + find = txt.contains(exp); + break; + case FilterSearch::RegisterAndRegular: + exp = QRegExp(phrase); + find = txt.contains(exp); + break; + case FilterSearch::Regular: + exp = QRegExp(phrase, Qt::CaseInsensitive); + find = txt.contains(exp); + break; + default: + find = txt.contains(phrase, Qt::CaseInsensitive); + break; + } + + if (!find) { continue; } - int index = indexForSearchInLine(txt, phrase, searchUp); - if ((index == -1 && searchPoint.y() > -1)) { + auto point = indexForSearchInLine(txt, phrase, parameter, searchUp); + if ((point.first == -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 (exp.isEmpty()) { + text->selectText(phrase, point); + } else { + text->selectText(exp, point); + } + + searchPoint = QPoint(numLines - i, point.first); isSearch = true; break; @@ -621,9 +686,10 @@ bool GenericChatForm::searchInText(const QString& phrase, bool searchUp) return isSearch; } -int GenericChatForm::indexForSearchInLine(const QString& txt, const QString& phrase, bool searchUp) +std::pair GenericChatForm::indexForSearchInLine(const QString& txt, const QString& phrase, const ParameterSearch& parameter, bool searchUp) { int index = 0; + QRegExp exp; if (searchUp) { int startIndex = -1; @@ -631,17 +697,76 @@ int GenericChatForm::indexForSearchInLine(const QString& txt, const QString& phr startIndex = searchPoint.y() - 1; } - index = txt.lastIndexOf(phrase, startIndex, Qt::CaseInsensitive); + switch (parameter.filter) { + case FilterSearch::Register: + index = txt.lastIndexOf(phrase, startIndex, Qt::CaseSensitive); + break; + case FilterSearch::WordsOnly: + exp = QRegExp(QString("\\b%1\\b").arg(phrase), Qt::CaseInsensitive); + index = exp.lastIndexIn(txt, startIndex); + break; + case FilterSearch::RegisterAndWordsOnly: + exp = QRegExp(QString("\\b%1\\b").arg(phrase)); + index = exp.lastIndexIn(txt, startIndex); + break; + case FilterSearch::RegisterAndRegular: + exp = QRegExp(phrase); + index = exp.lastIndexIn(txt, startIndex); + break; + case FilterSearch::Regular: + exp = QRegExp(phrase, Qt::CaseInsensitive); + index = exp.lastIndexIn(txt, startIndex); + break; + default: + index = txt.lastIndexOf(phrase, startIndex, Qt::CaseInsensitive); + break; + } } else { int startIndex = 0; if (searchPoint.y() > -1) { startIndex = searchPoint.y() + 1; } - index = txt.indexOf(phrase, startIndex, Qt::CaseInsensitive); + switch (parameter.filter) { + case FilterSearch::Register: + index = txt.indexOf(phrase, startIndex, Qt::CaseSensitive); + break; + case FilterSearch::WordsOnly: + exp = QRegExp(QString("\\b%1\\b").arg(phrase), Qt::CaseInsensitive); + index = exp.indexIn(txt, startIndex); + break; + case FilterSearch::RegisterAndWordsOnly: + exp = QRegExp(QString("\\b%1\\b").arg(phrase)); + index = exp.indexIn(txt, startIndex); + break; + case FilterSearch::RegisterAndRegular: + exp = QRegExp(phrase); + index = exp.indexIn(txt, startIndex); + break; + case FilterSearch::Regular: + exp = QRegExp(phrase, Qt::CaseInsensitive); + index = exp.indexIn(txt, startIndex); + break; + default: + index = txt.indexOf(phrase, startIndex, Qt::CaseInsensitive); + break; + } } - return index; + int size = 0; + if (index > -1) { + if (exp.isEmpty()) { + size = phrase.size(); + } else { + auto lExp = exp.capturedTexts(); + + if (!lExp.isEmpty()) { + size = lExp[0].size(); + } + } + } + + return std::make_pair(index, size); } void GenericChatForm::clearChatArea() @@ -806,20 +931,18 @@ void GenericChatForm::onSearchTriggered() } } -void GenericChatForm::searchInBegin(const QString& phrase) -{ - disableSearchText(); - - searchPoint = QPoint(1, -1); - onSearchUp(phrase); -} - void GenericChatForm::onContinueSearch() { QString phrase = searchForm->getSearchPhrase(); + ParameterSearch parameter = searchForm->getParametrSearch(); if (!phrase.isEmpty() && searchAfterLoadHistory) { searchAfterLoadHistory = false; - onSearchUp(phrase); + + if (parameter.period == PeriodSearch::WithTheFirst || parameter.period == PeriodSearch::AfterDate) { + onSearchDown(phrase, parameter); + } else { + onSearchUp(phrase, parameter); + } } } diff --git a/src/widget/form/genericchatform.h b/src/widget/form/genericchatform.h index 2fc630947..f5685ebe5 100644 --- a/src/widget/form/genericchatform.h +++ b/src/widget/form/genericchatform.h @@ -22,6 +22,7 @@ #include "src/chatlog/chatmessage.h" #include "src/core/toxpk.h" +#include "src/widget/searchtypes.h" #include #include @@ -75,6 +76,7 @@ public: void addAlertMessage(const ToxPk& author, const QString& message, const QDateTime& datetime); static QString resolveToxPk(const ToxPk& pk); QDate getLatestDate() const; + QDate getFirstDate() const; signals: void sendMessage(uint32_t, QString); @@ -107,14 +109,15 @@ protected slots: void searchFormShow(); void onSearchTriggered(); - void searchInBegin(const QString& phrase); - virtual void onSearchUp(const QString& phrase) = 0; - virtual void onSearchDown(const QString& phrase) = 0; + virtual void searchInBegin(const QString& phrase, const ParameterSearch& parameter) = 0; + virtual void onSearchUp(const QString& phrase, const ParameterSearch& parameter) = 0; + virtual void onSearchDown(const QString& phrase, const ParameterSearch& parameter) = 0; void onContinueSearch(); private: void retranslateUi(); void addSystemDateMessage(); + QDate getDate(const ChatLine::Ptr& chatLine) const; protected: ChatMessage::Ptr createMessage(const ToxPk& author, const QString& message, @@ -133,8 +136,8 @@ protected: virtual void resizeEvent(QResizeEvent* event) final override; virtual bool eventFilter(QObject* object, QEvent* event) final override; void disableSearchText(); - bool searchInText(const QString& phrase, bool searchUp); - int indexForSearchInLine(const QString& txt, const QString& phrase, bool searchUp); + bool searchInText(const QString& phrase, const ParameterSearch& parameter, bool searchUp); + std::pair indexForSearchInLine(const QString& txt, const QString& phrase, const ParameterSearch& parameter, bool searchUp); protected: bool audioInputFlag; diff --git a/src/widget/form/groupchatform.cpp b/src/widget/form/groupchatform.cpp index 38b00bd07..f3b3a7582 100644 --- a/src/widget/form/groupchatform.cpp +++ b/src/widget/form/groupchatform.cpp @@ -199,14 +199,27 @@ void GroupChatForm::onTitleChanged(uint32_t groupId, const QString& author, cons addSystemInfoMessage(message, ChatMessage::INFO, curTime); } -void GroupChatForm::onSearchUp(const QString& phrase) +void GroupChatForm::searchInBegin(const QString& phrase, const ParameterSearch& parameter) { - searchInText(phrase, true); + disableSearchText(); + + searchPoint = QPoint(1, -1); + + if (parameter.period == PeriodSearch::WithTheFirst || parameter.period == PeriodSearch::AfterDate) { + onSearchDown(phrase, parameter); + } else { + onSearchUp(phrase, parameter); + } } -void GroupChatForm::onSearchDown(const QString& phrase) +void GroupChatForm::onSearchUp(const QString& phrase, const ParameterSearch& parameter) { - searchInText(phrase, false); + searchInText(phrase, parameter, true); +} + +void GroupChatForm::onSearchDown(const QString& phrase, const ParameterSearch& parameter) +{ + searchInText(phrase, parameter, false); } void GroupChatForm::onScreenshotClicked() diff --git a/src/widget/form/groupchatform.h b/src/widget/form/groupchatform.h index 81364eaaa..63c1c6e3b 100644 --- a/src/widget/form/groupchatform.h +++ b/src/widget/form/groupchatform.h @@ -50,8 +50,9 @@ 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; + void searchInBegin(const QString& phrase, const ParameterSearch& parameter) override; + void onSearchUp(const QString& phrase, const ParameterSearch& parameter) override; + void onSearchDown(const QString& phrase, const ParameterSearch& parameter) override; void onLabelContextMenuRequested(const QPoint& localPos); protected: diff --git a/src/widget/form/loadhistorydialog.cpp b/src/widget/form/loadhistorydialog.cpp index 379a40b45..7ae2d8736 100644 --- a/src/widget/form/loadhistorydialog.cpp +++ b/src/widget/form/loadhistorydialog.cpp @@ -37,6 +37,13 @@ LoadHistoryDialog::LoadHistoryDialog(const ToxPk& friendPk, QWidget* parent) &LoadHistoryDialog::highlightDates); } +LoadHistoryDialog::LoadHistoryDialog(QWidget* parent) + : QDialog(parent) + , ui(new Ui::LoadHistoryDialog) +{ + ui->setupUi(this); +} + LoadHistoryDialog::~LoadHistoryDialog() { delete ui; diff --git a/src/widget/form/loadhistorydialog.h b/src/widget/form/loadhistorydialog.h index 4c95e7235..33de3f737 100644 --- a/src/widget/form/loadhistorydialog.h +++ b/src/widget/form/loadhistorydialog.h @@ -34,6 +34,7 @@ class LoadHistoryDialog : public QDialog public: explicit LoadHistoryDialog(const ToxPk& friendPk, QWidget* parent = 0); + explicit LoadHistoryDialog(QWidget* parent = 0); ~LoadHistoryDialog(); QDateTime getFromDate(); diff --git a/src/widget/form/searchsettingsform.cpp b/src/widget/form/searchsettingsform.cpp index 574d4e0c3..534597b1c 100644 --- a/src/widget/form/searchsettingsform.cpp +++ b/src/widget/form/searchsettingsform.cpp @@ -1,6 +1,7 @@ #include "searchsettingsform.h" #include "ui_searchsettingsform.h" #include "src/widget/style.h" +#include "src/widget/form/loadhistorydialog.h" SearchSettingsForm::SearchSettingsForm(QWidget *parent) : QWidget(parent), @@ -16,12 +17,14 @@ SearchSettingsForm::SearchSettingsForm(QWidget *parent) : ui->choiceDateButton->setStyleSheet(Style::getStylesheet(QStringLiteral(":/ui/chatForm/buttons.css"))); ui->startDateLabel->setStyleSheet("QLabel{color: #ddd;}"); + isUpdate = false; connect(ui->startSearchComboBox, static_cast(&QComboBox::currentIndexChanged), this, &SearchSettingsForm::onStartSearchSelected); connect(ui->registerCheckBox, &QCheckBox::clicked, this, &SearchSettingsForm::onRegisterClicked); - connect(ui->wordsOnlyCheckBox, &QCheckBox::clicked, this, &SearchSettingsForm::onWordsOnlyClicked); - connect(ui->regularCheckBox, &QCheckBox::clicked, this, &SearchSettingsForm::onRegularClicked); + connect(ui->wordsOnlyRadioButton, &QCheckBox::clicked, this, &SearchSettingsForm::onWordsOnlyClicked); + connect(ui->regularRadioButton, &QCheckBox::clicked, this, &SearchSettingsForm::onRegularClicked); + connect(ui->choiceDateButton, &QPushButton::clicked, this, &SearchSettingsForm::onChoiceDate); } SearchSettingsForm::~SearchSettingsForm() @@ -29,8 +32,57 @@ SearchSettingsForm::~SearchSettingsForm() delete ui; } +ParameterSearch SearchSettingsForm::getParameterSearch() +{ + ParameterSearch ps; + + if (ui->regularRadioButton->isChecked()) { + ps.filter = FilterSearch::Regular; + } else if (ui->registerCheckBox->isChecked() && ui->wordsOnlyRadioButton->isChecked()) { + ps.filter = FilterSearch::RegisterAndWordsOnly; + } else if (ui->registerCheckBox->isChecked() && ui->regularRadioButton->isChecked()) { + ps.filter = FilterSearch::RegisterAndRegular; + } else if (ui->registerCheckBox->isChecked()) { + ps.filter = FilterSearch::Register; + } else if (ui->wordsOnlyRadioButton->isChecked()) { + ps.filter = FilterSearch::WordsOnly; + } else { + ps.filter = FilterSearch::None; + } + + switch (ui->startSearchComboBox->currentIndex()) { + case 0: + ps.period = PeriodSearch::WithTheEnd; + break; + case 1: + ps.period = PeriodSearch::WithTheFirst; + break; + case 2: + ps.period = PeriodSearch::AfterDate; + break; + case 3: + ps.period = PeriodSearch::BeforeDate; + break; + default: + ps.period = PeriodSearch::WithTheEnd; + break; + } + + ps.date = startDate; + ps.isUpdate = isUpdate; + isUpdate = false; + + return ps; +} + +void SearchSettingsForm::updateStartDateLabel() +{ + ui->startDateLabel->setText(startDate.toString("dd.MM.yyyy")); +} + void SearchSettingsForm::onStartSearchSelected(const int index) { + isUpdate = true; if (index > 1) { ui->choiceDateButton->setEnabled(true); ui->startDateLabel->setEnabled(true); @@ -39,6 +91,12 @@ void SearchSettingsForm::onStartSearchSelected(const int index) ui->choiceDateButton->setStyleSheet(Style::getStylesheet(QStringLiteral(":/ui/chatForm/buttons.css"))); ui->startDateLabel->setStyleSheet("QLabel{color: #000;}"); + + if (startDate.isNull()) { + startDate = QDate::currentDate(); + updateStartDateLabel(); + } + } else { ui->choiceDateButton->setEnabled(false); ui->startDateLabel->setEnabled(false); @@ -52,22 +110,31 @@ void SearchSettingsForm::onStartSearchSelected(const int index) void SearchSettingsForm::onRegisterClicked(const bool checked) { - if (checked) { - ui->regularCheckBox->setChecked(false); - } + isUpdate = true; } void SearchSettingsForm::onWordsOnlyClicked(const bool checked) { + isUpdate = true; if (checked) { - ui->regularCheckBox->setChecked(false); + ui->regularRadioButton->setChecked(false); } } void SearchSettingsForm::onRegularClicked(const bool checked) { + isUpdate = true; if (checked) { - ui->registerCheckBox->setChecked(false); - ui->wordsOnlyCheckBox->setChecked(false); + ui->wordsOnlyRadioButton->setChecked(false); + } +} + +void SearchSettingsForm::onChoiceDate() +{ + isUpdate = true; + LoadHistoryDialog dlg; + if (dlg.exec()) { + startDate = dlg.getFromDate().date(); + updateStartDateLabel(); } } diff --git a/src/widget/form/searchsettingsform.h b/src/widget/form/searchsettingsform.h index b1f878427..ceee881a9 100644 --- a/src/widget/form/searchsettingsform.h +++ b/src/widget/form/searchsettingsform.h @@ -2,6 +2,7 @@ #define SEARCHSETTINGSFORM_H #include +#include "../searchtypes.h" namespace Ui { class SearchSettingsForm; @@ -15,14 +16,21 @@ public: explicit SearchSettingsForm(QWidget *parent = nullptr); ~SearchSettingsForm(); + ParameterSearch getParameterSearch(); + private: Ui::SearchSettingsForm *ui; + QDate startDate; + bool isUpdate; + + void updateStartDateLabel(); private slots: void onStartSearchSelected(const int index); void onRegisterClicked(const bool checked); void onWordsOnlyClicked(const bool checked); void onRegularClicked(const bool checked); + void onChoiceDate(); }; #endif // SEARCHSETTINGSFORM_H diff --git a/src/widget/form/searchsettingsform.ui b/src/widget/form/searchsettingsform.ui index 864f212cf..654d2cd9d 100644 --- a/src/widget/form/searchsettingsform.ui +++ b/src/widget/form/searchsettingsform.ui @@ -7,7 +7,7 @@ 0 0 473 - 78 + 83 @@ -20,16 +20,7 @@ Form - - 0 - - - 0 - - - 0 - - + 0 @@ -107,17 +98,38 @@ - + Whole words only + + true + + + false + + + false + + + false + - + Use regular expressions + + true + + + false + + + false + diff --git a/src/widget/searchform.cpp b/src/widget/searchform.cpp index 1bd8d9351..214013c20 100644 --- a/src/widget/searchform.cpp +++ b/src/widget/searchform.cpp @@ -34,6 +34,7 @@ SearchForm::SearchForm(QWidget* parent) : QWidget(parent) settings->setVisible(false); isActiveSettings = false; + isChangedPhrase = false; settingsButton = createButton("searchSettingsButton", "green"); upButton = createButton("searchUpButton", "green"); @@ -73,6 +74,11 @@ QString SearchForm::getSearchPhrase() const return searchPhrase; } +ParameterSearch SearchForm::getParametrSearch() +{ + return parameter; +} + void SearchForm::setFocusEditor() { searchLine->setFocus(); @@ -100,20 +106,46 @@ QPushButton *SearchForm::createButton(const QString& name, const QString& state) return btn; } +ParameterSearch SearchForm::getAndCheckParametrSearch() +{ + auto sendParam = settings->getParameterSearch(); + if (!isChangedPhrase && !sendParam.isUpdate) { + sendParam.period = PeriodSearch::None; + } + + isChangedPhrase = false; + parameter = sendParam; + + return sendParam; +} + void SearchForm::changedSearchPhrase(const QString& text) { searchPhrase = text; - emit searchInBegin(searchPhrase); + isChangedPhrase = true; + if (!isActiveSettings) { + emit searchInBegin(searchPhrase, getAndCheckParametrSearch()); + } } void SearchForm::clickedUp() { - emit searchUp(searchPhrase); + auto param = getAndCheckParametrSearch(); + if (param.period == PeriodSearch::None) { + emit searchUp(searchPhrase, param); + } else { + emit searchInBegin(searchPhrase, param); + } } void SearchForm::clickedDown() { - emit searchDown(searchPhrase); + auto param = getAndCheckParametrSearch(); + if (param.period == PeriodSearch::None) { + emit searchDown(searchPhrase, param); + } else { + emit searchInBegin(searchPhrase, param); + } } void SearchForm::clickedHide() diff --git a/src/widget/searchform.h b/src/widget/searchform.h index 127a11acc..c84af2cd9 100644 --- a/src/widget/searchform.h +++ b/src/widget/searchform.h @@ -22,6 +22,7 @@ #include #include +#include "searchtypes.h" class QPushButton; class LineEdit; @@ -34,6 +35,7 @@ public: explicit SearchForm(QWidget* parent = nullptr); void removeSearchPhrase(); QString getSearchPhrase() const; + ParameterSearch getParametrSearch(); void setFocusEditor(); void insertEditor(const QString &text); @@ -43,6 +45,7 @@ protected: private: // TODO: Merge with 'createButton' from chatformheader.cpp QPushButton* createButton(const QString& name, const QString& state); + ParameterSearch getAndCheckParametrSearch(); QPushButton* settingsButton; QPushButton* upButton; @@ -52,8 +55,10 @@ private: SearchSettingsForm* settings; QString searchPhrase; + ParameterSearch parameter; bool isActiveSettings; + bool isChangedPhrase; private slots: void changedSearchPhrase(const QString& text); @@ -63,9 +68,9 @@ private slots: void clickedSearch(); signals: - void searchInBegin(const QString& phrase); - void searchUp(const QString& phrase); - void searchDown(const QString& phrase); + void searchInBegin(const QString& phrase, const ParameterSearch& parameter); + void searchUp(const QString& phrase, const ParameterSearch& parameter); + void searchDown(const QString& phrase, const ParameterSearch& parameter); void visibleChanged(); }; diff --git a/src/widget/searchtypes.h b/src/widget/searchtypes.h new file mode 100644 index 000000000..fb2effac0 --- /dev/null +++ b/src/widget/searchtypes.h @@ -0,0 +1,50 @@ +#ifndef SEARCHTYPES_H +#define SEARCHTYPES_H + +#include + +enum class FilterSearch { + None, + Register, + WordsOnly, + Regular, + RegisterAndWordsOnly, + RegisterAndRegular +}; + +enum class PeriodSearch { + None, + WithTheEnd, + WithTheFirst, + AfterDate, + BeforeDate +}; + +struct ParameterSearch { + FilterSearch filter; + PeriodSearch period; + QDate date; + bool isUpdate; + + bool operator ==(const ParameterSearch& other) { + if (this->filter != other.filter) { + return false; + } + + if (this->period != other.period) { + return false; + } + + if (this->date != other.date) { + return false; + } + + return true; + } + + bool operator !=(const ParameterSearch& other) { + return !(*this == other); + } +}; + +#endif //SEARCHTYPES_H diff --git a/ui/settings/mainContent.css b/ui/settings/mainContent.css index f009a09ea..b4192e5e8 100644 --- a/ui/settings/mainContent.css +++ b/ui/settings/mainContent.css @@ -223,3 +223,9 @@ QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal { background: none; } + +QRadioButton +{ + background: white; + color: black; +} From 3b7ba023242ba9e2a5340eb9c1b8ed69db710aef Mon Sep 17 00:00:00 2001 From: TriKriSta Date: Sun, 24 Jun 2018 21:20:49 +0300 Subject: [PATCH 03/19] feat: add functions for change title and info in LoadHistoryDialog --- src/widget/form/loadhistorydialog.cpp | 10 ++++++++++ src/widget/form/loadhistorydialog.h | 2 ++ src/widget/form/searchsettingsform.cpp | 2 ++ 3 files changed, 14 insertions(+) diff --git a/src/widget/form/loadhistorydialog.cpp b/src/widget/form/loadhistorydialog.cpp index 7ae2d8736..d82628d90 100644 --- a/src/widget/form/loadhistorydialog.cpp +++ b/src/widget/form/loadhistorydialog.cpp @@ -61,6 +61,16 @@ QDateTime LoadHistoryDialog::getFromDate() return res; } +void LoadHistoryDialog::setTitle(const QString& title) +{ + setWindowTitle(title); +} + +void LoadHistoryDialog::setInfoLabel(const QString& info) +{ + ui->fromLabel->setText(info); +} + void LoadHistoryDialog::highlightDates(int year, int month) { History* history = Nexus::getProfile()->getHistory(); diff --git a/src/widget/form/loadhistorydialog.h b/src/widget/form/loadhistorydialog.h index 33de3f737..d28dd4396 100644 --- a/src/widget/form/loadhistorydialog.h +++ b/src/widget/form/loadhistorydialog.h @@ -38,6 +38,8 @@ public: ~LoadHistoryDialog(); QDateTime getFromDate(); + void setTitle(const QString& title); + void setInfoLabel(const QString& info); public slots: void highlightDates(int year, int month); diff --git a/src/widget/form/searchsettingsform.cpp b/src/widget/form/searchsettingsform.cpp index 534597b1c..87675b01a 100644 --- a/src/widget/form/searchsettingsform.cpp +++ b/src/widget/form/searchsettingsform.cpp @@ -133,6 +133,8 @@ void SearchSettingsForm::onChoiceDate() { isUpdate = true; LoadHistoryDialog dlg; + dlg.setTitle(tr("Select Date Dialog")); + dlg.setInfoLabel(tr("Select a date")); if (dlg.exec()) { startDate = dlg.getFromDate().date(); updateStartDateLabel(); From 8dd83477591f9c357abba1892e1a7a6b9ca11af9 Mon Sep 17 00:00:00 2001 From: TriKriSta Date: Sun, 24 Jun 2018 22:01:45 +0300 Subject: [PATCH 04/19] feat: add startButton in SearchForm --- src/widget/form/searchsettingsform.cpp | 20 +++++-- src/widget/form/searchsettingsform.h | 4 ++ src/widget/searchform.cpp | 77 ++++++++++++++++++++------ src/widget/searchform.h | 3 + src/widget/searchtypes.h | 6 ++ ui/chatForm/buttons.css | 8 +++ 6 files changed, 97 insertions(+), 21 deletions(-) diff --git a/src/widget/form/searchsettingsform.cpp b/src/widget/form/searchsettingsform.cpp index 87675b01a..1a642975c 100644 --- a/src/widget/form/searchsettingsform.cpp +++ b/src/widget/form/searchsettingsform.cpp @@ -80,9 +80,14 @@ void SearchSettingsForm::updateStartDateLabel() ui->startDateLabel->setText(startDate.toString("dd.MM.yyyy")); } +void SearchSettingsForm::setUpdate(const bool isUpdate) +{ + this->isUpdate = isUpdate; + emit updateSettings(isUpdate); +} + void SearchSettingsForm::onStartSearchSelected(const int index) { - isUpdate = true; if (index > 1) { ui->choiceDateButton->setEnabled(true); ui->startDateLabel->setEnabled(true); @@ -106,32 +111,35 @@ void SearchSettingsForm::onStartSearchSelected(const int index) ui->startDateLabel->setStyleSheet("QLabel{color: #ddd;}"); } + + setUpdate(true); } void SearchSettingsForm::onRegisterClicked(const bool checked) { - isUpdate = true; + setUpdate(true); } void SearchSettingsForm::onWordsOnlyClicked(const bool checked) { - isUpdate = true; if (checked) { ui->regularRadioButton->setChecked(false); } + + setUpdate(true); } void SearchSettingsForm::onRegularClicked(const bool checked) { - isUpdate = true; if (checked) { ui->wordsOnlyRadioButton->setChecked(false); } + + setUpdate(true); } void SearchSettingsForm::onChoiceDate() { - isUpdate = true; LoadHistoryDialog dlg; dlg.setTitle(tr("Select Date Dialog")); dlg.setInfoLabel(tr("Select a date")); @@ -139,4 +147,6 @@ void SearchSettingsForm::onChoiceDate() startDate = dlg.getFromDate().date(); updateStartDateLabel(); } + + setUpdate(true); } diff --git a/src/widget/form/searchsettingsform.h b/src/widget/form/searchsettingsform.h index ceee881a9..a2441c55d 100644 --- a/src/widget/form/searchsettingsform.h +++ b/src/widget/form/searchsettingsform.h @@ -24,6 +24,7 @@ private: bool isUpdate; void updateStartDateLabel(); + void setUpdate(const bool isUpdate); private slots: void onStartSearchSelected(const int index); @@ -31,6 +32,9 @@ private slots: void onWordsOnlyClicked(const bool checked); void onRegularClicked(const bool checked); void onChoiceDate(); + +signals: + void updateSettings(const bool isUpdate); }; #endif // SEARCHSETTINGSFORM_H diff --git a/src/widget/searchform.cpp b/src/widget/searchform.cpp index 214013c20..7f9b7cd95 100644 --- a/src/widget/searchform.cpp +++ b/src/widget/searchform.cpp @@ -40,10 +40,13 @@ SearchForm::SearchForm(QWidget* parent) : QWidget(parent) upButton = createButton("searchUpButton", "green"); downButton = createButton("searchDownButton", "green"); hideButton = createButton("searchHideButton", "red"); + startButton = createButton("startButton", "green"); + startButton->setText(tr("Start")); layoutNavigation->setMargin(0); layoutNavigation->addWidget(settingsButton); layoutNavigation->addWidget(searchLine); + layoutNavigation->addWidget(startButton); layoutNavigation->addWidget(upButton); layoutNavigation->addWidget(downButton); layoutNavigation->addWidget(hideButton); @@ -51,6 +54,8 @@ SearchForm::SearchForm(QWidget* parent) : QWidget(parent) layout->addLayout(layoutNavigation); layout->addWidget(settings); + startButton->setHidden(true); + setLayout(layout); connect(searchLine, &LineEdit::textChanged, this, &SearchForm::changedSearchPhrase); @@ -61,7 +66,10 @@ SearchForm::SearchForm(QWidget* parent) : QWidget(parent) connect(upButton, &QPushButton::clicked, this, &SearchForm::clickedUp); connect(downButton, &QPushButton::clicked, this, &SearchForm::clickedDown); connect(hideButton, &QPushButton::clicked, this, &SearchForm::clickedHide); + connect(startButton, &QPushButton::clicked, this, &SearchForm::clickedStart); connect(settingsButton, &QPushButton::clicked, this, &SearchForm::clickedSearch); + + connect(settings, &SearchSettingsForm::updateSettings, this, &SearchForm::changedButtons); } void SearchForm::removeSearchPhrase() @@ -108,43 +116,60 @@ QPushButton *SearchForm::createButton(const QString& name, const QString& state) ParameterSearch SearchForm::getAndCheckParametrSearch() { - auto sendParam = settings->getParameterSearch(); - if (!isChangedPhrase && !sendParam.isUpdate) { - sendParam.period = PeriodSearch::None; + if (isActiveSettings) { + auto sendParam = settings->getParameterSearch(); + if (!isChangedPhrase && !sendParam.isUpdate) { + sendParam.period = PeriodSearch::None; + } + + isChangedPhrase = false; + parameter = sendParam; + + return sendParam; } - isChangedPhrase = false; - parameter = sendParam; - - return sendParam; + return ParameterSearch(); } void SearchForm::changedSearchPhrase(const QString& text) { + QString l = text.right(1); + + if (searchPhrase == text) { + return; + } + + if (!l.isEmpty() && l != " " && l[0].isSpace()) { + searchLine->setText(searchPhrase); + return; + } + searchPhrase = text; isChangedPhrase = true; - if (!isActiveSettings) { + if (isActiveSettings) { + if (startButton->isHidden()) { + changedButtons(true); + } + } else { emit searchInBegin(searchPhrase, getAndCheckParametrSearch()); } } void SearchForm::clickedUp() { - auto param = getAndCheckParametrSearch(); - if (param.period == PeriodSearch::None) { - emit searchUp(searchPhrase, param); + if (startButton->isHidden()) { + emit searchUp(searchPhrase, getAndCheckParametrSearch()); } else { - emit searchInBegin(searchPhrase, param); + clickedStart(); } } void SearchForm::clickedDown() { - auto param = getAndCheckParametrSearch(); - if (param.period == PeriodSearch::None) { - emit searchDown(searchPhrase, param); + if (startButton->isHidden()) { + emit searchDown(searchPhrase, getAndCheckParametrSearch()); } else { - emit searchInBegin(searchPhrase, param); + clickedStart(); } } @@ -154,6 +179,12 @@ void SearchForm::clickedHide() emit visibleChanged(); } +void SearchForm::clickedStart() +{ + changedButtons(false); + emit searchInBegin(searchPhrase, getAndCheckParametrSearch()); +} + void SearchForm::clickedSearch() { isActiveSettings = !isActiveSettings; @@ -163,11 +194,25 @@ void SearchForm::clickedSearch() settingsButton->setProperty("state", "red"); } else { settingsButton->setProperty("state", "green"); + changedButtons(false); } settingsButton->setStyleSheet(Style::getStylesheet(QStringLiteral(":/ui/chatForm/buttons.css"))); settingsButton->update(); } +void SearchForm::changedButtons(const bool isUpdate) +{ + if (isUpdate) { + startButton->setHidden(false); + upButton->setHidden(true); + downButton->setHidden(true); + } else { + startButton->setHidden(true); + upButton->setHidden(false); + downButton->setHidden(false); + } +} + LineEdit::LineEdit(QWidget* parent) : QLineEdit(parent) { } diff --git a/src/widget/searchform.h b/src/widget/searchform.h index c84af2cd9..13c17e25a 100644 --- a/src/widget/searchform.h +++ b/src/widget/searchform.h @@ -51,6 +51,7 @@ private: QPushButton* upButton; QPushButton* downButton; QPushButton* hideButton; + QPushButton* startButton; LineEdit* searchLine; SearchSettingsForm* settings; @@ -65,7 +66,9 @@ private slots: void clickedUp(); void clickedDown(); void clickedHide(); + void clickedStart(); void clickedSearch(); + void changedButtons(const bool isUpdate); signals: void searchInBegin(const QString& phrase, const ParameterSearch& parameter); diff --git a/src/widget/searchtypes.h b/src/widget/searchtypes.h index fb2effac0..4f3b70b74 100644 --- a/src/widget/searchtypes.h +++ b/src/widget/searchtypes.h @@ -26,6 +26,12 @@ struct ParameterSearch { QDate date; bool isUpdate; + ParameterSearch() { + filter = FilterSearch::None; + period = PeriodSearch::None; + isUpdate = false; + } + bool operator ==(const ParameterSearch& other) { if (this->filter != other.filter) { return false; diff --git a/ui/chatForm/buttons.css b/ui/chatForm/buttons.css index 3c1b2f454..bef35130e 100644 --- a/ui/chatForm/buttons.css +++ b/ui/chatForm/buttons.css @@ -109,6 +109,14 @@ QAbstractButton#choiceDateButton color: #fff } +QAbstractButton#startButton +{ + border-radius: 5px; + width: 60px; + height: 35px; + color: #fff +} + /* Common */ QAbstractButton From d1afc7f6dfa13c0570e1c37e3bede37a5a1f13a8 Mon Sep 17 00:00:00 2001 From: TriKriSta Date: Tue, 26 Jun 2018 20:58:59 +0300 Subject: [PATCH 05/19] chore: install sqlite in travis --- .travis/build-ubuntu-14-04.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.travis/build-ubuntu-14-04.sh b/.travis/build-ubuntu-14-04.sh index f19b5e97e..34343b39a 100755 --- a/.travis/build-ubuntu-14-04.sh +++ b/.travis/build-ubuntu-14-04.sh @@ -52,6 +52,15 @@ sudo apt-get install -y --force-yes \ # Qt source /opt/qt55/bin/qt55-env.sh || yes +# sqlite +wget https://sqlite.org/2018/sqlite-autoconf-3240000.tar.gz +tar xvfz sqlite-autoconf-3240000.tar.gz +cd sqlite-autoconf-3240000 +./configure +make -j$(nproc) +sudo make install +cd .. + # ffmpeg if [ ! -e "libs" ]; then mkdir libs; fi if [ ! -e "ffmpeg" ]; then mkdir ffmpeg; fi From 4fdf73f2f03bd1c401d3f564c213847108a7fa24 Mon Sep 17 00:00:00 2001 From: TriKriSta Date: Fri, 29 Jun 2018 19:31:34 +0300 Subject: [PATCH 06/19] refactor: remove commented code, use QStringLiteral --- src/persistence/db/rawdatabase.h | 3 ++- src/persistence/history.cpp | 24 ++++++++++++------------ src/widget/form/chatform.cpp | 11 ----------- src/widget/form/genericchatform.cpp | 2 +- src/widget/searchform.cpp | 2 +- src/widget/searchform.h | 2 +- 6 files changed, 17 insertions(+), 27 deletions(-) diff --git a/src/persistence/db/rawdatabase.h b/src/persistence/db/rawdatabase.h index e2ca9d5a3..6a3179707 100644 --- a/src/persistence/db/rawdatabase.h +++ b/src/persistence/db/rawdatabase.h @@ -89,9 +89,10 @@ protected: static QVariant extractData(sqlite3_stmt* stmt, int col); static void regexpInsensitive(sqlite3_context* ctx, int argc, sqlite3_value** argv); static void regexpSensitive(sqlite3_context* ctx, int argc, sqlite3_value** argv); - static void regexp(sqlite3_context* ctx, int argc, sqlite3_value** argv, const Qt::CaseSensitivity cs); private: + static void regexp(sqlite3_context* ctx, int argc, sqlite3_value** argv, const Qt::CaseSensitivity cs); + struct Transaction { QVector queries; diff --git a/src/persistence/history.cpp b/src/persistence/history.cpp index 024609efc..affb28cd5 100644 --- a/src/persistence/history.cpp +++ b/src/persistence/history.cpp @@ -328,22 +328,22 @@ QDateTime History::getDateWhereFindPhrase(const QString& friendPk, const QDateTi switch (parameter.filter) { case FilterSearch::Register: - message = QString("message LIKE '%%1%'").arg(phrase); + message = QStringLiteral("message LIKE '%%1%'").arg(phrase); break; case FilterSearch::WordsOnly: - message = QString("message REGEXP '\\b%1\\b'").arg(phrase.toLower()); + message = QStringLiteral("message REGEXP '\\b%1\\b'").arg(phrase.toLower()); break; case FilterSearch::RegisterAndWordsOnly: - message = QString("REGEXPSENSITIVE(message, '\\b%1\\b')").arg(phrase); + message = QStringLiteral("REGEXPSENSITIVE(message, '\\b%1\\b')").arg(phrase); break; case FilterSearch::Regular: - message = QString("message REGEXP '%1'").arg(phrase); + message = QStringLiteral("message REGEXP '%1'").arg(phrase); break; case FilterSearch::RegisterAndRegular: - message = QString("REGEXPSENSITIVE(message '%1')").arg(phrase); + message = QStringLiteral("REGEXPSENSITIVE(message '%1')").arg(phrase); break; default: - message = QString("LOWER(message) LIKE '%%1%'").arg(phrase.toLower()); + message = QStringLiteral("LOWER(message) LIKE '%%1%'").arg(phrase.toLower()); break; } @@ -355,21 +355,21 @@ QDateTime History::getDateWhereFindPhrase(const QString& friendPk, const QDateTi QString period; switch (parameter.period) { case PeriodSearch::WithTheFirst: - period = QString("ORDER BY timestamp ASC LIMIT 1;"); + period = QStringLiteral("ORDER BY timestamp ASC LIMIT 1;"); break; case PeriodSearch::AfterDate: - period = QString("AND timestamp > '%1' ORDER BY timestamp ASC LIMIT 1;").arg(date.toMSecsSinceEpoch()); + period = QStringLiteral("AND timestamp > '%1' ORDER BY timestamp ASC LIMIT 1;").arg(date.toMSecsSinceEpoch()); break; case PeriodSearch::BeforeDate: - period = QString("AND timestamp < '%1' ORDER BY timestamp DESC LIMIT 1;").arg(date.toMSecsSinceEpoch()); + period = QStringLiteral("AND timestamp < '%1' ORDER BY timestamp DESC LIMIT 1;").arg(date.toMSecsSinceEpoch()); break; default: - period = QString("AND timestamp < '%1' ORDER BY timestamp DESC LIMIT 1;").arg(date.toMSecsSinceEpoch()); + period = QStringLiteral("AND timestamp < '%1' ORDER BY timestamp DESC LIMIT 1;").arg(date.toMSecsSinceEpoch()); break; } QString queryText = - QString("SELECT timestamp " + QStringLiteral("SELECT timestamp " "FROM history " "LEFT JOIN faux_offline_pending ON history.id = faux_offline_pending.id " "JOIN peers chat ON chat_id = chat.id " @@ -397,7 +397,7 @@ QDateTime History::getStartDateChatHistory(const QString &friendPk) }; QString queryText = - QString("SELECT timestamp " + QStringLiteral("SELECT timestamp " "FROM history " "LEFT JOIN faux_offline_pending ON history.id = faux_offline_pending.id " "JOIN peers chat ON chat_id = chat.id " diff --git a/src/widget/form/chatform.cpp b/src/widget/form/chatform.cpp index e897e2685..a064b07a1 100644 --- a/src/widget/form/chatform.cpp +++ b/src/widget/form/chatform.cpp @@ -540,17 +540,6 @@ void ChatForm::onSearchUp(const QString& phrase, const ParameterSearch& paramete int startLine = numLines - searchPoint.x(); if (startLine == 0 && loadHistory(phrase, parameter)) { -// QString pk = f->getPublicKey().toString(); -// QDateTime newBaseDate = history->getDateWhereFindPhrase(pk, earliestMessage, phrase, parameter); - -// if (!newBaseDate.isValid()) { -// return; -// } - -// searchAfterLoadHistory = true; -// loadHistoryByDateRange(newBaseDate); - -// return; return; } diff --git a/src/widget/form/genericchatform.cpp b/src/widget/form/genericchatform.cpp index e67749ccb..986690fe0 100644 --- a/src/widget/form/genericchatform.cpp +++ b/src/widget/form/genericchatform.cpp @@ -934,7 +934,7 @@ void GenericChatForm::onSearchTriggered() void GenericChatForm::onContinueSearch() { QString phrase = searchForm->getSearchPhrase(); - ParameterSearch parameter = searchForm->getParametrSearch(); + ParameterSearch parameter = searchForm->getParameterSearch(); if (!phrase.isEmpty() && searchAfterLoadHistory) { searchAfterLoadHistory = false; diff --git a/src/widget/searchform.cpp b/src/widget/searchform.cpp index 7f9b7cd95..23d6b2faf 100644 --- a/src/widget/searchform.cpp +++ b/src/widget/searchform.cpp @@ -82,7 +82,7 @@ QString SearchForm::getSearchPhrase() const return searchPhrase; } -ParameterSearch SearchForm::getParametrSearch() +ParameterSearch SearchForm::getParameterSearch() { return parameter; } diff --git a/src/widget/searchform.h b/src/widget/searchform.h index 13c17e25a..7690d961f 100644 --- a/src/widget/searchform.h +++ b/src/widget/searchform.h @@ -35,7 +35,7 @@ public: explicit SearchForm(QWidget* parent = nullptr); void removeSearchPhrase(); QString getSearchPhrase() const; - ParameterSearch getParametrSearch(); + ParameterSearch getParameterSearch(); void setFocusEditor(); void insertEditor(const QString &text); From 74468fde32b67ab27dc8fc8af6e0a89619f1edbb Mon Sep 17 00:00:00 2001 From: TriKriSta Date: Fri, 29 Jun 2018 19:58:28 +0300 Subject: [PATCH 07/19] docs: add documentation for some new functions --- src/persistence/db/rawdatabase.cpp | 12 ++++++++++++ src/persistence/history.cpp | 13 +++++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/persistence/db/rawdatabase.cpp b/src/persistence/db/rawdatabase.cpp index 6085d3a34..7a83fe794 100644 --- a/src/persistence/db/rawdatabase.cpp +++ b/src/persistence/db/rawdatabase.cpp @@ -718,11 +718,23 @@ QVariant RawDatabase::extractData(sqlite3_stmt* stmt, int col) } } +/** + * @brief Use for create function in db for search data use regular experessions without case sensitive + * @param ctx ctx the context in which an SQL function executes + * @param argc number of arguments + * @param argv arguments + */ void RawDatabase::regexpInsensitive(sqlite3_context* ctx, int argc, sqlite3_value** argv) { regexp(ctx, argc, argv, Qt::CaseInsensitive); } +/** + * @brief Use for create function in db for search data use regular experessions without case sensitive + * @param ctx the context in which an SQL function executes + * @param argc number of arguments + * @param argv arguments + */ void RawDatabase::regexpSensitive(sqlite3_context* ctx, int argc, sqlite3_value** argv) { regexp(ctx, argc, argv, Qt::CaseSensitive); diff --git a/src/persistence/history.cpp b/src/persistence/history.cpp index affb28cd5..2eb5bffca 100644 --- a/src/persistence/history.cpp +++ b/src/persistence/history.cpp @@ -315,6 +315,14 @@ QList History::getChatHistoryCounts(const ToxPk& friendPk return counts; } +/** + * @brief Search phrase in chat messages + * @param friendPk Friend public key + * @param from a date message where need to start a search + * @param phrase what need to find + * @param parameter for search + * @return date of the message where the phrase was found + */ QDateTime History::getDateWhereFindPhrase(const QString& friendPk, const QDateTime& from, QString phrase, const ParameterSearch& parameter) { QList counts; @@ -389,6 +397,11 @@ QDateTime History::getDateWhereFindPhrase(const QString& friendPk, const QDateTi return QDateTime(); } +/** + * @brief get start date of correspondence + * @param friendPk Friend public key + * @return start date of correspondence + */ QDateTime History::getStartDateChatHistory(const QString &friendPk) { QList counts; From 60a2c5e65110349677840f3a1fd0ab0813272f1a Mon Sep 17 00:00:00 2001 From: TriKriSta Date: Sat, 7 Jul 2018 20:56:02 +0300 Subject: [PATCH 08/19] refactor: change QRegExp on QRegularExpression for some search functions --- src/chatlog/content/text.cpp | 2 +- src/chatlog/content/text.h | 2 +- src/persistence/db/rawdatabase.cpp | 11 ++-- src/persistence/db/rawdatabase.h | 3 +- src/widget/form/chatform.cpp | 11 +++- src/widget/form/genericchatform.cpp | 92 +++++++++++++++++------------ 6 files changed, 71 insertions(+), 50 deletions(-) diff --git a/src/chatlog/content/text.cpp b/src/chatlog/content/text.cpp index b25d97c0c..0f419df73 100644 --- a/src/chatlog/content/text.cpp +++ b/src/chatlog/content/text.cpp @@ -71,7 +71,7 @@ void Text::selectText(const QString& txt, const std::pair& point) selectText(cursor, point); } -void Text::selectText(const QRegExp &exp, const std::pair& point) +void Text::selectText(const QRegularExpression &exp, const std::pair& point) { regenerate(); diff --git a/src/chatlog/content/text.h b/src/chatlog/content/text.h index 15e1f7f77..633a8a06f 100644 --- a/src/chatlog/content/text.h +++ b/src/chatlog/content/text.h @@ -37,7 +37,7 @@ public: void setText(const QString& txt); void selectText(const QString& txt, const std::pair& point); - void selectText(const QRegExp& exp, const std::pair& point); + void selectText(const QRegularExpression& exp, const std::pair& point); void deselectText(); virtual void setWidth(qreal width) final; diff --git a/src/persistence/db/rawdatabase.cpp b/src/persistence/db/rawdatabase.cpp index 7a83fe794..aff9b11ec 100644 --- a/src/persistence/db/rawdatabase.cpp +++ b/src/persistence/db/rawdatabase.cpp @@ -28,7 +28,6 @@ #include #include #include -#include /// The two following defines are required to use SQLCipher /// They are used by the sqlite3.h header @@ -726,7 +725,7 @@ QVariant RawDatabase::extractData(sqlite3_stmt* stmt, int col) */ void RawDatabase::regexpInsensitive(sqlite3_context* ctx, int argc, sqlite3_value** argv) { - regexp(ctx, argc, argv, Qt::CaseInsensitive); + regexp(ctx, argc, argv, QRegularExpression::CaseInsensitiveOption | QRegularExpression::UseUnicodePropertiesOption); } /** @@ -737,17 +736,17 @@ void RawDatabase::regexpInsensitive(sqlite3_context* ctx, int argc, sqlite3_valu */ void RawDatabase::regexpSensitive(sqlite3_context* ctx, int argc, sqlite3_value** argv) { - regexp(ctx, argc, argv, Qt::CaseSensitive); + regexp(ctx, argc, argv, QRegularExpression::UseUnicodePropertiesOption); } -void RawDatabase::regexp(sqlite3_context* ctx, int argc, sqlite3_value** argv, const Qt::CaseSensitivity cs) +void RawDatabase::regexp(sqlite3_context* ctx, int argc, sqlite3_value** argv, const QRegularExpression::PatternOptions cs) { - QRegExp regex; + QRegularExpression regex; QString str1((const char*)sqlite3_value_text(argv[0])); QString str2((const char*)sqlite3_value_text(argv[1])); regex.setPattern(str1); - regex.setCaseSensitivity(cs); + regex.setPatternOptions(cs); bool b = str2.contains(regex); diff --git a/src/persistence/db/rawdatabase.h b/src/persistence/db/rawdatabase.h index 6a3179707..f4a8b37a4 100644 --- a/src/persistence/db/rawdatabase.h +++ b/src/persistence/db/rawdatabase.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -91,7 +92,7 @@ protected: static void regexpSensitive(sqlite3_context* ctx, int argc, sqlite3_value** argv); private: - static void regexp(sqlite3_context* ctx, int argc, sqlite3_value** argv, const Qt::CaseSensitivity cs); + static void regexp(sqlite3_context* ctx, int argc, sqlite3_value** argv, const QRegularExpression::PatternOptions cs); struct Transaction { diff --git a/src/widget/form/chatform.cpp b/src/widget/form/chatform.cpp index a064b07a1..c6a0a9f31 100644 --- a/src/widget/form/chatform.cpp +++ b/src/widget/form/chatform.cpp @@ -537,7 +537,14 @@ void ChatForm::onSearchUp(const QString& phrase, const ParameterSearch& paramete QVector lines = chatWidget->getLines(); int numLines = lines.size(); - int startLine = numLines - searchPoint.x(); + int startLine; + + if (searchAfterLoadHistory) { + startLine = 1; + searchAfterLoadHistory = false; + } else { + startLine = numLines - searchPoint.x(); + } if (startLine == 0 && loadHistory(phrase, parameter)) { return; @@ -746,7 +753,7 @@ void ChatForm::loadHistoryDefaultNum(bool processUndelivered) QString pk = f->getPublicKey().toString(); QList msgs = history->getChatHistoryDefaultNum(pk); if (!msgs.isEmpty()) { - earliestMessage = msgs.back().timestamp; + earliestMessage = msgs.first().timestamp; } handleLoadedMessages(msgs, processUndelivered); } diff --git a/src/widget/form/genericchatform.cpp b/src/widget/form/genericchatform.cpp index 986690fe0..911db2a13 100644 --- a/src/widget/form/genericchatform.cpp +++ b/src/widget/form/genericchatform.cpp @@ -45,7 +45,7 @@ #include #include #include -#include +#include /** * @class GenericChatForm @@ -585,8 +585,6 @@ bool GenericChatForm::searchInText(const QString& phrase, const ParameterSearch& int numLines = lines.size(); - auto d = QDate::currentDate(); - int startLine = numLines - searchPoint.x(); if (parameter.period == PeriodSearch::WithTheFirst) { startLine = 0; @@ -632,25 +630,29 @@ bool GenericChatForm::searchInText(const QString& phrase, const ParameterSearch& QString txt = content->getText(); bool find = false; - QRegExp exp; + QRegularExpression exp; + QRegularExpressionMatch match; + + auto flagIns = QRegularExpression::CaseInsensitiveOption | QRegularExpression::UseUnicodePropertiesOption; + auto flag = QRegularExpression::UseUnicodePropertiesOption; switch (parameter.filter) { case FilterSearch::Register: find = txt.contains(phrase, Qt::CaseSensitive); break; case FilterSearch::WordsOnly: - exp = QRegExp(QString("\\b%1\\b").arg(phrase), Qt::CaseInsensitive); + exp = QRegularExpression(QString("\\b%1\\b").arg(phrase), flagIns); find = txt.contains(exp); break; case FilterSearch::RegisterAndWordsOnly: - exp = QRegExp(QString("\\b%1\\b").arg(phrase)); + exp = QRegularExpression(QString("\\b%1\\b").arg(phrase), flag); find = txt.contains(exp); break; case FilterSearch::RegisterAndRegular: - exp = QRegExp(phrase); + exp = QRegularExpression(phrase, flag); find = txt.contains(exp); break; case FilterSearch::Regular: - exp = QRegExp(phrase, Qt::CaseInsensitive); + exp = QRegularExpression(phrase, flagIns); find = txt.contains(exp); break; default: @@ -670,7 +672,7 @@ bool GenericChatForm::searchInText(const QString& phrase, const ParameterSearch& chatWidget->scrollToLine(l); text->deselectText(); - if (exp.isEmpty()) { + if (exp.pattern().isEmpty()) { text->selectText(phrase, point); } else { text->selectText(exp, point); @@ -688,9 +690,12 @@ bool GenericChatForm::searchInText(const QString& phrase, const ParameterSearch& std::pair GenericChatForm::indexForSearchInLine(const QString& txt, const QString& phrase, const ParameterSearch& parameter, bool searchUp) { - int index = 0; - QRegExp exp; + int index = -1; + int size = 0; + QRegularExpression exp; + auto flagIns = QRegularExpression::CaseInsensitiveOption | QRegularExpression::UseUnicodePropertiesOption; + auto flag = QRegularExpression::UseUnicodePropertiesOption; if (searchUp) { int startIndex = -1; if (searchPoint.y() > -1) { @@ -702,25 +707,42 @@ std::pair GenericChatForm::indexForSearchInLine(const QString& txt, co index = txt.lastIndexOf(phrase, startIndex, Qt::CaseSensitive); break; case FilterSearch::WordsOnly: - exp = QRegExp(QString("\\b%1\\b").arg(phrase), Qt::CaseInsensitive); - index = exp.lastIndexIn(txt, startIndex); + exp = QRegularExpression(QString("\\b%1\\b").arg(phrase), flagIns); break; case FilterSearch::RegisterAndWordsOnly: - exp = QRegExp(QString("\\b%1\\b").arg(phrase)); - index = exp.lastIndexIn(txt, startIndex); + exp = QRegularExpression(QString("\\b%1\\b").arg(phrase), flag); break; case FilterSearch::RegisterAndRegular: - exp = QRegExp(phrase); - index = exp.lastIndexIn(txt, startIndex); + exp = QRegularExpression(phrase, flag); break; case FilterSearch::Regular: - exp = QRegExp(phrase, Qt::CaseInsensitive); - index = exp.lastIndexIn(txt, startIndex); + exp = QRegularExpression(phrase, flagIns); break; default: index = txt.lastIndexOf(phrase, startIndex, Qt::CaseInsensitive); break; } + + if (!exp.pattern().isEmpty()) { + auto matchIt = exp.globalMatch(txt); + + while (matchIt.hasNext()) { + auto match = matchIt.next(); + + int sizeItem = match.capturedLength(); + int indexItem = match.capturedStart(); + + if (startIndex == -1 || indexItem < startIndex) { + index = indexItem; + size = sizeItem; + } else { + break; + } + } + } else { + size = phrase.size(); + } + } else { int startIndex = 0; if (searchPoint.y() > -1) { @@ -732,37 +754,30 @@ std::pair GenericChatForm::indexForSearchInLine(const QString& txt, co index = txt.indexOf(phrase, startIndex, Qt::CaseSensitive); break; case FilterSearch::WordsOnly: - exp = QRegExp(QString("\\b%1\\b").arg(phrase), Qt::CaseInsensitive); - index = exp.indexIn(txt, startIndex); + exp = QRegularExpression(QString("\\b%1\\b").arg(phrase), flagIns); break; case FilterSearch::RegisterAndWordsOnly: - exp = QRegExp(QString("\\b%1\\b").arg(phrase)); - index = exp.indexIn(txt, startIndex); + exp = QRegularExpression(QString("\\b%1\\b").arg(phrase), flag); break; case FilterSearch::RegisterAndRegular: - exp = QRegExp(phrase); - index = exp.indexIn(txt, startIndex); + exp = QRegularExpression(phrase, flag); break; case FilterSearch::Regular: - exp = QRegExp(phrase, Qt::CaseInsensitive); - index = exp.indexIn(txt, startIndex); + exp = QRegularExpression(phrase, flagIns); break; default: index = txt.indexOf(phrase, startIndex, Qt::CaseInsensitive); break; } - } - int size = 0; - if (index > -1) { - if (exp.isEmpty()) { - size = phrase.size(); - } else { - auto lExp = exp.capturedTexts(); - - if (!lExp.isEmpty()) { - size = lExp[0].size(); + if (!exp.pattern().isEmpty()) { + auto match = exp.match(txt, startIndex); + if (match.hasMatch()) { + size = match.capturedLength(0); + index = match.capturedEnd() - size; } + } else { + size = phrase.size(); } } @@ -936,9 +951,8 @@ void GenericChatForm::onContinueSearch() QString phrase = searchForm->getSearchPhrase(); ParameterSearch parameter = searchForm->getParameterSearch(); if (!phrase.isEmpty() && searchAfterLoadHistory) { - searchAfterLoadHistory = false; - if (parameter.period == PeriodSearch::WithTheFirst || parameter.period == PeriodSearch::AfterDate) { + searchAfterLoadHistory = false; onSearchDown(phrase, parameter); } else { onSearchUp(phrase, parameter); From 17a97f1ff68af50588012bf3b9b31a61cdf2b194 Mon Sep 17 00:00:00 2001 From: TriKriSta Date: Sun, 8 Jul 2018 12:33:37 +0300 Subject: [PATCH 09/19] feat: add function for generating a filter for search word only --- src/persistence/history.cpp | 6 +++--- src/widget/form/genericchatform.cpp | 12 ++++++------ src/widget/searchtypes.h | 22 ++++++++++++++++++++++ 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/persistence/history.cpp b/src/persistence/history.cpp index 2eb5bffca..6daf32a37 100644 --- a/src/persistence/history.cpp +++ b/src/persistence/history.cpp @@ -339,10 +339,10 @@ QDateTime History::getDateWhereFindPhrase(const QString& friendPk, const QDateTi message = QStringLiteral("message LIKE '%%1%'").arg(phrase); break; case FilterSearch::WordsOnly: - message = QStringLiteral("message REGEXP '\\b%1\\b'").arg(phrase.toLower()); + message = QStringLiteral("message REGEXP '%1'").arg(SearchExtraFunctions::generateFilterWordsOnly(phrase).toLower()); break; case FilterSearch::RegisterAndWordsOnly: - message = QStringLiteral("REGEXPSENSITIVE(message, '\\b%1\\b')").arg(phrase); + message = QStringLiteral("REGEXPSENSITIVE(message, '%1')").arg(SearchExtraFunctions::generateFilterWordsOnly(phrase)); break; case FilterSearch::Regular: message = QStringLiteral("message REGEXP '%1'").arg(phrase); @@ -388,7 +388,7 @@ QDateTime History::getDateWhereFindPhrase(const QString& friendPk, const QDateTi .arg(message) .arg(period); - + qDebug() << "mes:" << queryText; db->execNow({queryText, rowCallback}); if (!counts.isEmpty()) { return counts[0]; diff --git a/src/widget/form/genericchatform.cpp b/src/widget/form/genericchatform.cpp index 911db2a13..6007ea357 100644 --- a/src/widget/form/genericchatform.cpp +++ b/src/widget/form/genericchatform.cpp @@ -640,11 +640,11 @@ bool GenericChatForm::searchInText(const QString& phrase, const ParameterSearch& find = txt.contains(phrase, Qt::CaseSensitive); break; case FilterSearch::WordsOnly: - exp = QRegularExpression(QString("\\b%1\\b").arg(phrase), flagIns); + exp = QRegularExpression(SearchExtraFunctions::generateFilterWordsOnly(phrase), flagIns); find = txt.contains(exp); break; case FilterSearch::RegisterAndWordsOnly: - exp = QRegularExpression(QString("\\b%1\\b").arg(phrase), flag); + exp = QRegularExpression(SearchExtraFunctions::generateFilterWordsOnly(phrase), flag); find = txt.contains(exp); break; case FilterSearch::RegisterAndRegular: @@ -707,10 +707,10 @@ std::pair GenericChatForm::indexForSearchInLine(const QString& txt, co index = txt.lastIndexOf(phrase, startIndex, Qt::CaseSensitive); break; case FilterSearch::WordsOnly: - exp = QRegularExpression(QString("\\b%1\\b").arg(phrase), flagIns); + exp = QRegularExpression(SearchExtraFunctions::generateFilterWordsOnly(phrase), flagIns); break; case FilterSearch::RegisterAndWordsOnly: - exp = QRegularExpression(QString("\\b%1\\b").arg(phrase), flag); + exp = QRegularExpression(SearchExtraFunctions::generateFilterWordsOnly(phrase), flag); break; case FilterSearch::RegisterAndRegular: exp = QRegularExpression(phrase, flag); @@ -754,10 +754,10 @@ std::pair GenericChatForm::indexForSearchInLine(const QString& txt, co index = txt.indexOf(phrase, startIndex, Qt::CaseSensitive); break; case FilterSearch::WordsOnly: - exp = QRegularExpression(QString("\\b%1\\b").arg(phrase), flagIns); + exp = QRegularExpression(SearchExtraFunctions::generateFilterWordsOnly(phrase), flagIns); break; case FilterSearch::RegisterAndWordsOnly: - exp = QRegularExpression(QString("\\b%1\\b").arg(phrase), flag); + exp = QRegularExpression(SearchExtraFunctions::generateFilterWordsOnly(phrase), flag); break; case FilterSearch::RegisterAndRegular: exp = QRegularExpression(phrase, flag); diff --git a/src/widget/searchtypes.h b/src/widget/searchtypes.h index 4f3b70b74..dfceb442f 100644 --- a/src/widget/searchtypes.h +++ b/src/widget/searchtypes.h @@ -53,4 +53,26 @@ struct ParameterSearch { } }; +class SearchExtraFunctions { +public: + static QString generateFilterWordsOnly(const QString &phrase) { + QString filter = phrase; + + if (filter.contains("\\")) { + filter.replace("\\", "\\\\"); + + if (filter.front() != '\\') { + filter = "\\b" + filter; + } + if (filter.back() != '\\') { + filter += "\\b"; + } + } else { + filter = QStringLiteral("\\b%1\\b").arg(filter); + } + + return filter; + }; +}; + #endif //SEARCHTYPES_H From ea8bbfd8a531faa6ff06900a6db367757ddaa66a Mon Sep 17 00:00:00 2001 From: TriKriSta Date: Sun, 8 Jul 2018 14:02:03 +0300 Subject: [PATCH 10/19] refactor: use const and QStringLiteral --- src/persistence/db/rawdatabase.cpp | 6 +++--- src/persistence/history.cpp | 1 - src/widget/form/chatform.cpp | 24 +++++++++++----------- src/widget/form/genericchatform.cpp | 4 ++-- src/widget/form/searchsettingsform.cpp | 16 +++++++-------- src/widget/form/searchsettingsform.h | 2 +- src/widget/searchform.cpp | 10 +++------ src/widget/searchform.h | 4 ++-- src/widget/searchtypes.h | 28 ++++++-------------------- 9 files changed, 37 insertions(+), 58 deletions(-) diff --git a/src/persistence/db/rawdatabase.cpp b/src/persistence/db/rawdatabase.cpp index aff9b11ec..c11cea6da 100644 --- a/src/persistence/db/rawdatabase.cpp +++ b/src/persistence/db/rawdatabase.cpp @@ -742,13 +742,13 @@ void RawDatabase::regexpSensitive(sqlite3_context* ctx, int argc, sqlite3_value* void RawDatabase::regexp(sqlite3_context* ctx, int argc, sqlite3_value** argv, const QRegularExpression::PatternOptions cs) { QRegularExpression regex; - QString str1((const char*)sqlite3_value_text(argv[0])); - QString str2((const char*)sqlite3_value_text(argv[1])); + const QString str1(reinterpret_cast(sqlite3_value_text(argv[0]))); + const QString str2(reinterpret_cast(sqlite3_value_text(argv[1]))); regex.setPattern(str1); regex.setPatternOptions(cs); - bool b = str2.contains(regex); + const bool b = str2.contains(regex); if (b) { sqlite3_result_int(ctx, 1); diff --git a/src/persistence/history.cpp b/src/persistence/history.cpp index 6daf32a37..84dcb16ed 100644 --- a/src/persistence/history.cpp +++ b/src/persistence/history.cpp @@ -388,7 +388,6 @@ QDateTime History::getDateWhereFindPhrase(const QString& friendPk, const QDateTi .arg(message) .arg(period); - qDebug() << "mes:" << queryText; db->execNow({queryText, rowCallback}); if (!counts.isEmpty()) { return counts[0]; diff --git a/src/widget/form/chatform.cpp b/src/widget/form/chatform.cpp index c6a0a9f31..030c6992b 100644 --- a/src/widget/form/chatform.cpp +++ b/src/widget/form/chatform.cpp @@ -503,12 +503,12 @@ void ChatForm::searchInBegin(const QString& phrase, const ParameterSearch& param searchPoint = QPoint(1, -1); - bool b = (parameter.period == PeriodSearch::WithTheFirst); - bool b1 = (parameter.period == PeriodSearch::AfterDate); - if (b || b1) { - if (b || (b1 && parameter.date < getFirstDate())) { - QString pk = f->getPublicKey().toString(); - if ((b || parameter.date >= history->getStartDateChatHistory(pk).date()) && + const bool isFirst = (parameter.period == PeriodSearch::WithTheFirst); + const bool isAfter = (parameter.period == PeriodSearch::AfterDate); + if (isFirst || isAfter) { + if (isFirst || (isAfter && parameter.date < getFirstDate())) { + const QString pk = f->getPublicKey().toString(); + if ((isFirst || parameter.date >= history->getStartDateChatHistory(pk).date()) && loadHistory(phrase, parameter)) { return; @@ -518,7 +518,7 @@ void ChatForm::searchInBegin(const QString& phrase, const ParameterSearch& param onSearchDown(phrase, parameter); } else { if (parameter.period == PeriodSearch::BeforeDate && parameter.date < getFirstDate()) { - QString pk = f->getPublicKey().toString(); + const QString pk = f->getPublicKey().toString(); if (parameter.date >= history->getStartDateChatHistory(pk).date() && loadHistory(phrase, parameter)) { return; } @@ -553,8 +553,8 @@ void ChatForm::onSearchUp(const QString& phrase, const ParameterSearch& paramete bool isSearch = searchInText(phrase, parameter, true); if (!isSearch) { - QString pk = f->getPublicKey().toString(); - QDateTime newBaseDate = history->getDateWhereFindPhrase(pk, earliestMessage, phrase, parameter); + const QString pk = f->getPublicKey().toString(); + const QDateTime newBaseDate = history->getDateWhereFindPhrase(pk, earliestMessage, phrase, parameter); if (!newBaseDate.isValid()) { return; @@ -750,7 +750,7 @@ QString getMsgAuthorDispName(const ToxPk& authorPk, const QString& dispName) void ChatForm::loadHistoryDefaultNum(bool processUndelivered) { - QString pk = f->getPublicKey().toString(); + const QString pk = f->getPublicKey().toString(); QList msgs = history->getChatHistoryDefaultNum(pk); if (!msgs.isEmpty()) { earliestMessage = msgs.first().timestamp; @@ -1075,8 +1075,8 @@ void ChatForm::SendMessageStr(QString msg) bool ChatForm::loadHistory(const QString& phrase, const ParameterSearch& parameter) { - QString pk = f->getPublicKey().toString(); - QDateTime newBaseDate = history->getDateWhereFindPhrase(pk, earliestMessage, phrase, parameter); + const QString pk = f->getPublicKey().toString(); + const QDateTime newBaseDate = history->getDateWhereFindPhrase(pk, earliestMessage, phrase, parameter); if (newBaseDate.isValid() && getFirstDate().isValid() && newBaseDate.date() < getFirstDate()) { searchAfterLoadHistory = true; diff --git a/src/widget/form/genericchatform.cpp b/src/widget/form/genericchatform.cpp index 6007ea357..ff411d66c 100644 --- a/src/widget/form/genericchatform.cpp +++ b/src/widget/form/genericchatform.cpp @@ -948,8 +948,8 @@ void GenericChatForm::onSearchTriggered() void GenericChatForm::onContinueSearch() { - QString phrase = searchForm->getSearchPhrase(); - ParameterSearch parameter = searchForm->getParameterSearch(); + const QString phrase = searchForm->getSearchPhrase(); + const ParameterSearch parameter = searchForm->getParameterSearch(); if (!phrase.isEmpty() && searchAfterLoadHistory) { if (parameter.period == PeriodSearch::WithTheFirst || parameter.period == PeriodSearch::AfterDate) { searchAfterLoadHistory = false; diff --git a/src/widget/form/searchsettingsform.cpp b/src/widget/form/searchsettingsform.cpp index 1a642975c..20507e715 100644 --- a/src/widget/form/searchsettingsform.cpp +++ b/src/widget/form/searchsettingsform.cpp @@ -13,11 +13,10 @@ SearchSettingsForm::SearchSettingsForm(QWidget *parent) : ui->startDateLabel->setEnabled(false); ui->choiceDateButton->setAttribute(Qt::WA_LayoutUsesWidgetRect); - ui->choiceDateButton->setObjectName("choiceDateButton"); + ui->choiceDateButton->setObjectName(QStringLiteral("choiceDateButton")); ui->choiceDateButton->setStyleSheet(Style::getStylesheet(QStringLiteral(":/ui/chatForm/buttons.css"))); - ui->startDateLabel->setStyleSheet("QLabel{color: #ddd;}"); - isUpdate = false; + ui->startDateLabel->setStyleSheet(QStringLiteral("QLabel{color: #ddd;}")); // TODO: need use a style file (.css) connect(ui->startSearchComboBox, static_cast(&QComboBox::currentIndexChanged), this, &SearchSettingsForm::onStartSearchSelected); @@ -77,7 +76,7 @@ ParameterSearch SearchSettingsForm::getParameterSearch() void SearchSettingsForm::updateStartDateLabel() { - ui->startDateLabel->setText(startDate.toString("dd.MM.yyyy")); + ui->startDateLabel->setText(startDate.toString(QStringLiteral("dd.MM.yyyy"))); } void SearchSettingsForm::setUpdate(const bool isUpdate) @@ -92,10 +91,10 @@ void SearchSettingsForm::onStartSearchSelected(const int index) ui->choiceDateButton->setEnabled(true); ui->startDateLabel->setEnabled(true); - ui->choiceDateButton->setProperty("state", "green"); + ui->choiceDateButton->setProperty("state", QStringLiteral("green")); ui->choiceDateButton->setStyleSheet(Style::getStylesheet(QStringLiteral(":/ui/chatForm/buttons.css"))); - ui->startDateLabel->setStyleSheet("QLabel{color: #000;}"); + ui->startDateLabel->setStyleSheet(QStringLiteral("QLabel{color: #000;}")); if (startDate.isNull()) { startDate = QDate::currentDate(); @@ -106,10 +105,10 @@ void SearchSettingsForm::onStartSearchSelected(const int index) ui->choiceDateButton->setEnabled(false); ui->startDateLabel->setEnabled(false); - ui->choiceDateButton->setProperty("state", ""); + ui->choiceDateButton->setProperty("state", QString()); ui->choiceDateButton->setStyleSheet(Style::getStylesheet(QStringLiteral(":/ui/chatForm/buttons.css"))); - ui->startDateLabel->setStyleSheet("QLabel{color: #ddd;}"); + ui->startDateLabel->setStyleSheet(QStringLiteral("QLabel{color: #ddd;}")); } setUpdate(true); @@ -117,6 +116,7 @@ void SearchSettingsForm::onStartSearchSelected(const int index) void SearchSettingsForm::onRegisterClicked(const bool checked) { + Q_UNUSED(checked) setUpdate(true); } diff --git a/src/widget/form/searchsettingsform.h b/src/widget/form/searchsettingsform.h index a2441c55d..dfdc59428 100644 --- a/src/widget/form/searchsettingsform.h +++ b/src/widget/form/searchsettingsform.h @@ -21,7 +21,7 @@ public: private: Ui::SearchSettingsForm *ui; QDate startDate; - bool isUpdate; + bool isUpdate{false}; void updateStartDateLabel(); void setUpdate(const bool isUpdate); diff --git a/src/widget/searchform.cpp b/src/widget/searchform.cpp index 23d6b2faf..4de119b06 100644 --- a/src/widget/searchform.cpp +++ b/src/widget/searchform.cpp @@ -33,9 +33,6 @@ SearchForm::SearchForm(QWidget* parent) : QWidget(parent) settings = new SearchSettingsForm(); settings->setVisible(false); - isActiveSettings = false; - isChangedPhrase = false; - settingsButton = createButton("searchSettingsButton", "green"); upButton = createButton("searchUpButton", "green"); downButton = createButton("searchDownButton", "green"); @@ -133,12 +130,11 @@ ParameterSearch SearchForm::getAndCheckParametrSearch() void SearchForm::changedSearchPhrase(const QString& text) { - QString l = text.right(1); - if (searchPhrase == text) { return; } + QString l = text.right(1); if (!l.isEmpty() && l != " " && l[0].isSpace()) { searchLine->setText(searchPhrase); return; @@ -191,9 +187,9 @@ void SearchForm::clickedSearch() settings->setVisible(isActiveSettings); if (isActiveSettings) { - settingsButton->setProperty("state", "red"); + settingsButton->setProperty("state", QStringLiteral("red")); } else { - settingsButton->setProperty("state", "green"); + settingsButton->setProperty("state", QStringLiteral("green")); changedButtons(false); } settingsButton->setStyleSheet(Style::getStylesheet(QStringLiteral(":/ui/chatForm/buttons.css"))); diff --git a/src/widget/searchform.h b/src/widget/searchform.h index 7690d961f..4329d1275 100644 --- a/src/widget/searchform.h +++ b/src/widget/searchform.h @@ -58,8 +58,8 @@ private: QString searchPhrase; ParameterSearch parameter; - bool isActiveSettings; - bool isChangedPhrase; + bool isActiveSettings{false}; + bool isChangedPhrase{false}; private slots: void changedSearchPhrase(const QString& text); diff --git a/src/widget/searchtypes.h b/src/widget/searchtypes.h index dfceb442f..0f1141ffb 100644 --- a/src/widget/searchtypes.h +++ b/src/widget/searchtypes.h @@ -21,31 +21,15 @@ enum class PeriodSearch { }; struct ParameterSearch { - FilterSearch filter; - PeriodSearch period; + FilterSearch filter{FilterSearch::None}; + PeriodSearch period{PeriodSearch::None}; QDate date; - bool isUpdate; - - ParameterSearch() { - filter = FilterSearch::None; - period = PeriodSearch::None; - isUpdate = false; - } + bool isUpdate{false}; bool operator ==(const ParameterSearch& other) { - if (this->filter != other.filter) { - return false; - } - - if (this->period != other.period) { - return false; - } - - if (this->date != other.date) { - return false; - } - - return true; + return filter == other.filter && + period == other.period && + date == other.date; } bool operator !=(const ParameterSearch& other) { From 4b2942d51d69795a165c720cf252b82c05f43b0b Mon Sep 17 00:00:00 2001 From: TriKriSta Date: Sun, 8 Jul 2018 16:01:22 +0300 Subject: [PATCH 11/19] style: add labels.css --- res.qrc | 1 + src/widget/form/searchsettingsform.cpp | 6 +----- ui/chatForm/labels.css | 9 +++++++++ 3 files changed, 11 insertions(+), 5 deletions(-) create mode 100644 ui/chatForm/labels.css diff --git a/res.qrc b/res.qrc index 5edb06960..c357773f6 100644 --- a/res.qrc +++ b/res.qrc @@ -55,6 +55,7 @@ ui/chatForm/buttons.css ui/chatForm/fullScreenButtons.css ui/chatForm/callButton.svg + ui/chatForm/labels.css ui/chatForm/micButton.svg ui/chatForm/micButtonRed.svg ui/chatForm/videoButton.svg diff --git a/src/widget/form/searchsettingsform.cpp b/src/widget/form/searchsettingsform.cpp index 20507e715..628ae1108 100644 --- a/src/widget/form/searchsettingsform.cpp +++ b/src/widget/form/searchsettingsform.cpp @@ -16,7 +16,7 @@ SearchSettingsForm::SearchSettingsForm(QWidget *parent) : ui->choiceDateButton->setObjectName(QStringLiteral("choiceDateButton")); ui->choiceDateButton->setStyleSheet(Style::getStylesheet(QStringLiteral(":/ui/chatForm/buttons.css"))); - ui->startDateLabel->setStyleSheet(QStringLiteral("QLabel{color: #ddd;}")); // TODO: need use a style file (.css) + ui->startDateLabel->setStyleSheet(Style::getStylesheet(QStringLiteral(":/ui/chatForm/labels.css"))); connect(ui->startSearchComboBox, static_cast(&QComboBox::currentIndexChanged), this, &SearchSettingsForm::onStartSearchSelected); @@ -94,8 +94,6 @@ void SearchSettingsForm::onStartSearchSelected(const int index) ui->choiceDateButton->setProperty("state", QStringLiteral("green")); ui->choiceDateButton->setStyleSheet(Style::getStylesheet(QStringLiteral(":/ui/chatForm/buttons.css"))); - ui->startDateLabel->setStyleSheet(QStringLiteral("QLabel{color: #000;}")); - if (startDate.isNull()) { startDate = QDate::currentDate(); updateStartDateLabel(); @@ -107,8 +105,6 @@ void SearchSettingsForm::onStartSearchSelected(const int index) ui->choiceDateButton->setProperty("state", QString()); ui->choiceDateButton->setStyleSheet(Style::getStylesheet(QStringLiteral(":/ui/chatForm/buttons.css"))); - - ui->startDateLabel->setStyleSheet(QStringLiteral("QLabel{color: #ddd;}")); } setUpdate(true); diff --git a/ui/chatForm/labels.css b/ui/chatForm/labels.css new file mode 100644 index 000000000..ec14e05d2 --- /dev/null +++ b/ui/chatForm/labels.css @@ -0,0 +1,9 @@ +QLabel +{ + color: #000; +} + +QLabel:disabled +{ + color: #ddd; +} From 42f5ac67e7b5afee1d86807346e19592d91bf489 Mon Sep 17 00:00:00 2001 From: TriKriSta Date: Sun, 8 Jul 2018 16:25:29 +0300 Subject: [PATCH 12/19] refactor: edit generateFilterWordsOnly --- src/chatlog/content/text.cpp | 2 +- src/chatlog/content/text.h | 1 + src/widget/form/searchsettingsform.h | 2 +- src/widget/searchtypes.h | 23 +++++++++++++++++------ 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/chatlog/content/text.cpp b/src/chatlog/content/text.cpp index 0f419df73..bc89709b0 100644 --- a/src/chatlog/content/text.cpp +++ b/src/chatlog/content/text.cpp @@ -450,7 +450,7 @@ void Text::selectText(QTextCursor& cursor, const std::pair& point) cursor.endEditBlock(); QTextCharFormat format; - format.setBackground(QBrush(QColor("#ff7626"))); + format.setBackground(QBrush(colorHighlight)); cursor.mergeCharFormat(format); regenerate(); diff --git a/src/chatlog/content/text.h b/src/chatlog/content/text.h index 633a8a06f..c0eb1d7ce 100644 --- a/src/chatlog/content/text.h +++ b/src/chatlog/content/text.h @@ -97,6 +97,7 @@ private: QFont defFont; QString defStyleSheet; QColor color; + const QColor colorHighlight{"#ff7626"}; }; #endif // TEXT_H diff --git a/src/widget/form/searchsettingsform.h b/src/widget/form/searchsettingsform.h index dfdc59428..bf9c15d8c 100644 --- a/src/widget/form/searchsettingsform.h +++ b/src/widget/form/searchsettingsform.h @@ -2,7 +2,7 @@ #define SEARCHSETTINGSFORM_H #include -#include "../searchtypes.h" +#include "src/widget/searchtypes.h" namespace Ui { class SearchSettingsForm; diff --git a/src/widget/searchtypes.h b/src/widget/searchtypes.h index 0f1141ffb..be618dba1 100644 --- a/src/widget/searchtypes.h +++ b/src/widget/searchtypes.h @@ -2,6 +2,7 @@ #define SEARCHTYPES_H #include +#include enum class FilterSearch { None, @@ -39,24 +40,34 @@ struct ParameterSearch { class SearchExtraFunctions { public: + /** + * @brief generateFilterWordsOnly generate string for filter "Whole words only" for correct search phrase + * containing symbols "\[]/^$.|?*+(){}" + * @param phrase for search + * @return new phrase for search + */ static QString generateFilterWordsOnly(const QString &phrase) { - QString filter = phrase; + QString filter = QRegularExpression::escape(phrase); - if (filter.contains("\\")) { - filter.replace("\\", "\\\\"); + QString symbols = {"\\[]/^$.|?*+(){}"}; - if (filter.front() != '\\') { + if (filter != phrase) { + if (filter.left(1) != QLatin1String("\\")) { filter = "\\b" + filter; + } else { + filter = "(^|\\s)" + filter; } - if (filter.back() != '\\') { + if (!symbols.contains(filter.right(1))) { filter += "\\b"; + } else { + filter += "($|\\s)"; } } else { filter = QStringLiteral("\\b%1\\b").arg(filter); } return filter; - }; + } }; #endif //SEARCHTYPES_H From 706822123f80c426ffb5c64edf2d31038aa8c276 Mon Sep 17 00:00:00 2001 From: TriKriSta Date: Sat, 14 Jul 2018 00:06:04 +0300 Subject: [PATCH 13/19] refactor: delete sqlite in travis, edit some functions --- .travis/build-ubuntu-14-04.sh | 9 -------- src/chatlog/content/text.cpp | 4 +++- src/chatlog/content/text.h | 1 - src/persistence/db/rawdatabase.cpp | 7 ------- src/persistence/db/rawdatabase.h | 11 ++++++---- src/persistence/history.cpp | 23 ++++++++------------- src/widget/form/genericchatform.cpp | 32 +++++++++++++++++------------ src/widget/searchtypes.h | 10 ++++----- 8 files changed, 42 insertions(+), 55 deletions(-) diff --git a/.travis/build-ubuntu-14-04.sh b/.travis/build-ubuntu-14-04.sh index 34343b39a..f19b5e97e 100755 --- a/.travis/build-ubuntu-14-04.sh +++ b/.travis/build-ubuntu-14-04.sh @@ -52,15 +52,6 @@ sudo apt-get install -y --force-yes \ # Qt source /opt/qt55/bin/qt55-env.sh || yes -# sqlite -wget https://sqlite.org/2018/sqlite-autoconf-3240000.tar.gz -tar xvfz sqlite-autoconf-3240000.tar.gz -cd sqlite-autoconf-3240000 -./configure -make -j$(nproc) -sudo make install -cd .. - # ffmpeg if [ ! -e "libs" ]; then mkdir libs; fi if [ ! -e "ffmpeg" ]; then mkdir ffmpeg; fi diff --git a/src/chatlog/content/text.cpp b/src/chatlog/content/text.cpp index bc89709b0..f34ff8aea 100644 --- a/src/chatlog/content/text.cpp +++ b/src/chatlog/content/text.cpp @@ -33,6 +33,8 @@ #include "src/widget/style.h" +static const QString COLOR_HIGHLIGHT = QStringLiteral("#ff7626"); + Text::Text(const QString& txt, const QFont& font, bool enableElide, const QString& rwText, const QColor c) : rawText(rwText) @@ -450,7 +452,7 @@ void Text::selectText(QTextCursor& cursor, const std::pair& point) cursor.endEditBlock(); QTextCharFormat format; - format.setBackground(QBrush(colorHighlight)); + format.setBackground(QBrush(QColor(COLOR_HIGHLIGHT))); cursor.mergeCharFormat(format); regenerate(); diff --git a/src/chatlog/content/text.h b/src/chatlog/content/text.h index c0eb1d7ce..633a8a06f 100644 --- a/src/chatlog/content/text.h +++ b/src/chatlog/content/text.h @@ -97,7 +97,6 @@ private: QFont defFont; QString defStyleSheet; QColor color; - const QColor colorHighlight{"#ff7626"}; }; #endif // TEXT_H diff --git a/src/persistence/db/rawdatabase.cpp b/src/persistence/db/rawdatabase.cpp index c11cea6da..686bc7746 100644 --- a/src/persistence/db/rawdatabase.cpp +++ b/src/persistence/db/rawdatabase.cpp @@ -29,13 +29,6 @@ #include #include -/// The two following defines are required to use SQLCipher -/// They are used by the sqlite3.h header -#define SQLITE_HAS_CODEC -#define SQLITE_TEMP_STORE 2 - -#include - /** * @class RawDatabase diff --git a/src/persistence/db/rawdatabase.h b/src/persistence/db/rawdatabase.h index f4a8b37a4..9fd820233 100644 --- a/src/persistence/db/rawdatabase.h +++ b/src/persistence/db/rawdatabase.h @@ -14,10 +14,13 @@ #include #include -struct sqlite3; -struct sqlite3_stmt; -struct sqlite3_context; -struct sqlite3_value; +/// The two following defines are required to use SQLCipher +/// They are used by the sqlite3.h header +#define SQLITE_HAS_CODEC +#define SQLITE_TEMP_STORE 2 + +#include + class RawDatabase : QObject { diff --git a/src/persistence/history.cpp b/src/persistence/history.cpp index 84dcb16ed..7c52a8f76 100644 --- a/src/persistence/history.cpp +++ b/src/persistence/history.cpp @@ -325,9 +325,9 @@ QList History::getChatHistoryCounts(const ToxPk& friendPk */ QDateTime History::getDateWhereFindPhrase(const QString& friendPk, const QDateTime& from, QString phrase, const ParameterSearch& parameter) { - QList counts; - auto rowCallback = [&counts](const QVector& row) { - counts.append(QDateTime::fromMSecsSinceEpoch(row[0].toLongLong())); + QDateTime result; + auto rowCallback = [&result](const QVector& row) { + result = QDateTime::fromMSecsSinceEpoch(row[0].toLongLong()); }; phrase.replace("'", "''"); @@ -389,11 +389,8 @@ QDateTime History::getDateWhereFindPhrase(const QString& friendPk, const QDateTi .arg(period); db->execNow({queryText, rowCallback}); - if (!counts.isEmpty()) { - return counts[0]; - } - return QDateTime(); + return result; } /** @@ -403,9 +400,9 @@ QDateTime History::getDateWhereFindPhrase(const QString& friendPk, const QDateTi */ QDateTime History::getStartDateChatHistory(const QString &friendPk) { - QList counts; - auto rowCallback = [&counts](const QVector& row) { - counts.append(QDateTime::fromMSecsSinceEpoch(row[0].toLongLong())); + QDateTime result; + auto rowCallback = [&result](const QVector& row) { + result = QDateTime::fromMSecsSinceEpoch(row[0].toLongLong()); }; QString queryText = @@ -418,11 +415,7 @@ QDateTime History::getStartDateChatHistory(const QString &friendPk) db->execNow({queryText, rowCallback}); - if (!counts.isEmpty()) { - return counts[0]; - } - - return QDateTime(); + return result; } /** diff --git a/src/widget/form/genericchatform.cpp b/src/widget/form/genericchatform.cpp index ff411d66c..af8dd80c2 100644 --- a/src/widget/form/genericchatform.cpp +++ b/src/widget/form/genericchatform.cpp @@ -540,7 +540,7 @@ void GenericChatForm::addSystemDateMessage() QDate GenericChatForm::getDate(const ChatLine::Ptr &chatLine) const { if (chatLine) { - Timestamp* timestamp = qobject_cast(chatLine->getContent(2)); + Timestamp* const timestamp = qobject_cast(chatLine->getContent(2)); if (timestamp) { return timestamp->getTime().date(); @@ -589,20 +589,26 @@ bool GenericChatForm::searchInText(const QString& phrase, const ParameterSearch& if (parameter.period == PeriodSearch::WithTheFirst) { startLine = 0; } else if (parameter.period == PeriodSearch::AfterDate) { - for (int i = 0; i < lines.size(); ++i) { - auto d = getDate(lines[i]); - if (d.isValid() && parameter.date <= d) { - startLine = i; - break; - } + auto lambda = [=](const ChatLine::Ptr& item) { + auto d = getDate(item); + return d.isValid() && parameter.date <= d; + }; + + auto find = std::find_if(lines.begin(), lines.end(), lambda); + + if (find != lines.end()) { + startLine = static_cast(std::distance(lines.begin(), find)); } } else if (parameter.period == PeriodSearch::BeforeDate) { - for (int i = lines.size() - 1; i >= 0; --i) { - auto d = getDate(lines[i]); - if (d.isValid() && parameter.date >= d) { - startLine = i; - break; - } + auto lambda = [=](const ChatLine::Ptr& item) { + auto d = getDate(item); + return d.isValid() && parameter.date >= d; + }; + + auto find = std::find_if(lines.rbegin(), lines.rend(), lambda); + + if (find != lines.rend()) { + startLine = static_cast(std::distance(find, lines.rend())) - 1; } } diff --git a/src/widget/searchtypes.h b/src/widget/searchtypes.h index be618dba1..319964d6c 100644 --- a/src/widget/searchtypes.h +++ b/src/widget/searchtypes.h @@ -49,18 +49,18 @@ public: static QString generateFilterWordsOnly(const QString &phrase) { QString filter = QRegularExpression::escape(phrase); - QString symbols = {"\\[]/^$.|?*+(){}"}; + const QString symbols = QStringLiteral("\\[]/^$.|?*+(){}"); if (filter != phrase) { if (filter.left(1) != QLatin1String("\\")) { - filter = "\\b" + filter; + filter = QLatin1String("\\b") + filter; } else { - filter = "(^|\\s)" + filter; + filter = QLatin1String("(^|\\s)") + filter; } if (!symbols.contains(filter.right(1))) { - filter += "\\b"; + filter += QLatin1String("\\b"); } else { - filter += "($|\\s)"; + filter += QLatin1String("($|\\s)"); } } else { filter = QStringLiteral("\\b%1\\b").arg(filter); From 5668aa57c5da9d21aada4a506ce1771a247f138d Mon Sep 17 00:00:00 2001 From: TriKriSta Date: Sat, 14 Jul 2018 00:59:28 +0300 Subject: [PATCH 14/19] chore: install Qt 5.6 in travis --- .travis/build-ubuntu-14-04.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.travis/build-ubuntu-14-04.sh b/.travis/build-ubuntu-14-04.sh index f19b5e97e..a78d5b068 100755 --- a/.travis/build-ubuntu-14-04.sh +++ b/.travis/build-ubuntu-14-04.sh @@ -19,8 +19,8 @@ # stop as soon as one of steps will fail set -e -o pipefail -# Qt 5.5, since that's the lowest supported version -sudo add-apt-repository -y ppa:beineri/opt-qt551-trusty +# Qt 5.6, since that's the lowest supported version +sudo add-apt-repository -y ppa:beineri/opt-qt562-trusty sudo apt-get update -qq # install needed Qt, OpenAL, opus, qrencode, GTK tray deps, sqlcipher @@ -42,15 +42,15 @@ sudo apt-get install -y --force-yes \ libtool \ libvpx-dev \ libxss-dev qrencode \ - qt55base \ - qt55script \ - qt55svg \ - qt55tools \ - qt55xmlpatterns \ + qt56base \ + qt56script \ + qt56svg \ + qt56tools \ + qt56xmlpatterns \ pkg-config || yes # Qt -source /opt/qt55/bin/qt55-env.sh || yes +source /opt/qt56/bin/qt56-env.sh || yes # ffmpeg if [ ! -e "libs" ]; then mkdir libs; fi From 7977c80a52b70378564b9f725f375606534a33e0 Mon Sep 17 00:00:00 2001 From: TriKriSta Date: Sun, 15 Jul 2018 23:00:38 +0300 Subject: [PATCH 15/19] refactor: use Settings, add const --- src/widget/form/genericchatform.cpp | 16 ++++++++-------- src/widget/form/searchsettingsform.cpp | 3 ++- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/widget/form/genericchatform.cpp b/src/widget/form/genericchatform.cpp index af8dd80c2..8a1c9ac8a 100644 --- a/src/widget/form/genericchatform.cpp +++ b/src/widget/form/genericchatform.cpp @@ -589,23 +589,23 @@ bool GenericChatForm::searchInText(const QString& phrase, const ParameterSearch& if (parameter.period == PeriodSearch::WithTheFirst) { startLine = 0; } else if (parameter.period == PeriodSearch::AfterDate) { - auto lambda = [=](const ChatLine::Ptr& item) { - auto d = getDate(item); + const auto lambda = [=](const ChatLine::Ptr& item) { + const auto d = getDate(item); return d.isValid() && parameter.date <= d; }; - auto find = std::find_if(lines.begin(), lines.end(), lambda); + const auto find = std::find_if(lines.begin(), lines.end(), lambda); if (find != lines.end()) { startLine = static_cast(std::distance(lines.begin(), find)); } } else if (parameter.period == PeriodSearch::BeforeDate) { - auto lambda = [=](const ChatLine::Ptr& item) { - auto d = getDate(item); + const auto lambda = [=](const ChatLine::Ptr& item) { + const auto d = getDate(item); return d.isValid() && parameter.date >= d; }; - auto find = std::find_if(lines.rbegin(), lines.rend(), lambda); + const auto find = std::find_if(lines.rbegin(), lines.rend(), lambda); if (find != lines.rend()) { startLine = static_cast(std::distance(find, lines.rend())) - 1; @@ -733,7 +733,7 @@ std::pair GenericChatForm::indexForSearchInLine(const QString& txt, co auto matchIt = exp.globalMatch(txt); while (matchIt.hasNext()) { - auto match = matchIt.next(); + const auto match = matchIt.next(); int sizeItem = match.capturedLength(); int indexItem = match.capturedStart(); @@ -777,7 +777,7 @@ std::pair GenericChatForm::indexForSearchInLine(const QString& txt, co } if (!exp.pattern().isEmpty()) { - auto match = exp.match(txt, startIndex); + const auto match = exp.match(txt, startIndex); if (match.hasMatch()) { size = match.capturedLength(0); index = match.capturedEnd() - size; diff --git a/src/widget/form/searchsettingsform.cpp b/src/widget/form/searchsettingsform.cpp index 628ae1108..3c9223e10 100644 --- a/src/widget/form/searchsettingsform.cpp +++ b/src/widget/form/searchsettingsform.cpp @@ -1,5 +1,6 @@ #include "searchsettingsform.h" #include "ui_searchsettingsform.h" +#include "src/persistence/settings.h" #include "src/widget/style.h" #include "src/widget/form/loadhistorydialog.h" @@ -76,7 +77,7 @@ ParameterSearch SearchSettingsForm::getParameterSearch() void SearchSettingsForm::updateStartDateLabel() { - ui->startDateLabel->setText(startDate.toString(QStringLiteral("dd.MM.yyyy"))); + ui->startDateLabel->setText(startDate.toString(Settings::getInstance().getDateFormat())); } void SearchSettingsForm::setUpdate(const bool isUpdate) From 81587d0fbb91926ff394d737a877dd9af940e760 Mon Sep 17 00:00:00 2001 From: TriKriSta Date: Sat, 21 Jul 2018 00:48:56 +0300 Subject: [PATCH 16/19] refactor: add code for work in Qt5.5 --- .travis/build-ubuntu-14-04.sh | 16 ++++++++-------- src/widget/form/genericchatform.cpp | 10 ++++++++++ 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/.travis/build-ubuntu-14-04.sh b/.travis/build-ubuntu-14-04.sh index a78d5b068..f19b5e97e 100755 --- a/.travis/build-ubuntu-14-04.sh +++ b/.travis/build-ubuntu-14-04.sh @@ -19,8 +19,8 @@ # stop as soon as one of steps will fail set -e -o pipefail -# Qt 5.6, since that's the lowest supported version -sudo add-apt-repository -y ppa:beineri/opt-qt562-trusty +# Qt 5.5, since that's the lowest supported version +sudo add-apt-repository -y ppa:beineri/opt-qt551-trusty sudo apt-get update -qq # install needed Qt, OpenAL, opus, qrencode, GTK tray deps, sqlcipher @@ -42,15 +42,15 @@ sudo apt-get install -y --force-yes \ libtool \ libvpx-dev \ libxss-dev qrencode \ - qt56base \ - qt56script \ - qt56svg \ - qt56tools \ - qt56xmlpatterns \ + qt55base \ + qt55script \ + qt55svg \ + qt55tools \ + qt55xmlpatterns \ pkg-config || yes # Qt -source /opt/qt56/bin/qt56-env.sh || yes +source /opt/qt55/bin/qt55-env.sh || yes # ffmpeg if [ ! -e "libs" ]; then mkdir libs; fi diff --git a/src/widget/form/genericchatform.cpp b/src/widget/form/genericchatform.cpp index 8a1c9ac8a..3d231ba57 100644 --- a/src/widget/form/genericchatform.cpp +++ b/src/widget/form/genericchatform.cpp @@ -600,6 +600,7 @@ bool GenericChatForm::searchInText(const QString& phrase, const ParameterSearch& startLine = static_cast(std::distance(lines.begin(), find)); } } else if (parameter.period == PeriodSearch::BeforeDate) { +#if QT_VERSION > QT_VERSION_CHECK(5, 6, 0) const auto lambda = [=](const ChatLine::Ptr& item) { const auto d = getDate(item); return d.isValid() && parameter.date >= d; @@ -610,6 +611,15 @@ bool GenericChatForm::searchInText(const QString& phrase, const ParameterSearch& if (find != lines.rend()) { startLine = static_cast(std::distance(find, lines.rend())) - 1; } +#else + for (int i = lines.size() - 1; i >= 0; --i) { + auto d = getDate(lines[i]); + if (d.isValid() && parameter.date >= d) { + startLine = i; + break; + } + } +#endif } if (startLine < 0 || startLine >= numLines) { From eb92ce15f131378e926f25f3bc99a813dce03703 Mon Sep 17 00:00:00 2001 From: TriKriSta Date: Fri, 27 Jul 2018 21:39:14 +0300 Subject: [PATCH 17/19] refactor: change text and icons in search forms --- res.qrc | 1 + src/widget/form/searchsettingsform.ui | 8 +-- ui/chatForm/buttons.css | 6 +- ui/chatForm/searchCalendarButton.svg | 98 +++++++++++++++++++++++++++ ui/chatForm/searchDownButton.svg | 44 ++++++------ ui/chatForm/searchHideButton.svg | 46 ++++++------- ui/chatForm/searchSettingsButton.svg | 2 +- ui/chatForm/searchUpButton.svg | 44 ++++++------ 8 files changed, 171 insertions(+), 78 deletions(-) create mode 100644 ui/chatForm/searchCalendarButton.svg diff --git a/res.qrc b/res.qrc index c357773f6..4e53a84a7 100644 --- a/res.qrc +++ b/res.qrc @@ -67,6 +67,7 @@ ui/chatForm/emoteButton.svg ui/chatForm/fileButton.svg ui/chatForm/screenshotButton.svg + ui/chatForm/searchCalendarButton.svg ui/chatForm/searchDownButton.svg ui/chatForm/searchHideButton.svg ui/chatForm/searchSettingsButton.svg diff --git a/src/widget/form/searchsettingsform.ui b/src/widget/form/searchsettingsform.ui index 654d2cd9d..f7f91a609 100644 --- a/src/widget/form/searchsettingsform.ui +++ b/src/widget/form/searchsettingsform.ui @@ -7,7 +7,7 @@ 0 0 473 - 83 + 84 @@ -52,12 +52,12 @@ - with the end + from the end - with the first + from the beginning @@ -82,7 +82,7 @@ - Choice + diff --git a/ui/chatForm/buttons.css b/ui/chatForm/buttons.css index bef35130e..a556510b8 100644 --- a/ui/chatForm/buttons.css +++ b/ui/chatForm/buttons.css @@ -103,10 +103,10 @@ QAbstractButton#searchDownButton QAbstractButton#choiceDateButton { + background-image: url(":/ui/chatForm/searchCalendarButton.svg"); border-radius: 5px; - width: 55px; - height: 25px; - color: #fff + width: 45px; + height: 35px; } QAbstractButton#startButton diff --git a/ui/chatForm/searchCalendarButton.svg b/ui/chatForm/searchCalendarButton.svg new file mode 100644 index 000000000..e0839be6c --- /dev/null +++ b/ui/chatForm/searchCalendarButton.svg @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/ui/chatForm/searchDownButton.svg b/ui/chatForm/searchDownButton.svg index e99f985c5..9068ae888 100644 --- a/ui/chatForm/searchDownButton.svg +++ b/ui/chatForm/searchDownButton.svg @@ -9,37 +9,35 @@ 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="7.0183306mm" - height="4.1245208mm" - viewBox="0 0 7.0183304 4.1245209" + width="26.525974" + height="15.58874" + viewBox="0 0 26.525974 15.58874" version="1.1" id="svg8" - inkscape:version="0.92.2 5c3e80d, 2017-08-06" - sodipodi:docname="searchDownButton.svg"> - + sodipodi:docname="searchDownButton.svg" + inkscape:version="0.92.2 2405546, 2018-03-11"> + inkscape:window-y="36" + inkscape:window-maximized="1" + inkscape:current-layer="layer1" /> + @@ -60,7 +58,7 @@ + transform="matrix(0.1242249,0,0,0.1242249,-52.303786,36.122025)"> - + sodipodi:docname="searchHideButton.svg" + inkscape:version="0.92.2 2405546, 2018-03-11"> + inkscape:window-y="36" + inkscape:window-maximized="1" + inkscape:current-layer="layer1" /> + @@ -48,7 +46,7 @@ image/svg+xml - + @@ -59,7 +57,7 @@ transform="translate(59.891963,-41.449704)"> - \ No newline at end of file + diff --git a/ui/chatForm/searchUpButton.svg b/ui/chatForm/searchUpButton.svg index d579c81fc..e425ae579 100644 --- a/ui/chatForm/searchUpButton.svg +++ b/ui/chatForm/searchUpButton.svg @@ -9,37 +9,35 @@ 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="7.0183306mm" - height="4.1245208mm" - viewBox="0 0 7.0183304 4.1245209" + width="26.525974" + height="15.58874" + viewBox="0 0 26.525974 15.58874" version="1.1" id="svg8" - inkscape:version="0.92.2 2405546, 2018-03-11" - sodipodi:docname="searchUpButton.svg"> - + sodipodi:docname="searchUpButton.svg" + inkscape:version="0.92.2 2405546, 2018-03-11"> + inkscape:window-maximized="1" + inkscape:current-layer="layer1" /> + @@ -56,11 +54,11 @@ inkscape:label="Layer 1" inkscape:groupmode="layer" id="layer1" - transform="translate(59.722852,-41.245778)"> + transform="translate(59.722851,-41.245778)"> + transform="matrix(0.12336383,0,0,-0.12336383,-52.355211,61.903867)"> Date: Sat, 28 Jul 2018 01:36:07 +0300 Subject: [PATCH 18/19] feat: add message if text not found --- src/widget/form/chatform.cpp | 5 +- src/widget/form/genericchatform.cpp | 1 + src/widget/form/genericchatform.h | 1 + src/widget/form/groupchatform.cpp | 8 ++- src/widget/searchform.cpp | 80 +++++++++++++++++++++++++---- src/widget/searchform.h | 16 +++++- ui/chatForm/labels.css | 5 ++ 7 files changed, 103 insertions(+), 13 deletions(-) diff --git a/src/widget/form/chatform.cpp b/src/widget/form/chatform.cpp index 030c6992b..3ac986817 100644 --- a/src/widget/form/chatform.cpp +++ b/src/widget/form/chatform.cpp @@ -557,6 +557,7 @@ void ChatForm::onSearchUp(const QString& phrase, const ParameterSearch& paramete const QDateTime newBaseDate = history->getDateWhereFindPhrase(pk, earliestMessage, phrase, parameter); if (!newBaseDate.isValid()) { + emit messageNotFoundShow(true); return; } @@ -568,7 +569,9 @@ void ChatForm::onSearchUp(const QString& phrase, const ParameterSearch& paramete void ChatForm::onSearchDown(const QString& phrase, const ParameterSearch& parameter) { - searchInText(phrase, parameter, false); + if (!searchInText(phrase, parameter, false)) { + emit messageNotFoundShow(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 3d231ba57..e9e4e3777 100644 --- a/src/widget/form/genericchatform.cpp +++ b/src/widget/form/genericchatform.cpp @@ -224,6 +224,7 @@ GenericChatForm::GenericChatForm(const Contact* contact, QWidget* parent) connect(searchForm, &SearchForm::searchUp, this, &GenericChatForm::onSearchUp); connect(searchForm, &SearchForm::searchDown, this, &GenericChatForm::onSearchDown); connect(searchForm, &SearchForm::visibleChanged, this, &GenericChatForm::onSearchTriggered); + connect(this, &GenericChatForm::messageNotFoundShow, searchForm, &SearchForm::showMessageNotFound); connect(chatWidget, &ChatLog::workerTimeoutFinished, this, &GenericChatForm::onContinueSearch); diff --git a/src/widget/form/genericchatform.h b/src/widget/form/genericchatform.h index f5685ebe5..c8a8f7216 100644 --- a/src/widget/form/genericchatform.h +++ b/src/widget/form/genericchatform.h @@ -83,6 +83,7 @@ signals: void sendAction(uint32_t, QString); void chatAreaCleared(); void messageInserted(); + void messageNotFoundShow(const bool searchUp); public slots: void focusInput(); diff --git a/src/widget/form/groupchatform.cpp b/src/widget/form/groupchatform.cpp index f3b3a7582..619e387a9 100644 --- a/src/widget/form/groupchatform.cpp +++ b/src/widget/form/groupchatform.cpp @@ -214,12 +214,16 @@ void GroupChatForm::searchInBegin(const QString& phrase, const ParameterSearch& void GroupChatForm::onSearchUp(const QString& phrase, const ParameterSearch& parameter) { - searchInText(phrase, parameter, true); + if (!searchInText(phrase, parameter, true)) { + emit messageNotFoundShow(true); + } } void GroupChatForm::onSearchDown(const QString& phrase, const ParameterSearch& parameter) { - searchInText(phrase, parameter, false); + if (!searchInText(phrase, parameter, false)) { + emit messageNotFoundShow(false); + } } void GroupChatForm::onScreenshotClicked() diff --git a/src/widget/searchform.cpp b/src/widget/searchform.cpp index 4de119b06..fce873d07 100644 --- a/src/widget/searchform.cpp +++ b/src/widget/searchform.cpp @@ -23,15 +23,31 @@ #include #include #include +#include #include +const QString STATE_NAME[] = { + QString{}, + QStringLiteral("green"), + QStringLiteral("red"), +}; + SearchForm::SearchForm(QWidget* parent) : QWidget(parent) { QVBoxLayout* layout = new QVBoxLayout(); QHBoxLayout* layoutNavigation = new QHBoxLayout(); + QHBoxLayout* layoutMessage = new QHBoxLayout(); + QSpacerItem *lSpacer = new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Ignored); + QSpacerItem *rSpacer = new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Ignored); searchLine = new LineEdit(); settings = new SearchSettingsForm(); + messageLabel = new QLabel(); + settings->setVisible(false); + messageLabel->setProperty("state", QStringLiteral("red")); + messageLabel->setStyleSheet(Style::getStylesheet(QStringLiteral(":/ui/chatForm/labels.css"))); + messageLabel->setText(tr("The text could not be found.")); + messageLabel->setVisible(false); settingsButton = createButton("searchSettingsButton", "green"); upButton = createButton("searchUpButton", "green"); @@ -51,6 +67,11 @@ SearchForm::SearchForm(QWidget* parent) : QWidget(parent) layout->addLayout(layoutNavigation); layout->addWidget(settings); + layoutMessage->addSpacerItem(lSpacer); + layoutMessage->addWidget(messageLabel); + layoutMessage->addSpacerItem(rSpacer); + layout->addLayout(layoutMessage); + startButton->setHidden(true); setLayout(layout); @@ -66,7 +87,7 @@ SearchForm::SearchForm(QWidget* parent) : QWidget(parent) connect(startButton, &QPushButton::clicked, this, &SearchForm::clickedStart); connect(settingsButton, &QPushButton::clicked, this, &SearchForm::clickedSearch); - connect(settings, &SearchSettingsForm::updateSettings, this, &SearchForm::changedButtons); + connect(settings, &SearchSettingsForm::updateSettings, this, &SearchForm::changedState); } void SearchForm::removeSearchPhrase() @@ -128,8 +149,25 @@ ParameterSearch SearchForm::getAndCheckParametrSearch() return ParameterSearch(); } +void SearchForm::setStateName(QPushButton *btn, ToolButtonState state) +{ + const int index = static_cast(state); + btn->setProperty("state", STATE_NAME[index]); + btn->setStyleSheet(Style::getStylesheet(QStringLiteral(":/ui/chatForm/buttons.css"))); + btn->setEnabled(index != 0); +} + +void SearchForm::useBeginState() +{ + setStateName(upButton, ToolButtonState::Common); + setStateName(downButton, ToolButtonState::Common); + messageLabel->setVisible(false); +} + void SearchForm::changedSearchPhrase(const QString& text) { + useBeginState(); + if (searchPhrase == text) { return; } @@ -144,16 +182,21 @@ void SearchForm::changedSearchPhrase(const QString& text) isChangedPhrase = true; if (isActiveSettings) { if (startButton->isHidden()) { - changedButtons(true); + changedState(true); } } else { + isSearchInBegin = true; emit searchInBegin(searchPhrase, getAndCheckParametrSearch()); } } void SearchForm::clickedUp() { + setStateName(downButton, ToolButtonState::Common); + messageLabel->setVisible(false); + if (startButton->isHidden()) { + isSearchInBegin = false; emit searchUp(searchPhrase, getAndCheckParametrSearch()); } else { clickedStart(); @@ -162,7 +205,11 @@ void SearchForm::clickedUp() void SearchForm::clickedDown() { + setStateName(upButton, ToolButtonState::Common); + messageLabel->setVisible(false); + if (startButton->isHidden()) { + isSearchInBegin = false; emit searchDown(searchPhrase, getAndCheckParametrSearch()); } else { clickedStart(); @@ -177,7 +224,8 @@ void SearchForm::clickedHide() void SearchForm::clickedStart() { - changedButtons(false); + changedState(false); + isSearchInBegin = true; emit searchInBegin(searchPhrase, getAndCheckParametrSearch()); } @@ -185,18 +233,17 @@ void SearchForm::clickedSearch() { isActiveSettings = !isActiveSettings; settings->setVisible(isActiveSettings); + useBeginState(); if (isActiveSettings) { - settingsButton->setProperty("state", QStringLiteral("red")); + setStateName(settingsButton, ToolButtonState::Active); } else { - settingsButton->setProperty("state", QStringLiteral("green")); - changedButtons(false); + setStateName(settingsButton, ToolButtonState::Common); + changedState(false); } - settingsButton->setStyleSheet(Style::getStylesheet(QStringLiteral(":/ui/chatForm/buttons.css"))); - settingsButton->update(); } -void SearchForm::changedButtons(const bool isUpdate) +void SearchForm::changedState(const bool isUpdate) { if (isUpdate) { startButton->setHidden(false); @@ -207,6 +254,21 @@ void SearchForm::changedButtons(const bool isUpdate) upButton->setHidden(false); downButton->setHidden(false); } + + useBeginState(); +} + +void SearchForm::showMessageNotFound(const bool searchUp) +{ + if (isSearchInBegin) { + setStateName(upButton, ToolButtonState::Disabled); + setStateName(downButton, ToolButtonState::Disabled); + } else if (searchUp) { + setStateName(upButton, ToolButtonState::Disabled); + } else { + setStateName(downButton, ToolButtonState::Disabled); + } + messageLabel->setVisible(true); } LineEdit::LineEdit(QWidget* parent) : QLineEdit(parent) diff --git a/src/widget/searchform.h b/src/widget/searchform.h index 4329d1275..1f6656120 100644 --- a/src/widget/searchform.h +++ b/src/widget/searchform.h @@ -25,6 +25,7 @@ #include "searchtypes.h" class QPushButton; +class QLabel; class LineEdit; class SearchSettingsForm; @@ -32,6 +33,12 @@ class SearchForm final : public QWidget { Q_OBJECT public: + enum class ToolButtonState { + Disabled = 0, // Grey + Common = 1, // Green + Active = 2, // Red + }; + explicit SearchForm(QWidget* parent = nullptr); void removeSearchPhrase(); QString getSearchPhrase() const; @@ -46,6 +53,8 @@ private: // TODO: Merge with 'createButton' from chatformheader.cpp QPushButton* createButton(const QString& name, const QString& state); ParameterSearch getAndCheckParametrSearch(); + void setStateName(QPushButton* btn, ToolButtonState state); + void useBeginState(); QPushButton* settingsButton; QPushButton* upButton; @@ -54,12 +63,14 @@ private: QPushButton* startButton; LineEdit* searchLine; SearchSettingsForm* settings; + QLabel* messageLabel; QString searchPhrase; ParameterSearch parameter; bool isActiveSettings{false}; bool isChangedPhrase{false}; + bool isSearchInBegin{true}; private slots: void changedSearchPhrase(const QString& text); @@ -68,7 +79,10 @@ private slots: void clickedHide(); void clickedStart(); void clickedSearch(); - void changedButtons(const bool isUpdate); + void changedState(const bool isUpdate); + +public slots: + void showMessageNotFound(const bool searchUp); signals: void searchInBegin(const QString& phrase, const ParameterSearch& parameter); diff --git a/ui/chatForm/labels.css b/ui/chatForm/labels.css index ec14e05d2..8f0b0173b 100644 --- a/ui/chatForm/labels.css +++ b/ui/chatForm/labels.css @@ -7,3 +7,8 @@ QLabel:disabled { color: #ddd; } + +QLabel[state="red"] +{ + color: #e84747; +} From b6ab0ec2ca7ed85e20d0c14001392c078e294499 Mon Sep 17 00:00:00 2001 From: TriKriSta Date: Wed, 8 Aug 2018 21:35:28 +0300 Subject: [PATCH 19/19] refactor: add SearchDirection --- src/persistence/history.cpp | 2 +- src/widget/form/chatform.cpp | 8 +++--- src/widget/form/genericchatform.cpp | 16 +++++++---- src/widget/form/genericchatform.h | 6 ++-- src/widget/form/groupchatform.cpp | 8 +++--- src/widget/form/searchsettingsform.ui | 13 +++++++-- src/widget/searchform.cpp | 41 +++++++++++++++++++++------ src/widget/searchform.h | 5 ++-- src/widget/searchtypes.h | 5 ++++ 9 files changed, 73 insertions(+), 31 deletions(-) diff --git a/src/persistence/history.cpp b/src/persistence/history.cpp index 7c52a8f76..114595d7e 100644 --- a/src/persistence/history.cpp +++ b/src/persistence/history.cpp @@ -356,7 +356,7 @@ QDateTime History::getDateWhereFindPhrase(const QString& friendPk, const QDateTi } QDateTime date = from; - if (parameter.period != PeriodSearch::None) { + if (parameter.period == PeriodSearch::AfterDate || parameter.period == PeriodSearch::BeforeDate) { date = QDateTime(parameter.date); } diff --git a/src/widget/form/chatform.cpp b/src/widget/form/chatform.cpp index 3ac986817..86f1850d0 100644 --- a/src/widget/form/chatform.cpp +++ b/src/widget/form/chatform.cpp @@ -550,14 +550,14 @@ void ChatForm::onSearchUp(const QString& phrase, const ParameterSearch& paramete return; } - bool isSearch = searchInText(phrase, parameter, true); + const bool isSearch = searchInText(phrase, parameter, SearchDirection::Up); if (!isSearch) { const QString pk = f->getPublicKey().toString(); const QDateTime newBaseDate = history->getDateWhereFindPhrase(pk, earliestMessage, phrase, parameter); if (!newBaseDate.isValid()) { - emit messageNotFoundShow(true); + emit messageNotFoundShow(SearchDirection::Up); return; } @@ -569,8 +569,8 @@ void ChatForm::onSearchUp(const QString& phrase, const ParameterSearch& paramete void ChatForm::onSearchDown(const QString& phrase, const ParameterSearch& parameter) { - if (!searchInText(phrase, parameter, false)) { - emit messageNotFoundShow(false); + if (!searchInText(phrase, parameter, SearchDirection::Down)) { + emit messageNotFoundShow(SearchDirection::Down); } } diff --git a/src/widget/form/genericchatform.cpp b/src/widget/form/genericchatform.cpp index e9e4e3777..c4d63f4f8 100644 --- a/src/widget/form/genericchatform.cpp +++ b/src/widget/form/genericchatform.cpp @@ -570,7 +570,7 @@ void GenericChatForm::disableSearchText() } } -bool GenericChatForm::searchInText(const QString& phrase, const ParameterSearch& parameter, bool searchUp) +bool GenericChatForm::searchInText(const QString& phrase, const ParameterSearch& parameter, SearchDirection direction) { bool isSearch = false; @@ -586,8 +586,11 @@ bool GenericChatForm::searchInText(const QString& phrase, const ParameterSearch& int numLines = lines.size(); - int startLine = numLines - searchPoint.x(); - if (parameter.period == PeriodSearch::WithTheFirst) { + int startLine = -1; + + if (parameter.period == PeriodSearch::WithTheEnd || parameter.period == PeriodSearch::None) { + startLine = numLines - searchPoint.x(); + } else if (parameter.period == PeriodSearch::WithTheFirst) { startLine = 0; } else if (parameter.period == PeriodSearch::AfterDate) { const auto lambda = [=](const ChatLine::Ptr& item) { @@ -627,6 +630,7 @@ bool GenericChatForm::searchInText(const QString& phrase, const ParameterSearch& return isSearch; } + const bool searchUp = (direction == SearchDirection::Up); for (int i = startLine; searchUp ? i >= 0 : i < numLines; searchUp ? --i : ++i) { ChatLine::Ptr l = lines[i]; @@ -681,7 +685,7 @@ bool GenericChatForm::searchInText(const QString& phrase, const ParameterSearch& continue; } - auto point = indexForSearchInLine(txt, phrase, parameter, searchUp); + auto point = indexForSearchInLine(txt, phrase, parameter, direction); if ((point.first == -1 && searchPoint.y() > -1)) { text->deselectText(); searchPoint.setY(-1); @@ -705,7 +709,7 @@ bool GenericChatForm::searchInText(const QString& phrase, const ParameterSearch& return isSearch; } -std::pair GenericChatForm::indexForSearchInLine(const QString& txt, const QString& phrase, const ParameterSearch& parameter, bool searchUp) +std::pair GenericChatForm::indexForSearchInLine(const QString& txt, const QString& phrase, const ParameterSearch& parameter, SearchDirection direction) { int index = -1; int size = 0; @@ -713,7 +717,7 @@ std::pair GenericChatForm::indexForSearchInLine(const QString& txt, co QRegularExpression exp; auto flagIns = QRegularExpression::CaseInsensitiveOption | QRegularExpression::UseUnicodePropertiesOption; auto flag = QRegularExpression::UseUnicodePropertiesOption; - if (searchUp) { + if (direction == SearchDirection::Up) { int startIndex = -1; if (searchPoint.y() > -1) { startIndex = searchPoint.y() - 1; diff --git a/src/widget/form/genericchatform.h b/src/widget/form/genericchatform.h index c8a8f7216..62b36e575 100644 --- a/src/widget/form/genericchatform.h +++ b/src/widget/form/genericchatform.h @@ -83,7 +83,7 @@ signals: void sendAction(uint32_t, QString); void chatAreaCleared(); void messageInserted(); - void messageNotFoundShow(const bool searchUp); + void messageNotFoundShow(SearchDirection direction); public slots: void focusInput(); @@ -137,8 +137,8 @@ protected: virtual void resizeEvent(QResizeEvent* event) final override; virtual bool eventFilter(QObject* object, QEvent* event) final override; void disableSearchText(); - bool searchInText(const QString& phrase, const ParameterSearch& parameter, bool searchUp); - std::pair indexForSearchInLine(const QString& txt, const QString& phrase, const ParameterSearch& parameter, bool searchUp); + bool searchInText(const QString& phrase, const ParameterSearch& parameter, SearchDirection direction); + std::pair indexForSearchInLine(const QString& txt, const QString& phrase, const ParameterSearch& parameter, SearchDirection direction); protected: bool audioInputFlag; diff --git a/src/widget/form/groupchatform.cpp b/src/widget/form/groupchatform.cpp index 619e387a9..2a73d8ca4 100644 --- a/src/widget/form/groupchatform.cpp +++ b/src/widget/form/groupchatform.cpp @@ -214,15 +214,15 @@ void GroupChatForm::searchInBegin(const QString& phrase, const ParameterSearch& void GroupChatForm::onSearchUp(const QString& phrase, const ParameterSearch& parameter) { - if (!searchInText(phrase, parameter, true)) { - emit messageNotFoundShow(true); + if (!searchInText(phrase, parameter, SearchDirection::Up)) { + emit messageNotFoundShow(SearchDirection::Up); } } void GroupChatForm::onSearchDown(const QString& phrase, const ParameterSearch& parameter) { - if (!searchInText(phrase, parameter, false)) { - emit messageNotFoundShow(false); + if (!searchInText(phrase, parameter, SearchDirection::Down)) { + emit messageNotFoundShow(SearchDirection::Down); } } diff --git a/src/widget/form/searchsettingsform.ui b/src/widget/form/searchsettingsform.ui index f7f91a609..33af9b761 100644 --- a/src/widget/form/searchsettingsform.ui +++ b/src/widget/form/searchsettingsform.ui @@ -20,7 +20,16 @@ Form - + + 0 + + + 0 + + + 0 + + 0 @@ -38,7 +47,7 @@ - Start searching: + Start search: diff --git a/src/widget/searchform.cpp b/src/widget/searchform.cpp index fce873d07..7ed28c476 100644 --- a/src/widget/searchform.cpp +++ b/src/widget/searchform.cpp @@ -20,13 +20,16 @@ #include "searchform.h" #include "form/searchsettingsform.h" #include "src/widget/style.h" + #include #include #include #include #include -const QString STATE_NAME[] = { +#include + +static std::array STATE_NAME = { QString{}, QStringLiteral("green"), QStringLiteral("red"), @@ -151,7 +154,7 @@ ParameterSearch SearchForm::getAndCheckParametrSearch() void SearchForm::setStateName(QPushButton *btn, ToolButtonState state) { - const int index = static_cast(state); + const auto index = static_cast(state); btn->setProperty("state", STATE_NAME[index]); btn->setStyleSheet(Style::getStylesheet(QStringLiteral(":/ui/chatForm/buttons.css"))); btn->setEnabled(index != 0); @@ -162,6 +165,7 @@ void SearchForm::useBeginState() setStateName(upButton, ToolButtonState::Common); setStateName(downButton, ToolButtonState::Common); messageLabel->setVisible(false); + isPrevSearch = false; } void SearchForm::changedSearchPhrase(const QString& text) @@ -192,8 +196,13 @@ void SearchForm::changedSearchPhrase(const QString& text) void SearchForm::clickedUp() { - setStateName(downButton, ToolButtonState::Common); - messageLabel->setVisible(false); + if (downButton->isEnabled()) { + isPrevSearch = false; + } else { + isPrevSearch = true; + setStateName(downButton, ToolButtonState::Common); + messageLabel->setVisible(false); + } if (startButton->isHidden()) { isSearchInBegin = false; @@ -205,8 +214,13 @@ void SearchForm::clickedUp() void SearchForm::clickedDown() { - setStateName(upButton, ToolButtonState::Common); - messageLabel->setVisible(false); + if (upButton->isEnabled()) { + isPrevSearch = false; + } else { + isPrevSearch = true; + setStateName(upButton, ToolButtonState::Common); + messageLabel->setVisible(false); + } if (startButton->isHidden()) { isSearchInBegin = false; @@ -243,7 +257,7 @@ void SearchForm::clickedSearch() } } -void SearchForm::changedState(const bool isUpdate) +void SearchForm::changedState(bool isUpdate) { if (isUpdate) { startButton->setHidden(false); @@ -258,12 +272,21 @@ void SearchForm::changedState(const bool isUpdate) useBeginState(); } -void SearchForm::showMessageNotFound(const bool searchUp) +void SearchForm::showMessageNotFound(SearchDirection direction) { if (isSearchInBegin) { + if (parameter.period == PeriodSearch::AfterDate) { + setStateName(downButton, ToolButtonState::Disabled); + } else if (parameter.period == PeriodSearch::BeforeDate) { + setStateName(upButton, ToolButtonState::Disabled); + } else { + setStateName(upButton, ToolButtonState::Disabled); + setStateName(downButton, ToolButtonState::Disabled); + } + } else if (isPrevSearch) { setStateName(upButton, ToolButtonState::Disabled); setStateName(downButton, ToolButtonState::Disabled); - } else if (searchUp) { + } else if (direction == SearchDirection::Up) { setStateName(upButton, ToolButtonState::Disabled); } else { setStateName(downButton, ToolButtonState::Disabled); diff --git a/src/widget/searchform.h b/src/widget/searchform.h index 1f6656120..4adc4103c 100644 --- a/src/widget/searchform.h +++ b/src/widget/searchform.h @@ -71,6 +71,7 @@ private: bool isActiveSettings{false}; bool isChangedPhrase{false}; bool isSearchInBegin{true}; + bool isPrevSearch{false}; private slots: void changedSearchPhrase(const QString& text); @@ -79,10 +80,10 @@ private slots: void clickedHide(); void clickedStart(); void clickedSearch(); - void changedState(const bool isUpdate); + void changedState(bool isUpdate); public slots: - void showMessageNotFound(const bool searchUp); + void showMessageNotFound(SearchDirection direction); signals: void searchInBegin(const QString& phrase, const ParameterSearch& parameter); diff --git a/src/widget/searchtypes.h b/src/widget/searchtypes.h index 319964d6c..ab8224196 100644 --- a/src/widget/searchtypes.h +++ b/src/widget/searchtypes.h @@ -21,6 +21,11 @@ enum class PeriodSearch { BeforeDate }; +enum class SearchDirection { + Up, + Down +}; + struct ParameterSearch { FilterSearch filter{FilterSearch::None}; PeriodSearch period{PeriodSearch::None};