Browse Source

VSearch: support searching Explorer directory

Le Tan 7 years ago
parent
commit
5f65dc95c5
7 changed files with 213 additions and 15 deletions
  1. 11 0
      src/vexplorer.cpp
  2. 2 0
      src/vexplorer.h
  3. 144 4
      src/vsearch.cpp
  4. 11 0
      src/vsearch.h
  5. 2 1
      src/vsearchconfig.h
  6. 38 10
      src/vsearcher.cpp
  7. 5 0
      src/vsearchresulttree.cpp

+ 11 - 0
src/vexplorer.cpp

@@ -783,3 +783,14 @@ void VExplorer::keyPressEvent(QKeyEvent *p_event)
 
     QWidget::keyPressEvent(p_event);
 }
+
+QString VExplorer::getRootDirectory() const
+{
+    const_cast<VExplorer *>(this)->init();
+
+    if (checkIndex()) {
+        return m_entries[m_index].m_directory;
+    }
+
+    return QString();
+}

+ 2 - 0
src/vexplorer.h

@@ -23,6 +23,8 @@ public:
 
     void setRootDirectory(const QString &p_path);
 
+    QString getRootDirectory() const;
+
 protected:
     void showEvent(QShowEvent *p_event) Q_DECL_OVERRIDE;
 

+ 144 - 4
src/vsearch.cpp

@@ -133,6 +133,39 @@ QSharedPointer<VSearchResult> VSearch::search(const QVector<VNotebook *> &p_note
     return result;
 }
 
+QSharedPointer<VSearchResult> VSearch::search(const QString &p_directoryPath)
+{
+    Q_ASSERT(!askedToStop());
+
+    QSharedPointer<VSearchResult> result(new VSearchResult(this));
+
+    if (p_directoryPath.isEmpty() || m_config->isEmpty()) {
+        result->m_state = VSearchState::Success;
+        return result;
+    }
+
+    if ((!testTarget(VSearchConfig::Note)
+         && !testTarget(VSearchConfig::Folder))
+        || testObject(VSearchConfig::Outline)
+        || testObject(VSearchConfig::Tag)) {
+        qDebug() << "search is not applicable for directory";
+        result->m_state = VSearchState::Success;
+        return result;
+    }
+
+    result->m_state = VSearchState::Busy;
+
+    searchFirstPhase(p_directoryPath, p_directoryPath, result);
+
+    if (result->hasSecondPhaseItems()) {
+        searchSecondPhase(result);
+    } else if (result->m_state == VSearchState::Busy) {
+        result->m_state = VSearchState::Success;
+    }
+
+    return result;
+}
+
 void VSearch::searchFirstPhase(VFile *p_file,
                                const QSharedPointer<VSearchResult> &p_result,
                                bool p_searchContent)
@@ -209,10 +242,7 @@ void VSearch::searchFirstPhase(VFile *p_file,
 void VSearch::searchFirstPhase(VDirectory *p_directory,
                                const QSharedPointer<VSearchResult> &p_result)
 {
-    if (!testTarget(VSearchConfig::Note)
-        && !testTarget(VSearchConfig::Folder)) {
-        return;
-    }
+    Q_ASSERT(testTarget(VSearchConfig::Note) || testTarget(VSearchConfig::Folder));
 
     bool opened = p_directory->isOpened();
     if (!opened && !p_directory->open()) {
@@ -324,6 +354,116 @@ exit:
     }
 }
 
+void VSearch::searchFirstPhase(const QString &p_basePath,
+                               const QString &p_directoryPath,
+                               const QSharedPointer<VSearchResult> &p_result)
+{
+    Q_ASSERT(testTarget(VSearchConfig::Note) || testTarget(VSearchConfig::Folder));
+    Q_ASSERT(!p_directoryPath.isEmpty());
+
+    QDir dir(p_directoryPath);
+    if (!dir.exists()) {
+        p_result->logError(QString("Directory %1 does not exist.").arg(p_directoryPath));
+        p_result->m_state = VSearchState::Fail;
+        return;
+    }
+
+    Q_ASSERT(dir.isAbsolute());
+
+    if (testTarget(VSearchConfig::Folder)) {
+        QString name = dir.dirName();
+        if (testObject(VSearchConfig::Name)) {
+            if (matchNonContent(name)) {
+                VSearchResultItem *item = new VSearchResultItem(VSearchResultItem::Folder,
+                                                                VSearchResultItem::LineNumber,
+                                                                name,
+                                                                p_directoryPath);
+                QSharedPointer<VSearchResultItem> pitem(item);
+                emit resultItemAdded(pitem);
+            }
+        }
+
+        if (testObject(VSearchConfig::Path)) {
+            QString normPath(QDir(p_basePath).relativeFilePath(p_directoryPath));
+            removeSlashFromPath(normPath);
+            if (matchNonContent(normPath)) {
+                VSearchResultItem *item = new VSearchResultItem(VSearchResultItem::Folder,
+                                                                VSearchResultItem::LineNumber,
+                                                                name,
+                                                                p_directoryPath);
+                QSharedPointer<VSearchResultItem> pitem(item);
+                emit resultItemAdded(pitem);
+            }
+        }
+    }
+
+    if (testTarget(VSearchConfig::Note)) {
+        QStringList files = dir.entryList(QDir::Files);
+        for (auto const & file : files) {
+            if (askedToStop()) {
+                qDebug() << "asked to cancel the search";
+                p_result->m_state = VSearchState::Cancelled;
+                return;
+            }
+
+            searchFirstPhaseFile(p_basePath, dir.absoluteFilePath(file), p_result);
+        }
+    }
+
+    // Search subfolders.
+    QStringList subdirs = dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot);
+    for (auto const & sub : subdirs) {
+        if (askedToStop()) {
+            qDebug() << "asked to cancel the search";
+            p_result->m_state = VSearchState::Cancelled;
+            return;
+        }
+
+        searchFirstPhase(p_basePath, dir.absoluteFilePath(sub), p_result);
+    }
+}
+
+void VSearch::searchFirstPhaseFile(const QString &p_basePath,
+                                   const QString &p_filePath,
+                                   const QSharedPointer<VSearchResult> &p_result)
+{
+    Q_ASSERT(testTarget(VSearchConfig::Note));
+
+    QString name = VUtils::fileNameFromPath(p_filePath);
+    if (!matchPattern(name)) {
+        return;
+    }
+
+    if (testObject(VSearchConfig::Name)) {
+        if (matchNonContent(name)) {
+            VSearchResultItem *item = new VSearchResultItem(VSearchResultItem::Note,
+                                                            VSearchResultItem::LineNumber,
+                                                            name,
+                                                            p_filePath);
+            QSharedPointer<VSearchResultItem> pitem(item);
+            emit resultItemAdded(pitem);
+        }
+    }
+
+    if (testObject(VSearchConfig::Path)) {
+        QString normFilePath(QDir(p_basePath).relativeFilePath(p_filePath));
+        removeSlashFromPath(normFilePath);
+        if (matchNonContent(normFilePath)) {
+            VSearchResultItem *item = new VSearchResultItem(VSearchResultItem::Note,
+                                                            VSearchResultItem::LineNumber,
+                                                            name,
+                                                            p_filePath);
+            QSharedPointer<VSearchResultItem> pitem(item);
+            emit resultItemAdded(pitem);
+        }
+    }
+
+    if (testObject(VSearchConfig::Content)) {
+        // Add an item for second phase process.
+        p_result->addSecondPhaseItem(p_filePath);
+    }
+}
+
 VSearchResultItem *VSearch::searchForOutline(const VFile *p_file) const
 {
     VEditTab *tab = g_mainWin->getEditArea()->getTab(p_file);

+ 11 - 0
src/vsearch.h

@@ -32,6 +32,9 @@ public:
     // Search folder for CurrentNotebook and AllNotebooks.
     QSharedPointer<VSearchResult> search(const QVector<VNotebook *> &p_notebooks);
 
+    // Search directory path for ExplorerDirectory.
+    QSharedPointer<VSearchResult> search(const QString &p_directoryPath);
+
     // Clear resources after a search completed.
     void clear();
 
@@ -60,6 +63,14 @@ private:
     void searchFirstPhase(VNotebook *p_notebook,
                           const QSharedPointer<VSearchResult> &p_result);
 
+    void searchFirstPhase(const QString &p_basePath,
+                          const QString &p_directoryPath,
+                          const QSharedPointer<VSearchResult> &p_result);
+
+    void searchFirstPhaseFile(const QString &p_basePath,
+                              const QString &p_filePath,
+                              const QSharedPointer<VSearchResult> &p_result);
+
     bool testTarget(VSearchConfig::Target p_target) const;
 
     bool testObject(VSearchConfig::Object p_object) const;

+ 2 - 1
src/vsearchconfig.h

@@ -194,7 +194,8 @@ struct VSearchConfig
         OpenedNotes,
         CurrentFolder,
         CurrentNotebook,
-        AllNotebooks
+        AllNotebooks,
+        ExplorerDirectory
     };
 
     enum Object

+ 38 - 10
src/vsearcher.cpp

@@ -16,6 +16,7 @@
 #include "vnotebook.h"
 #include "vnote.h"
 #include "vconfigmanager.h"
+#include "vexplorer.h"
 
 extern VMainWindow *g_mainWin;
 
@@ -243,12 +244,14 @@ void VSearcher::initUIFields()
     m_searchScopeCB->addItem(tr("Current Folder"), VSearchConfig::CurrentFolder);
     m_searchScopeCB->addItem(tr("Current Notebook"), VSearchConfig::CurrentNotebook);
     m_searchScopeCB->addItem(tr("All Notebooks"), VSearchConfig::AllNotebooks);
+    m_searchScopeCB->addItem(tr("Explorer Directory"), VSearchConfig::ExplorerDirectory);
     m_searchScopeCB->setCurrentIndex(m_searchScopeCB->findData(config.m_scope));
 
     // Object.
     m_searchObjectCB->addItem(tr("Name"), VSearchConfig::Name);
     m_searchObjectCB->addItem(tr("Content"), VSearchConfig::Content);
     m_searchObjectCB->addItem(tr("Tag"), VSearchConfig::Tag);
+    m_searchObjectCB->addItem(tr("Path"), VSearchConfig::Path);
     m_searchObjectCB->setCurrentIndex(m_searchObjectCB->findData(config.m_object));
 
     // Target.
@@ -314,20 +317,32 @@ void VSearcher::handleInputChanged()
     readyToSearch = !keyword.isEmpty();
 
     if (readyToSearch) {
-        // Other targets are only available for Name and Path.
         int obj = m_searchObjectCB->currentData().toInt();
-        if (obj != VSearchConfig::Name && obj != VSearchConfig::Path) {
-            int target = m_searchTargetCB->currentData().toInt();
-            if (!(target & VSearchConfig::Note)) {
-                readyToSearch = false;
-            }
+        int target = m_searchTargetCB->currentData().toInt();
+        int scope = m_searchScopeCB->currentData().toInt();
+
+        // Other targets are only available for Name and Path.
+        if (!(obj & VSearchConfig::Name)
+            && !(obj & VSearchConfig::Path)
+            && !(target & VSearchConfig::Note)) {
+            readyToSearch = false;
         }
 
-        if (readyToSearch && obj == VSearchConfig::Outline) {
+        if (readyToSearch
+            && obj == VSearchConfig::Outline
+            && scope != VSearchConfig::CurrentNotebook
+            && scope != VSearchConfig::OpenedNotes) {
             // Outline is available only for CurrentNote and OpenedNotes.
-            int scope = m_searchScopeCB->currentData().toInt();
-            if (scope != VSearchConfig::CurrentNote
-                && scope != VSearchConfig::OpenedNotes) {
+            readyToSearch = false;
+        }
+
+        if (readyToSearch && scope == VSearchConfig::ExplorerDirectory) {
+            if (!(obj & VSearchConfig::Name)
+                && !(obj & VSearchConfig::Path)
+                && !(obj & VSearchConfig::Content)) {
+                readyToSearch = false;
+            } else if (!(target & VSearchConfig::Note)
+                && !(target & VSearchConfig::Folder)) {
                 readyToSearch = false;
             }
         }
@@ -429,6 +444,19 @@ void VSearcher::startSearch()
         break;
     }
 
+    case VSearchConfig::ExplorerDirectory:
+    {
+        QString rootDirectory = g_mainWin->getExplorer()->getRootDirectory();
+        if (!rootDirectory.isEmpty()) {
+            QString msg(tr("Search Explorer directory %1.").arg(rootDirectory));
+            appendLogLine(msg);
+            showMessage(msg);
+        }
+
+        result = m_search.search(rootDirectory);
+        break;
+    }
+
     default:
         break;
     }

+ 5 - 0
src/vsearchresulttree.cpp

@@ -10,6 +10,7 @@
 #include "vnotefile.h"
 #include "vcart.h"
 #include "vhistorylist.h"
+#include "vexplorer.h"
 
 extern VNote *g_vnote;
 
@@ -272,6 +273,10 @@ void VSearchResultTree::activateItem(const QTreeWidgetItem *p_item) const
         VDirectory *dir = g_vnote->getInternalDirectory(resItem->m_path);
         if (dir) {
             g_mainWin->locateDirectory(dir);
+        } else {
+            // External directory.
+            g_mainWin->showExplorerPanel(true);
+            g_mainWin->getExplorer()->setRootDirectory(resItem->m_path);
         }
 
         break;