feat(ViperQtProject): 许可协议逐份同意、树形组件占满高度、移除点击复选框展开

This commit is contained in:
TermiNexus committed 2026-09-03 11:06:35 +08:00
1 parent a5463a71f8
commit 7c85fa8ac0
1 file changed
+65 -35
+65 -35
View File
@@ -5,7 +5,7 @@
# → 步骤3 安装选项 → 步骤4 安装进度 → 步骤5 完成
#
# 完善功能:
# - 许可协议页:多份协议文件(QComboBox 切换)+ "我接受" 勾选后才可继续
# - 许可协议页:4 份协议逐份查看、逐份勾选同意(下一步才放下一份,不可跳过)
# - 组件选择:QTreeWidget 树状图分组 + 勾选实时统计(数量 / 磁盘占用)
# - 安装选项(独立页):发布渠道 QComboBox + 安装目录 + 快捷方式/PATH/桌面图标
# - 安装进度:进度条 + 阶段文案 + 实时日志(QPlainTextEdit)
@@ -42,7 +42,7 @@ finish_summary_ptr: t.CPtr = None
timer_ptr: t.CPtr = None
tree_ptr: t.CPtr = None
license_box_ptr: t.CPtr = None
license_sel_ptr: t.CPtr = None
eula_name_ptr: t.CPtr = None
agree_cb_ptr: t.CPtr = None
license_next_ptr: t.CPtr = None
channel_ptr: t.CPtr = None
@@ -57,6 +57,8 @@ progress_val: int = 0
comp_count: int = 0
install_path: str = "C:/Program Files/Viper6"
channel_name: str = "稳定版(Stable)"
eula_idx: int = 0
eula_agreed: int = 0
# ============================================================
@@ -81,6 +83,12 @@ privacy_text: str = "隐私政策\n\n本安装向导为本地演示程序,在
credits_text: str = "商标与版权声明\n\nViper、Viper 徽标与相关名称是 Viper Software Foundation 及其关联方的商标。\n\n本演示程序界面设计参考了行业通用安装向导的交互范式,仅用于功能与技术展示,不构成对任何第三方安装程序视觉风格的授权主张。\n\n本软件版权归 Viper Software Foundation 所有,保留一切权利。\n\n版本信息:Viper 6.0.1 · 2026"
# EULA 文档名(显示序号用)
doc_name0: str = "Viper 6.0 最终用户许可协议"
doc_name1: str = "第三方开源组件许可声明"
doc_name2: str = "隐私政策"
doc_name3: str = "商标与版权声明"
# 发布渠道文本
channel_stable: str = "稳定版(Stable)"
channel_preview: str = "预览版(Preview)"
@@ -113,30 +121,68 @@ def GotoStep(step: int):
# 步骤0:欢迎页
# ============================================================
def OnNext(slot_id: int, data: t.CPtr):
EnterEulaPage()
GotoStep(1)
# ============================================================
# 步骤1:许可协议
# 步骤1:许可协议(逐份查看 + 逐份同意)
# ============================================================
def OnLicenseDocChanged(slot_id: int, data: t.CPtr):
"""QComboBox 切换多份协议文件"""
idx: int = vqt6.vqt6_qcombobox_current_index(license_sel_ptr)
def ShowEulaDoc(idx: int):
"""显示第 idx 份协议,并回填该协议的已同意状态"""
txt: str = license_text
if idx == 1: txt = oss_text
elif idx == 2: txt = privacy_text
elif idx == 3: txt = credits_text
name: str = doc_name0
if idx == 1:
txt = oss_text
name = doc_name1
elif idx == 2:
txt = privacy_text
name = doc_name2
elif idx == 3:
txt = credits_text
name = doc_name3
# 标题(x/4 · 协议名)
buf: bytes = stdlib.malloc(128)
viperlib.snprintf(buf, 128, "%d/4 · %s", idx + 1, name)
vqt6.vqt6_qlabel_set_text_utf8(eula_name_ptr, buf)
stdlib.free(buf)
# 正文
vqt6.vqt6_qplaintextedit_set_plain_text_utf8(license_box_ptr, txt)
# 回填该协议已同意状态
agreed: int = (eula_agreed >> idx) & 1
vqt6.vqt6_qcheckbox_set_checked(agree_cb_ptr, agreed)
vqt6.vqt6_qwidget_set_enabled(license_next_ptr, agreed)
def EnterEulaPage():
"""进入许可页:全部已同意则停在末份,否则续接当前进度"""
global eula_idx
if eula_agreed == 15:
ShowEulaDoc(3)
else:
ShowEulaDoc(eula_idx)
def OnLicenseToggled(slot_id: int, data: t.CPtr):
"""勾选"我接受"后启用下一步"""
"""勾选当前协议后才允许下一步"""
checked: int = vqt6.vqt6_qcheckbox_is_checked(agree_cb_ptr)
vqt6.vqt6_qwidget_set_enabled(license_next_ptr, checked)
def OnLicenseNext(slot_id: int, data: t.CPtr):
GotoStep(2)
"""逐份同意:点下一步才放下一份;末份同意后进入组件选择"""
global eula_idx, eula_agreed
idx: int = eula_idx
if idx < 0 or idx > 3:
GotoStep(2)
return
if vqt6.vqt6_qcheckbox_is_checked(agree_cb_ptr) != 0:
eula_agreed = eula_agreed | (1 << idx)
if idx >= 3:
GotoStep(2)
else:
eula_idx = idx + 1
ShowEulaDoc(eula_idx)
def OnLicenseBack(slot_id: int, data: t.CPtr):
@@ -147,6 +193,7 @@ def OnLicenseBack(slot_id: int, data: t.CPtr):
# 步骤2:组件选择(树状图)
# ============================================================
def OnBack(slot_id: int, data: t.CPtr):
EnterEulaPage()
GotoStep(1)
@@ -175,11 +222,6 @@ def OnCompToggled(slot_id: int, data: t.CPtr):
UpdateCompInfo()
def OnTreeItemClicked(slot_id: int, data: t.CPtr):
"""点击带子节点的行 → 展开/折叠"""
vqt6.qtree_click_toggle(tree_ptr)
# ============================================================
# 步骤3:安装选项(独立页)
# ============================================================
@@ -260,7 +302,7 @@ def main() -> int:
global nav0_ptr, nav1_ptr, nav2_ptr, nav3_ptr, nav4_ptr, nav5_ptr
global progress_ptr, progress_status_ptr, log_ptr, path_label_ptr
global summary_ptr, disk_ptr, finish_summary_ptr, timer_ptr
global tree_ptr, license_box_ptr, license_sel_ptr
global tree_ptr, license_box_ptr, eula_name_ptr
global agree_cb_ptr, license_next_ptr, install_btn_ptr
global channel_ptr, opt0_ptr, opt1_ptr, opt2_ptr
@@ -358,7 +400,7 @@ def main() -> int:
stack.addWidget(page0._ptr)
# ---------- 页1:许可协议(多文件) ----------
# ---------- 页1:许可协议(逐份同意) ----------
page1 = vqt6.QWidget()
p1 = vqt6.QVBoxLayout(page1)
p1.setContentsMargins(36, 32, 36, 24)
@@ -368,19 +410,10 @@ def main() -> int:
vqt6.vqt6_qwidget_set_stylesheet_utf8(lh._ptr, "font-size: 22px; color: #ffffff; font-weight: bold;")
p1.addWidget(lh._ptr)
doc_row = vqt6.QHBoxLayout()
p1.addLayout(doc_row._ptr)
doc_lb = vqt6.QLabel("协议文件:")
doc_row.addWidget(doc_lb._ptr)
lic_sel = vqt6.QComboBox()
lic_sel.addItem("Viper 6.0 最终用户许可协议")
lic_sel.addItem("第三方开源组件许可声明")
lic_sel.addItem("隐私政策")
lic_sel.addItem("商标与版权声明")
doc_row.addWidget(lic_sel._ptr)
doc_row.addStretch(1)
license_sel_ptr = t.CPtr(lic_sel._ptr)
lic_sel.currentIndexChanged(OnLicenseDocChanged, 0)
eula_name = vqt6.QLabel("1/4 · Viper 6.0 最终用户许可协议")
vqt6.vqt6_qwidget_set_stylesheet_utf8(eula_name._ptr, "font-size: 13px; color: #9cdcfe;")
p1.addWidget(eula_name._ptr)
eula_name_ptr = t.CPtr(eula_name._ptr)
license_box = vqt6.QPlainTextEdit()
license_box.setPlainText(license_text)
@@ -388,7 +421,7 @@ def main() -> int:
p1.addWidget(license_box._ptr)
license_box_ptr = t.CPtr(license_box._ptr)
agree_cb = vqt6.QCheckBox("我接受许可协议中的条款")
agree_cb = vqt6.QCheckBox("我接受上述协议条款")
p1.addWidget(agree_cb._ptr)
agree_cb_ptr = t.CPtr(agree_cb._ptr)
agree_cb.toggled(OnLicenseToggled, 0)
@@ -463,7 +496,6 @@ def main() -> int:
tree.expandAll()
tree.itemChanged(OnCompToggled, 0)
tree.itemClicked(OnTreeItemClicked, 0)
summary = vqt6.QLabel("已选择 3 个组件")
vqt6.vqt6_qwidget_set_stylesheet_utf8(summary._ptr, "font-size: 13px; color: #9cdcfe;")
@@ -475,8 +507,6 @@ def main() -> int:
p2.addWidget(disk._ptr)
disk_ptr = t.CPtr(disk._ptr)
p2.addStretch(1)
btn_row2 = vqt6.QHBoxLayout()
p2.addLayout(btn_row2._ptr)
btn_row2.addStretch(1)