Skip to content

feat: Added search priority display.#591

Merged
deepin-bot[bot] merged 1 commit intolinuxdeepin:masterfrom
wjyrich:feat-addSearch-advance
Jul 4, 2025
Merged

feat: Added search priority display.#591
deepin-bot[bot] merged 1 commit intolinuxdeepin:masterfrom
wjyrich:feat-addSearch-advance

Conversation

@wjyrich
Copy link
Contributor

@wjyrich wjyrich commented Jul 3, 2025

as title.

pms:task-377379

Summary by Sourcery

Implement priority-based search display by calculating and caching a relevance weight per item and sorting results by weight then launch times.

New Features:

  • Sort search results by a computed priority weight to surface the most relevant items first.

Enhancements:

  • Override SearchFilterProxyModel::lessThan to rank items by match weight and launch frequency.
  • Introduce calculateMatchWeight to compute relevance based on name, transliteration, abbreviation, and match position.
  • Cache computed weights in m_weightCache and clear it when the search pattern changes.

@deepin-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: wjyrich

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@sourcery-ai
Copy link

sourcery-ai bot commented Jul 3, 2025

Reviewer's Guide

This PR replaces the previous boolean matching in the proxy model with a weight-based ranking: it computes a detailed match weight for each item (via a new calculateMatchWeight method), caches these weights, and overrides lessThan to sort by weight then launch frequency, while falling back to the base sort.

Class diagram for updated SearchFilterProxyModel with weight-based ranking

classDiagram
    class QSortFilterProxyModel {
        <<Qt Base>>
        +filterAcceptsRow(int, QModelIndex) : bool
        +lessThan(QModelIndex, QModelIndex) : bool
    }
    class SearchFilterProxyModel {
        +filterAcceptsRow(int, QModelIndex) : bool
        +lessThan(QModelIndex, QModelIndex) : bool
        -calculateMatchWeight(QString, QString, QString, QString, QString, QString) : int
        -m_weightCache : QHash<QPersistentModelIndex, int>
    }
    QSortFilterProxyModel <|-- SearchFilterProxyModel
Loading

Flow diagram for search filtering and ranking process

flowchart TD
    A[User enters search query] --> B[SearchFilterProxyModel::filterAcceptsRow]
    B --> C[calculateMatchWeight]
    C --> D{Weight > 0?}
    D -- Yes --> E[Item accepted]
    D -- No --> F[Item filtered out]
    E & F --> G[Weights cached in m_weightCache]
    G --> H[SearchFilterProxyModel::lessThan]
    H --> I[Sort by weight desc]
    I --> J[If tie, sort by launch count]
    J --> K[If still tie, fallback to base sort]
Loading

File-Level Changes

Change Details Files
Refactor filterAcceptsRow to use weight caching
  • Clear m_weightCache when the search pattern changes
  • Compute weight via calculateMatchWeight instead of ad-hoc conditionals
  • Store weight in m_weightCache using QPersistentModelIndex
  • Return weight > 0 as the match result
src/models/searchfilterproxymodel.cpp
Introduce calculateMatchWeight with detailed ranking rules
  • Add calculateMatchWeight method that assigns tiered weights for exact, prefix, and contains matches across displayName, targetName, transliteration, jianpin, and initials
  • Enhance regexes to handle hyphens, dots, and uppercase word sequences
  • Apply special case to reduce weight for purely English application names
src/models/searchfilterproxymodel.cpp
src/models/searchfilterproxymodel.h
Override lessThan to sort by weight and launch count
  • Add lessThan override that retrieves weights from m_weightCache and sorts in descending order
  • For equal weights, compare AppItem::LaunchedTimesRole so frequently used apps appear first
  • Fallback to QSortFilterProxyModel::lessThan when both weight and launch count are equal
src/models/searchfilterproxymodel.cpp
src/models/searchfilterproxymodel.h
Remove old numeric and English matching branches
  • Eliminate legacy isNumberSearch logic and manual prefix scans
  • Strip out previous English prefix/contains blocks in filterAcceptsRow
  • Simplify include directives by removing unused headers and adding
src/models/searchfilterproxymodel.cpp

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @wjyrich - I've reviewed your changes and they look great!

Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments

### Comment 1
<location> `src/models/searchfilterproxymodel.cpp:28` </location>
<code_context>
     const QRegularExpression searchPattern = this->filterRegularExpression();

+    // 如果是新的搜索,清理权重缓存
+    static QString lastSearchPattern;
+    if (lastSearchPattern != searchPattern.pattern()) {
+        m_weightCache.clear();
+        lastSearchPattern = searchPattern.pattern();
</code_context>

<issue_to_address>
Use of static variable for lastSearchPattern may cause issues in multi-instance scenarios.

A static lastSearchPattern will be shared across all SearchFilterProxyModel instances, which can cause incorrect cache clearing. Make it an instance member to avoid this issue.
</issue_to_address>

### Comment 2
<location> `src/models/searchfilterproxymodel.cpp:90` </location>
<code_context>
+    QPersistentModelIndex leftPersistent(source_left);
+    QPersistentModelIndex rightPersistent(source_right);
+
+    int leftWeight = m_weightCache.value(leftPersistent, 0);
+    int rightWeight = m_weightCache.value(rightPersistent, 0);
+
+
</code_context>

<issue_to_address>
Defaulting to weight 0 for missing cache entries may cause inconsistent sorting.

Assigning a default weight of 0 for missing cache entries can lead to incorrect ordering. Make sure the cache is complete for all indices or recalculate weights when missing.
</issue_to_address>

### Comment 3
<location> `src/models/searchfilterproxymodel.cpp:66` </location>
<code_context>
+    }
+
+    // 处理英文搜索的特殊情况
+    QRegularExpression searchEnglishCheck("^[a-zA-Z0-9\\s\\-\\.]+$");
+    bool isEnglishSearch = searchEnglishCheck.match(searchPattern).hasMatch();
+
+    if (isEnglishSearch) {
</code_context>

<issue_to_address>
Redundant redefinition of searchEnglishCheck regular expression.

Please reuse the existing searchEnglishCheck definition or move it to a shared scope within the function to avoid redundancy.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +28 to +29
static QString lastSearchPattern;
if (lastSearchPattern != searchPattern.pattern()) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Use of static variable for lastSearchPattern may cause issues in multi-instance scenarios.

A static lastSearchPattern will be shared across all SearchFilterProxyModel instances, which can cause incorrect cache clearing. Make it an instance member to avoid this issue.

Comment on lines +90 to +91
int leftWeight = m_weightCache.value(leftPersistent, 0);
int rightWeight = m_weightCache.value(rightPersistent, 0);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Defaulting to weight 0 for missing cache entries may cause inconsistent sorting.

Assigning a default weight of 0 for missing cache entries can lead to incorrect ordering. Make sure the cache is complete for all indices or recalculate weights when missing.

Comment on lines +66 to +75
QRegularExpression searchEnglishCheck("^[a-zA-Z0-9\\s\\-\\.]+$");
bool isEnglishSearch = searchEnglishCheck.match(searchPattern.pattern()).hasMatch();

QRegularExpression searchHasLetterCheck("[a-zA-Z]");
bool hasLetter = searchHasLetterCheck.match(searchPattern.pattern()).hasMatch();

if (isNumberSearch || isEnglishSearch) {
bool hasMatch = false;
// Handle number prefix matching eg: 360zip
if (isNumberSearch) {
QRegularExpression numberRegex("\\d+");
QRegularExpressionMatchIterator matches = numberRegex.globalMatch(targetName);

while (matches.hasNext()) {
QRegularExpressionMatch match = matches.next();
QString numberInDisplayName = match.captured(0);
hasMatch = true;
if (numberInDisplayName.startsWith(searchPatternDelBlank)) {
return true;
}
// 计算匹配权重并存储到缓存
int weight = calculateMatchWeight(searchPatternDelBlank, displayName, targetName,
transliterated, jianpin, nameFirstLetters);

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: Redundant redefinition of searchEnglishCheck regular expression.

Please reuse the existing searchEnglishCheck definition or move it to a shared scope within the function to avoid redundancy.

@wjyrich wjyrich force-pushed the feat-addSearch-advance branch from fe2404c to 2e04686 Compare July 3, 2025 08:45
@deepin-bot
Copy link

deepin-bot bot commented Jul 3, 2025

TAG Bot

New tag: 2.0.2
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #592

QString nameFirstLettersLower = nameFirstLetters.toLower();

// 使用 QMap 存储权重计算函数,QString 表示匹配类型
QMap<QString, std::function<int()>> weightCalculators;
Copy link
Contributor

@18202781743 18202781743 Jul 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image
可以类似这样,这样可以按权重进行优化,从权重最高的开始执行,
是不是可以不用数字了,

@wjyrich wjyrich force-pushed the feat-addSearch-advance branch from 2e04686 to e926bfe Compare July 4, 2025 02:30
@deepin-ci-robot
Copy link

deepin pr auto review

关键摘要:

  • calculateWeight 函数中使用了 QVector 来存储匹配类型和对应的函数,提高了代码的可读性和可维护性。
  • lessThan 函数中,对索引值和启动次数进行了比较,确保了排序的正确性。
  • 代码中增加了对英文搜索的特殊处理,提高了搜索的准确性。

是否建议立即修改:

  • 否,提交的代码已经实现了预期的功能,并且没有明显的语法或逻辑错误。但是,可以考虑以下几点来进一步优化代码:
    • calculateWeight 函数中,可以添加注释来解释每个匹配类型的权重计算逻辑,以便其他开发者更好地理解代码。
    • 可以考虑将 calculateWeight 函数中的正则表达式匹配逻辑提取出来,作为一个独立的函数,以提高代码的复用性。
    • lessThan 函数中,可以添加注释来解释排序逻辑,以便其他开发者更好地理解代码。
    • 可以考虑对 calculateWeight 函数中的匹配类型进行排序,以确保匹配的优先级是正确的。

if (hasMatch && isNumberSearch) {
return false;
// 对于以英文单词开头的应用名,在英文搜索时降低优先级(增加索引值)
if (isEnglishSearch && matchIndex < 10) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个10有什么含义么,

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

保证英文名在开头的匹配的时候, 能够让他优先级靠后 。小于10是防止在最后索引在匹配英语的时候 他的优先级发生变化

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

那为啥不是8?

if (isEnglishSearch && matchIndex < 10) {
QRegularExpression startsWithEnglishCheck("^[a-zA-Z][a-zA-Z0-9]*");
if (startsWithEnglishCheck.match(displayName).hasMatch()) {
matchIndex += 1; // 增加索引值来降低优先级
Copy link
Contributor

@18202781743 18202781743 Jul 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个条件能不能合入到一个条件,变成一个组合条件,可以来依赖其它的子条件的,

}));

// 计算匹配索引(索引越小优先级越高)
int matchIndex = -1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这种遍历的逻辑,可以改成使用标准库里的函数,


#include <QDebug>
#include <DPinyin>
#include <cmath>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这种头文件应该不需要,

int matchIndex = calculateWeight(modelIndex);

// 如果索引为0,表示不匹配
return matchIndex > 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

第一个的index就是0,

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

下面计算的时候,返回的索引+1

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1是为了这个让0无效?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

是的

@wjyrich wjyrich force-pushed the feat-addSearch-advance branch 2 times, most recently from f7738fa to 672c396 Compare July 4, 2025 05:43
as title.

pms:task-377379
@wjyrich wjyrich force-pushed the feat-addSearch-advance branch from 672c396 to cb77de7 Compare July 4, 2025 05:56

const int matchIndex = std::distance(matchTypes.begin(), it);

// 返回索引值+1,确保返回值大于0(0表示不匹配)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

注释没删除,

@wjyrich
Copy link
Contributor Author

wjyrich commented Jul 4, 2025

/forcemerge

@deepin-bot
Copy link

deepin-bot bot commented Jul 4, 2025

This pr force merged! (status: behind)

@deepin-bot deepin-bot bot merged commit 61fb89f into linuxdeepin:master Jul 4, 2025
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants