1
0
mirror of https://github.com/qTox/qTox.git synced 2024-03-22 14:00:36 +08:00

feat: use search settings

This commit is contained in:
TriKriSta 2018-06-24 21:11:20 +03:00
parent 87b340f4a1
commit 610e04aa26
24 changed files with 625 additions and 103 deletions

View File

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

View File

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

View File

@ -62,6 +62,7 @@ public:
ChatLine::Ptr getTypingNotification() const;
QVector<ChatLine::Ptr> getLines();
ChatLine::Ptr getLatestLine() const;
ChatLine::Ptr getFirstLine() const;
ChatLineContent* getContentFromGlobalPos(QPoint pos) const;
const uint repNameAfter = 5 * 60;

View File

@ -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<int, int>& 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<int, int>& 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<int, int>& 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();
}
}

View File

@ -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<int, int>& point);
void selectText(const QRegExp& exp, const std::pair<int, int>& 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<int, int>& point);
QTextDocument* doc = nullptr;
QString text;
QString rawText;

View File

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

View File

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

View File

@ -315,7 +315,7 @@ QList<History::DateMessages> 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<QDateTime> counts;
auto rowCallback = [&counts](const QVector<QVariant>& 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<QDateTime> counts;
auto rowCallback = [&counts](const QVector<QVariant>& 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()) {

View File

@ -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<HistMessage> getChatHistoryDefaultNum(const QString& friendPk);
QList<DateMessages> 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 &parameter);
QDateTime getStartDateChatHistory(const QString& friendPk);
void markAsSent(qint64 messageId);

View File

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

View File

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

View File

@ -45,6 +45,7 @@
#include <QFileDialog>
#include <QKeyEvent>
#include <QMessageBox>
#include <QRegExp>
/**
* @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<Timestamp*>(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<Timestamp*>(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<ChatLine::Ptr> 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<int, int> 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);
}
}
}

View File

@ -22,6 +22,7 @@
#include "src/chatlog/chatmessage.h"
#include "src/core/toxpk.h"
#include "src/widget/searchtypes.h"
#include <QMenu>
#include <QWidget>
@ -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<int, int> indexForSearchInLine(const QString& txt, const QString& phrase, const ParameterSearch& parameter, bool searchUp);
protected:
bool audioInputFlag;

View File

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

View File

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

View File

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

View File

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

View File

@ -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<void(QComboBox::*)(int)>(&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();
}
}

View File

@ -2,6 +2,7 @@
#define SEARCHSETTINGSFORM_H
#include <QWidget>
#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

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>473</width>
<height>78</height>
<height>83</height>
</rect>
</property>
<property name="sizePolicy">
@ -20,16 +20,7 @@
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<property name="margin">
<number>0</number>
</property>
<item row="0" column="0">
@ -107,17 +98,38 @@
</widget>
</item>
<item>
<widget class="QCheckBox" name="wordsOnlyCheckBox">
<widget class="QRadioButton" name="wordsOnlyRadioButton">
<property name="text">
<string>Whole words only</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<property name="autoRepeat">
<bool>false</bool>
</property>
<property name="autoExclusive">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="regularCheckBox">
<widget class="QRadioButton" name="regularRadioButton">
<property name="text">
<string>Use regular expressions</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="autoRepeat">
<bool>false</bool>
</property>
<property name="autoExclusive">
<bool>false</bool>
</property>
</widget>
</item>
<item>

View File

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

View File

@ -22,6 +22,7 @@
#include <QWidget>
#include <QLineEdit>
#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();
};

50
src/widget/searchtypes.h Normal file
View File

@ -0,0 +1,50 @@
#ifndef SEARCHTYPES_H
#define SEARCHTYPES_H
#include <QDate>
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

View File

@ -223,3 +223,9 @@ QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal
{
background: none;
}
QRadioButton
{
background: white;
color: black;
}