优化状态栏显示网络图标,优化IP信息更新不及时问题,实现注册码页面

Squashed commit of the following:

commit 69bcfa4bd00fc1af8da8df191b6a4d86309c7d23
Merge: 2dba9f8e 964a81c3
Author: zkk <1007518571@qq.com>
Date:   Mon Mar 3 15:25:49 2025 +0800

    Merge commit '964a81c37cd165b9f8df20db87fd915ba03d10b5' into release

commit 964a81c37cd165b9f8df20db87fd915ba03d10b5
Author: zkk <1007518571@qq.com>
Date:   Fri Feb 28 16:27:57 2025 +0800

    状态栏增加网络连接图标

commit 9c99cd91250c7aeb3d9728e540590299a1caf150
Author: zkk <1007518571@qq.com>
Date:   Fri Feb 28 16:20:52 2025 +0800

    修复网络页面IP更新不及时的问题

commit 842a616c2558757d19b7553d23aee9f1daffdc80
Author: zkk <1007518571@qq.com>
Date:   Tue Feb 25 14:53:31 2025 +0800

    注册码功能的实现

commit 2dba9f8ee2725847f31c891b19df6d9b81e03568
Merge: 03cd3722 18f05cc5
Author: zkk <1007518571@qq.com>
Date:   Fri Feb 14 15:21:36 2025 +0800

    Merge commit '18f05cc52dfb7889853a4f84aad975309ab7dbbe' into release

commit 18f05cc52dfb7889853a4f84aad975309ab7dbbe
Author: zkk <1007518571@qq.com>
Date:   Wed Feb 5 10:59:00 2025 +0800

    修复连接不了未加密网络的旧问题

commit 025a26209cbe15a0b7f5f1aba5166da63d6eaebf
Author: zkk <1007518571@qq.com>
Date:   Fri Jan 24 15:48:52 2025 +0800

    重构网络页面,解决卡顿问题

commit fdc851c4e66e3b872eb2564442f0c67369b9e3e2
Author: zkk <1007518571@qq.com>
Date:   Fri Jan 24 15:13:41 2025 +0800

    优化菜单页面的点击效果和增加列表风格属性

commit e6cfa874208f8d98d0360fb073e4da15c935b202
Author: zkk <1007518571@qq.com>
Date:   Tue Jan 21 15:11:28 2025 +0800

    优化进入工厂模式的方式为10s内点击5次

commit 03cd37229ee6c606e9814af602709d81b2c79bec
Merge: cf7cafef adcbaa17
Author: zkk <1007518571@qq.com>
Date:   Fri Jan 17 14:38:18 2025 +0800

    Merge commit 'adcbaa1795bffedc3000bc9e59eabba04d946dd4' into release

commit adcbaa1795bffedc3000bc9e59eabba04d946dd4
Author: zkk <1007518571@qq.com>
Date:   Tue Jan 14 15:34:10 2025 +0800

    实现探针偏移值校准保存前范围检测,避免保存错误值无法启动问题

commit cf7cafefbcd2274c9a481e58042d11db8cd79961
Merge: dc3478b4 8d259cea
Author: zkk <1007518571@qq.com>
Date:   Tue Jan 7 17:26:59 2025 +0800

    Merge commit '8d259ceadd5026cecc1dc61224d91aef4f3877b4' into release

commit 8d259ceadd5026cecc1dc61224d91aef4f3877b4
Author: zkk <1007518571@qq.com>
Date:   Tue Jan 7 17:15:46 2025 +0800

    实现 打印中恢复喷头温度 提示语的翻译

commit dd11c9683cb5af5407e650eea9b683b1066256c7
Author: zkk <1007518571@qq.com>
Date:   Tue Jan 7 16:52:04 2025 +0800

    优化单个喷头时不显示喷头偏移菜单

commit c3ec7a81bbe1490b76202485d0502a4829a3cee5
Author: zkk <1007518571@qq.com>
Date:   Fri Jan 3 17:52:24 2025 +0800

    修复屏幕耗材检测显示偶尔不准确的问题

commit 413bf6fc4a740f53d265c63abe7c51eaad483cb0
Author: zkk <1007518571@qq.com>
Date:   Fri Jan 3 15:00:54 2025 +0800

    修复耗材检测弹窗异常问题

commit dc3478b48c7da1dbae120d1270c9ab64646d6647
Merge: 02c7556c 3bfc1aa7
Author: zkk <1007518571@qq.com>
Date:   Thu Jan 2 11:18:07 2025 +0800

    Merge commit '3bfc1aa714e282d74b801155d830377ca58d8f59' into release

commit 3bfc1aa714e282d74b801155d830377ca58d8f59
Author: zkk <1007518571@qq.com>
Date:   Thu Jan 2 11:17:15 2025 +0800

    修复移轴页面移轴功能失效问题

commit 02c7556cdadf8de1ef3c54d2831920927cadbe30
Merge: 6bfa42e0 991003e6
Author: zkk <1007518571@qq.com>
Date:   Tue Dec 31 15:07:54 2024 +0800

    Merge commit '991003e6cbea335eca73d3783aa1837059614724' into release

commit 991003e6cbea335eca73d3783aa1837059614724
Author: zkk <1007518571@qq.com>
Date:   Tue Dec 31 15:03:34 2024 +0800

    优化完整 简体中文和繁体中文的翻译

commit 1a177e90d09b9b9949bff2a1e3c6b12173420620
Author: zkk <1007518571@qq.com>
Date:   Tue Dec 31 14:10:03 2024 +0800

    优化排除对象的英文语法错误

commit e8d509cb6c2883b1fadb5ab9f9ca658e61849055
Author: zkk <1007518571@qq.com>
Date:   Fri Dec 27 16:40:52 2024 +0800

    优化耗材检测显示内容

commit 1b7670485a918cb334119175777525f768e670be
Author: zkk <1007518571@qq.com>
Date:   Fri Dec 27 14:56:25 2024 +0800

    完善断料自动切头功能描述

commit ecc0c3dd16442497e56f5f8ab3a0c6be00bd180e
Author: zkk <1007518571@qq.com>
Date:   Fri Dec 27 13:40:01 2024 +0800

    实现弹窗翻译功能

commit bc6d60fa183af50b7b16fea685139ca9d5df90ea
Author: zkk <1007518571@qq.com>
Date:   Fri Dec 27 09:53:16 2024 +0800

    优化不合理名称和不合理大小写

commit 2e650926bdba1c65baa506be1b1dd09621e8d8ea
Author: zkk <1007518571@qq.com>
Date:   Thu Dec 26 15:06:11 2024 +0800

    修复10寸屏幕偏移值微调页面出界问题

commit c481b551f777a3a6cadf7be3bfcab38448b51694
Author: zkk <1007518571@qq.com>
Date:   Wed Dec 25 15:28:26 2024 +0800

    优化移轴设置页面没有返回按钮的问题

commit 2b3c9936bd693c8fc265d6352799f382680f4920
Author: zkk <1007518571@qq.com>
Date:   Wed Dec 25 10:05:04 2024 +0800

    删除移动设置页面中轴反转的选项

commit 5e37d59497c54086d3f1e215cbabc03254857a58
Author: zkk <1007518571@qq.com>
Date:   Wed Dec 25 09:05:03 2024 +0800

    优化选择语言标题

commit 5214c3697baac78bd0a465e33d6f4f3c1e30862e
Author: zkk <1007518571@qq.com>
Date:   Tue Dec 24 10:57:41 2024 +0800

    增加设置hostname功能

commit 3709a7465cc2e0d677ecc9979fb18144f7e0ec33
Author: zkk <1007518571@qq.com>
Date:   Tue Dec 24 10:43:46 2024 +0800

    增加工厂设置中打包模式

commit 0c2a2618beb68d50601e433beef06122fb0ffd40
Author: zkk <1007518571@qq.com>
Date:   Mon Dec 23 16:25:37 2024 +0800

    实现恢复出厂设置功能

commit e3a38f85613d53a4a063e835c34c701196010c6e
Author: zkk <1007518571@qq.com>
Date:   Mon Dec 23 15:48:17 2024 +0800

    一点格式化

commit 4e9e452e8bed4b53eaaae8f0a69142de8aa50611
Author: zkk <1007518571@qq.com>
Date:   Sat Dec 21 14:20:22 2024 +0800

    优化探针偏移值校准时如果当前激活为第一个喷头时不会重复激活喷头

commit 3b85e8e8d59b0d4eae75f80d9e637fe9dc272cbe
Merge: 882850db 10ec2029
Author: zkk <1007518571@qq.com>
Date:   Wed Dec 18 17:26:08 2024 +0800

    Merge branch 'develop' of https://server.creatbot.com/Gitea/CreatBot/CreatBotKlipperScreen into develop

commit 882850dbde648598e5f91281101d0ea01fd56d56
Author: zkk <1007518571@qq.com>
Date:   Wed Dec 18 17:21:16 2024 +0800

    补充双喷头偏移校准页面二维码图片

commit 10ec2029eb73e66874d5a0ec492c016480641110
Author: ruipeng <1041589370@qq.com>
Date:   Wed Dec 18 17:17:18 2024 +0800

    增加自动切换喷头开关选项

commit 3d6eed9d9526b77472ba7df29014b5768c594026
Author: zkk <1007518571@qq.com>
Date:   Mon Dec 16 16:33:34 2024 +0800

    喷头偏移值校准功能的实现

commit 40ecbb3ea4827c9bac1aa271cccc958c94c1114a
Author: zkk <1007518571@qq.com>
Date:   Fri Dec 13 09:20:00 2024 +0800

    z探针校准时指定默认激活工具头为第一个头

commit bce3caa409618ef5bc2067865940d14a1441c0f8
Author: zkk <1007518571@qq.com>
Date:   Fri Dec 13 09:19:19 2024 +0800

    优化z探针校准时候移动过慢问题

commit 6bfa42e036a521c8ff7db1bf8ccb65500eabb6ea
Merge: 1a87ced3 4f3aa9aa
Author: zkk <1007518571@qq.com>
Date:   Thu Dec 12 10:33:58 2024 +0800

    Merge commit '4f3aa9aa4c581ae9e7a740bd37f9e80ba064c27f' into release

commit 4f3aa9aa4c581ae9e7a740bd37f9e80ba064c27f
Merge: e3fd413d 1a69b518
Author: zkk <1007518571@qq.com>
Date:   Thu Dec 12 10:30:00 2024 +0800

    Merge branch 'develop' of https://server.creatbot.com/Gitea/CreatBot/CreatBotKlipperScreen into develop

commit 1a69b5180de733f15550a1294a7221d6070306a0
Author: ruipeng <1041589370@qq.com>
Date:   Wed Dec 11 11:44:36 2024 +0800

    新增D600pro2、D1000的V0版机型

commit e3fd413d6256414441e9fe653c1132b1799a5cb2
Author: zkk <1007518571@qq.com>
Date:   Tue Dec 10 14:34:13 2024 +0800

    修复打印时没有修改z偏移值 仍提示保存z偏移的按钮的bug

commit 594fb668fe94fe907c028bf65ecced43ea8660cb
Author: zkk <1007518571@qq.com>
Date:   Tue Dec 10 14:25:04 2024 +0800

    设置自适应调平选项默认为关闭状态

commit 1a87ced3f5725569a6b9a7ee5f5250044d01d852
Merge: 629416d1 6064a6e1
Author: zkk <1007518571@qq.com>
Date:   Fri Nov 29 10:18:32 2024 +0800

    Merge branch 'develop' into release

# Conflicts:
#	ks_includes/locales/KlipperScreen.pot   resolved by 69bcfa4bd00fc1af8da8df191b6a4d86309c7d23 version
#	ks_includes/locales/zh_CN/LC_MESSAGES/KlipperScreen.mo   resolved by 69bcfa4bd00fc1af8da8df191b6a4d86309c7d23 version
#	ks_includes/locales/zh_CN/LC_MESSAGES/KlipperScreen.po   resolved by 69bcfa4bd00fc1af8da8df191b6a4d86309c7d23 version
#	ks_includes/locales/zh_TW/LC_MESSAGES/KlipperScreen.mo   resolved by 69bcfa4bd00fc1af8da8df191b6a4d86309c7d23 version
#	ks_includes/locales/zh_TW/LC_MESSAGES/KlipperScreen.po   resolved by 69bcfa4bd00fc1af8da8df191b6a4d86309c7d23 version
#	panels/factory_settings.py   resolved by 69bcfa4bd00fc1af8da8df191b6a4d86309c7d23 version
#	panels/network.py   resolved by 69bcfa4bd00fc1af8da8df191b6a4d86309c7d23 version
This commit is contained in:
张开科 2025-03-03 15:27:14 +08:00
parent bfd5ba6a3c
commit f892315588
16 changed files with 797 additions and 52 deletions

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-01-14 16:25+0800\n"
"POT-Creation-Date: 2025-02-26 11:12+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -70,6 +70,9 @@ msgstr ""
msgid "Accept"
msgstr ""
msgid "Activate"
msgstr ""
msgid "Adaptive Bed Leveling"
msgstr ""
@ -234,9 +237,6 @@ msgstr ""
msgid "Confirm factory reset?\n"
msgstr ""
msgid "Connected"
msgstr ""
msgid "Connecting"
msgstr ""
@ -306,15 +306,24 @@ msgstr ""
msgid "Do you want to recover %s?"
msgstr ""
msgid "Elapsed trial time:"
msgstr ""
msgid "Elapsed:"
msgstr ""
msgid "Emergency Stop"
msgstr ""
msgid "Enable Registration Code"
msgstr ""
msgid "Enable screen power management"
msgstr ""
msgid "Enabled successfully"
msgstr ""
msgid "Error"
msgstr ""
@ -462,9 +471,6 @@ msgstr ""
msgid "Host"
msgstr ""
msgid "Hostname"
msgstr ""
msgid "ID"
msgstr ""
@ -507,6 +513,18 @@ msgstr ""
msgid "Job Status"
msgstr ""
msgid "Key is empty"
msgstr ""
msgid "Key is invalid"
msgstr ""
msgid "Key is valid"
msgstr ""
msgid "Key:"
msgstr ""
msgid "Klipper Restart"
msgstr ""
@ -559,6 +577,9 @@ msgstr ""
msgid "Leveling only in the actual print area"
msgstr ""
msgid "License key"
msgstr ""
msgid "Limits"
msgstr ""
@ -682,6 +703,9 @@ msgstr ""
msgid "Not Inserted"
msgstr ""
msgid "Not activated"
msgstr ""
msgid "Not all screens support this"
msgstr ""
@ -745,12 +769,18 @@ msgstr ""
msgid "Perform a full upgrade?"
msgstr ""
msgid "Permanent Activation"
msgstr ""
msgid "Pins"
msgstr ""
msgid "Please ensure that the Probe Calibrate has been performed"
msgstr ""
msgid "Please enter a key to activate"
msgstr ""
msgid "Please enter a valid number"
msgstr ""
@ -835,6 +865,9 @@ msgstr ""
msgid "Refresh"
msgstr ""
msgid "Remaining Time:"
msgstr ""
msgid "Remove network"
msgstr ""
@ -844,6 +877,12 @@ msgstr ""
msgid "Reprint"
msgstr ""
msgid "Reset"
msgstr ""
msgid "Reset successfully"
msgstr ""
msgid "Restart"
msgstr ""
@ -923,6 +962,9 @@ msgstr ""
msgid "Send"
msgstr ""
msgid "Serial Number:"
msgstr ""
msgid "Settings"
msgstr ""
@ -944,6 +986,9 @@ msgstr ""
msgid "Size"
msgstr ""
msgid "Skip"
msgstr ""
msgid "Slicer"
msgstr ""
@ -983,15 +1028,15 @@ msgstr ""
msgid "Start testing the Z offset value of the second nozzle?\n"
msgstr ""
msgid "Starting WiFi Association"
msgstr ""
msgid "Starting recovery for"
msgstr ""
msgid "Starting update for"
msgstr ""
msgid "State:"
msgstr ""
msgid "System"
msgstr ""
@ -1019,6 +1064,9 @@ msgstr ""
msgid "The system will reboot!"
msgstr ""
msgid "This device is not activated and is available for trial use only"
msgstr ""
msgid "This operation is about to print the model"
msgstr ""
@ -1037,6 +1085,15 @@ msgstr ""
msgid "Total:"
msgstr ""
msgid "Trial"
msgstr ""
msgid "Trial Time:"
msgstr ""
msgid "Unknown"
msgstr ""
msgid "Unknown Heater"
msgstr ""
@ -1139,6 +1196,9 @@ msgid_plural "hours"
msgstr[0] ""
msgstr[1] ""
msgid "license"
msgstr ""
msgid "macros that use 'rename_existing' are hidden"
msgstr ""

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: KlipperScreen\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-01-07 17:11+0800\n"
"POT-Creation-Date: 2025-02-26 11:12+0800\n"
"PO-Revision-Date: 2024-06-03 19:09+0000\n"
"Last-Translator: wsj20050623 <2129426599@qq.com>\n"
"Language-Team: Chinese (Simplified) <https://hosted.weblate.org/projects/"
@ -63,7 +63,7 @@ msgid "ADXL Not Configured"
msgstr "未配置加速度计"
msgid "Abort"
msgstr "中止打印"
msgstr "终止"
msgid "Acceleration:"
msgstr "加速度:"
@ -71,6 +71,9 @@ msgstr "加速度:"
msgid "Accept"
msgstr "确定"
msgid "Activate"
msgstr "激活"
msgid "Adaptive Bed Leveling"
msgstr "自适应床调平"
@ -235,9 +238,6 @@ msgstr "紧急停止需要二次确认"
msgid "Confirm factory reset?\n"
msgstr "确定恢复出厂设置?\n"
msgid "Connected"
msgstr "已连接"
msgid "Connecting"
msgstr "连接中"
@ -307,15 +307,24 @@ msgstr "您要忘记或断开%s的连接吗?"
msgid "Do you want to recover %s?"
msgstr "你想恢复 %s 吗?"
msgid "Elapsed trial time:"
msgstr "已用时间:"
msgid "Elapsed:"
msgstr "已用时间:"
msgid "Emergency Stop"
msgstr "紧急停止"
msgid "Enable Registration Code"
msgstr "启用注册码"
msgid "Enable screen power management"
msgstr "开启屏幕功率管理功能"
msgid "Enabled successfully"
msgstr "启用成功"
msgid "Error"
msgstr "错误"
@ -463,9 +472,6 @@ msgstr "Z轴归零"
msgid "Host"
msgstr "主机"
msgid "Hostname"
msgstr "主机名"
msgid "ID"
msgstr "ID"
@ -508,6 +514,18 @@ msgstr "设置文件可能存在错误"
msgid "Job Status"
msgstr "工作状态"
msgid "Key is empty"
msgstr "密钥为空"
msgid "Key is invalid"
msgstr "密钥无效"
msgid "Key is valid"
msgstr "密钥有效"
msgid "Key:"
msgstr "密钥:"
msgid "Klipper Restart"
msgstr "重启Klipper"
@ -560,6 +578,9 @@ msgstr "剩余时间:"
msgid "Leveling only in the actual print area"
msgstr "仅在实际打印区域进行床调平"
msgid "License key"
msgstr "许可证密钥"
msgid "Limits"
msgstr "打印机限制"
@ -683,6 +704,9 @@ msgstr "未启用"
msgid "Not Inserted"
msgstr "未装载"
msgid "Not activated"
msgstr "未激活"
msgid "Not all screens support this"
msgstr "不一定所有屏幕都支持这项功能"
@ -745,12 +769,18 @@ msgstr "已暂停"
msgid "Perform a full upgrade?"
msgstr "是否更新全部?"
msgid "Permanent Activation"
msgstr "永久激活"
msgid "Pins"
msgstr "引脚"
msgid "Please ensure that the Probe Calibrate has been performed"
msgstr "请确保已完成探针偏移校准"
msgid "Please enter a key to activate"
msgstr "请输入密钥激活"
msgid "Please enter a valid number"
msgstr "请输入有效的数字"
@ -835,6 +865,9 @@ msgstr "参考"
msgid "Refresh"
msgstr "检查更新"
msgid "Remaining Time:"
msgstr "剩余时间:"
msgid "Remove network"
msgstr "删除网络"
@ -844,6 +877,12 @@ msgstr "重命名/移动:"
msgid "Reprint"
msgstr "再次打印"
msgid "Reset"
msgstr "重置"
msgid "Reset successfully"
msgstr "重置成功"
msgid "Restart"
msgstr "重启"
@ -923,6 +962,9 @@ msgstr "选择型号"
msgid "Send"
msgstr "发送"
msgid "Serial Number:"
msgstr "序列号:"
msgid "Settings"
msgstr "设置"
@ -944,6 +986,9 @@ msgstr "散热风扇"
msgid "Size"
msgstr "大小"
msgid "Skip"
msgstr "跳过"
msgid "Slicer"
msgstr "切片软件"
@ -983,15 +1028,15 @@ msgstr "开始"
msgid "Start testing the Z offset value of the second nozzle?\n"
msgstr "开始测试第二个喷嘴的 Z 偏移值吗?\n"
msgid "Starting WiFi Association"
msgstr "开始WiFi连接"
msgid "Starting recovery for"
msgstr "开始恢复"
msgid "Starting update for"
msgstr "开始更新"
msgid "State:"
msgstr "状态:"
msgid "System"
msgstr "系统"
@ -1019,6 +1064,9 @@ msgstr ""
msgid "The system will reboot!"
msgstr "系统将重新启动!"
msgid "This device is not activated and is available for trial use only"
msgstr "此设备尚未激活,仅供试用"
msgid "This operation is about to print the model"
msgstr "此操作即将开始打印模型"
@ -1037,6 +1085,15 @@ msgstr "打印过程中超过倒计时后关闭屏幕"
msgid "Total:"
msgstr "合计:"
msgid "Trial"
msgstr "试用"
msgid "Trial Time:"
msgstr "试用时间:"
msgid "Unknown"
msgstr "未知"
msgid "Unknown Heater"
msgstr "未知加热器"
@ -1136,6 +1193,9 @@ msgid "hour"
msgid_plural "hours"
msgstr[0] "小时"
msgid "license"
msgstr "许可证"
msgid "macros that use 'rename_existing' are hidden"
msgstr "使用\"rename_existing\"的宏将被隐藏"
@ -1168,6 +1228,15 @@ msgid "second"
msgid_plural "seconds"
msgstr[0] "秒"
#~ msgid "Connected"
#~ msgstr "已连接"
#~ msgid "Hostname"
#~ msgstr "主机名"
#~ msgid "Starting WiFi Association"
#~ msgstr "开始WiFi连接"
#~ msgid "Restoring Left extruder temperature, this may take some time"
#~ msgstr "恢复左挤出机温度,这可能需要一些时间"
@ -1243,9 +1312,6 @@ msgstr[0] "秒"
#~ msgid "KlipperScreen will drop support in June 2024"
#~ msgstr "KlipperScreen将于2024 年6月停止适配"
#~ msgid "Print Time"
#~ msgstr "打印用时"
#~ msgid "Warning"
#~ msgstr "警告"
@ -1420,6 +1486,3 @@ msgstr[0] "秒"
#~ msgid "Load Average"
#~ msgstr "平均负载"
#~ msgid "Screen Blanking Time"
#~ msgstr "关闭屏幕时间"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: KlipperScreen\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-01-07 17:11+0800\n"
"POT-Creation-Date: 2025-02-26 11:12+0800\n"
"PO-Revision-Date: 2024-06-01 12:09+0000\n"
"Last-Translator: 峻瑜哥 <a728728728@gmail.com>\n"
"Language-Team: Chinese (Traditional) <https://hosted.weblate.org/projects/"
@ -71,6 +71,9 @@ msgstr "加速度:"
msgid "Accept"
msgstr "接受"
msgid "Activate"
msgstr "激活"
msgid "Adaptive Bed Leveling"
msgstr "自適應床調平"
@ -235,9 +238,6 @@ msgstr "緊急停止需確認"
msgid "Confirm factory reset?\n"
msgstr "確定恢復出廠設置?\n"
msgid "Connected"
msgstr "已連線"
msgid "Connecting"
msgstr "連接中"
@ -307,15 +307,24 @@ msgstr "您要忘記或斷開%s的連接嗎?"
msgid "Do you want to recover %s?"
msgstr "你想恢復 %s 嗎?"
msgid "Elapsed trial time:"
msgstr "已用時間"
msgid "Elapsed:"
msgstr "已用時間:"
msgid "Emergency Stop"
msgstr "緊急停止"
msgid "Enable Registration Code"
msgstr "啟用註冊碼"
msgid "Enable screen power management"
msgstr "開啟螢幕功率管理功能"
msgid "Enabled successfully"
msgstr "啟用成功"
msgid "Error"
msgstr "錯誤"
@ -463,9 +472,6 @@ msgstr "Z軸歸零"
msgid "Host"
msgstr "主機"
msgid "Hostname"
msgstr "主機名"
msgid "ID"
msgstr "ID"
@ -508,6 +514,18 @@ msgstr "設置文件可能存在錯誤"
msgid "Job Status"
msgstr "工作狀態"
msgid "Key is empty"
msgstr "密鑰為空"
msgid "Key is invalid"
msgstr "密鑰無效"
msgid "Key is valid"
msgstr "密鑰有效"
msgid "Key:"
msgstr "密鑰:"
msgid "Klipper Restart"
msgstr "重啟Klipper"
@ -560,6 +578,9 @@ msgstr "剩餘時間:"
msgid "Leveling only in the actual print area"
msgstr "僅在實際打印區域進行床調平"
msgid "License key"
msgstr "許可證密鑰"
msgid "Limits"
msgstr "列印機限制"
@ -683,6 +704,9 @@ msgstr "未啟用"
msgid "Not Inserted"
msgstr "未裝載"
msgid "Not activated"
msgstr "未激活"
msgid "Not all screens support this"
msgstr "不一定所有屏幕都支持這項功能"
@ -745,12 +769,18 @@ msgstr "已暫停"
msgid "Perform a full upgrade?"
msgstr "是否全部升級?"
msgid "Permanent Activation"
msgstr "永久激活"
msgid "Pins"
msgstr "引腳"
msgid "Please ensure that the Probe Calibrate has been performed"
msgstr "請確保已完成探針偏移校準"
msgid "Please enter a key to activate"
msgstr "請輸入密鑰激活"
msgid "Please enter a valid number"
msgstr "請輸入有效的數字"
@ -835,6 +865,9 @@ msgstr "參考"
msgid "Refresh"
msgstr "重新整理"
msgid "Remaining Time:"
msgstr "剩余時間:"
msgid "Remove network"
msgstr "刪除網絡"
@ -844,6 +877,12 @@ msgstr "重新命名/移動:"
msgid "Reprint"
msgstr "再次打印"
msgid "Reset"
msgstr "重置"
msgid "Reset successfully"
msgstr "重置成功"
msgid "Restart"
msgstr "重啟"
@ -923,6 +962,9 @@ msgstr "選擇型號"
msgid "Send"
msgstr "發送"
msgid "Serial Number:"
msgstr "序列號"
msgid "Settings"
msgstr "設定"
@ -944,6 +986,9 @@ msgstr "散熱風扇"
msgid "Size"
msgstr "大小"
msgid "Skip"
msgstr "跳過"
msgid "Slicer"
msgstr "切片軟體"
@ -983,15 +1028,15 @@ msgstr "開始"
msgid "Start testing the Z offset value of the second nozzle?\n"
msgstr "開始測試第二個噴嘴的 Z 偏移值嗎?\n"
msgid "Starting WiFi Association"
msgstr "開始WiFi連線"
msgid "Starting recovery for"
msgstr "開始恢復"
msgid "Starting update for"
msgstr "開始更新"
msgid "State:"
msgstr "狀態:"
msgid "System"
msgstr "系統"
@ -1019,6 +1064,9 @@ msgstr ""
msgid "The system will reboot!"
msgstr "系統將重新啟動!"
msgid "This device is not activated and is available for trial use only"
msgstr "此設備尚未激活,僅供試用"
msgid "This operation is about to print the model"
msgstr "此操作即將開始打印模型"
@ -1037,6 +1085,15 @@ msgstr "打印過程中超過倒計時後關閉屏幕"
msgid "Total:"
msgstr "合計:"
msgid "Trial"
msgstr "試用"
msgid "Trial Time:"
msgstr "試用時間:"
msgid "Unknown"
msgstr "未知"
msgid "Unknown Heater"
msgstr "未知加熱器"
@ -1136,6 +1193,9 @@ msgid "hour"
msgid_plural "hours"
msgstr[0] "小時"
msgid "license"
msgstr "許可證"
msgid "macros that use 'rename_existing' are hidden"
msgstr "使用\"rename_existing\"的宏將被隱藏"
@ -1168,6 +1228,15 @@ msgid "second"
msgid_plural "seconds"
msgstr[0] "秒"
#~ msgid "Connected"
#~ msgstr "已連線"
#~ msgid "Hostname"
#~ msgstr "主機名"
#~ msgid "Starting WiFi Association"
#~ msgstr "開始WiFi連線"
#~ msgid "Restoring Left extruder temperature, this may take some time"
#~ msgstr "恢復左擠出機溫度,這可能需要一些時間"
@ -1216,9 +1285,6 @@ msgstr[0] "秒"
#~ msgid "Hidden"
#~ msgstr "隱藏的"
#~ msgid "Print Time"
#~ msgstr "列印時間"
#~ msgid "dBm"
#~ msgstr "dBm"
@ -1390,6 +1456,3 @@ msgstr[0] "秒"
#~ msgid "Load Average"
#~ msgstr "平均负载"
#~ msgid "Screen Blanking Time"
#~ msgstr "关闭屏幕时间"

View File

@ -230,6 +230,10 @@ class SdbusNm:
else None
)
def get_signal_strength(self):
ap = self.get_connected_ap()
return ap.strength if ap else None
def get_security_type(self, ssid):
return next(
(

165
ks_includes/sdbus_reg.py Normal file
View File

@ -0,0 +1,165 @@
from asyncio import new_event_loop, run_coroutine_threadsafe
from threading import Thread
import ast
import logging
from typing import Optional
from sdbus import DbusInterfaceCommonAsync, dbus_method_async, dbus_property_async
logger = logging.getLogger(__name__)
class RegistrationInterface(DbusInterfaceCommonAsync, interface_name="org.registration.interface"):
def __init__(self, bus_name: str, object_path: str):
super().__init__()
self.proxy = self.new_proxy(bus_name, object_path)
@dbus_property_async(property_signature="s")
def get_unique_id(self) -> str:
raise NotImplementedError
@dbus_property_async(property_signature="a{sv}")
def get_time_info(self) -> str:
raise NotImplementedError
@dbus_property_async(property_signature="b")
def is_active(self) -> bool:
raise NotImplementedError
@dbus_property_async(property_signature="b")
def is_trial_active(self) -> bool:
raise NotImplementedError
@dbus_method_async(input_signature="s", result_signature="b")
async def verify_activation_code(self, val: str) -> bool:
raise NotImplementedError
@dbus_method_async(input_signature="s", result_signature="b")
async def reset_registration(self, val: str) -> bool:
raise NotImplementedError
@dbus_property_async(property_signature="b")
def enabled_registration(self) -> bool:
raise NotImplementedError
class LicenseManager:
def __init__(self, bus_name: str = "org.registration.link", object_path: str = "/"):
self.loop = new_event_loop()
self.registration_interface: Optional[RegistrationInterface] = None
self.interface_valid = False
self._thread: Optional[Thread] = None
self.callback = None
try:
self.registration_interface = RegistrationInterface(bus_name, object_path)
self.interface_valid = True
logger.info("DBus connection established successfully")
except Exception as e:
logger.error(f"Failed to initialize DBus connection: {e}")
self._cleanup_resources()
return
self._thread = Thread(target=self._run_loop, daemon=True)
self._thread.start()
def _run_loop(self) -> None:
try:
self.loop.run_forever()
finally:
self.loop.close()
def _cleanup_resources(self) -> None:
if self.loop.is_running():
self.loop.call_soon_threadsafe(self.loop.stop)
if self._thread and self._thread.is_alive():
self._thread.join(timeout=1)
self.loop.close()
def is_interface_valid(self) -> bool:
return self.interface_valid
def _async_call(self, coroutine_func, default=None):
if not self.is_interface_valid():
logger.warning("Attempting to use invalid DBus interface")
return default
try:
future = run_coroutine_threadsafe(coroutine_func(), self.loop)
return future.result()
except Exception as e:
logger.error(f"DBus operation failed: {e}")
self.interface_valid = False
return default
def get_unique_id(self) -> str:
async def _get():
return await self.registration_interface.proxy.get_unique_id
return self._async_call(_get, default="")
def get_trial_time(self) -> int:
async def _get():
return await self.registration_interface.proxy.get_time_info
result = self._async_call(_get, default="{}")
try:
data_dict = ast.literal_eval(result)
return data_dict.get("trial_time", 0)
except Exception as e:
logger.error(f"Parse time info failed: {e}")
return 0
def get_total_printed_time(self) -> int:
async def _get():
return await self.registration_interface.proxy.get_time_info
result = self._async_call(_get, default="{}")
try:
data_dict = ast.literal_eval(result)
return int(data_dict.get("total_printed_time", 0))
except Exception as e:
logger.error(f"Parse time info failed: {e}")
return 0
def is_active(self) -> bool:
async def _get():
return await self.registration_interface.proxy.is_active
return self._async_call(_get, default=False)
def is_trial_active(self) -> bool:
async def _get():
return await self.registration_interface.proxy.is_trial_active
return self._async_call(_get, default=False)
def is_time_sufficient(self, required_seconds: int = 40 * 3600) -> bool:
trial_time = self.get_trial_time()
printed_time = self.get_total_printed_time()
return (trial_time - printed_time) > required_seconds
def verify_activation_code(self, code: str) -> bool:
async def _verify():
return await self.registration_interface.proxy.verify_activation_code(code)
return self._async_call(_verify, default=False)
def reset_registration(self, code: str) -> bool:
async def _reset():
return await self.registration_interface.proxy.reset_registration(code)
return self._async_call(_reset, default=False)
def enabled_registration(self) -> bool:
async def _get():
return await self.registration_interface.proxy.enabled_registration
return self._async_call(_get, default=False)
def close(self) -> None:
if self.is_interface_valid():
logger.info("Closing DBus connection...")
self._cleanup_resources()
self.interface_valid = False

View File

@ -8,6 +8,7 @@ from gi.repository import GLib, Gtk, Pango
from jinja2 import Environment
from datetime import datetime
from math import log
from ks_includes.sdbus_nm import SdbusNm
from ks_includes.screen_panel import ScreenPanel
@ -18,11 +19,37 @@ class BasePanel(ScreenPanel):
self.time_min = -1
self.time_format = self._config.get_main_config().getboolean("24htime", True)
self.time_update = None
self.network_update = None
self.titlebar_items = []
self.titlebar_name_type = None
self.current_extruder = None
self.last_usage_report = datetime.now()
self.usage_report = 0
icon_size_width = self._gtk.content_width * 0.05
icon_size_height = self._gtk.content_height * 0.05
network_icons_map = {
"excellent": "wifi_excellent",
"good": "wifi_good",
"fair": "wifi_fair",
"weak": "wifi_weak",
"ethernet": "ethernet",
}
self.network_icons = {
key: self._gtk.PixbufFromIcon(value, width=icon_size_width, height=icon_size_height)
for key, value in network_icons_map.items()
}
try:
self.sdbus_nm = SdbusNm(self.network_interface_refresh)
except Exception as e:
logging.exception("Failed to initialize SdbusNm: %s", e)
self.sdbus_nm = None
# Action bar buttons
abscale = self.bts * 1.1
self.control['back'] = self._gtk.Button('back', scale=abscale)
@ -100,6 +127,26 @@ class BasePanel(ScreenPanel):
self.titlelbl = Gtk.Label(hexpand=True, halign=Gtk.Align.CENTER, ellipsize=Pango.EllipsizeMode.END)
if self._screen.license.is_interface_valid() and not self._screen.license.is_active():
img_size = self._gtk.img_scale * self.bts
self.control["license"] = self._gtk.Image("license", img_size, img_size)
license_eventbox = Gtk.EventBox()
license_eventbox.add(self.control["license"])
license_eventbox.connect("button-press-event", self.show_license_key_page)
self.control["license_box"] = Gtk.Box(halign=Gtk.Align.END)
self.control["license_box"].pack_end(license_eventbox, True, True, 5)
if self.sdbus_nm:
img_size = self._gtk.img_scale * self.bts
self.control["network_ico"] = self._gtk.Image("wifi_excellent", img_size, img_size)
network_eventbox = Gtk.EventBox()
network_eventbox.add(self.control["network_ico"])
network_eventbox.connect("button-press-event", self.show_network_page)
self.control["network_box"] = Gtk.Box(halign=Gtk.Align.END)
self.control["network_box"].pack_end(network_eventbox, True, True, 5)
self.control["network_ico"].set_no_show_all(True)
self.control["network_ico"].set_visible(False)
self.control['time'] = Gtk.Label(label="00:00 AM")
self.control['time_box'] = Gtk.Box(halign=Gtk.Align.END)
self.control['time_box'].pack_end(self.control['time'], True, True, 10)
@ -108,6 +155,10 @@ class BasePanel(ScreenPanel):
self.titlebar.get_style_context().add_class("title_bar")
self.titlebar.add(self.control['temp_box'])
self.titlebar.add(self.titlelbl)
if self._screen.license.is_interface_valid() and not self._screen.license.is_active():
self.titlebar.add(self.control["license_box"])
if self.sdbus_nm:
self.titlebar.add(self.control["network_box"])
self.titlebar.add(self.control['time_box'])
self.set_title(title)
@ -127,6 +178,14 @@ class BasePanel(ScreenPanel):
self.update_time()
def show_license_key_page(self, widget, event):
if "license" not in self._screen._cur_panels:
self._screen.show_panel("license", remove_all=False)
def show_network_page(self, widget, event):
if "network" not in self._screen._cur_panels:
self._screen.show_panel("network", remove_all=False)
def reload_icons(self):
button: Gtk.Button
for button in self.action_bar.get_children():
@ -212,6 +271,8 @@ class BasePanel(ScreenPanel):
def activate(self):
if self.time_update is None:
self.time_update = GLib.timeout_add_seconds(1, self.update_time)
if self.sdbus_nm and self.network_update is None:
self.network_update = GLib.timeout_add_seconds(5, self.network_interface_refresh)
def add_content(self, panel):
printing = self._printer and self._printer.state in {"printing", "paused"}
@ -381,6 +442,35 @@ class BasePanel(ScreenPanel):
self.time_format = confopt
return True
def network_interface_refresh(self, msg=None, level=3):
if self.sdbus_nm:
self.interface = self.sdbus_nm.get_primary_interface()
if self.interface:
if '?' not in self.sdbus_nm.get_ip_address():
if self.interface == "eth0":
self.control["network_ico"].set_from_pixbuf(self.network_icons["ethernet"])
self.control["network_ico"].set_visible(True)
elif self.interface == "wlan0":
strength = self.sdbus_nm.get_signal_strength()
if strength:
self.control["network_ico"].set_from_pixbuf(self.get_signal_strength_icon(strength))
self.control["network_ico"].set_visible(True)
else:
self.control["network_ico"].set_visible(False)
else:
self.control["network_ico"].set_visible(False)
return True
def get_signal_strength_icon(self, signal_level):
if signal_level > 75:
return self.network_icons["excellent"]
elif signal_level > 60:
return self.network_icons["good"]
elif signal_level > 30:
return self.network_icons["fair"]
else:
return self.network_icons["weak"]
def set_ks_printer_cfg(self, printer):
ScreenPanel.ks_printer_cfg = self._config.get_printer_config(printer)
if self.ks_printer_cfg is not None:

View File

@ -37,6 +37,14 @@ class Panel(ScreenPanel):
"callback": self.reset_factory_settings,
}
},
{
"License key": {
"section": "main",
"name": _("License key"),
"type": "button",
"callback": self.license_key,
}
},
{
"version_info": {
"section": "main",
@ -132,19 +140,47 @@ class Panel(ScreenPanel):
self.content.show_all()
self.select_model = False
def license_key(self, *args):
self._screen.show_panel("license", title="license", remove_all=False, full=True)
def reset_factory_settings(self, *args):
text = _("Are you sure?\n") + "\n\n" + _("The system will reboot!")
label = Gtk.Label(wrap=True, vexpand=True)
label.set_markup(text)
buttons = [
{"name": _("Accept"), "response": Gtk.ResponseType.OK, "style": "dialog-error"},
{"name": _("Cancel"), "response": Gtk.ResponseType.CANCEL, "style": "dialog-info"},
]
self._gtk.Dialog(_("factory settings"), buttons, label, self.confirm_factory_reset_production)
text = _("Are you sure?\n") + "\n\n" + _("The system will reboot!")
label = Gtk.Label(wrap=True, vexpand=True)
label.set_markup(text)
label.set_margin_top(100)
def confirm_factory_reset_production(self, dialog, response_id):
checkbox = Gtk.CheckButton(label=" " + _("Enable Registration Code"))
checkbox.set_halign(Gtk.Align.CENTER)
checkbox.set_valign(Gtk.Align.CENTER)
grid = Gtk.Grid(row_homogeneous=True, column_homogeneous=True)
grid.set_row_spacing(20)
grid.set_column_spacing(0)
grid.attach(label, 0, 0, 1, 1)
if self._screen.license.is_interface_valid() and self._screen.license.is_active():
grid.attach(checkbox, 0, 1, 1, 1)
self._gtk.Dialog(
_("factory settings"),
buttons,
grid,
self.confirm_factory_reset_production,
checkbox,
)
def confirm_factory_reset_production(self, dialog, response_id, checkbox):
self._gtk.remove_dialog(dialog)
if response_id == Gtk.ResponseType.OK:
if checkbox.get_active():
if self._screen.license.is_interface_valid():
self._screen.license.enabled_registration()
KlippyFactory.production_factory_reset(self._screen._ws.klippy, self._config)
def version_selection(self, val):

View File

@ -341,6 +341,17 @@ class Panel(ScreenPanel):
def confirm_print_response(self, dialog, response_id, filename):
self._gtk.remove_dialog(dialog)
if response_id == Gtk.ResponseType.OK:
if self._screen.license.is_interface_valid() and not self._screen.license.is_active():
if not self._screen.license.is_time_sufficient():
if "license" not in self._screen._cur_panels:
self._screen.show_panel(
"license",
title="license",
remove_all=False,
func=self._screen._ws.klippy.print_start,
file=filename,
)
return
logging.info(f"Starting print: {filename}")
self._screen._ws.klippy.print_start(filename)

234
panels/license.py Normal file
View File

@ -0,0 +1,234 @@
import logging
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Pango
from ks_includes.screen_panel import ScreenPanel
class Panel(ScreenPanel):
def __init__(self, screen, title, **kwargs):
title = title or _("license")
super().__init__(screen, title)
self.title_text = (
_("This device is not activated and is available for trial use only")
+ "\n"
+ _("Please enter a key to activate")
)
self.key_len = 15
self.full = False
self.interface = screen.license
self.serial_num = self.interface.get_unique_id() or _("Unknown")
self.is_active = self.interface.is_active()
self.args = {}
def update_time(self):
total_printed_time = max(0, self.interface.get_total_printed_time())
trial_time = max(0, self.interface.get_trial_time())
remaining_time = max(0, trial_time - total_printed_time)
self.license_box["elapsed_trial_time_value"].set_text(self.seconds_to_hms(total_printed_time))
self.license_box["trial_time_value"].set_text(self.seconds_to_hms(trial_time))
self.license_box["remain_time_value"].set_text(self.seconds_to_hms(remaining_time))
def seconds_to_hms(self, seconds):
if not isinstance(seconds, (int, float)) or seconds < 0:
raise ValueError(f"seconds must be a non-negative number, got {seconds}")
hours, remainder = divmod(int(seconds), 3600)
minutes, secs = divmod(remainder, 60)
return f"{hours:03}:{minutes:02}:{secs:02}"
def state_update(self, text):
self.license_box["state_text_value"].set_text(text)
def verify_key(self, key):
try:
res = self.interface.verify_activation_code(key)
if res:
if self.interface.is_active():
self.is_active = True
self.state_update(_("Permanent Activation"))
else:
self.state_update(_("Key is valid"))
else:
self.state_update(_("Key is invalid"))
except Exception as e:
logging.exception(e)
def active_refresh(self, **args):
self.args["full"] = args.get("full")
self.args["callback"] = args.get("func")
self.args["file"] = args.get("file")
self.args["onboarding"] = args.get("onboarding")
self.display_dialog()
def deactivate(self):
self._screen.remove_keyboard()
for child in self.content.get_children():
self.content.remove(child)
def display_dialog(self, full=False, key=""):
BUTTON_CONFIGS = {
"trial_with_callback": [
{"name": _("Activate"), "response": Gtk.ResponseType.OK, "style": "dialog-info"},
{"name": _("Skip"), "response": Gtk.ResponseType.CANCEL, "style": "dialog-error"},
],
"full_features": [
{"name": _("Reset"), "response": Gtk.ResponseType.APPLY, "style": "dialog-secondary"},
{"name": _("Activate"), "response": Gtk.ResponseType.OK, "style": "dialog-info"},
{"name": _("Close"), "response": Gtk.ResponseType.CLOSE, "style": "dialog-error"},
],
"Trial": [
{"name": _("Activate"), "response": Gtk.ResponseType.OK, "style": "dialog-info"},
{"name": _("Trial"), "response": Gtk.ResponseType.CLOSE, "style": "dialog-error"},
],
"default": [
{"name": _("Activate"), "response": Gtk.ResponseType.OK, "style": "dialog-info"},
{"name": _("Close"), "response": Gtk.ResponseType.CLOSE, "style": "dialog-error"},
],
}
if self.args.get("callback") and self.interface.is_trial_active():
buttons = BUTTON_CONFIGS["trial_with_callback"]
elif self.args.get("full"):
buttons = BUTTON_CONFIGS["full_features"]
elif self.args.get("onboarding"):
buttons = BUTTON_CONFIGS["Trial"]
else:
buttons = BUTTON_CONFIGS["default"]
self.create_license_key_dialog(buttons=buttons, key=key)
def create_license_key_dialog(self, buttons=None, key=""):
if buttons is None:
buttons = [
{"name": _("Activate"), "response": Gtk.ResponseType.OK, "style": "dialog-info"},
{"name": _("Close"), "response": Gtk.ResponseType.CLOSE, "style": "dialog-error"},
]
self.title_label = Gtk.Label(hexpand=True, vexpand=False, wrap=True, wrap_mode=Pango.WrapMode.WORD_CHAR)
self.title_label.set_markup(f"<big>{self.title_text}</big>\n")
self.title_label.set_margin_top(50)
self.title_label.set_margin_start(20)
self.title_label.set_halign(Gtk.Align.START)
self.license_box = {}
self.grid = Gtk.Grid(column_spacing=20, row_spacing=20, hexpand=True, vexpand=True)
def add_labeled_value(row, label_text, value_text):
label = Gtk.Label(label=label_text, use_markup=True, xalign=0, wrap=True)
value = Gtk.Label(label=value_text, use_markup=True, xalign=0, wrap=True)
self.grid.attach(label, 0, row, 1, 1)
self.grid.attach(value, 1, row, 1, 1)
return label, value
status_text = _("Not activated")
if not self.interface.is_interface_valid():
status_text = _("Unknown")
elif self.is_active:
status_text = _("Permanent Activation")
self.license_box["state_text"], self.license_box["state_text_value"] = add_labeled_value(
0, _("State:"), status_text
)
self.license_box["serial_num_text"], self.license_box["serial_num_value"] = add_labeled_value(
1, _("Serial Number:"), self.serial_num
)
self.license_box["trial_time_text"], self.license_box["trial_time_value"] = add_labeled_value(
2, _("Trial Time:"), "000:00:00"
)
self.license_box["elapsed_trial_time_text"], self.license_box["elapsed_trial_time_value"] = add_labeled_value(
3, _("Elapsed trial time:"), "000:00:00"
)
self.license_box["remain_time_text"], self.license_box["remain_time_value"] = add_labeled_value(
4, _("Remaining Time:"), "000:00:00"
)
self.license_box["key_text"] = Gtk.Label(label=_("Key:"), use_markup=True, xalign=0, wrap=True)
self.grid.attach(self.license_box["key_text"], 0, 5, 1, 1)
self.license_box["key_input"] = Gtk.Entry(hexpand=False, vexpand=False)
self.license_box["key_input"].set_max_length(self.key_len)
self.license_box["key_input"].set_text(key)
self.license_box["key_input"].connect("button-press-event", self.on_show_keyboard)
self.grid.attach(self.license_box["key_input"], 1, 5, 1, 1)
image = self._gtk.Image("license", self._gtk.content_width * 0.4, self._gtk.content_height * 0.4)
image.set_margin_start(60)
image.set_margin_end(20)
main_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, vexpand=True)
horizontal_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, vexpand=True)
horizontal_box.set_margin_top(20)
self.grid.set_margin_start(60)
horizontal_box.pack_start(image, False, True, 0)
horizontal_box.pack_start(self.grid, True, True, 0)
main_box.pack_start(self.title_label, False, True, 0)
main_box.pack_start(horizontal_box, True, True, 0)
self.dialog = self._gtk.Dialog("License", buttons, main_box, self.confirm_license_response)
self.update_time()
def confirm_license_response(self, dialog, response_id):
if response_id == Gtk.ResponseType.YES:
if self.interface.enabled_registration():
self.state_update(_("Enabled successfully"))
elif response_id == Gtk.ResponseType.APPLY:
if len(self.license_box["key_input"].get_text()) == 0:
self.state_update(_("Key is empty"))
return
else:
if self.interface.reset_registration(self.license_box["key_input"].get_text()):
self.update_time()
self.state_update(_("Reset successfully"))
else:
self.state_update(_("Key is invalid"))
elif response_id == Gtk.ResponseType.CLOSE:
self._gtk.remove_dialog(dialog)
self._screen._menu_go_back()
elif response_id == Gtk.ResponseType.CANCEL:
self._gtk.remove_dialog(dialog)
self._screen._menu_go_back()
if not self.interface.is_active() and self.interface.is_trial_active():
if self.args.get("callback"):
self.args["callback"](self.args["file"])
elif response_id == Gtk.ResponseType.OK:
if len(self.license_box["key_input"].get_text()) == 0:
self.state_update(_("Key is empty"))
return
self.verify_key(self.license_box["key_input"].get_text())
self.update_time()
def on_show_keyboard(self, entry=None, event=None):
self._gtk.remove_dialog(self.dialog)
lbl = Gtk.Label(_("Please enter a key to activate"), halign=Gtk.Align.START, hexpand=False)
self.labels["entry"] = Gtk.Entry(hexpand=True)
self.labels["entry"].set_max_length(self.key_len)
self.labels["entry"].connect("focus-in-event", self._screen.show_keyboard)
save = self._gtk.Button("complete", _("Save"), "color3")
save.set_hexpand(False)
save.connect("clicked", self.on_save_key)
input_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=5)
input_box.pack_start(self.labels["entry"], True, True, 5)
input_box.pack_start(save, False, False, 5)
self.labels["input_box"] = Gtk.Box(
orientation=Gtk.Orientation.VERTICAL, spacing=5, hexpand=True, vexpand=True, valign=Gtk.Align.CENTER
)
self.labels["input_box"].pack_start(lbl, True, True, 5)
self.labels["input_box"].pack_start(input_box, True, True, 5)
self.content.add(self.labels["input_box"])
self.labels["entry"].grab_focus_without_selecting()
def on_save_key(self, dialog):
key_text = self.labels["entry"].get_text()
self._screen.remove_keyboard()
for child in self.content.get_children():
self.content.remove(child)
self.display_dialog(self.full, key=key_text)

View File

@ -77,9 +77,7 @@ class Panel(ScreenPanel):
self.labels['interface'] = Gtk.Label(hexpand=True)
self.labels['ip'] = Gtk.Label(hexpand=True)
if self.interface is not None:
self.labels['interface'].set_text(_("Interface") + f': {self.interface}')
self.labels['ip'].set_text(f"IP: {self.sdbus_nm.get_ip_address()}")
self.network_interface_refresh()
self.reload_button = self._gtk.Button("refresh", None, "custom-icon-button", self.bts)
self.reload_button.set_no_show_all(True)
@ -120,6 +118,7 @@ class Panel(ScreenPanel):
self.network_list.connect("row-activated", self.handle_wifi_selection)
def popup_callback(self, msg, level=3):
self.network_interface_refresh()
if not self.refresh_status(msg):
for item in self.network_rows:
if self.network_rows[item]["label_state"] is not None:
@ -127,6 +126,12 @@ class Panel(ScreenPanel):
self.network_rows[item]["label_state"].hide()
self._screen.show_popup_message(msg, level)
def network_interface_refresh(self):
if self.interface is not None:
self.interface = self.sdbus_nm.get_primary_interface()
self.labels['interface'].set_text(_("Interface") + f': {self.interface}')
self.labels['ip'].set_text(f"IP: {self.sdbus_nm.get_ip_address()}")
def handle_wifi_selection(self, list_box, row):
index = row.get_index()
logging.info(f"clicked SSID is {self.networks[index]['SSID']}")
@ -407,6 +412,7 @@ class Panel(ScreenPanel):
if self.delay_reload_timer_id:
GLib.source_remove(self.delay_reload_timer_id)
self.delay_reload_timer_id = None
self.network_interface_refresh()
return self.sdbus_nm.nm.wireless_enabled
@ -438,7 +444,7 @@ class Panel(ScreenPanel):
return
if self.sdbus_nm.wifi:
if self.sdbus_nm.is_wifi_enabled():
self.delay_reload_networks(1000)
self.delay_reload_networks(2000)
self.start_refresh_timer()
def deactivate(self):
@ -464,3 +470,4 @@ class Panel(ScreenPanel):
self.reload_button.hide()
self.network_list.set_no_show_all(True)
self.network_list.hide()
self.network_interface_refresh()

View File

@ -67,3 +67,6 @@ class Panel(ScreenPanel):
self._screen.show_panel("main_menu", remove_all=True, items=self._config.get_menu_items("__main"))
self._config.set("main", "onboarding", "False")
self._config.save_user_config_options()
if self._screen.license.is_interface_valid() and not self._screen.license.is_active():
self._gtk.remove_dialog(dialog)
self._screen.show_panel("license", remove_all=False, onboarding=True)

View File

@ -28,6 +28,7 @@ from ks_includes.printer import Printer
from ks_includes.widgets.keyboard import Keyboard
from ks_includes.widgets.prompts import Prompt
from ks_includes.config import KlipperScreenConfig
from ks_includes.sdbus_reg import LicenseManager
from panels.base_panel import BasePanel
logging.getLogger("urllib3").setLevel(logging.WARNING)
@ -89,6 +90,8 @@ class KlipperScreen(Gtk.Window):
self.confirm = None
self.panels_reinit = []
self.last_popup_time = datetime.now()
self.license = LicenseManager()
logging.info(f"license interface:{self.license}")
configfile = os.path.normpath(os.path.expanduser(args.configfile))

View File

@ -0,0 +1,3 @@
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M37.4 25.6C37 21.2 33.6 18.2 29 18H26C25.8 15.4 26.8 11.8 31 11.4C32.8 11.2 34.4 11.6 35.8 13C37 14.4 37.4 16 37.4 17.8C37.4 18 37.4 18.4 37.6 18.6L39.4 20.4C40 18.6 40 16.8 39.6 15C38.6 11.4 35.6 9.2 31.8 9C29.6 9 27.6 9.4 26 11C23.2 13.6 22.2 19.4 26.2 23.2C26.8 23.8 27.6 24.2 28.4 24.6C29.4 25 30.2 24.2 30.2 23.4C30.2 22.6 29.8 22 28.8 21.8C28.6 21.8 28.4 21.6 28.2 21.4V21.2C29 21 30 21.2 30.6 21.8C31.2 22.4 31.4 23.2 31.2 24.2C30.8 25.6 29.6 26.2 28 25.8C25.8 25.2 24.4 23.8 23.4 21.8C23.2 21.2 22.8 20.6 22.6 20C21.2 21.4 20 22.8 19.6 24.8C18.8 28.4 19.8 31.4 22.4 33.8C22.6 34 22.8 34.2 22.6 34.6C22.4 36.2 22.2 37.6 21.8 39.2C21.2 42.6 20.8 45.8 20.2 49.2C20 50.2 20 51.4 20.2 52.4C20.4 53.2 20.8 53.8 21.8 54.2C22 53.4 22 52.6 22.2 51.8C22.8 48.4 23.2 45.2 23.8 41.8C24.2 39.8 24.4 37.6 24.8 35.6C24.8 35.2 25 35 25.4 35C25.8 35 25.8 35.4 25.8 35.8C25.6 37.8 25.2 39.8 24.8 41.6C24.2 45.8 23.4 50 22.8 54.2C22.8 54.4 23 54.6 23 54.6C24 54.6 24.8 54.8 25.8 54.8C26.8 54.8 27.6 54 28.2 53.2C28.8 52.6 28.8 51.8 28.4 51C28.2 50.8 28 50.6 28 50.4C27.4 49.6 27.6 49 28.4 48.6C28.6 48.4 29 48.4 29.2 48.2C29.6 48 29.8 47.4 29.4 47C28.8 46.4 28.4 45.8 27.8 45.4C27.4 45 27.6 44.2 28 44C28.6 43.6 29.4 43.4 30 43C30.4 42.8 30.6 42.4 30.2 42C30 41.8 29.8 41.6 29.6 41.2C29 40.6 29.2 39.6 29.8 39.2C30 39 30.2 38.8 30.6 38.8C31 38.6 31.2 38.4 31.2 38C31.2 37.4 31.4 36.8 31.4 36.2C31.4 36 31.6 35.6 31.8 35.4C32.4 34.8 33.2 34.4 34 34C36.8 32 37.8 29 37.4 25.6ZM44.6 48.4C44.6 48 44.4 47.6 43.8 47.6C43.4 47.6 42.8 47.6 42.6 47C42.4 46.4 42.4 45.8 42.6 45.2C43 44.4 42.8 43.8 41.8 43.6C41.4 43.6 41 43.4 40.4 43.4C40 43.4 39.8 43.2 39.8 42.8C39.8 42.4 39.6 42 39.6 41.6C39.6 41 40 40.6 40.4 40.2C40.8 39.6 40.8 39.4 40.2 39C40 38.8 39.6 38.6 39.4 38.4C38.6 38 38.6 37.6 39 36.8C39.2 36.6 39.4 36.4 39.4 36.2C39.8 35.8 39.8 35.4 39.6 35C39.4 34.6 39.2 34 38.8 33.6C38.6 33.2 38.6 32.8 38.8 32.4C40.4 29.2 40.8 26 39.4 22.6C38.4 20.4 36.6 19 34.2 18.4L34 18.6C34.2 18.8 34.4 19.2 34.6 19.4C37 21.4 38.4 24 38.4 27.2C38.4 30.6 37 33.4 34 35.6C33.6 35.8 33.4 36.2 33.6 36.6C34.4 38.6 35 40.4 35.8 42.4C37.4 46.2 39 49.8 40.6 53.6C40.8 53.8 40.8 54 41.2 54C43.6 52.8 45 50.6 44.6 48.4ZM32.6 36.6C32.4 37.4 32.4 38 32.2 38.6C32.2 39 32 39.4 32.2 39.8C33.6 43.2 35 46.8 36.4 50.2C36.8 51.2 37.4 52.2 38.4 53C38.8 53.2 39.2 53.4 39.4 53.6L39.6 53.4C37.4 47.8 35 42.2 32.6 36.6Z" fill="#DBCD68"/>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1,3 @@
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M37.4 25.6C37 21.2 33.6 18.2 29 18H26C25.8 15.4 26.8 11.8 31 11.4C32.8 11.2 34.4 11.6 35.8 13C37 14.4 37.4 16 37.4 17.8C37.4 18 37.4 18.4 37.6 18.6L39.4 20.4C40 18.6 40 16.8 39.6 15C38.6 11.4 35.6 9.2 31.8 9C29.6 9 27.6 9.4 26 11C23.2 13.6 22.2 19.4 26.2 23.2C26.8 23.8 27.6 24.2 28.4 24.6C29.4 25 30.2 24.2 30.2 23.4C30.2 22.6 29.8 22 28.8 21.8C28.6 21.8 28.4 21.6 28.2 21.4V21.2C29 21 30 21.2 30.6 21.8C31.2 22.4 31.4 23.2 31.2 24.2C30.8 25.6 29.6 26.2 28 25.8C25.8 25.2 24.4 23.8 23.4 21.8C23.2 21.2 22.8 20.6 22.6 20C21.2 21.4 20 22.8 19.6 24.8C18.8 28.4 19.8 31.4 22.4 33.8C22.6 34 22.8 34.2 22.6 34.6C22.4 36.2 22.2 37.6 21.8 39.2C21.2 42.6 20.8 45.8 20.2 49.2C20 50.2 20 51.4 20.2 52.4C20.4 53.2 20.8 53.8 21.8 54.2C22 53.4 22 52.6 22.2 51.8C22.8 48.4 23.2 45.2 23.8 41.8C24.2 39.8 24.4 37.6 24.8 35.6C24.8 35.2 25 35 25.4 35C25.8 35 25.8 35.4 25.8 35.8C25.6 37.8 25.2 39.8 24.8 41.6C24.2 45.8 23.4 50 22.8 54.2C22.8 54.4 23 54.6 23 54.6C24 54.6 24.8 54.8 25.8 54.8C26.8 54.8 27.6 54 28.2 53.2C28.8 52.6 28.8 51.8 28.4 51C28.2 50.8 28 50.6 28 50.4C27.4 49.6 27.6 49 28.4 48.6C28.6 48.4 29 48.4 29.2 48.2C29.6 48 29.8 47.4 29.4 47C28.8 46.4 28.4 45.8 27.8 45.4C27.4 45 27.6 44.2 28 44C28.6 43.6 29.4 43.4 30 43C30.4 42.8 30.6 42.4 30.2 42C30 41.8 29.8 41.6 29.6 41.2C29 40.6 29.2 39.6 29.8 39.2C30 39 30.2 38.8 30.6 38.8C31 38.6 31.2 38.4 31.2 38C31.2 37.4 31.4 36.8 31.4 36.2C31.4 36 31.6 35.6 31.8 35.4C32.4 34.8 33.2 34.4 34 34C36.8 32 37.8 29 37.4 25.6ZM44.6 48.4C44.6 48 44.4 47.6 43.8 47.6C43.4 47.6 42.8 47.6 42.6 47C42.4 46.4 42.4 45.8 42.6 45.2C43 44.4 42.8 43.8 41.8 43.6C41.4 43.6 41 43.4 40.4 43.4C40 43.4 39.8 43.2 39.8 42.8C39.8 42.4 39.6 42 39.6 41.6C39.6 41 40 40.6 40.4 40.2C40.8 39.6 40.8 39.4 40.2 39C40 38.8 39.6 38.6 39.4 38.4C38.6 38 38.6 37.6 39 36.8C39.2 36.6 39.4 36.4 39.4 36.2C39.8 35.8 39.8 35.4 39.6 35C39.4 34.6 39.2 34 38.8 33.6C38.6 33.2 38.6 32.8 38.8 32.4C40.4 29.2 40.8 26 39.4 22.6C38.4 20.4 36.6 19 34.2 18.4L34 18.6C34.2 18.8 34.4 19.2 34.6 19.4C37 21.4 38.4 24 38.4 27.2C38.4 30.6 37 33.4 34 35.6C33.6 35.8 33.4 36.2 33.6 36.6C34.4 38.6 35 40.4 35.8 42.4C37.4 46.2 39 49.8 40.6 53.6C40.8 53.8 40.8 54 41.2 54C43.6 52.8 45 50.6 44.6 48.4ZM32.6 36.6C32.4 37.4 32.4 38 32.2 38.6C32.2 39 32 39.4 32.2 39.8C33.6 43.2 35 46.8 36.4 50.2C36.8 51.2 37.4 52.2 38.4 53C38.8 53.2 39.2 53.4 39.4 53.6L39.6 53.4C37.4 47.8 35 42.2 32.6 36.6Z" fill="#DBCD68"/>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB