From 2bf3562f3734297b6542aa0075cf7478388439e5 Mon Sep 17 00:00:00 2001 From: Zhang Sheng Date: Thu, 23 Apr 2026 08:55:55 +0800 Subject: [PATCH 1/3] feat: enhance OCR search with highlighting and config options MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Added highlighting support for OCR text search results 2. Implemented preview content length restriction for OCR results 3. Added new configuration options for OCR text search: - Maximum preview length - Highlighting enable/disable toggle - Full text retrieval enable/disable toggle 4. Updated command line interface and documentation for OCR search features 5. Removed deprecated comments about lack of highlighting support 6. Default max results changed to 0 (unlimited) from 100 7. Added highlightedContent field in OCR result API Log: Added OCR search result highlighting and preview features with configurable options Influence: 1. Test OCR search with highlighting enabled/disabled 2. Verify preview length restriction works as expected 3. Test full text retrieval vs metadata only modes 4. Check JSON and text output formats for highlighted content 5. Test various max-results values including 0 (unlimited) 6. Verify backward compatibility with existing OCR searches feat: 增强OCR搜索功能,支持高亮和配置选项 1. 为OCR文本搜索结果添加高亮支持 2. 实现OCR结果预览内容长度限制 3. 新增OCR文本搜索配置选项: - 最大预览长度 - 高亮显示开关 - 全文检索开关 4. 更新命令行接口和文档以支持OCR搜索特性 5. 移除关于不支持高亮的过时注释 6. 默认最大结果数从100改为0(无限制) 7. 在OCR结果API中添加highlightedContent字段 Log: 新增OCR搜索结果高亮和预览功能,支持配置选项 Influence: 1. 测试启用/禁用高亮时的OCR搜索 2. 验证预览长度限制是否正常工作 3. 测试全文检索与仅元数据模式 4. 检查高亮内容在JSON和文本输出格式中的显示 5. 测试各种max-results值,包括0(无限制) 6. 验证与现有OCR搜索功能的向后兼容性 --- .../dfm-search/dfm-search/ocrtextsearchapi.h | 66 ++++++++++++++++++- src/dfm-search/dfm-search-client/README.md | 11 +++- .../dfm-search-client/cli_options.cpp | 8 +-- .../dfm-search-client/cli_options.h | 2 +- src/dfm-search/dfm-search-client/main.cpp | 3 + .../dfm-search-client/output/json_output.cpp | 2 + .../dfm-search-client/output/text_output.cpp | 2 + .../contentsearch/contentsearchapi.cpp | 6 +- .../ocrtextsearch/ocrtextsearchapi.cpp | 50 ++++++++++++++ .../ocrtextstrategies/indexedstrategy.cpp | 38 +++++++++-- 10 files changed, 168 insertions(+), 20 deletions(-) diff --git a/include/dfm-search/dfm-search/ocrtextsearchapi.h b/include/dfm-search/dfm-search/ocrtextsearchapi.h index 4e854ee2..7f14b6ed 100644 --- a/include/dfm-search/dfm-search/ocrtextsearchapi.h +++ b/include/dfm-search/dfm-search/ocrtextsearchapi.h @@ -14,7 +14,6 @@ DFM_SEARCH_BEGIN_NS * @brief The OcrTextOptionsAPI class provides OCR text search specific options * * This class extends the base SearchOptions with OCR text search specific settings. - * OCR text search is a simplified version of content search without highlighting support. */ class OcrTextOptionsAPI { @@ -25,6 +24,58 @@ class OcrTextOptionsAPI */ explicit OcrTextOptionsAPI(SearchOptions &options); + // ==================== Preview and Highlight Settings ==================== + + /** + * @brief Sets the maximum length for content preview in search results. + * @param length The maximum preview length in characters. + */ + void setMaxPreviewLength(int length); + + /** + * @brief Gets the maximum length for content preview in search results. + * @return The maximum preview length in characters. + */ + int maxPreviewLength() const; + + /** + * @brief Enables or disables HTML highlighting in search results. + * + * When enabled, matching keywords in search results will be wrapped in HTML tags + * (e.g., `keyword`) for visual highlighting. + * Note: Enabling this feature may incur additional processing overhead. + * + * @param enable Set to @c true to enable HTML highlighting, @c false to disable. + */ + void setSearchResultHighlightEnabled(bool enable); + + /** + * @brief Returns whether HTML highlighting in search results is enabled. + * + * @return @c true if search results will include HTML highlighting tags, + * @c false otherwise (plaintext results). + */ + bool isSearchResultHighlightEnabled() const; + + /** + * @brief Enables or disables full-text content retrieval in search results. + * + * When enabled, search operations will return the complete OCR text content along with metadata. + * This provides more detailed results but significantly increases memory usage and processing time. + * + * @param enable Set to @c true to retrieve full OCR text contents, @c false to return metadata only. + */ + void setFullTextRetrievalEnabled(bool enable); + + /** + * @brief Returns whether full-text content retrieval is enabled. + * + * @return @c true if full-text content retrieval is enabled, @c false otherwise. + */ + bool isFullTextRetrievalEnabled() const; + + // ==================== Mixed Search Settings ==================== + /** * @brief Sets whether the extended AND search behavior across 'ocr_contents' and 'filename' fields is enabled. * @param enabled True to enable the feature, false to disable it. @@ -57,7 +108,6 @@ class OcrTextOptionsAPI * @brief The OcrTextResultAPI class provides OCR text search specific result handling * * This class extends the base SearchResult with OCR text search specific features. - * Note: OCR text search does not support content highlighting like content search. * * When detailed results are enabled, this API provides access to additional * metadata including filename, hidden status, and time information. @@ -85,6 +135,18 @@ class OcrTextResultAPI */ void setOcrContent(const QString &content); + /** + * @brief Get the highlighted OCR content preview + * @return The highlighted content as QString + */ + QString highlightedContent() const; + + /** + * @brief Set the highlighted OCR content preview + * @param content The highlighted content to set + */ + void setHighlightedContent(const QString &content); + // ==================== Extended Attributes ==================== /** diff --git a/src/dfm-search/dfm-search-client/README.md b/src/dfm-search/dfm-search-client/README.md index 6b8af335..2f8d976f 100644 --- a/src/dfm-search/dfm-search-client/README.md +++ b/src/dfm-search/dfm-search-client/README.md @@ -18,6 +18,11 @@ A comprehensive file search utility for Deepin File Manager that provides high-p - Result highlighting - Preview of matching content +- **OCR search**: Search text extracted from images via OCR: + - Search text in image files (PNG, JPG, etc.) + - Result highlighting + - Preview of matching OCR text + ## Search Methods - **Indexed search**: Fast search using pre-built Lucene indexes @@ -33,7 +38,7 @@ dfm6-search-client [options] ### Options -- `--type=`: Search type (default: filename) +- `--type=`: Search type (default: filename) - `--method=`: Search method (default: indexed) - `--query=`: Query type (default: simple) - `--case-sensitive`: Enable case sensitivity @@ -41,8 +46,8 @@ dfm6-search-client [options] - `--pinyin`: Enable pinyin search (for filename search) - `--file-types=`: Filter by file types, comma separated - `--file-extensions=`: Filter by file extensions, comma separated -- `--max-results=`: Maximum number of results -- `--max-preview=`: Max content preview length (for content search) +- `--max-results=`: Maximum number of results (0 for unlimited, default: 0) +- `--max-preview=`: Max content preview length (for content/ocr search) ### Examples diff --git a/src/dfm-search/dfm-search-client/cli_options.cpp b/src/dfm-search/dfm-search-client/cli_options.cpp index 0327cb3c..63986e61 100644 --- a/src/dfm-search/dfm-search-client/cli_options.cpp +++ b/src/dfm-search/dfm-search-client/cli_options.cpp @@ -23,7 +23,7 @@ CliOptions::CliOptions() m_pinyinAcronymOption(QStringList() << "pinyin-acronym", "Enable pinyin acronym search (for filename search)"), m_fileTypesOption(QStringList() << "file-types", "Filter by file types, comma separated", "types"), m_fileExtensionsOption(QStringList() << "file-extensions", "Filter by file extensions, comma separated", "extensions"), - m_maxResultsOption(QStringList() << "max-results", "Maximum number of results", "number", "100"), + m_maxResultsOption(QStringList() << "max-results", "Maximum number of results (0 for unlimited)", "number", "0"), m_maxPreviewOption(QStringList() << "max-preview", "Max content preview length", "length", "200"), m_wildcardOption(QStringList() << "wildcard", "Enable wildcard search with * and ? patterns"), m_jsonOption(QStringList() << "json" @@ -106,8 +106,8 @@ void CliOptions::printHelp() const std::cout << " --pinyin-acronym Enable pinyin acronym search (for filename search)" << std::endl; std::cout << " --file-types= Filter by file types, comma separated" << std::endl; std::cout << " --file-extensions= Filter by file extensions, comma separated" << std::endl; - std::cout << " --max-results= Maximum number of results" << std::endl; - std::cout << " --max-preview= Max content preview length (for content search)" << std::endl; + std::cout << " --max-results= Maximum number of results (0 for unlimited)" << std::endl; + std::cout << " --max-preview= Max content preview length (for content/ocr search)" << std::endl; std::cout << std::endl; std::cout << "Time Range Filter Options:" << std::endl; std::cout << " --time-field= Time field to filter (birth=creation, modify=modification)" << std::endl; @@ -224,7 +224,7 @@ bool CliOptions::parse(QCoreApplication &app, SearchCliConfig &config) if (m_parser.isSet(m_maxResultsOption)) { bool ok; int maxResults = m_parser.value(m_maxResultsOption).toInt(&ok); - if (ok && maxResults > 0) { + if (ok && maxResults >= 0) { config.maxResults = maxResults; } } diff --git a/src/dfm-search/dfm-search-client/cli_options.h b/src/dfm-search/dfm-search-client/cli_options.h index f93a6817..10bdbf15 100644 --- a/src/dfm-search/dfm-search-client/cli_options.h +++ b/src/dfm-search/dfm-search-client/cli_options.h @@ -41,7 +41,7 @@ struct SearchCliConfig // 过滤选项 QStringList fileTypes; QStringList fileExtensions; - int maxResults = 100; + int maxResults = 0; // 0 表示不限制 int maxPreviewLength = 200; // 时间范围过滤 diff --git a/src/dfm-search/dfm-search-client/main.cpp b/src/dfm-search/dfm-search-client/main.cpp index 11241f88..26ed2457 100644 --- a/src/dfm-search/dfm-search-client/main.cpp +++ b/src/dfm-search/dfm-search-client/main.cpp @@ -55,6 +55,9 @@ static void configureSearchOptions(SearchOptions &options, const SearchCliConfig contentOptions.setFilenameContentMixedAndSearchEnabled(true); } else if (config.searchType == SearchType::Ocr) { OcrTextOptionsAPI ocrTextOptions(options); + ocrTextOptions.setMaxPreviewLength(config.maxPreviewLength); + ocrTextOptions.setFullTextRetrievalEnabled(true); + ocrTextOptions.setSearchResultHighlightEnabled(true); ocrTextOptions.setFilenameOcrContentMixedAndSearchEnabled(true); } diff --git a/src/dfm-search/dfm-search-client/output/json_output.cpp b/src/dfm-search/dfm-search-client/output/json_output.cpp index f1811862..b6208a2d 100644 --- a/src/dfm-search/dfm-search-client/output/json_output.cpp +++ b/src/dfm-search/dfm-search-client/output/json_output.cpp @@ -114,6 +114,8 @@ QJsonValue JsonOutput::resultToJson(const SearchResult &result) OcrTextResultAPI resultAPI(const_cast(result)); + obj["contentMatch"] = resultAPI.highlightedContent(); + QString ocrContent = resultAPI.ocrContent(); if (!ocrContent.isEmpty()) { obj["ocrContent"] = ocrContent; diff --git a/src/dfm-search/dfm-search-client/output/text_output.cpp b/src/dfm-search/dfm-search-client/output/text_output.cpp index 15b0bd87..c1cca72e 100644 --- a/src/dfm-search/dfm-search-client/output/text_output.cpp +++ b/src/dfm-search/dfm-search-client/output/text_output.cpp @@ -134,6 +134,8 @@ void TextOutput::printSearchResult(const SearchResult &result) } else if (m_searchType == SearchType::Ocr) { OcrTextResultAPI resultAPI(const_cast(result)); + std::cout << " Content match: " << resultAPI.highlightedContent().toStdString() << std::endl; + QString ocrContent = resultAPI.ocrContent(); if (!ocrContent.isEmpty()) { std::cout << " OCR content: " << ocrContent.toStdString() << std::endl; diff --git a/src/dfm-search/dfm-search-lib/contentsearch/contentsearchapi.cpp b/src/dfm-search/dfm-search-lib/contentsearch/contentsearchapi.cpp index 913df0ca..0be88fee 100644 --- a/src/dfm-search/dfm-search-lib/contentsearch/contentsearchapi.cpp +++ b/src/dfm-search/dfm-search-lib/contentsearch/contentsearchapi.cpp @@ -14,7 +14,7 @@ ContentOptionsAPI::ContentOptionsAPI(SearchOptions &options) // init default if (!m_options.hasCustomOption("maxPreviewLength")) setMaxPreviewLength(50); - if (!m_options.hasCustomOption("searchResultHighligh")) + if (!m_options.hasCustomOption("searchResultHighlight")) setSearchResultHighlightEnabled(false); if (!m_options.hasCustomOption("fullTextRetrieval")) setFullTextRetrievalEnabled(true); @@ -32,12 +32,12 @@ int ContentOptionsAPI::maxPreviewLength() const void ContentOptionsAPI::setSearchResultHighlightEnabled(bool enable) { - m_options.setCustomOption("searchResultHighligh", enable); + m_options.setCustomOption("searchResultHighlight", enable); } bool ContentOptionsAPI::isSearchResultHighlightEnabled() const { - return m_options.customOption("searchResultHighligh").toBool(); + return m_options.customOption("searchResultHighlight").toBool(); } void ContentOptionsAPI::setFullTextRetrievalEnabled(bool enable) diff --git a/src/dfm-search/dfm-search-lib/ocrtextsearch/ocrtextsearchapi.cpp b/src/dfm-search/dfm-search-lib/ocrtextsearch/ocrtextsearchapi.cpp index d7d1b06c..f3f1a93f 100644 --- a/src/dfm-search/dfm-search-lib/ocrtextsearch/ocrtextsearchapi.cpp +++ b/src/dfm-search/dfm-search-lib/ocrtextsearch/ocrtextsearchapi.cpp @@ -12,10 +12,50 @@ OcrTextOptionsAPI::OcrTextOptionsAPI(SearchOptions &options) : m_options(options) { // init default + if (!m_options.hasCustomOption("maxPreviewLength")) + setMaxPreviewLength(50); + if (!m_options.hasCustomOption("searchResultHighlight")) + setSearchResultHighlightEnabled(false); + if (!m_options.hasCustomOption("fullTextRetrieval")) + setFullTextRetrievalEnabled(true); if (!m_options.hasCustomOption("filenameOcrContentMixedAndSearchEnabled")) setFilenameOcrContentMixedAndSearchEnabled(false); } +// ==================== Preview and Highlight Settings ==================== + +void OcrTextOptionsAPI::setMaxPreviewLength(int length) +{ + m_options.setCustomOption("maxPreviewLength", length); +} + +int OcrTextOptionsAPI::maxPreviewLength() const +{ + return m_options.customOption("maxPreviewLength").toInt(); +} + +void OcrTextOptionsAPI::setSearchResultHighlightEnabled(bool enable) +{ + m_options.setCustomOption("searchResultHighlight", enable); +} + +bool OcrTextOptionsAPI::isSearchResultHighlightEnabled() const +{ + return m_options.customOption("searchResultHighlight").toBool(); +} + +void OcrTextOptionsAPI::setFullTextRetrievalEnabled(bool enable) +{ + m_options.setCustomOption("fullTextRetrieval", enable); +} + +bool OcrTextOptionsAPI::isFullTextRetrievalEnabled() const +{ + return m_options.customOption("fullTextRetrieval").toBool(); +} + +// ==================== Mixed Search Settings ==================== + void OcrTextOptionsAPI::setFilenameOcrContentMixedAndSearchEnabled(bool enabled) { m_options.setCustomOption("filenameOcrContentMixedAndSearchEnabled", enabled); @@ -41,6 +81,16 @@ void OcrTextResultAPI::setOcrContent(const QString &content) m_result.setCustomAttribute("ocrContent", content); } +QString OcrTextResultAPI::highlightedContent() const +{ + return m_result.customAttribute("highlightedContent").toString(); +} + +void OcrTextResultAPI::setHighlightedContent(const QString &content) +{ + m_result.setCustomAttribute("highlightedContent", content); +} + // ==================== Extended Attributes ==================== QString OcrTextResultAPI::filename() const diff --git a/src/dfm-search/dfm-search-lib/ocrtextsearch/ocrtextstrategies/indexedstrategy.cpp b/src/dfm-search/dfm-search-lib/ocrtextsearch/ocrtextstrategies/indexedstrategy.cpp index 0a496d77..e561b2a6 100644 --- a/src/dfm-search/dfm-search-lib/ocrtextsearch/ocrtextstrategies/indexedstrategy.cpp +++ b/src/dfm-search/dfm-search-lib/ocrtextsearch/ocrtextstrategies/indexedstrategy.cpp @@ -20,6 +20,7 @@ #include "3rdparty/fulltext/chineseanalyzer.h" #include "utils/cancellablecollector.h" +#include "utils/contenthighlighter.h" #include "utils/lucenequeryutils.h" #include "utils/searchutility.h" #include "utils/lucene_cancellation_compat.h" @@ -245,6 +246,11 @@ void OcrTextIndexedStrategy::processSearchResults(const Lucene::IndexSearcherPtr const QStringList &searchExcludedPaths = m_options.searchExcludedPaths(); auto docsSize = scoreDocs.size(); + OcrTextOptionsAPI optAPI(m_options); + bool enableHTML = optAPI.isSearchResultHighlightEnabled(); + int previewLen = optAPI.maxPreviewLength() > 0 ? optAPI.maxPreviewLength() : 50; + bool enableRetrieval = optAPI.isFullTextRetrievalEnabled(); + for (int32_t i = 0; i < docsSize; ++i) { if (m_cancelled.load()) { qInfo() << "OCR text search cancelled"; @@ -320,16 +326,34 @@ void OcrTextIndexedStrategy::processSearchResults(const Lucene::IndexSearcherPtr // Create search result SearchResult result(path); - // 设置详细结果(如果启用) - if (Q_UNLIKELY(m_options.detailedResultsEnabled())) { - OcrTextResultAPI resultApi(result); + // 设置 OCR 内容结果 + OcrTextResultAPI resultApi(result); - // OCR 内容 - Lucene::String ocrContentField = doc->get(LuceneFieldNames::OcrText::kOcrContents); - if (!ocrContentField.empty()) { - resultApi.setOcrContent(QString::fromStdWString(ocrContentField)); + // 使用ContentHighlighter命名空间进行高亮 + if (enableRetrieval) { + try { + // Safely get OCR contents with null check + Lucene::String ocrContentField = doc->get(LuceneFieldNames::OcrText::kOcrContents); + if (!ocrContentField.empty()) { + const QString content = QString::fromStdWString(ocrContentField); + // 设置原始 OCR 内容 + resultApi.setOcrContent(content); + // 设置高亮内容 + const QString highlightedContent = ContentHighlighter::customHighlight( + m_keywords, content, previewLen, enableHTML); + resultApi.setHighlightedContent(highlightedContent); + } + } catch (const Lucene::LuceneException &e) { + qWarning() << "Exception retrieving OCR content field:" << QString::fromStdWString(e.getError()); + // Continue without content highlight + } catch (const std::exception &e) { + qWarning() << "Standard exception retrieving OCR content field:" << e.what(); + // Continue without content highlight } + } + // 设置详细结果(如果启用) + if (Q_UNLIKELY(m_options.detailedResultsEnabled())) { // 文件名 Lucene::String filenameField = doc->get(LuceneFieldNames::OcrText::kFilename); if (!filenameField.empty()) { From d116f424113eda663b4f5753c05ba8e4cec30a5a Mon Sep 17 00:00:00 2001 From: Zhang Sheng Date: Thu, 23 Apr 2026 10:38:31 +0800 Subject: [PATCH 2/3] refactor: restructure text search APIs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Created new base classes TextSearchOptionsAPI and TextSearchResultAPI 2. Moved common functionality from ContentSearch and OcrTextSearch to base classes 3. Changed ContentOptionsAPI and OcrTextOptionsAPI to inherit from TextSearchOptionsAPI 4. Changed ContentResultAPI and OcrTextResultAPI to inherit from TextSearchResultAPI 5. Consolidated duplicate code for preview length, highlighting, file attributes and timestamps 6. Updated implementation files to reflect inheritance changes The changes introduce better code organization by: 1. Removing duplicate code across different search types 2. Creating a clear hierarchy for search API classes 3. Making it easier to maintain and extend common functionality 4. Following DRY (Don't Repeat Yourself) principle 5. Increasing default preview length from 50 to 200 characters All existing functionality remains the same, only the implementation structure changed. refactor: 重构文本搜索API结构 1. 创建新的基类TextSearchOptionsAPI和TextSearchResultAPI 2. 将ContentSearch和OcrTextSearch中的通用功能移至基类 3. 修改ContentOptionsAPI和OcrTextOptionsAPI继承自TextSearchOptionsAPI 4. 修改ContentResultAPI和OcrTextResultAPI继承自TextSearchResultAPI 5. 整合预览长度、高亮显示、文件属性和时间戳处理的重复代码 6. 更新实现文件以反映继承关系变化 这些改动通过以下方式改善了代码组织: 1. 消除了不同类型搜索间的重复代码 2. 为搜索API类创建了清晰的层次结构 3. 使得维护和扩展通用功能更加容易 4. 遵循DRY(不要重复自己)原则 5. 将默认预览长度从50字符增加到200字符 所有现有功能保持不变,仅改变了实现结构。 --- .../dfm-search/dfm-search/contentsearchapi.h | 152 +-------------- .../dfm-search/dfm-search/ocrtextsearchapi.h | 152 +-------------- include/dfm-search/dfm-search/textsearchapi.h | 183 ++++++++++++++++++ .../contentsearch/contentsearchapi.cpp | 109 +---------- .../ocrtextsearch/ocrtextsearchapi.cpp | 113 +---------- .../textsearch/textsearchapi.cpp | 117 +++++++++++ 6 files changed, 321 insertions(+), 505 deletions(-) create mode 100644 include/dfm-search/dfm-search/textsearchapi.h create mode 100644 src/dfm-search/dfm-search-lib/textsearch/textsearchapi.cpp diff --git a/include/dfm-search/dfm-search/contentsearchapi.h b/include/dfm-search/dfm-search/contentsearchapi.h index abb1414c..793f54a0 100644 --- a/include/dfm-search/dfm-search/contentsearchapi.h +++ b/include/dfm-search/dfm-search/contentsearchapi.h @@ -7,16 +7,16 @@ #include #include #include +#include DFM_SEARCH_BEGIN_NS /** * @brief The ContentOptionsAPI class provides content search specific options * - * This class extends the base SearchOptions with content search specific settings, - * such as file type filters and content preview length. + * This class extends TextSearchOptionsAPI with content search specific settings. */ -class ContentOptionsAPI +class ContentOptionsAPI : public TextSearchOptionsAPI { public: /** @@ -25,55 +25,6 @@ class ContentOptionsAPI */ explicit ContentOptionsAPI(SearchOptions &options); - /** - * @brief Set the maximum length for content preview - * @param length The maximum preview length in characters - */ - void setMaxPreviewLength(int length); - - /** - * @brief Get the maximum content preview length - * @return The maximum preview length in characters - */ - int maxPreviewLength() const; - - /** - * @brief Enables or disables HTML highlighting in search results. - * - * When enabled, matching keywords in search results will be wrapped in HTML tags - * (e.g., `keyword`) for visual highlighting. - * Note: Enabling this feature may incur additional processing overhead. - * - * @param enable Set to @c true to enable HTML highlighting, @c false to disable. - */ - void setSearchResultHighlightEnabled(bool enable); - - /** - * @brief Returns whether HTML highlighting in search results is enabled. - * - * @return @c true if search results will include HTML highlighting tags, - * @c false otherwise (plaintext results). - */ - bool isSearchResultHighlightEnabled() const; - - /** - * @brief Enables or disables full-text content retrieval in search results. - * - * When enable, search operations will return the complete file content along with metadata. - * This provides more detailed results but significantly increases memory usage and processing time. - * - * @param enable Set to @c true to retrieve full file contents, @c false to return metadata only. - */ - void setFullTextRetrievalEnabled(bool enable); - - /** - * @brief Checks if full-text content retrieval is enabled. - * - * @return @c true if search results will include complete file contents, - * @c false if only file metadata will be returned. - */ - bool isFullTextRetrievalEnabled() const; - /** * @brief Sets whether the extended AND search behavior across 'contents' and 'filename' fields is enabled. * @param enabled True to enable the feature, false to disable it. @@ -97,112 +48,23 @@ class ContentOptionsAPI * @return True if the filename-content mixed AND search is enabled, false otherwise. */ bool isFilenameContentMixedAndSearchEnabled() const; - -private: - SearchOptions &m_options; }; /** * @brief The ContentResultAPI class provides content search specific result handling * - * This class extends the base SearchResult with content search specific features, - * such as highlighted content preview. - * - * When detailed results are enabled, this API provides access to additional - * metadata including filename, hidden status, and time information. + * This class extends TextSearchResultAPI for content search results. */ -class ContentResultAPI +class ContentResultAPI : public TextSearchResultAPI { public: /** * @brief Constructor * @param result The SearchResult object to operate on */ - ContentResultAPI(SearchResult &result); - - // ==================== Content Attributes ==================== - - /** - * @brief Get the highlighted content preview - * @return The highlighted content as QString - */ - QString highlightedContent() const; - - /** - * @brief Set the highlighted content preview - * @param content The highlighted content to set - */ - void setHighlightedContent(const QString &content); - - // ==================== Extended Attributes ==================== - - /** - * @brief Get the file name (without path) - * @return The file name - */ - QString filename() const; - - /** - * @brief Set the file name - * @param name The file name to set - */ - void setFilename(const QString &name); - - /** - * @brief Check if the file is hidden - * @return true if the file is hidden, false otherwise - */ - bool isHidden() const; - - /** - * @brief Set whether the file is hidden - * @param hidden true if the file is hidden, false otherwise - */ - void setIsHidden(bool hidden); - - // ==================== Modification Time ==================== - - /** - * @brief Set the modification time timestamp - * @param timestamp Unix timestamp in seconds - */ - void setModifyTimestamp(qint64 timestamp); - - /** - * @brief Get the modification time timestamp - * @return Unix timestamp in seconds, 0 if not set - */ - qint64 modifyTimestamp() const; - - /** - * @brief Get the modification time as a formatted string - * @return Formatted time string (yyyy-MM-dd HH:mm:ss) - */ - QString modifyTimeString() const; - - // ==================== Birth/Creation Time ==================== - - /** - * @brief Set the birth/creation time timestamp - * @param timestamp Unix timestamp in seconds - */ - void setBirthTimestamp(qint64 timestamp); - - /** - * @brief Get the birth/creation time timestamp - * @return Unix timestamp in seconds, 0 if not set - */ - qint64 birthTimestamp() const; - - /** - * @brief Get the birth/creation time as a formatted string - * @return Formatted time string (yyyy-MM-dd HH:mm:ss) - */ - QString birthTimeString() const; - -private: - SearchResult &m_result; + explicit ContentResultAPI(SearchResult &result); }; + DFM_SEARCH_END_NS #endif // CONTENTSEARCHAPI_H diff --git a/include/dfm-search/dfm-search/ocrtextsearchapi.h b/include/dfm-search/dfm-search/ocrtextsearchapi.h index 7f14b6ed..51ef0207 100644 --- a/include/dfm-search/dfm-search/ocrtextsearchapi.h +++ b/include/dfm-search/dfm-search/ocrtextsearchapi.h @@ -7,15 +7,16 @@ #include #include #include +#include DFM_SEARCH_BEGIN_NS /** * @brief The OcrTextOptionsAPI class provides OCR text search specific options * - * This class extends the base SearchOptions with OCR text search specific settings. + * This class extends TextSearchOptionsAPI with OCR text search specific settings. */ -class OcrTextOptionsAPI +class OcrTextOptionsAPI : public TextSearchOptionsAPI { public: /** @@ -24,58 +25,6 @@ class OcrTextOptionsAPI */ explicit OcrTextOptionsAPI(SearchOptions &options); - // ==================== Preview and Highlight Settings ==================== - - /** - * @brief Sets the maximum length for content preview in search results. - * @param length The maximum preview length in characters. - */ - void setMaxPreviewLength(int length); - - /** - * @brief Gets the maximum length for content preview in search results. - * @return The maximum preview length in characters. - */ - int maxPreviewLength() const; - - /** - * @brief Enables or disables HTML highlighting in search results. - * - * When enabled, matching keywords in search results will be wrapped in HTML tags - * (e.g., `keyword`) for visual highlighting. - * Note: Enabling this feature may incur additional processing overhead. - * - * @param enable Set to @c true to enable HTML highlighting, @c false to disable. - */ - void setSearchResultHighlightEnabled(bool enable); - - /** - * @brief Returns whether HTML highlighting in search results is enabled. - * - * @return @c true if search results will include HTML highlighting tags, - * @c false otherwise (plaintext results). - */ - bool isSearchResultHighlightEnabled() const; - - /** - * @brief Enables or disables full-text content retrieval in search results. - * - * When enabled, search operations will return the complete OCR text content along with metadata. - * This provides more detailed results but significantly increases memory usage and processing time. - * - * @param enable Set to @c true to retrieve full OCR text contents, @c false to return metadata only. - */ - void setFullTextRetrievalEnabled(bool enable); - - /** - * @brief Returns whether full-text content retrieval is enabled. - * - * @return @c true if full-text content retrieval is enabled, @c false otherwise. - */ - bool isFullTextRetrievalEnabled() const; - - // ==================== Mixed Search Settings ==================== - /** * @brief Sets whether the extended AND search behavior across 'ocr_contents' and 'filename' fields is enabled. * @param enabled True to enable the feature, false to disable it. @@ -99,29 +48,21 @@ class OcrTextOptionsAPI * @return True if the filename-OCR content mixed AND search is enabled, false otherwise. */ bool isFilenameOcrContentMixedAndSearchEnabled() const; - -private: - SearchOptions &m_options; }; /** * @brief The OcrTextResultAPI class provides OCR text search specific result handling * - * This class extends the base SearchResult with OCR text search specific features. - * - * When detailed results are enabled, this API provides access to additional - * metadata including filename, hidden status, and time information. + * This class extends TextSearchResultAPI for OCR text search results. */ -class OcrTextResultAPI +class OcrTextResultAPI : public TextSearchResultAPI { public: /** * @brief Constructor * @param result The SearchResult object to operate on */ - OcrTextResultAPI(SearchResult &result); - - // ==================== OCR Content Attributes ==================== + explicit OcrTextResultAPI(SearchResult &result); /** * @brief Get the OCR extracted text content @@ -134,87 +75,6 @@ class OcrTextResultAPI * @param content The OCR extracted text to set */ void setOcrContent(const QString &content); - - /** - * @brief Get the highlighted OCR content preview - * @return The highlighted content as QString - */ - QString highlightedContent() const; - - /** - * @brief Set the highlighted OCR content preview - * @param content The highlighted content to set - */ - void setHighlightedContent(const QString &content); - - // ==================== Extended Attributes ==================== - - /** - * @brief Get the file name (without path) - * @return The file name - */ - QString filename() const; - - /** - * @brief Set the file name - * @param name The file name to set - */ - void setFilename(const QString &name); - - /** - * @brief Check if the file is hidden - * @return true if the file is hidden, false otherwise - */ - bool isHidden() const; - - /** - * @brief Set whether the file is hidden - * @param hidden true if the file is hidden, false otherwise - */ - void setIsHidden(bool hidden); - - // ==================== Modification Time ==================== - - /** - * @brief Set the modification time timestamp - * @param timestamp Unix timestamp in seconds - */ - void setModifyTimestamp(qint64 timestamp); - - /** - * @brief Get the modification time timestamp - * @return Unix timestamp in seconds, 0 if not set - */ - qint64 modifyTimestamp() const; - - /** - * @brief Get the modification time as a formatted string - * @return Formatted time string (yyyy-MM-dd HH:mm:ss) - */ - QString modifyTimeString() const; - - // ==================== Birth/Creation Time ==================== - - /** - * @brief Set the birth/creation time timestamp - * @param timestamp Unix timestamp in seconds - */ - void setBirthTimestamp(qint64 timestamp); - - /** - * @brief Get the birth/creation time timestamp - * @return Unix timestamp in seconds, 0 if not set - */ - qint64 birthTimestamp() const; - - /** - * @brief Get the birth/creation time as a formatted string - * @return Formatted time string (yyyy-MM-dd HH:mm:ss) - */ - QString birthTimeString() const; - -private: - SearchResult &m_result; }; DFM_SEARCH_END_NS diff --git a/include/dfm-search/dfm-search/textsearchapi.h b/include/dfm-search/dfm-search/textsearchapi.h new file mode 100644 index 00000000..3f52e8be --- /dev/null +++ b/include/dfm-search/dfm-search/textsearchapi.h @@ -0,0 +1,183 @@ +// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later +#ifndef TEXTSEARCHAPI_H +#define TEXTSEARCHAPI_H + +#include +#include +#include + +DFM_SEARCH_BEGIN_NS + +/** + * @brief The TextSearchOptionsAPI class provides common text search options + * + * This class serves as a base for content and OCR text search options, + * providing shared functionality for preview length, highlighting, and full-text retrieval. + */ +class TextSearchOptionsAPI +{ +public: + /** + * @brief Constructor + * @param options The SearchOptions object to operate on + */ + explicit TextSearchOptionsAPI(SearchOptions &options); + + // ==================== Preview and Highlight Settings ==================== + + /** + * @brief Sets the maximum length for content preview in search results. + * @param length The maximum preview length in characters. + */ + void setMaxPreviewLength(int length); + + /** + * @brief Gets the maximum length for content preview in search results. + * @return The maximum preview length in characters. + */ + int maxPreviewLength() const; + + /** + * @brief Enables or disables HTML highlighting in search results. + * + * When enabled, matching keywords in search results will be wrapped in HTML tags + * (e.g., `keyword`) for visual highlighting. + * Note: Enabling this feature may incur additional processing overhead. + * + * @param enable Set to @c true to enable HTML highlighting, @c false to disable. + */ + void setSearchResultHighlightEnabled(bool enable); + + /** + * @brief Returns whether HTML highlighting in search results is enabled. + * + * @return @c true if search results will include HTML highlighting tags, + * @c false otherwise (plaintext results). + */ + bool isSearchResultHighlightEnabled() const; + + /** + * @brief Enables or disables full-text content retrieval in search results. + * + * When enabled, search operations will return the complete text content along with metadata. + * This provides more detailed results but significantly increases memory usage and processing time. + * + * @param enable Set to @c true to retrieve full text contents, @c false to return metadata only. + */ + void setFullTextRetrievalEnabled(bool enable); + + /** + * @brief Returns whether full-text content retrieval is enabled. + * + * @return @c true if full-text content retrieval is enabled, @c false otherwise. + */ + bool isFullTextRetrievalEnabled() const; + +protected: + SearchOptions &m_options; +}; + +/** + * @brief The TextSearchResultAPI class provides common text search result handling + * + * This class serves as a base for content and OCR text search results, + * providing shared functionality for highlighted content and file metadata. + */ +class TextSearchResultAPI +{ +public: + /** + * @brief Constructor + * @param result The SearchResult object to operate on + */ + explicit TextSearchResultAPI(SearchResult &result); + + // ==================== Highlighted Content ==================== + + /** + * @brief Get the highlighted content preview + * @return The highlighted content as QString + */ + QString highlightedContent() const; + + /** + * @brief Set the highlighted content preview + * @param content The highlighted content to set + */ + void setHighlightedContent(const QString &content); + + // ==================== Extended Attributes ==================== + + /** + * @brief Get the file name (without path) + * @return The file name + */ + QString filename() const; + + /** + * @brief Set the file name + * @param name The file name to set + */ + void setFilename(const QString &name); + + /** + * @brief Check if the file is hidden + * @return true if the file is hidden, false otherwise + */ + bool isHidden() const; + + /** + * @brief Set whether the file is hidden + * @param hidden true if the file is hidden, false otherwise + */ + void setIsHidden(bool hidden); + + // ==================== Modification Time ==================== + + /** + * @brief Set the modification time timestamp + * @param timestamp Unix timestamp in seconds + */ + void setModifyTimestamp(qint64 timestamp); + + /** + * @brief Get the modification time timestamp + * @return Unix timestamp in seconds, 0 if not set + */ + qint64 modifyTimestamp() const; + + /** + * @brief Get the modification time as a formatted string + * @return Formatted time string (yyyy-MM-dd HH:mm:ss) + */ + QString modifyTimeString() const; + + // ==================== Birth/Creation Time ==================== + + /** + * @brief Set the birth/creation time timestamp + * @param timestamp Unix timestamp in seconds + */ + void setBirthTimestamp(qint64 timestamp); + + /** + * @brief Get the birth/creation time timestamp + * @return Unix timestamp in seconds, 0 if not set + */ + qint64 birthTimestamp() const; + + /** + * @brief Get the birth/creation time as a formatted string + * @return Formatted time string (yyyy-MM-dd HH:mm:ss) + */ + QString birthTimeString() const; + +protected: + SearchResult &m_result; +}; + +DFM_SEARCH_END_NS + +#endif // TEXTSEARCHAPI_H diff --git a/src/dfm-search/dfm-search-lib/contentsearch/contentsearchapi.cpp b/src/dfm-search/dfm-search-lib/contentsearch/contentsearchapi.cpp index 0be88fee..4d8e627f 100644 --- a/src/dfm-search/dfm-search-lib/contentsearch/contentsearchapi.cpp +++ b/src/dfm-search/dfm-search-lib/contentsearch/contentsearchapi.cpp @@ -2,54 +2,21 @@ // // SPDX-License-Identifier: GPL-3.0-or-later #include -#include - -#include DFM_SEARCH_BEGIN_NS ContentOptionsAPI::ContentOptionsAPI(SearchOptions &options) - : m_options(options) + : TextSearchOptionsAPI(options) { // init default if (!m_options.hasCustomOption("maxPreviewLength")) - setMaxPreviewLength(50); - if (!m_options.hasCustomOption("searchResultHighlight")) + setMaxPreviewLength(200); + if (!m_options.hasCustomOption("searchResultHighligh")) setSearchResultHighlightEnabled(false); if (!m_options.hasCustomOption("fullTextRetrieval")) setFullTextRetrievalEnabled(true); } -void ContentOptionsAPI::setMaxPreviewLength(int length) -{ - m_options.setCustomOption("maxPreviewLength", length); -} - -int ContentOptionsAPI::maxPreviewLength() const -{ - return m_options.customOption("maxPreviewLength").toInt(); -} - -void ContentOptionsAPI::setSearchResultHighlightEnabled(bool enable) -{ - m_options.setCustomOption("searchResultHighlight", enable); -} - -bool ContentOptionsAPI::isSearchResultHighlightEnabled() const -{ - return m_options.customOption("searchResultHighlight").toBool(); -} - -void ContentOptionsAPI::setFullTextRetrievalEnabled(bool enable) -{ - m_options.setCustomOption("fullTextRetrieval", enable); -} - -bool ContentOptionsAPI::isFullTextRetrievalEnabled() const -{ - return m_options.customOption("fullTextRetrieval").toBool(); -} - void ContentOptionsAPI::setFilenameContentMixedAndSearchEnabled(bool enabled) { m_options.setCustomOption("filenameContentMixedAndSearchEnabled", enabled); @@ -61,76 +28,8 @@ bool ContentOptionsAPI::isFilenameContentMixedAndSearchEnabled() const } ContentResultAPI::ContentResultAPI(SearchResult &result) - : m_result(result) -{ -} - -QString ContentResultAPI::highlightedContent() const -{ - return m_result.customAttribute("highlightedContent").toString(); -} - -void ContentResultAPI::setHighlightedContent(const QString &content) -{ - m_result.setCustomAttribute("highlightedContent", content); -} - -// ==================== Extended Attributes ==================== - -QString ContentResultAPI::filename() const -{ - return m_result.customAttribute("filename").toString(); -} - -void ContentResultAPI::setFilename(const QString &name) -{ - m_result.setCustomAttribute("filename", name); -} - -bool ContentResultAPI::isHidden() const -{ - return m_result.customAttribute("isHidden").toBool(); -} - -void ContentResultAPI::setIsHidden(bool hidden) -{ - m_result.setCustomAttribute("isHidden", hidden); -} - -// ==================== Modification Time ==================== - -void ContentResultAPI::setModifyTimestamp(qint64 timestamp) -{ - m_result.setCustomAttribute("modifyTimestamp", timestamp); -} - -qint64 ContentResultAPI::modifyTimestamp() const -{ - return m_result.customAttribute("modifyTimestamp").toLongLong(); -} - -QString ContentResultAPI::modifyTimeString() const -{ - qint64 ts = modifyTimestamp(); - return ts > 0 ? TimeResultAPI::formatTimestamp(ts) : QString(); -} - -// ==================== Birth/Creation Time ==================== - -void ContentResultAPI::setBirthTimestamp(qint64 timestamp) -{ - m_result.setCustomAttribute("birthTimestamp", timestamp); -} - -qint64 ContentResultAPI::birthTimestamp() const -{ - return m_result.customAttribute("birthTimestamp").toLongLong(); -} - -QString ContentResultAPI::birthTimeString() const + : TextSearchResultAPI(result) { - qint64 ts = birthTimestamp(); - return ts > 0 ? TimeResultAPI::formatTimestamp(ts) : QString(); } DFM_SEARCH_END_NS diff --git a/src/dfm-search/dfm-search-lib/ocrtextsearch/ocrtextsearchapi.cpp b/src/dfm-search/dfm-search-lib/ocrtextsearch/ocrtextsearchapi.cpp index f3f1a93f..8764e0c7 100644 --- a/src/dfm-search/dfm-search-lib/ocrtextsearch/ocrtextsearchapi.cpp +++ b/src/dfm-search/dfm-search-lib/ocrtextsearch/ocrtextsearchapi.cpp @@ -2,19 +2,16 @@ // // SPDX-License-Identifier: GPL-3.0-or-later #include -#include - -#include DFM_SEARCH_BEGIN_NS OcrTextOptionsAPI::OcrTextOptionsAPI(SearchOptions &options) - : m_options(options) + : TextSearchOptionsAPI(options) { // init default if (!m_options.hasCustomOption("maxPreviewLength")) - setMaxPreviewLength(50); - if (!m_options.hasCustomOption("searchResultHighlight")) + setMaxPreviewLength(200); + if (!m_options.hasCustomOption("searchResultHighligh")) setSearchResultHighlightEnabled(false); if (!m_options.hasCustomOption("fullTextRetrieval")) setFullTextRetrievalEnabled(true); @@ -22,40 +19,6 @@ OcrTextOptionsAPI::OcrTextOptionsAPI(SearchOptions &options) setFilenameOcrContentMixedAndSearchEnabled(false); } -// ==================== Preview and Highlight Settings ==================== - -void OcrTextOptionsAPI::setMaxPreviewLength(int length) -{ - m_options.setCustomOption("maxPreviewLength", length); -} - -int OcrTextOptionsAPI::maxPreviewLength() const -{ - return m_options.customOption("maxPreviewLength").toInt(); -} - -void OcrTextOptionsAPI::setSearchResultHighlightEnabled(bool enable) -{ - m_options.setCustomOption("searchResultHighlight", enable); -} - -bool OcrTextOptionsAPI::isSearchResultHighlightEnabled() const -{ - return m_options.customOption("searchResultHighlight").toBool(); -} - -void OcrTextOptionsAPI::setFullTextRetrievalEnabled(bool enable) -{ - m_options.setCustomOption("fullTextRetrieval", enable); -} - -bool OcrTextOptionsAPI::isFullTextRetrievalEnabled() const -{ - return m_options.customOption("fullTextRetrieval").toBool(); -} - -// ==================== Mixed Search Settings ==================== - void OcrTextOptionsAPI::setFilenameOcrContentMixedAndSearchEnabled(bool enabled) { m_options.setCustomOption("filenameOcrContentMixedAndSearchEnabled", enabled); @@ -67,7 +30,7 @@ bool OcrTextOptionsAPI::isFilenameOcrContentMixedAndSearchEnabled() const } OcrTextResultAPI::OcrTextResultAPI(SearchResult &result) - : m_result(result) + : TextSearchResultAPI(result) { } @@ -81,72 +44,4 @@ void OcrTextResultAPI::setOcrContent(const QString &content) m_result.setCustomAttribute("ocrContent", content); } -QString OcrTextResultAPI::highlightedContent() const -{ - return m_result.customAttribute("highlightedContent").toString(); -} - -void OcrTextResultAPI::setHighlightedContent(const QString &content) -{ - m_result.setCustomAttribute("highlightedContent", content); -} - -// ==================== Extended Attributes ==================== - -QString OcrTextResultAPI::filename() const -{ - return m_result.customAttribute("filename").toString(); -} - -void OcrTextResultAPI::setFilename(const QString &name) -{ - m_result.setCustomAttribute("filename", name); -} - -bool OcrTextResultAPI::isHidden() const -{ - return m_result.customAttribute("isHidden").toBool(); -} - -void OcrTextResultAPI::setIsHidden(bool hidden) -{ - m_result.setCustomAttribute("isHidden", hidden); -} - -// ==================== Modification Time ==================== - -void OcrTextResultAPI::setModifyTimestamp(qint64 timestamp) -{ - m_result.setCustomAttribute("modifyTimestamp", timestamp); -} - -qint64 OcrTextResultAPI::modifyTimestamp() const -{ - return m_result.customAttribute("modifyTimestamp").toLongLong(); -} - -QString OcrTextResultAPI::modifyTimeString() const -{ - qint64 ts = modifyTimestamp(); - return ts > 0 ? TimeResultAPI::formatTimestamp(ts) : QString(); -} - -// ==================== Birth/Creation Time ==================== - -void OcrTextResultAPI::setBirthTimestamp(qint64 timestamp) -{ - m_result.setCustomAttribute("birthTimestamp", timestamp); -} - -qint64 OcrTextResultAPI::birthTimestamp() const -{ - return m_result.customAttribute("birthTimestamp").toLongLong(); -} - -QString OcrTextResultAPI::birthTimeString() const -{ - qint64 ts = birthTimestamp(); - return ts > 0 ? TimeResultAPI::formatTimestamp(ts) : QString(); -} - DFM_SEARCH_END_NS diff --git a/src/dfm-search/dfm-search-lib/textsearch/textsearchapi.cpp b/src/dfm-search/dfm-search-lib/textsearch/textsearchapi.cpp new file mode 100644 index 00000000..d00f77e5 --- /dev/null +++ b/src/dfm-search/dfm-search-lib/textsearch/textsearchapi.cpp @@ -0,0 +1,117 @@ +// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later +#include +#include + +#include + +DFM_SEARCH_BEGIN_NS + +// ==================== TextSearchOptionsAPI ==================== + +TextSearchOptionsAPI::TextSearchOptionsAPI(SearchOptions &options) + : m_options(options) +{ +} + +void TextSearchOptionsAPI::setMaxPreviewLength(int length) +{ + m_options.setCustomOption("maxPreviewLength", length); +} + +int TextSearchOptionsAPI::maxPreviewLength() const +{ + return m_options.customOption("maxPreviewLength").toInt(); +} + +void TextSearchOptionsAPI::setSearchResultHighlightEnabled(bool enable) +{ + m_options.setCustomOption("searchResultHighligh", enable); +} + +bool TextSearchOptionsAPI::isSearchResultHighlightEnabled() const +{ + return m_options.customOption("searchResultHighligh").toBool(); +} + +void TextSearchOptionsAPI::setFullTextRetrievalEnabled(bool enable) +{ + m_options.setCustomOption("fullTextRetrieval", enable); +} + +bool TextSearchOptionsAPI::isFullTextRetrievalEnabled() const +{ + return m_options.customOption("fullTextRetrieval").toBool(); +} + +// ==================== TextSearchResultAPI ==================== + +TextSearchResultAPI::TextSearchResultAPI(SearchResult &result) + : m_result(result) +{ +} + +QString TextSearchResultAPI::highlightedContent() const +{ + return m_result.customAttribute("highlightedContent").toString(); +} + +void TextSearchResultAPI::setHighlightedContent(const QString &content) +{ + m_result.setCustomAttribute("highlightedContent", content); +} + +QString TextSearchResultAPI::filename() const +{ + return m_result.customAttribute("filename").toString(); +} + +void TextSearchResultAPI::setFilename(const QString &name) +{ + m_result.setCustomAttribute("filename", name); +} + +bool TextSearchResultAPI::isHidden() const +{ + return m_result.customAttribute("isHidden").toBool(); +} + +void TextSearchResultAPI::setIsHidden(bool hidden) +{ + m_result.setCustomAttribute("isHidden", hidden); +} + +void TextSearchResultAPI::setModifyTimestamp(qint64 timestamp) +{ + m_result.setCustomAttribute("modifyTimestamp", timestamp); +} + +qint64 TextSearchResultAPI::modifyTimestamp() const +{ + return m_result.customAttribute("modifyTimestamp").toLongLong(); +} + +QString TextSearchResultAPI::modifyTimeString() const +{ + qint64 ts = modifyTimestamp(); + return ts > 0 ? TimeResultAPI::formatTimestamp(ts) : QString(); +} + +void TextSearchResultAPI::setBirthTimestamp(qint64 timestamp) +{ + m_result.setCustomAttribute("birthTimestamp", timestamp); +} + +qint64 TextSearchResultAPI::birthTimestamp() const +{ + return m_result.customAttribute("birthTimestamp").toLongLong(); +} + +QString TextSearchResultAPI::birthTimeString() const +{ + qint64 ts = birthTimestamp(); + return ts > 0 ? TimeResultAPI::formatTimestamp(ts) : QString(); +} + +DFM_SEARCH_END_NS From eba837a3dde3b16215bac5c83124f5877939711f Mon Sep 17 00:00:00 2001 From: Zhang Sheng Date: Thu, 23 Apr 2026 11:03:19 +0800 Subject: [PATCH 3/3] test: add TextSearchAPI test to test runner MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Moved test object creation function declarations to file scope for better organization Added TextSearchAPI test suite to the main test runner Previously only DfmSearch, SearchUtils and TimeRangeFilter tests were executed Now TextSearchAPI tests will also be run as part of the test suite This ensures comprehensive testing coverage for all search-related components The change maintains backward compatibility while extending the test coverage Influence: 1. Verify all existing tests still pass 2. Check TextSearchAPI tests are executed and report results correctly 3. Ensure test suite exits with correct status code 4. Confirm no memory leaks from test object creation/deletion test: 在测试运行器中添加 TextSearchAPI 测试 将测试对象创建函数声明移至文件作用域以便更好组织 在主要测试运行器中添加了 TextSearchAPI 测试套件 之前仅执行了 DfmSearch、SearchUtils 和 TimeRangeFilter 测试 现在 TextSearchAPI 测试也将作为测试套件的一部分运行 此变更确保了对所有搜索相关组件的全面测试覆盖 该变更在保持向后兼容的同时扩展了测试范围 Influence: 1. 验证所有现有测试仍能通过 2. 检查 TextSearchAPI 测试是否被执行并正确报告结果 3. 确保测试套件以正确的状态码退出 4. 确认测试对象创建/删除不会导致内存泄漏 --- autotests/dfm-search-tests/main.cpp | 15 +- .../dfm-search-tests/tst_textsearch_api.cpp | 330 ++++++++++++++++++ .../contentsearch/contentsearchapi.cpp | 2 +- .../ocrtextsearch/ocrtextsearchapi.cpp | 2 +- .../textsearch/textsearchapi.cpp | 4 +- 5 files changed, 344 insertions(+), 9 deletions(-) create mode 100644 autotests/dfm-search-tests/tst_textsearch_api.cpp diff --git a/autotests/dfm-search-tests/main.cpp b/autotests/dfm-search-tests/main.cpp index 2728f95a..59a2f42e 100644 --- a/autotests/dfm-search-tests/main.cpp +++ b/autotests/dfm-search-tests/main.cpp @@ -4,15 +4,16 @@ #include +// Test object creation functions are defined in their respective .cpp files +extern QObject *create_tst_DfmSearch(); +extern QObject *create_tst_SearchUtils(); +extern QObject *create_tst_TimeRangeFilter(); +extern QObject *create_tst_TextSearchAPI(); + int main(int argc, char *argv[]) { int result = 0; - // Test object creation functions are defined in their respective .cpp files - extern QObject *create_tst_DfmSearch(); - extern QObject *create_tst_SearchUtils(); - extern QObject *create_tst_TimeRangeFilter(); - // Run all test objects QObject *testObj1 = create_tst_DfmSearch(); result |= QTest::qExec(testObj1, argc, argv); @@ -26,5 +27,9 @@ int main(int argc, char *argv[]) result |= QTest::qExec(testObj3, argc, argv); delete testObj3; + QObject *testObj4 = create_tst_TextSearchAPI(); + result |= QTest::qExec(testObj4, argc, argv); + delete testObj4; + return result; } diff --git a/autotests/dfm-search-tests/tst_textsearch_api.cpp b/autotests/dfm-search-tests/tst_textsearch_api.cpp new file mode 100644 index 00000000..92dec9e9 --- /dev/null +++ b/autotests/dfm-search-tests/tst_textsearch_api.cpp @@ -0,0 +1,330 @@ +// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include +#include +#include +#include +#include +#include + +using namespace DFMSEARCH; + +class tst_TextSearchAPI : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + + // TextSearchOptionsAPI tests + void textSearchOptions_defaultValues(); + void textSearchOptions_setMaxPreviewLength(); + void textSearchOptions_setSearchResultHighlightEnabled(); + void textSearchOptions_setFullTextRetrievalEnabled(); + + // TextSearchResultAPI tests + void textSearchResult_highlightedContent(); + void textSearchResult_filename(); + void textSearchResult_isHidden(); + void textSearchResult_modifyTimestamp(); + void textSearchResult_birthTimestamp(); + + // ContentOptionsAPI tests + void contentOptions_inheritance(); + void contentOptions_setFilenameContentMixedAndSearchEnabled(); + + // ContentResultAPI tests + void contentResult_inheritance(); + + // OcrTextOptionsAPI tests + void ocrTextOptions_inheritance(); + void ocrTextOptions_defaultValues(); + void ocrTextOptions_setFilenameOcrContentMixedAndSearchEnabled(); + + // OcrTextResultAPI tests + void ocrTextResult_inheritance(); + void ocrTextResult_ocrContent(); +}; + +void tst_TextSearchAPI::initTestCase() +{ +} + +void tst_TextSearchAPI::cleanupTestCase() +{ +} + +// ==================== TextSearchOptionsAPI Tests ==================== + +void tst_TextSearchAPI::textSearchOptions_defaultValues() +{ + SearchOptions options; + TextSearchOptionsAPI api(options); + + // 默认值在构造函数中设置,但基类构造函数不设置默认值 + // 默认值由子类设置 + QCOMPARE(api.maxPreviewLength(), 0); + QCOMPARE(api.isSearchResultHighlightEnabled(), false); + QCOMPARE(api.isFullTextRetrievalEnabled(), false); +} + +void tst_TextSearchAPI::textSearchOptions_setMaxPreviewLength() +{ + SearchOptions options; + TextSearchOptionsAPI api(options); + + api.setMaxPreviewLength(100); + QCOMPARE(api.maxPreviewLength(), 100); + + api.setMaxPreviewLength(500); + QCOMPARE(api.maxPreviewLength(), 500); + + api.setMaxPreviewLength(0); + QCOMPARE(api.maxPreviewLength(), 0); +} + +void tst_TextSearchAPI::textSearchOptions_setSearchResultHighlightEnabled() +{ + SearchOptions options; + TextSearchOptionsAPI api(options); + + api.setSearchResultHighlightEnabled(true); + QCOMPARE(api.isSearchResultHighlightEnabled(), true); + + api.setSearchResultHighlightEnabled(false); + QCOMPARE(api.isSearchResultHighlightEnabled(), false); +} + +void tst_TextSearchAPI::textSearchOptions_setFullTextRetrievalEnabled() +{ + SearchOptions options; + TextSearchOptionsAPI api(options); + + api.setFullTextRetrievalEnabled(true); + QCOMPARE(api.isFullTextRetrievalEnabled(), true); + + api.setFullTextRetrievalEnabled(false); + QCOMPARE(api.isFullTextRetrievalEnabled(), false); +} + +// ==================== TextSearchResultAPI Tests ==================== + +void tst_TextSearchAPI::textSearchResult_highlightedContent() +{ + SearchResult result("/test/path"); + TextSearchResultAPI api(result); + + QVERIFY(api.highlightedContent().isEmpty()); + + api.setHighlightedContent("test highlighted content"); + QCOMPARE(api.highlightedContent(), QString("test highlighted content")); + + api.setHighlightedContent(""); + QVERIFY(api.highlightedContent().isEmpty()); +} + +void tst_TextSearchAPI::textSearchResult_filename() +{ + SearchResult result("/test/path"); + TextSearchResultAPI api(result); + + QVERIFY(api.filename().isEmpty()); + + api.setFilename("test.txt"); + QCOMPARE(api.filename(), QString("test.txt")); + + api.setFilename(""); + QVERIFY(api.filename().isEmpty()); +} + +void tst_TextSearchAPI::textSearchResult_isHidden() +{ + SearchResult result("/test/path"); + TextSearchResultAPI api(result); + + QCOMPARE(api.isHidden(), false); + + api.setIsHidden(true); + QCOMPARE(api.isHidden(), true); + + api.setIsHidden(false); + QCOMPARE(api.isHidden(), false); +} + +void tst_TextSearchAPI::textSearchResult_modifyTimestamp() +{ + SearchResult result("/test/path"); + TextSearchResultAPI api(result); + + QCOMPARE(api.modifyTimestamp(), 0); + + api.setModifyTimestamp(1700000000); + QCOMPARE(api.modifyTimestamp(), 1700000000); + QVERIFY(!api.modifyTimeString().isEmpty()); + + api.setModifyTimestamp(0); + QCOMPARE(api.modifyTimestamp(), 0); +} + +void tst_TextSearchAPI::textSearchResult_birthTimestamp() +{ + SearchResult result("/test/path"); + TextSearchResultAPI api(result); + + QCOMPARE(api.birthTimestamp(), 0); + + api.setBirthTimestamp(1600000000); + QCOMPARE(api.birthTimestamp(), 1600000000); + QVERIFY(!api.birthTimeString().isEmpty()); + + api.setBirthTimestamp(0); + QCOMPARE(api.birthTimestamp(), 0); +} + +// ==================== ContentOptionsAPI Tests ==================== + +void tst_TextSearchAPI::contentOptions_inheritance() +{ + SearchOptions options; + ContentOptionsAPI api(options); + + // 验证继承自 TextSearchOptionsAPI + api.setMaxPreviewLength(300); + QCOMPARE(api.maxPreviewLength(), 300); + + api.setSearchResultHighlightEnabled(true); + QCOMPARE(api.isSearchResultHighlightEnabled(), true); + + api.setFullTextRetrievalEnabled(false); + QCOMPARE(api.isFullTextRetrievalEnabled(), false); +} + +void tst_TextSearchAPI::contentOptions_setFilenameContentMixedAndSearchEnabled() +{ + SearchOptions options; + ContentOptionsAPI api(options); + + QCOMPARE(api.isFilenameContentMixedAndSearchEnabled(), false); + + api.setFilenameContentMixedAndSearchEnabled(true); + QCOMPARE(api.isFilenameContentMixedAndSearchEnabled(), true); + + api.setFilenameContentMixedAndSearchEnabled(false); + QCOMPARE(api.isFilenameContentMixedAndSearchEnabled(), false); +} + +// ==================== ContentResultAPI Tests ==================== + +void tst_TextSearchAPI::contentResult_inheritance() +{ + SearchResult result("/test/path"); + ContentResultAPI api(result); + + // 验证继承自 TextSearchResultAPI + api.setHighlightedContent("content match"); + QCOMPARE(api.highlightedContent(), QString("content match")); + + api.setFilename("document.pdf"); + QCOMPARE(api.filename(), QString("document.pdf")); + + api.setIsHidden(true); + QCOMPARE(api.isHidden(), true); + + api.setModifyTimestamp(1700000000); + QCOMPARE(api.modifyTimestamp(), 1700000000); + + api.setBirthTimestamp(1600000000); + QCOMPARE(api.birthTimestamp(), 1600000000); +} + +// ==================== OcrTextOptionsAPI Tests ==================== + +void tst_TextSearchAPI::ocrTextOptions_inheritance() +{ + SearchOptions options; + OcrTextOptionsAPI api(options); + + // 验证继承自 TextSearchOptionsAPI + api.setMaxPreviewLength(250); + QCOMPARE(api.maxPreviewLength(), 250); + + api.setSearchResultHighlightEnabled(true); + QCOMPARE(api.isSearchResultHighlightEnabled(), true); + + api.setFullTextRetrievalEnabled(false); + QCOMPARE(api.isFullTextRetrievalEnabled(), false); +} + +void tst_TextSearchAPI::ocrTextOptions_defaultValues() +{ + SearchOptions options; + OcrTextOptionsAPI api(options); + + // 验证默认值 + QCOMPARE(api.maxPreviewLength(), 200); + QCOMPARE(api.isSearchResultHighlightEnabled(), false); + QCOMPARE(api.isFullTextRetrievalEnabled(), true); + QCOMPARE(api.isFilenameOcrContentMixedAndSearchEnabled(), false); +} + +void tst_TextSearchAPI::ocrTextOptions_setFilenameOcrContentMixedAndSearchEnabled() +{ + SearchOptions options; + OcrTextOptionsAPI api(options); + + QCOMPARE(api.isFilenameOcrContentMixedAndSearchEnabled(), false); + + api.setFilenameOcrContentMixedAndSearchEnabled(true); + QCOMPARE(api.isFilenameOcrContentMixedAndSearchEnabled(), true); + + api.setFilenameOcrContentMixedAndSearchEnabled(false); + QCOMPARE(api.isFilenameOcrContentMixedAndSearchEnabled(), false); +} + +// ==================== OcrTextResultAPI Tests ==================== + +void tst_TextSearchAPI::ocrTextResult_inheritance() +{ + SearchResult result("/test/path"); + OcrTextResultAPI api(result); + + // 验证继承自 TextSearchResultAPI + api.setHighlightedContent("OCR match"); + QCOMPARE(api.highlightedContent(), QString("OCR match")); + + api.setFilename("image.png"); + QCOMPARE(api.filename(), QString("image.png")); + + api.setIsHidden(true); + QCOMPARE(api.isHidden(), true); + + api.setModifyTimestamp(1700000000); + QCOMPARE(api.modifyTimestamp(), 1700000000); + + api.setBirthTimestamp(1600000000); + QCOMPARE(api.birthTimestamp(), 1600000000); +} + +void tst_TextSearchAPI::ocrTextResult_ocrContent() +{ + SearchResult result("/test/path"); + OcrTextResultAPI api(result); + + QVERIFY(api.ocrContent().isEmpty()); + + api.setOcrContent("This is extracted OCR text from image"); + QCOMPARE(api.ocrContent(), QString("This is extracted OCR text from image")); + + api.setOcrContent(""); + QVERIFY(api.ocrContent().isEmpty()); +} + +QObject *create_tst_TextSearchAPI() +{ + return new tst_TextSearchAPI(); +} + +#include "tst_textsearch_api.moc" diff --git a/src/dfm-search/dfm-search-lib/contentsearch/contentsearchapi.cpp b/src/dfm-search/dfm-search-lib/contentsearch/contentsearchapi.cpp index 4d8e627f..8e8d340f 100644 --- a/src/dfm-search/dfm-search-lib/contentsearch/contentsearchapi.cpp +++ b/src/dfm-search/dfm-search-lib/contentsearch/contentsearchapi.cpp @@ -11,7 +11,7 @@ ContentOptionsAPI::ContentOptionsAPI(SearchOptions &options) // init default if (!m_options.hasCustomOption("maxPreviewLength")) setMaxPreviewLength(200); - if (!m_options.hasCustomOption("searchResultHighligh")) + if (!m_options.hasCustomOption("searchResultHighlight")) setSearchResultHighlightEnabled(false); if (!m_options.hasCustomOption("fullTextRetrieval")) setFullTextRetrievalEnabled(true); diff --git a/src/dfm-search/dfm-search-lib/ocrtextsearch/ocrtextsearchapi.cpp b/src/dfm-search/dfm-search-lib/ocrtextsearch/ocrtextsearchapi.cpp index 8764e0c7..30e3f8c8 100644 --- a/src/dfm-search/dfm-search-lib/ocrtextsearch/ocrtextsearchapi.cpp +++ b/src/dfm-search/dfm-search-lib/ocrtextsearch/ocrtextsearchapi.cpp @@ -11,7 +11,7 @@ OcrTextOptionsAPI::OcrTextOptionsAPI(SearchOptions &options) // init default if (!m_options.hasCustomOption("maxPreviewLength")) setMaxPreviewLength(200); - if (!m_options.hasCustomOption("searchResultHighligh")) + if (!m_options.hasCustomOption("searchResultHighlight")) setSearchResultHighlightEnabled(false); if (!m_options.hasCustomOption("fullTextRetrieval")) setFullTextRetrievalEnabled(true); diff --git a/src/dfm-search/dfm-search-lib/textsearch/textsearchapi.cpp b/src/dfm-search/dfm-search-lib/textsearch/textsearchapi.cpp index d00f77e5..e2182d9f 100644 --- a/src/dfm-search/dfm-search-lib/textsearch/textsearchapi.cpp +++ b/src/dfm-search/dfm-search-lib/textsearch/textsearchapi.cpp @@ -27,12 +27,12 @@ int TextSearchOptionsAPI::maxPreviewLength() const void TextSearchOptionsAPI::setSearchResultHighlightEnabled(bool enable) { - m_options.setCustomOption("searchResultHighligh", enable); + m_options.setCustomOption("searchResultHighlight", enable); } bool TextSearchOptionsAPI::isSearchResultHighlightEnabled() const { - return m_options.customOption("searchResultHighligh").toBool(); + return m_options.customOption("searchResultHighlight").toBool(); } void TextSearchOptionsAPI::setFullTextRetrievalEnabled(bool enable)