fix: support scaling for local file icons#568
fix: support scaling for local file icons#568qxp930712 wants to merge 1 commit intolinuxdeepin:masterfrom
Conversation
Reviewer's GuideAdds explicit handling and high-DPI scaling for local PNG icon files by introducing a new FilePng icon type, routing PNG paths through a custom loader, and scaling images according to devicePixelRatio with smooth transformation before setting them on the QQuickImage. Sequence diagram for PNG icon loading and high-DPI scalingsequenceDiagram
actor Client
participant DQuickIconImage as DQuickIconImage
participant DQuickIconImagePrivate as DQuickIconImagePrivate
participant QQmlFile as QQmlFile
participant QUrl as QUrl
participant QImage as QImage
Client->>DQuickIconImage: setName(name)
DQuickIconImage->>QQmlFile: isLocalFile(name)
QQmlFile-->>DQuickIconImage: bool
alt name is local file
DQuickIconImage->>QUrl: QUrl(name)
QUrl-->>DQuickIconImage: url
DQuickIconImage->>QUrl: toLocalFile()
QUrl-->>DQuickIconImage: localFile
DQuickIconImage->>DQuickIconImagePrivate: set iconType = FilePng (if localFile endsWith .png)
DQuickIconImage->>DQuickIconImagePrivate: maybeUpdateUrl()
DQuickIconImagePrivate->>DQuickIconImagePrivate: check iconType
alt iconType is FilePng
DQuickIconImagePrivate->>DQuickIconImagePrivate: updatePngImage()
DQuickIconImagePrivate->>QUrl: QUrl(name)
QUrl-->>DQuickIconImagePrivate: url
DQuickIconImagePrivate->>QUrl: toLocalFile()
QUrl-->>DQuickIconImagePrivate: localFile
DQuickIconImagePrivate->>QImage: QImage(localFile)
QImage-->>DQuickIconImagePrivate: image
DQuickIconImagePrivate->>DQuickIconImage: sourceSize()
DQuickIconImage-->>DQuickIconImagePrivate: iconSize
DQuickIconImagePrivate->>DQuickIconImagePrivate: scale image using iconSize * devicePixelRatio with SmoothTransformation
DQuickIconImagePrivate->>DQuickIconImagePrivate: setImage(image)
end
end
Class diagram for updated DQuickIconImage and DQuickIconImagePrivate PNG handlingclassDiagram
class QQuickImagePrivate
class DQuickIconImagePrivate {
+bool updateDevicePixelRatio(targetDevicePixelRatio qreal)
+void updateBase64Image()
+void updatePngImage()
+static QImage requestImageFromBase64(name QString, requestedSize QSize, devicePixelRatio qreal)
+IconType iconType
+qreal devicePixelRatio
+void setImage(image QImage)
}
class DQuickIconImage {
+void setName(name QString)
+QSize sourceSize()
+void setSource(url QUrl)
}
class IconType {
<<enumeration>>
ThemeIconName
Base64Data
FileUrl
FilePng
}
QQuickImagePrivate <|-- DQuickIconImagePrivate
DQuickIconImagePrivate --> IconType
DQuickIconImage --> DQuickIconImagePrivate
Flow diagram for setName local file PNG vs non-PNG handlingflowchart TD
A["setName(name)"] --> B["QQmlFile::isLocalFile(name)?"]
B -->|no| Z["Other name handling (unchanged)"]
B -->|yes| C["url = QUrl(name)"]
C --> D["url.isValid()?"]
D -->|no| Z
D -->|yes| E["localFile = url.toLocalFile()"]
E --> F["localFile.endsWith(.png, CaseInsensitive)?"]
F -->|yes| G["iconType = FilePng"]
F -->|no| H["iconType = FileUrl"]
H --> I["setSource(url)"]
G --> J["maybeUpdateUrl() triggers updatePngImage for scaling"]
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 1 issue, and left some high level feedback:
- In updatePngImage(),
iconSize * devicePixelRatiowill either not compile or silently truncate the scale factor depending on types; consider explicitly constructing a scaled QSize (e.g. using qRound on width/height) so that high‑DPI scaling is accurate and type‑safe. - The
setNamebranch for non‑PNG local files still callssetSource(url)directly, which contradicts the new comment about routing throughmaybeUpdateUrlfor unified scaling; either route all local files throughmaybeUpdateUrlor adjust the comment/logic for consistency. - When creating the QUrl from a local path in updatePngImage(), using
QUrl::fromLocalFile(or avoiding round‑tripping through QUrl at all) would be more robust than constructing QUrl(name) and then callingtoLocalFile(), which can return an empty path for some valid local inputs.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In updatePngImage(), `iconSize * devicePixelRatio` will either not compile or silently truncate the scale factor depending on types; consider explicitly constructing a scaled QSize (e.g. using qRound on width/height) so that high‑DPI scaling is accurate and type‑safe.
- The `setName` branch for non‑PNG local files still calls `setSource(url)` directly, which contradicts the new comment about routing through `maybeUpdateUrl` for unified scaling; either route all local files through `maybeUpdateUrl` or adjust the comment/logic for consistency.
- When creating the QUrl from a local path in updatePngImage(), using `QUrl::fromLocalFile` (or avoiding round‑tripping through QUrl at all) would be more robust than constructing QUrl(name) and then calling `toLocalFile()`, which can return an empty path for some valid local inputs.
## Individual Comments
### Comment 1
<location> `src/private/dquickiconimage.cpp:43` </location>
<code_context>
setImage(image);
}
+void DQuickIconImagePrivate::updatePngImage()
+{
+ Q_ASSERT(iconType == FilePng);
</code_context>
<issue_to_address>
**issue (complexity):** Consider unifying all local-file handling into a single code path and helper instead of adding a PNG-specific icon type and branches.
You can keep the new PNG scaling behavior but simplify control flow by unifying local-file handling instead of introducing `FilePng` and PNG-specific branches.
### 1. Replace `FilePng`/`FileUrl` split with a single local-file path
Instead of deciding in `setName` whether something is `FilePng` vs `FileUrl`, treat all local files as a single icon type (e.g. `FileUrl` / `LocalFile`) and push the format-specific logic into one helper.
```cpp
// in setName
d->iconType = DQuickIconImagePrivate::ThemeIconName;
if (name.startsWith("data:image/")) {
d->iconType = DQuickIconImagePrivate::Base64Data;
} else if (QQmlFile::isLocalFile(name)) {
QUrl url(name);
if (url.isValid()) {
d->iconType = DQuickIconImagePrivate::FileUrl; // single local-file type
// don't setSource here; let maybeUpdateUrl handle scaling / loading
}
}
if (isComponentComplete()) {
d->maybeUpdateUrl();
}
```
### 2. Centralize local-file loading (including PNG scaling) in one helper
You can fold `updatePngImage` into a more generic local-file helper and reuse it for all local files:
```cpp
void DQuickIconImagePrivate::updateLocalFileImage()
{
Q_ASSERT(iconType == FileUrl);
D_Q(DQuickIconImage);
QUrl url(name);
if (!url.isValid() || !url.isLocalFile())
return;
const QString localFile = url.toLocalFile();
if (localFile.endsWith(".png", Qt::CaseInsensitive)) {
QImage image(localFile);
if (image.isNull())
return;
QSize iconSize = q->sourceSize();
if (iconSize.isEmpty())
iconSize = image.size();
image = image.scaled(iconSize * devicePixelRatio,
Qt::KeepAspectRatio,
Qt::SmoothTransformation);
setImage(image);
} else {
// non-PNG local files keep existing behavior
q->setSource(url);
}
}
```
### 3. Simplify `maybeUpdateUrl` branching
With the above, `maybeUpdateUrl` doesn’t need a `FilePng` case and stays stable as more formats are added:
```cpp
void DQuickIconImagePrivate::maybeUpdateUrl()
{
D_Q(DQuickIconImage);
// non-theme icons
if (iconType != ThemeIconName) {
if (iconType == Base64Data)
updateBase64Image();
else if (iconType == FileUrl)
updateLocalFileImage();
return;
}
// existing ThemeIconName handling...
}
```
This keeps all the new PNG scaling behavior, but:
- Removes the PNG-specific enum value and extension check from `setName`.
- Centralizes local-file behavior (including format-specific handling) in one place.
- Keeps `maybeUpdateUrl` from growing more `if/else` branches per file type.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| iconSize = image.size(); | ||
| } | ||
| // 应用devicePixelRatio进行缩放 | ||
| image = image.scaled(iconSize * devicePixelRatio, Qt::KeepAspectRatio, Qt::SmoothTransformation); |
There was a problem hiding this comment.
是不是走的这里呀,
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: qxp930712 The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
1. Add updateFileUrlImage method to handle FileUrl type icons 2. Load local file image and apply manual scaling based on devicePixelRatio 3. Use Qt::SmoothTransformation for quality scaling 4. Modify setName to delegate FileUrl loading to maybeUpdateUrl logic 5. This ensures local file icons scale correctly for high DPI displays Influence: 1. Test loading icons from local file paths on standard and high DPI screens 2. Verify image rendering quality and sharpness after scaling 3. Test behavior when sourceSize is explicitly specified vs default 4. Verify that Base64 and Theme icons still render correctly 5. Check for performance impact with large local image files PMS: BUG-333731
deepin pr auto review这份代码 diff 主要实现了对本地文件 URL 类型图标的自定义加载逻辑,以便支持设备像素比(devicePixelRatio)的缩放处理,而不是直接使用 QQuickImage 的默认 source 加载机制。 以下是对这段代码的审查意见,包括语法逻辑、代码质量、代码性能和代码安全四个方面: 1. 语法逻辑
2. 代码质量
3. 代码性能
4. 代码安全
改进建议总结
改进后的代码示例void DQuickIconImagePrivate::updateFileUrlImage()
{
Q_ASSERT(iconType == FileUrl);
D_Q(DQuickIconImage);
// 处理本地PNG文件
QUrl url(name);
if (url.isValid()) {
QImage image(url.toLocalFile());
if (!image.isNull()) {
QSize iconSize = q->sourceSize();
if (iconSize.isEmpty()) {
iconSize = image.size();
}
// 应用devicePixelRatio进行缩放
image = image.scaled(iconSize * devicePixelRatio, Qt::KeepAspectRatio, Qt::SmoothTransformation);
setImage(image);
} else {
// 增加错误日志,便于调试
qWarning() << "DQuickIconImage: Failed to load image from url:" << url << "Local file:" << url.toLocalFile();
}
}
} |
devicePixelRatio
Influence:
screens
PMS: BUG-333731
Summary by Sourcery
Add dedicated handling for local PNG icon files to support high-quality, devicePixelRatio-aware scaling in DQuickIconImage.
New Features:
Enhancements: