VSearchEngine: use batch mode to update results

This commit is contained in:
Le Tan 2018-03-29 19:48:17 +08:00
parent a2c2d57570
commit 2bfa5f9f52
13 changed files with 202 additions and 37 deletions

View File

@ -3,6 +3,7 @@
#include <QObject> #include <QObject>
#include <QVector> #include <QVector>
#include <QList>
#include "vsearchconfig.h" #include "vsearchconfig.h"
@ -16,6 +17,11 @@ public:
{ {
} }
virtual ~ISearchEngine()
{
m_result.clear();
}
virtual void search(const QSharedPointer<VSearchConfig> &p_config, virtual void search(const QSharedPointer<VSearchConfig> &p_config,
const QSharedPointer<VSearchResult> &p_result) = 0; const QSharedPointer<VSearchResult> &p_result) = 0;
@ -26,7 +32,7 @@ public:
signals: signals:
void finished(const QSharedPointer<VSearchResult> &p_result); void finished(const QSharedPointer<VSearchResult> &p_result);
void resultItemAdded(const QSharedPointer<VSearchResultItem> &p_item); void resultItemsAdded(const QList<QSharedPointer<VSearchResultItem> > &p_items);
protected: protected:
QSharedPointer<VSearchResult> m_result; QSharedPointer<VSearchResult> m_result;

View File

@ -5,12 +5,16 @@
#include "utils/vutils.h" #include "utils/vutils.h"
VLineEdit::VLineEdit(QWidget *p_parent) VLineEdit::VLineEdit(QWidget *p_parent)
: QLineEdit(p_parent), m_ctrlKEnabled(true) : QLineEdit(p_parent),
m_ctrlKEnabled(true),
m_ctrlEEnabled(true)
{ {
} }
VLineEdit::VLineEdit(const QString &p_contents, QWidget *p_parent) VLineEdit::VLineEdit(const QString &p_contents, QWidget *p_parent)
: QLineEdit(p_contents, p_parent), m_ctrlKEnabled(true) : QLineEdit(p_contents, p_parent),
m_ctrlKEnabled(true),
m_ctrlEEnabled(true)
{ {
} }
@ -74,6 +78,16 @@ void VLineEdit::keyPressEvent(QKeyEvent *p_event)
break; break;
} }
case Qt::Key_E:
{
if (VUtils::isControlModifierForVim(modifiers) && !m_ctrlEEnabled) {
QWidget::keyPressEvent(p_event);
accept = true;
}
break;
}
default: default:
break; break;
} }

View File

@ -14,6 +14,8 @@ public:
void setCtrlKEnabled(bool p_enabled); void setCtrlKEnabled(bool p_enabled);
void setCtrlEEnabled(bool p_enabled);
protected: protected:
void keyPressEvent(QKeyEvent *p_event) Q_DECL_OVERRIDE; void keyPressEvent(QKeyEvent *p_event) Q_DECL_OVERRIDE;
@ -21,6 +23,10 @@ private:
// Enable Ctrl+K shortcut. // Enable Ctrl+K shortcut.
// In QLineEdit, Ctrl+K will delete till the end. // In QLineEdit, Ctrl+K will delete till the end.
bool m_ctrlKEnabled; bool m_ctrlKEnabled;
// Enable Ctrl+E shortcut.
// In QLineEdit, Ctrl+E will move the cursor to the end.
bool m_ctrlEEnabled;
}; };
inline void VLineEdit::setCtrlKEnabled(bool p_enabled) inline void VLineEdit::setCtrlKEnabled(bool p_enabled)
@ -28,4 +34,8 @@ inline void VLineEdit::setCtrlKEnabled(bool p_enabled)
m_ctrlKEnabled = p_enabled; m_ctrlKEnabled = p_enabled;
} }
inline void VLineEdit::setCtrlEEnabled(bool p_enabled)
{
m_ctrlEEnabled = p_enabled;
}
#endif // VLINEEDIT_H #endif // VLINEEDIT_H

View File

@ -442,8 +442,8 @@ void VSearch::searchSecondPhase(const QSharedPointer<VSearchResult> &p_result)
if (m_engine) { if (m_engine) {
connect(m_engine, &ISearchEngine::finished, connect(m_engine, &ISearchEngine::finished,
this, &VSearch::finished); this, &VSearch::finished);
connect(m_engine, &ISearchEngine::resultItemAdded, connect(m_engine, &ISearchEngine::resultItemsAdded,
this, &VSearch::resultItemAdded); this, &VSearch::resultItemsAdded);
} }
} }

View File

@ -41,6 +41,8 @@ signals:
// Emitted when a new item added as result. // Emitted when a new item added as result.
void resultItemAdded(const QSharedPointer<VSearchResultItem> &p_item); void resultItemAdded(const QSharedPointer<VSearchResultItem> &p_item);
void resultItemsAdded(const QList<QSharedPointer<VSearchResultItem> > &p_items);
// Emitted when async task finished. // Emitted when async task finished.
void finished(const QSharedPointer<VSearchResult> &p_result); void finished(const QSharedPointer<VSearchResult> &p_result);

View File

@ -32,6 +32,8 @@ void VSearchEngineWorker::run()
QMimeDatabase mimeDatabase; QMimeDatabase mimeDatabase;
m_state = VSearchState::Busy; m_state = VSearchState::Busy;
m_results.clear();
int nr = 0;
for (auto const & fileName : m_files) { for (auto const & fileName : m_files) {
if (m_stop.load() == 1) { if (m_stop.load() == 1) {
m_state = VSearchState::Cancelled; m_state = VSearchState::Cancelled;
@ -47,10 +49,17 @@ void VSearchEngineWorker::run()
VSearchResultItem *item = searchFile(fileName); VSearchResultItem *item = searchFile(fileName);
if (item) { if (item) {
emit resultItemReady(item); m_results.append(QSharedPointer<VSearchResultItem>(item));
}
if (++nr >= BATCH_ITEM_SIZE) {
nr = 0;
postAndClearResults();
} }
} }
postAndClearResults();
if (m_state == VSearchState::Busy) { if (m_state == VSearchState::Busy) {
m_state = VSearchState::Success; m_state = VSearchState::Success;
} }
@ -122,6 +131,14 @@ VSearchResultItem *VSearchEngineWorker::searchFile(const QString &p_fileName)
return item; return item;
} }
void VSearchEngineWorker::postAndClearResults()
{
if (!m_results.isEmpty()) {
emit resultItemsReady(m_results);
m_results.clear();
}
}
VSearchEngine::VSearchEngine(QObject *p_parent) VSearchEngine::VSearchEngine(QObject *p_parent)
: ISearchEngine(p_parent), : ISearchEngine(p_parent),
@ -129,6 +146,12 @@ VSearchEngine::VSearchEngine(QObject *p_parent)
{ {
} }
VSearchEngine::~VSearchEngine()
{
stop();
clear();
}
void VSearchEngine::search(const QSharedPointer<VSearchConfig> &p_config, void VSearchEngine::search(const QSharedPointer<VSearchConfig> &p_config,
const QSharedPointer<VSearchResult> &p_result) const QSharedPointer<VSearchResult> &p_result)
{ {
@ -168,9 +191,9 @@ void VSearchEngine::search(const QSharedPointer<VSearchConfig> &p_config,
p_config->m_contentToken); p_config->m_contentToken);
connect(th, &VSearchEngineWorker::finished, connect(th, &VSearchEngineWorker::finished,
this, &VSearchEngine::handleWorkerFinished); this, &VSearchEngine::handleWorkerFinished);
connect(th, &VSearchEngineWorker::resultItemReady, connect(th, &VSearchEngineWorker::resultItemsReady,
this, [this](VSearchResultItem *p_item) { this, [this](const QList<QSharedPointer<VSearchResultItem> > &p_items) {
emit resultItemAdded(QSharedPointer<VSearchResultItem>(p_item)); emit resultItemsAdded(p_items);
}); });
m_workers.append(th); m_workers.append(th);

View File

@ -6,9 +6,12 @@
#include <QThread> #include <QThread>
#include <QRegExp> #include <QRegExp>
#include <QAtomicInt> #include <QAtomicInt>
#include <QList>
#include "vsearchconfig.h" #include "vsearchconfig.h"
#define BATCH_ITEM_SIZE 100
class VSearchEngineWorker : public QThread class VSearchEngineWorker : public QThread
{ {
Q_OBJECT Q_OBJECT
@ -25,7 +28,7 @@ public slots:
void stop(); void stop();
signals: signals:
void resultItemReady(VSearchResultItem *p_item); void resultItemsReady(const QList<QSharedPointer<VSearchResultItem> > &p_items);
protected: protected:
void run() Q_DECL_OVERRIDE; void run() Q_DECL_OVERRIDE;
@ -35,6 +38,8 @@ private:
VSearchResultItem *searchFile(const QString &p_fileName); VSearchResultItem *searchFile(const QString &p_fileName);
void postAndClearResults();
QAtomicInt m_stop; QAtomicInt m_stop;
QStringList m_files; QStringList m_files;
@ -44,6 +49,8 @@ private:
VSearchState m_state; VSearchState m_state;
QString m_error; QString m_error;
QList<QSharedPointer<VSearchResultItem> > m_results;
}; };
inline void VSearchEngineWorker::appendError(const QString &p_err) inline void VSearchEngineWorker::appendError(const QString &p_err)
@ -62,6 +69,8 @@ class VSearchEngine : public ISearchEngine
public: public:
explicit VSearchEngine(QObject *p_parent = nullptr); explicit VSearchEngine(QObject *p_parent = nullptr);
~VSearchEngine();
void search(const QSharedPointer<VSearchConfig> &p_config, void search(const QSharedPointer<VSearchConfig> &p_config,
const QSharedPointer<VSearchResult> &p_result) Q_DECL_OVERRIDE; const QSharedPointer<VSearchResult> &p_result) Q_DECL_OVERRIDE;

View File

@ -29,6 +29,8 @@ VSearcher::VSearcher(QWidget *p_parent)
m_askedToStop(false), m_askedToStop(false),
m_search(this) m_search(this)
{ {
qRegisterMetaType<QList<QSharedPointer<VSearchResultItem>>>("QList<QSharedPointer<VSearchResultItem>>");
setupUI(); setupUI();
initUIFields(); initUIFields();
@ -36,7 +38,17 @@ VSearcher::VSearcher(QWidget *p_parent)
handleInputChanged(); handleInputChanged();
connect(&m_search, &VSearch::resultItemAdded, connect(&m_search, &VSearch::resultItemAdded,
m_results, &VSearchResultTree::addResultItem); this, [this](const QSharedPointer<VSearchResultItem> &p_item) {
// Not sure if it works.
QCoreApplication::sendPostedEvents(NULL, QEvent::MouseButtonRelease);
m_results->addResultItem(p_item);
});
connect(&m_search, &VSearch::resultItemsAdded,
this, [this](const QList<QSharedPointer<VSearchResultItem> > &p_items) {
// Not sure if it works.
QCoreApplication::sendPostedEvents(NULL, QEvent::MouseButtonRelease);
m_results->addResultItems(p_items);
});
connect(&m_search, &VSearch::finished, connect(&m_search, &VSearch::finished,
this, &VSearcher::handleSearchFinished); this, &VSearcher::handleSearchFinished);
} }
@ -352,6 +364,8 @@ void VSearcher::startSearch()
updateItemToComboBox(m_keywordCB); updateItemToComboBox(m_keywordCB);
updateItemToComboBox(m_filePatternCB); updateItemToComboBox(m_filePatternCB);
m_search.clear();
QSharedPointer<VSearchConfig> config(new VSearchConfig(m_searchScopeCB->currentData().toInt(), QSharedPointer<VSearchConfig> config(new VSearchConfig(m_searchScopeCB->currentData().toInt(),
m_searchObjectCB->currentData().toInt(), m_searchObjectCB->currentData().toInt(),
m_searchTargetCB->currentData().toInt(), m_searchTargetCB->currentData().toInt(),

View File

@ -78,6 +78,15 @@ void VSearchResultTree::addResultItem(const QSharedPointer<VSearchResultItem> &p
emit countChanged(topLevelItemCount()); emit countChanged(topLevelItemCount());
} }
void VSearchResultTree::addResultItems(const QList<QSharedPointer<VSearchResultItem> > &p_items)
{
for (auto const & it : p_items) {
appendItem(it);
}
emit countChanged(topLevelItemCount());
}
void VSearchResultTree::clearResults() void VSearchResultTree::clearResults()
{ {
clearAll(); clearAll();

View File

@ -22,6 +22,8 @@ public:
public slots: public slots:
void addResultItem(const QSharedPointer<VSearchResultItem> &p_item); void addResultItem(const QSharedPointer<VSearchResultItem> &p_item);
void addResultItems(const QList<QSharedPointer<VSearchResultItem> > &p_items);
void handleContextMenuRequested(QPoint p_pos); void handleContextMenuRequested(QPoint p_pos);
signals: signals:

View File

@ -18,6 +18,8 @@ extern VNote *g_vnote;
extern VMainWindow *g_mainWin; extern VMainWindow *g_mainWin;
#define ITEM_NUM_TO_UPDATE_WIDGET 20
VSearchUE::VSearchUE(QObject *p_parent) VSearchUE::VSearchUE(QObject *p_parent)
: IUniversalEntry(p_parent), : IUniversalEntry(p_parent),
m_search(NULL), m_search(NULL),
@ -59,6 +61,8 @@ void VSearchUE::init()
m_search = new VSearch(this); m_search = new VSearch(this);
connect(m_search, &VSearch::resultItemAdded, connect(m_search, &VSearch::resultItemAdded,
this, &VSearchUE::handleSearchItemAdded); this, &VSearchUE::handleSearchItemAdded);
connect(m_search, &VSearch::resultItemsAdded,
this, &VSearchUE::handleSearchItemsAdded);
connect(m_search, &VSearch::finished, connect(m_search, &VSearch::finished,
this, &VSearchUE::handleSearchFinished); this, &VSearchUE::handleSearchFinished);
@ -132,7 +136,23 @@ void VSearchUE::processCommand(int p_id, const QString &p_cmd)
break; break;
} }
widget(p_id)->updateGeometry(); updateWidget();
}
void VSearchUE::updateWidget()
{
QWidget *wid = widget(m_id);
if (wid == m_treeWidget) {
if (m_treeWidget->topLevelItemCount() > 0) {
m_treeWidget->resizeColumnToContents(0);
} else {
QTreeWidgetItem *item = new QTreeWidgetItem(m_treeWidget, QStringList("test"));
m_treeWidget->resizeColumnToContents(0);
delete item;
}
}
wid->updateGeometry();
emit widgetUpdated(); emit widgetUpdated();
} }
@ -153,6 +173,7 @@ void VSearchUE::searchNameOfAllNotebooks(const QString &p_cmd)
emit stateUpdated(State::Success); emit stateUpdated(State::Success);
} else { } else {
// Do a fuzzy search against the name of the notebooks. // Do a fuzzy search against the name of the notebooks.
m_search->clear();
VSearchConfig::Option opt = VSearchConfig::Fuzzy; VSearchConfig::Option opt = VSearchConfig::Fuzzy;
QSharedPointer<VSearchConfig> config(new VSearchConfig(VSearchConfig::AllNotebooks, QSharedPointer<VSearchConfig> config(new VSearchConfig(VSearchConfig::AllNotebooks,
VSearchConfig::Name, VSearchConfig::Name,
@ -175,6 +196,7 @@ void VSearchUE::searchNameOfFolderNoteInAllNotebooks(const QString &p_cmd)
m_inSearch = false; m_inSearch = false;
emit stateUpdated(State::Success); emit stateUpdated(State::Success);
} else { } else {
m_search->clear();
VSearchConfig::Option opt = VSearchConfig::NoneOption; VSearchConfig::Option opt = VSearchConfig::NoneOption;
QSharedPointer<VSearchConfig> config(new VSearchConfig(VSearchConfig::AllNotebooks, QSharedPointer<VSearchConfig> config(new VSearchConfig(VSearchConfig::AllNotebooks,
VSearchConfig::Name, VSearchConfig::Name,
@ -196,6 +218,7 @@ void VSearchUE::searchContentOfNoteInAllNotebooks(const QString &p_cmd)
m_inSearch = false; m_inSearch = false;
emit stateUpdated(State::Success); emit stateUpdated(State::Success);
} else { } else {
m_search->clear();
VSearchConfig::Option opt = VSearchConfig::NoneOption; VSearchConfig::Option opt = VSearchConfig::NoneOption;
QSharedPointer<VSearchConfig> config(new VSearchConfig(VSearchConfig::AllNotebooks, QSharedPointer<VSearchConfig> config(new VSearchConfig(VSearchConfig::AllNotebooks,
VSearchConfig::Content, VSearchConfig::Content,
@ -227,14 +250,32 @@ void VSearchUE::entryHidden(int p_id)
void VSearchUE::handleSearchItemAdded(const QSharedPointer<VSearchResultItem> &p_item) void VSearchUE::handleSearchItemAdded(const QSharedPointer<VSearchResultItem> &p_item)
{ {
static int itemAdded = 0;
++itemAdded;
QCoreApplication::sendPostedEvents(NULL, QEvent::KeyPress);
switch (m_id) { switch (m_id) {
case ID::Name_Notebook_AllNotebook: case ID::Name_Notebook_AllNotebook:
case ID::Name_FolderNote_AllNotebook: case ID::Name_FolderNote_AllNotebook:
appendItemToList(p_item); appendItemToList(p_item);
if (itemAdded > 50) {
itemAdded = 0;
m_listWidget->updateGeometry();
emit widgetUpdated();
}
break; break;
case ID::Content_Note_AllNotebook: case ID::Content_Note_AllNotebook:
appendItemToTree(p_item); appendItemToTree(p_item);
if (itemAdded > 50) {
itemAdded = 0;
m_treeWidget->resizeColumnToContents(0);
m_treeWidget->updateGeometry();
emit widgetUpdated();
}
break; break;
default: default:
@ -242,9 +283,42 @@ void VSearchUE::handleSearchItemAdded(const QSharedPointer<VSearchResultItem> &p
} }
} }
void VSearchUE::handleSearchItemsAdded(const QList<QSharedPointer<VSearchResultItem> > &p_items)
{
QCoreApplication::sendPostedEvents(NULL, QEvent::KeyPress);
switch (m_id) {
case ID::Name_Notebook_AllNotebook:
case ID::Name_FolderNote_AllNotebook:
{
for (auto const & it : p_items) {
appendItemToList(it);
}
m_listWidget->updateGeometry();
emit widgetUpdated();
break;
}
case ID::Content_Note_AllNotebook:
{
for (auto const & it : p_items) {
appendItemToTree(it);
}
m_treeWidget->resizeColumnToContents(0);
m_treeWidget->updateGeometry();
emit widgetUpdated();
break;
}
default:
break;
}
}
void VSearchUE::appendItemToList(const QSharedPointer<VSearchResultItem> &p_item) void VSearchUE::appendItemToList(const QSharedPointer<VSearchResultItem> &p_item)
{ {
static int itemAdded = 0;
m_data.append(p_item); m_data.append(p_item);
QString first, second; QString first, second;
@ -277,21 +351,13 @@ void VSearchUE::appendItemToList(const QSharedPointer<VSearchResultItem> &p_item
item->setData(Qt::UserRole, m_data.size() - 1); item->setData(Qt::UserRole, m_data.size() - 1);
item->setToolTip(p_item->m_path); item->setToolTip(p_item->m_path);
++itemAdded;
if (m_listWidget->currentRow() == -1) { if (m_listWidget->currentRow() == -1) {
m_listWidget->setCurrentRow(0); m_listWidget->setCurrentRow(0);
m_listWidget->updateGeometry();
emit widgetUpdated();
} else if (itemAdded >= 20) {
itemAdded = 0;
m_listWidget->updateGeometry();
emit widgetUpdated();
} }
} }
void VSearchUE::appendItemToTree(const QSharedPointer<VSearchResultItem> &p_item) void VSearchUE::appendItemToTree(const QSharedPointer<VSearchResultItem> &p_item)
{ {
static int itemAdded = 0;
m_data.append(p_item); m_data.append(p_item);
QTreeWidgetItem *item = new QTreeWidgetItem(m_treeWidget); QTreeWidgetItem *item = new QTreeWidgetItem(m_treeWidget);
@ -329,16 +395,8 @@ void VSearchUE::appendItemToTree(const QSharedPointer<VSearchResultItem> &p_item
subItem->setToolTip(0, it.m_text); subItem->setToolTip(0, it.m_text);
} }
++itemAdded;
if (!m_treeWidget->currentItem()) { if (!m_treeWidget->currentItem()) {
m_treeWidget->setCurrentItem(item); m_treeWidget->setCurrentItem(item);
m_treeWidget->resizeColumnToContents(0);
m_treeWidget->updateGeometry();
emit widgetUpdated();
} else if (itemAdded >= 20) {
itemAdded = 0;
m_treeWidget->updateGeometry();
emit widgetUpdated();
} }
} }
@ -383,13 +441,7 @@ void VSearchUE::handleSearchFinished(const QSharedPointer<VSearchResult> &p_resu
m_inSearch = false; m_inSearch = false;
} }
QWidget *wid = widget(m_id); updateWidget();
if (wid == m_treeWidget) {
m_treeWidget->resizeColumnToContents(0);
}
wid->updateGeometry();
emit widgetUpdated();
emit stateUpdated(state); emit stateUpdated(state);
} }
@ -525,5 +577,7 @@ void VSearchUE::activate(int p_id)
void VSearchUE::askToStop(int p_id) void VSearchUE::askToStop(int p_id)
{ {
Q_UNUSED(p_id); Q_UNUSED(p_id);
if (m_inSearch) {
m_search->stop(); m_search->stop();
} }
}

View File

@ -55,6 +55,8 @@ protected:
private slots: private slots:
void handleSearchItemAdded(const QSharedPointer<VSearchResultItem> &p_item); void handleSearchItemAdded(const QSharedPointer<VSearchResultItem> &p_item);
void handleSearchItemsAdded(const QList<QSharedPointer<VSearchResultItem> > &p_items);
void handleSearchFinished(const QSharedPointer<VSearchResult> &p_result); void handleSearchFinished(const QSharedPointer<VSearchResult> &p_result);
void activateItem(QListWidgetItem *p_item); void activateItem(QListWidgetItem *p_item);
@ -81,6 +83,9 @@ private:
const QSharedPointer<VSearchResultItem> &itemResultData(const QTreeWidgetItem *p_item) const; const QSharedPointer<VSearchResultItem> &itemResultData(const QTreeWidgetItem *p_item) const;
// Update geometry of widget.
void updateWidget();
VSearch *m_search; VSearch *m_search;
bool m_inSearch; bool m_inSearch;

View File

@ -102,6 +102,8 @@ void VUniversalEntry::setupUI()
{ {
m_cmdEdit = new VMetaWordLineEdit(this); m_cmdEdit = new VMetaWordLineEdit(this);
m_cmdEdit->setPlaceholderText(tr("Welcome to Universal Entry")); m_cmdEdit->setPlaceholderText(tr("Welcome to Universal Entry"));
m_cmdEdit->setCtrlKEnabled(false);
m_cmdEdit->setCtrlEEnabled(false);
connect(m_cmdEdit, &VMetaWordLineEdit::textEdited, connect(m_cmdEdit, &VMetaWordLineEdit::textEdited,
this, [this]() { this, [this]() {
m_cmdTimer->stop(); m_cmdTimer->stop();
@ -136,6 +138,9 @@ void VUniversalEntry::showEvent(QShowEvent *p_event)
{ {
QWidget::showEvent(p_event); QWidget::showEvent(p_event);
// Fix Chinese input method issue.
activateWindow();
m_cmdEdit->setFocus(); m_cmdEdit->setFocus();
} }
@ -297,6 +302,18 @@ void VUniversalEntry::keyPressEvent(QKeyEvent *p_event)
break; break;
case Qt::Key_D:
if (VUtils::isControlModifierForVim(modifiers)) {
// Ctrl+D to cancel current command.
m_pendingCommand = false;
if (m_lastEntry) {
m_lastEntry->m_entry->askToStop(m_lastEntry->m_id);
}
return;
}
break;
default: default:
break; break;
} }