增加文件搜索插件标签搜索功能

This commit is contained in:
hewenfei 2022-04-28 15:49:51 +08:00
parent f76f8c8d14
commit 130c46508b
8 changed files with 125 additions and 27 deletions

View File

@ -37,6 +37,7 @@ public:
void clearAllConditions(); void clearAllConditions();
void clearKeyWords(); void clearKeyWords();
void clearSearchDir(); void clearSearchDir();
void clearFileLabel();
/** /**
* @brief * @brief

View File

@ -172,6 +172,7 @@ void SearchControllerPrivate::clearAllConditions()
{ {
clearKeyWords(); clearKeyWords();
clearSearchDir(); clearSearchDir();
clearFileLabel();
} }
void SearchControllerPrivate::clearKeyWords() void SearchControllerPrivate::clearKeyWords()
@ -184,6 +185,11 @@ void SearchControllerPrivate::clearSearchDir()
m_searchDirs.clear(); m_searchDirs.clear();
} }
void SearchControllerPrivate::clearFileLabel()
{
m_FileLabels.clear();
}
void SearchControllerPrivate::setPagination(unsigned int first, unsigned int maxResults) void SearchControllerPrivate::setPagination(unsigned int first, unsigned int maxResults)
{ {
m_first = first; m_first = first;
@ -337,6 +343,11 @@ void SearchController::clearSearchDir()
d->clearSearchDir(); d->clearSearchDir();
} }
void SearchController::clearFileLabel()
{
d->clearFileLabel();
}
void SearchController::setPagination(unsigned int first, unsigned int maxResults) void SearchController::setPagination(unsigned int first, unsigned int maxResults)
{ {
d->setPagination(first, maxResults); d->setPagination(first, maxResults);

View File

@ -52,6 +52,7 @@ public:
void clearAllConditions(); void clearAllConditions();
void clearKeyWords(); void clearKeyWords();
void clearSearchDir(); void clearSearchDir();
void clearFileLabel();
void setPagination(unsigned int first, unsigned int maxResults); void setPagination(unsigned int first, unsigned int maxResults);
unsigned int first() const; unsigned int first() const;

View File

@ -7,6 +7,7 @@
#include <QFile> #include <QFile>
#include <QQueue> #include <QQueue>
#include <QDebug> #include <QDebug>
#include <gio/gio.h>
using namespace UkuiSearch; using namespace UkuiSearch;
FileSearchTask::FileSearchTask(QObject *parent) FileSearchTask::FileSearchTask(QObject *parent)
@ -62,14 +63,23 @@ void FileSearchWorker::run()
searchDirs.removeDuplicates(); searchDirs.removeDuplicates();
for (QString &dir : searchDirs) { for (QString &dir : searchDirs) {
if (dir.endsWith("/")) { if (QFileInfo::exists(dir)) {
dir = dir.mid(0, dir.length() - 1); if (dir.endsWith("/")) {
} dir.remove(dir.length() - 1, 1);
}
QStringList blackListTmp = DirWatcher::getDirWatcher()->blackListOfDir(dir); QStringList blackListTmp = DirWatcher::getDirWatcher()->blackListOfDir(dir);
if (!blackListTmp.contains(dir)) { if (!blackListTmp.contains(dir)) {
m_validDirectories.append(dir); m_validDirectories.append(dir);
m_blackList.append(blackListTmp); m_blackList.append(blackListTmp);
}
}
}
//过滤空标签
for (QString &label : m_searchController->getFileLabel()) {
if (!label.isEmpty()) {
m_labels.append(label);
} }
} }
@ -80,6 +90,15 @@ void FileSearchWorker::run()
finished = searchWithIndex(); finished = searchWithIndex();
} else { } else {
if (m_validDirectories.empty()) {
//TODO 使用全局的默认可搜索目录
if (QFileInfo::exists(QDir::homePath())) {
sendErrorMsg(QObject::tr("Warning, Can not find home path."));
return;
}
m_validDirectories.append(QDir::homePath());
m_blackList.append(DirWatcher::getDirWatcher()->blackListOfDir(QDir::homePath()));
}
qDebug() << "direct search"; qDebug() << "direct search";
finished = directSearch(); finished = directSearch();
} }
@ -182,7 +201,12 @@ bool FileSearchWorker::directSearch()
for (const auto &fileInfo : infoList) { for (const auto &fileInfo : infoList) {
if (fileInfo.isDir() && !fileInfo.isSymLink()) { if (fileInfo.isDir() && !fileInfo.isSymLink()) {
QString newPath = fileInfo.absoluteFilePath(); QString newPath = fileInfo.absoluteFilePath();
if (m_blackList.contains(newPath)) {
bool inBlackList = std::any_of(m_blackList.begin(), m_blackList.end(), [&] (const QString &dir) {
return newPath.startsWith(dir + "/");
});
if (inBlackList) {
//在黑名单的路径忽略搜索 //在黑名单的路径忽略搜索
continue; continue;
} }
@ -203,6 +227,10 @@ bool FileSearchWorker::directSearch()
} }
} }
if (matched && !m_labels.empty()) {
matched = FileSearchFilter::checkFileLabel(fileInfo.absoluteFilePath(), m_labels);
}
if (m_searchController->beginSearchIdCheck(m_currentSearchId)) { if (m_searchController->beginSearchIdCheck(m_currentSearchId)) {
if (matched) { if (matched) {
ResultItem ri(m_currentSearchId, fileInfo.absoluteFilePath()); ResultItem ri(m_currentSearchId, fileInfo.absoluteFilePath());
@ -224,33 +252,69 @@ bool FileSearchWorker::directSearch()
return true; return true;
} }
FileSearchFilter::FileSearchFilter(FileSearchWorker *parent) : parent(parent) {} FileSearchFilter::FileSearchFilter(FileSearchWorker *parent) : m_parent(parent) {}
bool FileSearchFilter::operator ()(const Xapian::Document &doc) const bool FileSearchFilter::operator ()(const Xapian::Document &doc) const
{ {
if (parent) { if (m_parent) {
QString path = QString::fromStdString(doc.get_data()); QString path = QString::fromStdString(doc.get_data());
bool isRecurse = parent->m_searchController->isRecurse(); bool isRecurse = m_parent->m_searchController->isRecurse();
bool inSearchDir = std::any_of(parent->m_validDirectories.begin(), parent->m_validDirectories.end(), [&](QString &dir) { bool inSearchDir = true;
bool startWithDir = path.startsWith(dir);
if (!startWithDir) {
return false;
}
if (path.length() == dir.length()) { if (!m_parent->m_validDirectories.empty()) {
return false; inSearchDir = std::any_of(m_parent->m_validDirectories.begin(), m_parent->m_validDirectories.end(), [&](QString &dir) {
} //限制搜索在该目录下
if (!path.startsWith(dir + "/")) {
return false;
}
if (!isRecurse) { if (!isRecurse) {
//去除搜索路径后,是否包含 "/" //去除搜索路径后,是否包含 "/"
return !path.midRef((dir.length() + 1), (path.length() - dir.length() - 1)).contains("/"); return !path.midRef((dir.length() + 1), (path.length() - dir.length() - 1)).contains("/");
} }
return true; return true;
}); });
}
return inSearchDir; bool hasLabel = true;
if (inSearchDir && !m_parent->m_labels.empty()) {
hasLabel = FileSearchFilter::checkFileLabel(path, m_parent->m_labels);
}
return inSearchDir && hasLabel;
} }
return true; return true;
} }
bool FileSearchFilter::checkFileLabel(const QString &path, const QStringList &labels)
{
bool hasLabel = false;
GFile *file = g_file_new_for_path(path.toUtf8().constData());
if (file) {
GFileInfo *info = g_file_query_info(file, "metadata::*," G_FILE_ATTRIBUTE_ID_FILE, G_FILE_QUERY_INFO_NONE,
nullptr, nullptr);
if (info) {
gboolean hasKey = g_file_info_has_attribute(info, "metadata::peony-file-label-ids");
if (hasKey) {
char *fileLabels = g_file_info_get_attribute_as_string(info, "metadata::peony-file-label-ids");
if (fileLabels) {
QStringList fileLabelList = QString::fromUtf8(fileLabels).split("\n");
g_free(fileLabels);
hasLabel = std::any_of(fileLabelList.begin(), fileLabelList.end(), [&](QString &fileLabel) {
return labels.contains(fileLabel);
});
}
}
g_object_unref(info);
}
g_object_unref(file);
}
return hasLabel;
}

View File

@ -66,6 +66,7 @@ private:
size_t m_currentSearchId = 0; size_t m_currentSearchId = 0;
QStringList m_validDirectories; QStringList m_validDirectories;
QStringList m_blackList; QStringList m_blackList;
QStringList m_labels;
}; };
class FileSearchFilter : public Xapian::MatchDecider { class FileSearchFilter : public Xapian::MatchDecider {
@ -73,8 +74,16 @@ public:
explicit FileSearchFilter(FileSearchWorker *parent); explicit FileSearchFilter(FileSearchWorker *parent);
bool operator ()(const Xapian::Document &doc) const; bool operator ()(const Xapian::Document &doc) const;
/**
* @brief path对应的文件是否包含labels中的标签
* @param path
* @param labels
* @return
*/
static bool checkFileLabel(const QString &path, const QStringList &labels);
private: private:
FileSearchWorker *parent = nullptr; FileSearchWorker *m_parent = nullptr;
}; };
} }

View File

@ -27,6 +27,7 @@ public:
void clearAllConditions(); void clearAllConditions();
void clearKeyWords(); void clearKeyWords();
void clearSearchDir(); void clearSearchDir();
void clearFileLabel();
void setPagination(unsigned int first, unsigned int maxResults); void setPagination(unsigned int first, unsigned int maxResults);
size_t startSearch(SearchType searchtype, QString customSearchType = QString()); size_t startSearch(SearchType searchtype, QString customSearchType = QString());

View File

@ -100,6 +100,11 @@ void UkuiSearchTaskPrivate::clearSearchDir()
m_searchCotroller->clearSearchDir(); m_searchCotroller->clearSearchDir();
} }
void UkuiSearchTaskPrivate::clearFileLabel()
{
m_searchCotroller->clearFileLabel();
}
void UkuiSearchTaskPrivate::setPagination(unsigned int first, unsigned int maxResults) void UkuiSearchTaskPrivate::setPagination(unsigned int first, unsigned int maxResults)
{ {
m_searchCotroller->setPagination(first, maxResults); m_searchCotroller->setPagination(first, maxResults);
@ -184,6 +189,11 @@ void UkuiSearchTask::clearSearchDir()
d->clearSearchDir(); d->clearSearchDir();
} }
void UkuiSearchTask::clearFileLabel()
{
d->clearFileLabel();
}
void UkuiSearchTask::setPagination(unsigned int first, unsigned int maxResults) void UkuiSearchTask::setPagination(unsigned int first, unsigned int maxResults)
{ {
d->setPagination(first, maxResults); d->setPagination(first, maxResults);

View File

@ -24,6 +24,7 @@ public:
void clearAllConditions(); void clearAllConditions();
void clearKeyWords(); void clearKeyWords();
void clearSearchDir(); void clearSearchDir();
void clearFileLabel();
void setPagination(unsigned int first, unsigned int maxResults); void setPagination(unsigned int first, unsigned int maxResults);
size_t startSearch(SearchType searchtype, QString customSearchType = QString()); size_t startSearch(SearchType searchtype, QString customSearchType = QString());