Browse Source

VSearchEngine: use batch mode to update results

Le Tan 7 years ago
parent
commit
2bfa5f9f52

+ 7 - 1
src/isearchengine.h

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

+ 16 - 2
src/vlineedit.cpp

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

+ 10 - 0
src/vlineedit.h

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

+ 2 - 2
src/vsearch.cpp

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

+ 2 - 0
src/vsearch.h

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

+ 27 - 4
src/vsearchengine.cpp

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

+ 10 - 1
src/vsearchengine.h

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

+ 15 - 1
src/vsearcher.cpp

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

+ 9 - 0
src/vsearchresulttree.cpp

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

+ 2 - 0
src/vsearchresulttree.h

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

+ 80 - 26
src/vsearchue.cpp

@@ -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);
-    m_search->stop();
+    if (m_inSearch) {
+        m_search->stop();
+    }
 }

+ 5 - 0
src/vsearchue.h

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

+ 17 - 0
src/vuniversalentry.cpp

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