Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions devel/216_39.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# 216_39 PDF 预览对话框高分屏尺寸适配

## 如何测试

1. 编译:`xmake b stem`
2. 启动 Mogan,进入启动页 **Template** 页面。
3. 点击任意模板卡片打开预览对话框。
4. 在 **100% 缩放** 下确认:
- 对话框尺寸正常,预览框为正方形,PDF 内容保持 A4 比例居中显示。
5. 在 **200% 缩放**(或更高 DPI)下确认:
- 对话框**不会超出屏幕**,上下左右均完整可见。
- 预览框仍为 1:1 正方形,但尺寸已被限制在屏幕可用范围内,不会撑满整个屏幕。
- 对话框宽度紧紧包裹预览框,左右无大量留白。
6. 在不同分辨率屏幕(如 1080p / 4K)上重复验证,确认对话框始终适配当前屏幕。

## 2026/05/08 实现说明

### What

修复 Windows 高分屏(200% 缩放)下模板预览对话框尺寸过大、预览框超出屏幕导致上下显示不全的问题。通过引入屏幕可用区域检测和尺寸上限约束,使对话框和预览框在不同 DPI 下均保持合理大小。

#### 修改文件

**src/Plugins/Qt/qt_template_page.cpp**
- 新增 `#include <QGuiApplication>` / `#include <QScreen>`。
- `showTemplatePreview` 中:
- 获取当前屏幕 `availableGeometry`,对话框最大高度限制为屏幕可用高度的 **90%**。
- 预览框 1:1 正方形尺寸由对话框高度上限推导:最高占对话框高度的 **70%**,再与基准尺寸 `PREVIEW_IMAGE_WIDTH` 取较小值。
- 对话框最大宽度收紧为预览框边长 + 左右边距 + 一个间距余量,不再按屏幕宽度的固定比例扩张。
- 预览框仍使用 `setFixedSize`,内部 `QTPdfPreviewWidget` 通过 `KeepAspectRatio` 渲染保持 PDF A4 比例。

### Why

1. **高分屏溢出**:原代码中 `kPreviewDialogMinW × kPreviewDialogMinH`(700×800)经 `DpiUtils::scaled()` 在 200% 缩放下放大为 1400×1600,在 1080p/4K 逻辑分辨率下极易超出屏幕。
2. **预览框无上限**:原预览框固定为 `600×600` 逻辑像素,高分屏下放大为 1200×1200,加上标题、描述、按钮和边距,总高度远超屏幕可用区域。

### How

- 利用 `QScreen::availableGeometry()` 在对话框创建时获取当前屏幕可用区域,将对话框高度硬上限与屏幕绑定。
- 预览框尺寸改为由**对话框高度**主导(而非独立计算),确保垂直方向不会溢出。
- 对话框宽度反向推导:由确定的预览框边长 + `layoutMargin×2` + `layoutSpacing` 得出,实现“紧紧包裹”预览内容的效果,消除两侧无效留白。
36 changes: 29 additions & 7 deletions src/Plugins/Qt/qt_template_page.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@
#include <QEvent>
#include <QFrame>
#include <QGridLayout>
#include <QGuiApplication>
#include <QHBoxLayout>
#include <QLabel>
#include <QMessageBox>
#include <QMouseEvent>
#include <QProgressDialog>
#include <QPushButton>
#include <QResizeEvent>
#include <QScreen>
#include <QScrollArea>
#include <QShowEvent>
#include <QStyle>
Expand Down Expand Up @@ -463,10 +465,32 @@ QTTemplatePage::showTemplatePreview (const QString& templateId) {
QDialog* dialog= new QDialog (this);
dialog->setWindowTitle (
qt_translate ("Template Preview - %1").arg (tmpl->name));
dialog->setMinimumSize (DpiUtils::scaled (kPreviewDialogMinW),
DpiUtils::scaled (kPreviewDialogMinH));
dialog->resize (DpiUtils::scaled (kPreviewDialogMinW),
DpiUtils::scaled (kPreviewDialogMinH));

// 根据屏幕可用区域限制对话框尺寸,防止高分屏下溢出
QScreen* screen= this->screen ();
if (!screen) screen= QGuiApplication::primaryScreen ();
QRect availGeo= screen ? screen->availableGeometry () : QRect ();
int maxDlgH = availGeo.height () > 0 ? qRound (availGeo.height () * 0.9)
: DpiUtils::scaled (kPreviewDialogMinH);

// 预览区尺寸由对话框高度上限决定(1:1 正方形)
int basePreviewSize= DpiUtils::scaled (PREVIEW_IMAGE_WIDTH);
int maxPreviewSize = qRound (maxDlgH * 0.7);
int previewSize = qMin (basePreviewSize, maxPreviewSize);

// 对话框最大宽度收紧:仅比预览框宽一点(边距 + 少量余量)
int marginW = DpiUtils::scaled (kPreviewLayoutMargin) * 2;
int spacingW= DpiUtils::scaled (kPreviewLayoutSpacing);
int maxDlgW = previewSize + marginW + spacingW;
if (availGeo.width () > 0) {
maxDlgW= qMin (maxDlgW, qRound (availGeo.width () * 0.9));
}

int minW= qMin (DpiUtils::scaled (kPreviewDialogMinW), maxDlgW);
int minH= qMin (DpiUtils::scaled (kPreviewDialogMinH), maxDlgH);
dialog->setMinimumSize (minW, minH);
dialog->setMaximumSize (maxDlgW, maxDlgH);
dialog->resize (minW, minH);

QVBoxLayout* layout= new QVBoxLayout (dialog);
layout->setSpacing (DpiUtils::scaled (kPreviewLayoutSpacing));
Expand Down Expand Up @@ -502,9 +526,7 @@ QTTemplatePage::showTemplatePreview (const QString& templateId) {

// Preview area using reusable PDF preview widget
QTPdfPreviewWidget* previewWidget= new QTPdfPreviewWidget (dialog);
// 设置固定尺寸,确保无内容时也有足够显示区域
previewWidget->setFixedSize (DpiUtils::scaled (PREVIEW_IMAGE_WIDTH),
DpiUtils::scaled (PREVIEW_IMAGE_WIDTH));
previewWidget->setFixedSize (previewSize, previewSize);

// Load PDF preview
if (!tmpl->previewUrl.isEmpty ()) {
Expand Down
Loading