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

View File

@ -5,12 +5,16 @@
#include "utils/vutils.h"
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)
: 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;
}
case Qt::Key_E:
{
if (VUtils::isControlModifierForVim(modifiers) && !m_ctrlEEnabled) {
QWidget::keyPressEvent(p_event);
accept = true;
}
break;
}
default:
break;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -29,6 +29,8 @@ VSearcher::VSearcher(QWidget *p_parent)
m_askedToStop(false),
m_search(this)
{
qRegisterMetaType<QList<QSharedPointer<VSearchResultItem>>>("QList<QSharedPointer<VSearchResultItem>>");
setupUI();
initUIFields();
@ -36,7 +38,17 @@ VSearcher::VSearcher(QWidget *p_parent)
handleInputChanged();
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,
this, &VSearcher::handleSearchFinished);
}
@ -352,6 +364,8 @@ void VSearcher::startSearch()
updateItemToComboBox(m_keywordCB);
updateItemToComboBox(m_filePatternCB);
m_search.clear();
QSharedPointer<VSearchConfig> config(new VSearchConfig(m_searchScopeCB->currentData().toInt(),
m_searchObjectCB->currentData().toInt(),
m_searchTargetCB->currentData().toInt(),

View File

@ -78,6 +78,15 @@ void VSearchResultTree::addResultItem(const QSharedPointer<VSearchResultItem> &p
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()
{
clearAll();

View File

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

View File

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

View File

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

View File

@ -102,6 +102,8 @@ void VUniversalEntry::setupUI()
{
m_cmdEdit = new VMetaWordLineEdit(this);
m_cmdEdit->setPlaceholderText(tr("Welcome to Universal Entry"));
m_cmdEdit->setCtrlKEnabled(false);
m_cmdEdit->setCtrlEEnabled(false);
connect(m_cmdEdit, &VMetaWordLineEdit::textEdited,
this, [this]() {
m_cmdTimer->stop();
@ -136,6 +138,9 @@ void VUniversalEntry::showEvent(QShowEvent *p_event)
{
QWidget::showEvent(p_event);
// Fix Chinese input method issue.
activateWindow();
m_cmdEdit->setFocus();
}
@ -297,6 +302,18 @@ void VUniversalEntry::keyPressEvent(QKeyEvent *p_event)
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:
break;
}