diff --git a/libsearch/searchinterface/search-controller-private.h b/libsearch/searchinterface/search-controller-private.h index 9000f95..40d82e7 100644 --- a/libsearch/searchinterface/search-controller-private.h +++ b/libsearch/searchinterface/search-controller-private.h @@ -37,6 +37,7 @@ public: void clearAllConditions(); void clearKeyWords(); void clearSearchDir(); + void clearFileLabel(); /** * @brief 分页选项 diff --git a/libsearch/searchinterface/search-controller.cpp b/libsearch/searchinterface/search-controller.cpp index 4f9f485..66da16e 100644 --- a/libsearch/searchinterface/search-controller.cpp +++ b/libsearch/searchinterface/search-controller.cpp @@ -172,6 +172,7 @@ void SearchControllerPrivate::clearAllConditions() { clearKeyWords(); clearSearchDir(); + clearFileLabel(); } void SearchControllerPrivate::clearKeyWords() @@ -184,6 +185,11 @@ void SearchControllerPrivate::clearSearchDir() m_searchDirs.clear(); } +void SearchControllerPrivate::clearFileLabel() +{ + m_FileLabels.clear(); +} + void SearchControllerPrivate::setPagination(unsigned int first, unsigned int maxResults) { m_first = first; @@ -337,6 +343,11 @@ void SearchController::clearSearchDir() d->clearSearchDir(); } +void SearchController::clearFileLabel() +{ + d->clearFileLabel(); +} + void SearchController::setPagination(unsigned int first, unsigned int maxResults) { d->setPagination(first, maxResults); diff --git a/libsearch/searchinterface/search-controller.h b/libsearch/searchinterface/search-controller.h index 80edb45..4a9a992 100644 --- a/libsearch/searchinterface/search-controller.h +++ b/libsearch/searchinterface/search-controller.h @@ -52,6 +52,7 @@ public: void clearAllConditions(); void clearKeyWords(); void clearSearchDir(); + void clearFileLabel(); void setPagination(unsigned int first, unsigned int maxResults); unsigned int first() const; diff --git a/libsearch/searchinterface/searchtasks/file-search-task.cpp b/libsearch/searchinterface/searchtasks/file-search-task.cpp index d53b443..54bd923 100644 --- a/libsearch/searchinterface/searchtasks/file-search-task.cpp +++ b/libsearch/searchinterface/searchtasks/file-search-task.cpp @@ -7,6 +7,7 @@ #include #include #include +#include using namespace UkuiSearch; FileSearchTask::FileSearchTask(QObject *parent) @@ -62,14 +63,23 @@ void FileSearchWorker::run() searchDirs.removeDuplicates(); for (QString &dir : searchDirs) { - if (dir.endsWith("/")) { - dir = dir.mid(0, dir.length() - 1); - } + if (QFileInfo::exists(dir)) { + if (dir.endsWith("/")) { + dir.remove(dir.length() - 1, 1); + } - QStringList blackListTmp = DirWatcher::getDirWatcher()->blackListOfDir(dir); - if (!blackListTmp.contains(dir)) { - m_validDirectories.append(dir); - m_blackList.append(blackListTmp); + QStringList blackListTmp = DirWatcher::getDirWatcher()->blackListOfDir(dir); + if (!blackListTmp.contains(dir)) { + m_validDirectories.append(dir); + 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(); } 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"; finished = directSearch(); } @@ -182,7 +201,12 @@ bool FileSearchWorker::directSearch() for (const auto &fileInfo : infoList) { if (fileInfo.isDir() && !fileInfo.isSymLink()) { 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; } @@ -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 (matched) { ResultItem ri(m_currentSearchId, fileInfo.absoluteFilePath()); @@ -224,33 +252,69 @@ bool FileSearchWorker::directSearch() return true; } -FileSearchFilter::FileSearchFilter(FileSearchWorker *parent) : parent(parent) {} +FileSearchFilter::FileSearchFilter(FileSearchWorker *parent) : m_parent(parent) {} bool FileSearchFilter::operator ()(const Xapian::Document &doc) const { - if (parent) { + if (m_parent) { QString path = QString::fromStdString(doc.get_data()); - bool isRecurse = parent->m_searchController->isRecurse(); - bool inSearchDir = std::any_of(parent->m_validDirectories.begin(), parent->m_validDirectories.end(), [&](QString &dir) { - bool startWithDir = path.startsWith(dir); - if (!startWithDir) { - return false; - } + bool isRecurse = m_parent->m_searchController->isRecurse(); + bool inSearchDir = true; - if (path.length() == dir.length()) { - return false; - } + if (!m_parent->m_validDirectories.empty()) { + inSearchDir = std::any_of(m_parent->m_validDirectories.begin(), m_parent->m_validDirectories.end(), [&](QString &dir) { + //限制搜索在该目录下 + if (!path.startsWith(dir + "/")) { + return false; + } - if (!isRecurse) { - //去除搜索路径后,是否包含 "/" - return !path.midRef((dir.length() + 1), (path.length() - dir.length() - 1)).contains("/"); - } + if (!isRecurse) { + //去除搜索路径后,是否包含 "/" + 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; } + +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; +} diff --git a/libsearch/searchinterface/searchtasks/file-search-task.h b/libsearch/searchinterface/searchtasks/file-search-task.h index 428b603..216d250 100644 --- a/libsearch/searchinterface/searchtasks/file-search-task.h +++ b/libsearch/searchinterface/searchtasks/file-search-task.h @@ -66,6 +66,7 @@ private: size_t m_currentSearchId = 0; QStringList m_validDirectories; QStringList m_blackList; + QStringList m_labels; }; class FileSearchFilter : public Xapian::MatchDecider { @@ -73,8 +74,16 @@ public: explicit FileSearchFilter(FileSearchWorker *parent); 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: - FileSearchWorker *parent = nullptr; + FileSearchWorker *m_parent = nullptr; }; } diff --git a/libsearch/searchinterface/ukui-search-task-private.h b/libsearch/searchinterface/ukui-search-task-private.h index cf109a5..a28e1b6 100644 --- a/libsearch/searchinterface/ukui-search-task-private.h +++ b/libsearch/searchinterface/ukui-search-task-private.h @@ -27,6 +27,7 @@ public: void clearAllConditions(); void clearKeyWords(); void clearSearchDir(); + void clearFileLabel(); void setPagination(unsigned int first, unsigned int maxResults); size_t startSearch(SearchType searchtype, QString customSearchType = QString()); diff --git a/libsearch/searchinterface/ukui-search-task.cpp b/libsearch/searchinterface/ukui-search-task.cpp index e272667..891e327 100644 --- a/libsearch/searchinterface/ukui-search-task.cpp +++ b/libsearch/searchinterface/ukui-search-task.cpp @@ -100,6 +100,11 @@ void UkuiSearchTaskPrivate::clearSearchDir() m_searchCotroller->clearSearchDir(); } +void UkuiSearchTaskPrivate::clearFileLabel() +{ + m_searchCotroller->clearFileLabel(); +} + void UkuiSearchTaskPrivate::setPagination(unsigned int first, unsigned int maxResults) { m_searchCotroller->setPagination(first, maxResults); @@ -184,6 +189,11 @@ void UkuiSearchTask::clearSearchDir() d->clearSearchDir(); } +void UkuiSearchTask::clearFileLabel() +{ + d->clearFileLabel(); +} + void UkuiSearchTask::setPagination(unsigned int first, unsigned int maxResults) { d->setPagination(first, maxResults); diff --git a/libsearch/searchinterface/ukui-search-task.h b/libsearch/searchinterface/ukui-search-task.h index e9ed5eb..3b29ebd 100644 --- a/libsearch/searchinterface/ukui-search-task.h +++ b/libsearch/searchinterface/ukui-search-task.h @@ -24,6 +24,7 @@ public: void clearAllConditions(); void clearKeyWords(); void clearSearchDir(); + void clearFileLabel(); void setPagination(unsigned int first, unsigned int maxResults); size_t startSearch(SearchType searchtype, QString customSearchType = QString());