新增文件内容搜索插件

This commit is contained in:
hewenfei 2022-04-25 11:16:25 +08:00
parent 753ce85bd5
commit 338a090081
5 changed files with 290 additions and 5 deletions

View File

@ -4,6 +4,9 @@
#include <QString>
#include <QDir>
#define CONTENT_DATABASE_PATH_SLOT 1
#define CONTENT_DATABASE_SUFFIX_SLOT 2
static const int LABEL_MAX_WIDTH = 300;
static const QString HOME_PATH = QDir::homePath();

View File

@ -2,6 +2,8 @@
#include <QDebug>
#include "file-search-task.h"
#include "file-content-search-task.h"
using namespace UkuiSearch;
static SearchTaskPluginManager *global_instance = nullptr;
SearchTaskPluginManager *SearchTaskPluginManager::getInstance()
@ -14,9 +16,15 @@ SearchTaskPluginManager *SearchTaskPluginManager::getInstance()
void SearchTaskPluginManager::initPlugins(SearchType searchType)
{
size_t type = static_cast<size_t>(searchType);
if (type & static_cast<size_t>(SearchType::File)) {
registerBuildinPlugin(new FileSearchTask(this));
switch (searchType) {
case SearchType::File:
registerBuildinPlugin(new FileSearchTask(this));
break;
case SearchType::FileContent:
registerBuildinPlugin(new FileContentSearchTask(this));
break;
default:
break;
}
}

View File

@ -0,0 +1,194 @@
//
// Created by hxf on 2022/4/18.
//
//ukui-search
#include "file-content-search-task.h"
#include "index-status-recorder.h"
#include "chinese-segmentation.h"
#include "result-item.h"
#include "common.h"
#include "file-utils.h"
//Qt
#include <QIcon>
#include <QDebug>
#include <utility>
using namespace UkuiSearch;
FileContentSearchTask::FileContentSearchTask(QObject *parent)
{
this->setParent(parent);
qRegisterMetaType<size_t>("size_t");
m_pool = new QThreadPool(this);
m_pool->setMaxThreadCount(1);
}
FileContentSearchTask::~FileContentSearchTask()
{
}
PluginInterface::PluginType FileContentSearchTask::pluginType()
{
return PluginType::SearchTaskPlugin;
}
const QString FileContentSearchTask::name()
{
return "File Content";
}
const QString FileContentSearchTask::description()
{
return "File Content Search";
}
const QIcon FileContentSearchTask::icon()
{
return QIcon::fromTheme("folder");
}
void FileContentSearchTask::setEnable(bool enable)
{
}
bool FileContentSearchTask::isEnable()
{
return true;
}
QString FileContentSearchTask::getCustomSearchType()
{
return "File Content";
}
SearchType FileContentSearchTask::getSearchType()
{
return SearchType::FileContent;
}
void FileContentSearchTask::startSearch(std::shared_ptr<SearchController> searchController)
{
FileContentSearchWorker *worker = new FileContentSearchWorker(this, searchController);
m_pool->start(worker);
}
void FileContentSearchTask::stop()
{
}
void FileContentSearchTask::sendFinishSignal(size_t searchId)
{
Q_EMIT sendFinishSignal(searchId);
}
FileContentSearchWorker::FileContentSearchWorker(FileContentSearchTask *fileContentSearchTask, std::shared_ptr<SearchController> searchController)
{
m_fileContentSearchTask = fileContentSearchTask;
m_searchController = std::move(searchController);
m_currentSearchId = m_searchController->getCurrentSearchId();
}
void FileContentSearchWorker::run()
{
QStringList searchDirs = m_searchController->getSearchDir();
searchDirs.removeDuplicates();
for (QString &dir : searchDirs) {
if (dir.endsWith("/")) {
dir = dir.mid(0, dir.length() - 1);
}
//TODO 指定黑名单
m_validDirectories.append(dir);
}
bool finished = true;
if (IndexStatusRecorder::getInstance()->contentIndexDatabaseEnable()) {
qDebug() << "content index ready";
finished = execSearch();
} else {
qWarning() << "content index incomplete";
}
if (finished) QMetaObject::invokeMethod(m_fileContentSearchTask, "searchFinished", Q_ARG(size_t, m_currentSearchId));
}
bool FileContentSearchWorker::execSearch()
{
try {
Xapian::Database db(CONTENT_INDEX_PATH.toStdString());
Xapian::Enquire enquire(db);
enquire.set_query(createQuery());
FileContentSearchFilter filter(this);
Xapian::MSet result = enquire.get_mset(m_searchController->first(), m_searchController->maxResults(), 0, &filter);
for (auto it = result.begin(); it != result.end(); ++it) {
if (m_searchController->beginSearchIdCheck(m_currentSearchId)) {
QString path = QString::fromStdString(it.get_document().get_value(CONTENT_DATABASE_PATH_SLOT));
ResultItem resultItem(m_currentSearchId, path);
m_searchController->getDataQueue()->enqueue(resultItem);
m_searchController->finishSearchIdCheck();
} else {
qDebug() << "Search id changed!";
m_searchController->finishSearchIdCheck();
return false;
}
}
return true;
} catch (const Xapian::Error &e) {
qWarning() << QString::fromStdString(e.get_description());
return false;
}
}
inline Xapian::Query FileContentSearchWorker::createQuery()
{
std::vector<Xapian::Query> v;
for (const auto &keyword : m_searchController->getKeyword()) {
QVector<SKeyWord> sKeyWord = ChineseSegmentation::getInstance()->callSegement(keyword.toStdString());
for(const auto & c : sKeyWord) {
v.emplace_back(c.word);
}
}
return {Xapian::Query::OP_AND, v.begin(), v.end()};
}
FileContentSearchFilter::FileContentSearchFilter(FileContentSearchWorker *worker) : m_worker(worker)
{
}
bool FileContentSearchFilter::operator()(const Xapian::Document &doc) const
{
//在此处对搜索结果进行过滤
QString path = QString::fromStdString(doc.get_value(CONTENT_DATABASE_PATH_SLOT));
bool isExists = QFileInfo::exists(path);
bool inSearchDir = true;
//如果不指定搜索目录,那么搜索整个数据库
if (m_worker && !m_worker->m_validDirectories.empty()) {
inSearchDir = std::any_of(m_worker->m_validDirectories.begin(), m_worker->m_validDirectories.end(), [=] (const QString& dir) {
return path.startsWith(dir);
});
//TODO 黑名单
}
return isExists && inSearchDir;
}

View File

@ -0,0 +1,78 @@
//
// Created by hxf on 2022/4/18.
//
#ifndef UKUI_SEARCH_FILE_CONTENT_SEARCH_TASK_H
#define UKUI_SEARCH_FILE_CONTENT_SEARCH_TASK_H
//ukui-search
#include "search-task-plugin-iface.h"
//Qt
#include <QThreadPool>
#include <QRunnable>
//Xapian
#include <xapian.h>
namespace UkuiSearch {
class FileContentSearchTask : public SearchTaskPluginIface
{
public:
explicit FileContentSearchTask(QObject *parent = nullptr);
~FileContentSearchTask() override;
PluginType pluginType() override;
const QString name() override;
const QString description() override;
const QIcon icon() override;
void setEnable(bool enable) override;
bool isEnable() override;
QString getCustomSearchType() override;
SearchType getSearchType() override;
void startSearch(std::shared_ptr<SearchController> searchController) override;
void stop() override;
Q_INVOKABLE void sendFinishSignal(size_t searchId);
private:
QThreadPool *m_pool = nullptr;
};
class FileContentSearchWorker : public QRunnable
{
friend class FileContentSearchFilter;
public:
explicit FileContentSearchWorker(FileContentSearchTask *fileContentSearchTask, std::shared_ptr<SearchController> searchController);
void run() override;
private:
bool execSearch();
inline Xapian::Query createQuery();
private:
FileContentSearchTask *m_fileContentSearchTask = nullptr;
std::shared_ptr<SearchController> m_searchController;
QStringList m_validDirectories;
size_t m_currentSearchId = 0;
};
class FileContentSearchFilter : public Xapian::MatchDecider {
public:
explicit FileContentSearchFilter(FileContentSearchWorker*);
bool operator ()(const Xapian::Document &doc) const override;
private:
FileContentSearchWorker *m_worker;
};
}
#endif //UKUI_SEARCH_FILE_CONTENT_SEARCH_TASK_H

View File

@ -1,9 +1,11 @@
INCLUDEPATH += $$PWD
HEADERS += \
$$PWD/file-search-task.h
$$PWD/file-search-task.h \
$$PWD/file-content-search-task.h
SOURCES += \
$$PWD/file-search-task.cpp
$$PWD/file-search-task.cpp \
$$PWD/file-content-search-task.cpp