diff --git a/.gitignore b/.gitignore index a2caef9..417bced 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ __pycache__/ /TrimLog /logs *.llc.config +/MSCT salt.py diff --git a/llc_cli.py b/llc_cli.py index ce023ed..e58c0be 100644 --- a/llc_cli.py +++ b/llc_cli.py @@ -7,18 +7,19 @@ 伶伦转换器 命令行 Linglun Converter CLI -版权所有 © 2024 金羿 & 睿穆开发组 +版权所有 © 2024 金羿 & 睿乐开发组 Copyright © 2024 EillesWan & TriM Org. 开源相关声明请见 ./License.md Terms & Conditions: ./Lisense.md """ -__version__ = "0.0.6" +__version__ = "0.0.7" import datetime import os import random + # import sys import Musicreater @@ -29,8 +30,14 @@ from Musicreater.plugin.addonpack import ( to_addon_pack_in_repeater, to_addon_pack_in_score, ) + +from Musicreater.plugin.mcstructfile import ( + to_mcstructure_file_in_delay, + to_mcstructure_file_in_repeater, + # to_mcstructure_file_in_score, +) from Musicreater.plugin.bdxfile import to_BDX_file_in_delay, to_BDX_file_in_score -from utils.io import MainConsole, prt, ipt, myWords, isin, bool_str, float_str +from utils.io import MainConsole, int_str, prt, ipt, myWords, isin, bool_str, float_str # from Musicreater.plugin.mcstructure import commands_to_structure, commands_to_redstone_delay_structure @@ -57,10 +64,14 @@ MainConsole.print( # 显示大标题 -MainConsole.rule(title="[bold #AB70FF]欢迎使用伶伦独立转换器", characters="=", style="#26E2FF") +MainConsole.rule( + title="[bold #AB70FF]欢迎使用伶伦独立转换器", characters="=", style="#26E2FF" +) # MainConsole.rule(title="[bold #AB70FF]Welcome to Linglun Converter", characters="-") MainConsole.rule( - title="[#AB70FF]版本{} | 音·创内核版本{}".format(__version__, Musicreater.__version__), + title="[#AB70FF]版本{} | 音·创内核版本{}".format( + __version__, Musicreater.__version__ + ), characters="-", style="#26E2FF", ) @@ -70,14 +81,18 @@ nowYang = datetime.datetime.now() if nowYang.month == 8 and nowYang.day == 6: # 诸葛八卦生日 MainConsole.print( - "[#7DB5F0 on #121110]今天可不是催更的日子!\n诸葛亮与八卦阵{}岁生日快乐!".format(nowYang.year - 2008), + "[#7DB5F0 on #121110]今天可不是催更的日子!\n诸葛亮与八卦阵{}岁生日快乐!".format( + nowYang.year - 2008 + ), style="#7DB5F0 on #121110", justify="center", ) elif nowYang.month == 4 and nowYang.day == 3: # 金羿生日快乐 MainConsole.print( - "[#0089F2 on #F0F2F4]今天就不要催更啦!\n金羿{}岁生日快乐!".format(nowYang.year - 2006), + "[#0089F2 on #F0F2F4]今天就不要催更啦!\n金羿{}岁生日快乐!".format( + nowYang.year - 2006 + ), style="#0089F2 on #F0F2F4", justify="center", ) @@ -155,20 +170,36 @@ while True: def is_in_bdx_mcpack(sth: str): - return isin(sth, {1: ("bdx", "1", "币帝查", "币帝·艾克斯"), 0: ("mcpack", "0", "唉姆西·派克")}) - - -def is_in_player(sth: str): return isin( sth, { - 0: ("delay", "0", "延迟", "帝蕾"), - 1: ("score", "1", "计分板", "积分", "积分板", "计分", "斯阔尔"), - 2: ("repeater", "2", "中继器", "瑞皮特"), + 1: ("bdx", "1", "币帝查", "币帝·艾克斯", "一", "幺"), + 0: ("mcpack", "0", "唉姆西·派克", "零", "〇"), + 2: ("MCSTRUCTURE", "2", "二", "麦块结构", "MC结构", "两", "我的世界结构"), }, ) +def is_in_player(sth: str, in_ok: tuple): + return isin( + sth, + dict( + [ + (i, v) + for i, v in [ + 0, + ("delay", "0", "延迟", "帝蕾"), + 1, + ("score", "1", "计分板", "积分", "积分板", "计分", "斯阔尔"), + 2, + ("repeater", "2", "中继器", "瑞皮特"), + ] + if i in in_ok + ] + ), + ) + + output_file_format = format_ipt( "输出文件类型 (mcpack/0|bdx/1)", is_in_bdx_mcpack, @@ -181,15 +212,23 @@ if output_file_format == 0: is_in_player, "输入内容有误,请重新输入。", )[1] -else: +elif output_file_format == 1: player_format = format_ipt( "播放器类型 (延迟/0|计分板/1)", - is_in_player, + lambda a: is_in_player(a, (0, 1)), + "输入内容有误,请重新输入。", + )[1] +else: + player_format = format_ipt( + "播放器类型 (延迟/0|中继器/2)", + lambda a: is_in_player(a, (0, 2)), "输入内容有误,请重新输入。", )[1] old_exe_enabled = not format_ipt( - "启用新版代执行指令 (否/0|是/1):", bool_str, "输入内容格式错误,应为 是/1/真/t/y 或 否/0/假/f/n" + "启用新版代执行指令 (否/0|是/1):", + bool_str, + "输入内容格式错误,应为 是/1/真/t/y 或 否/0/假/f/n", )[1] @@ -216,41 +255,75 @@ else: bool_str, ), ( - "计分板名称:", - str, - ) - if player_format == 1 - else ( - "受播放玩家的选择器:", - str, + ( + "计分板名称:", + str, + ) + if player_format == 1 + else ( + "受播放玩家的选择器:", + str, + ) ), ( - "自动重置计分板 (否/0|是/1):", - bool_str, - ) - if player_format == 1 - else (), + ( + "自动重置计分板 (否/0|是/1):", + bool_str, + ) + if player_format == 1 + else () + ), ( - "BDX作者署名:", - str, - ) - if output_file_format == 1 - else (), + ( + "BDX作者署名:", + str, + ) + if output_file_format == 1 + else ( + ( + "结构延展方向(x+|z+|x-|z-):", + lambda a: isin( + a, + { + "z+": ["z+", "Z+"], + "x+": ["X+", "x+"], + "z-": ["Z-", "z-"], + "x-": ["x-", "X-"], + }, + ), + ) + if (player_format == 2 and output_file_format == 2) + else () + ) + ), ( - "结构生成最大高度 (0,+∞):", - int, - ) - if player_format == 0 - else (), + ( + "结构生成最大高度 (0,+∞):", + int_str, + ) + if player_format == 0 + else ( + ( + "基础空白方块(例:concrete):", + str, + ) + if (player_format == 2 and output_file_format == 2) + else () + ) + ), ]: if args: prompts.append( - format_ipt(*args, err_note="输入内容格式错误,应符合 {}".format(args[1]))[1] + format_ipt( + *args, err_note="输入内容格式错误,应符合 {}".format(args[1]) + )[1] ) if prompts[2]: costom_pgb_enabled = format_ipt( - "自定义进度条样式 (否/0|是/1):", bool_str, "输入内容格式错误,应为 是/1/真/t/y 或 否/0/假/f/n" + "自定义进度条样式 (否/0|是/1):", + bool_str, + "输入内容格式错误,应为 是/1/真/t/y 或 否/0/假/f/n", )[1] if costom_pgb_enabled: style = ipt("基本样式组 (回车默认):") @@ -263,12 +336,20 @@ if prompts[2]: if not done_part: done_part = DEFAULT_PROGRESSBAR_STYLE[1][0] -if player_format == 1: - cvt_method = to_addon_pack_in_score -elif player_format == 0: - cvt_method = to_addon_pack_in_delay -elif player_format == 2: - cvt_method = to_addon_pack_in_repeater +if output_file_format == 0: + if player_format == 1: + cvt_method = to_addon_pack_in_score + elif player_format == 0: + cvt_method = to_addon_pack_in_delay + elif player_format == 2: + cvt_method = to_addon_pack_in_repeater +elif output_file_format == 2: + # if player_format == 1: + # cvt_method = to_mcstructure_file_in_score + if player_format == 0: + cvt_method = to_mcstructure_file_in_delay + elif player_format == 2: + cvt_method = to_mcstructure_file_in_repeater for singleMidi in midis: @@ -276,20 +357,34 @@ for singleMidi in midis: cvt_mid = Musicreater.MidiConvert.from_midi_file( singleMidi, old_exe_format=old_exe_enabled ) - cvt_cfg = ConvertConfig(out_path, *prompts[:2], progressbar=((style, (done_part, yet_part)) if costom_pgb_enabled else True) if prompts[2] else False) # type: ignore + cvt_cfg = ConvertConfig( + out_path, + *prompts[:2], + progressbar=( + ((style, (done_part, yet_part)) if costom_pgb_enabled else True) # type: ignore + if prompts[2] + else False + ), + ) conversion_result = ( - (cvt_method(cvt_mid, cvt_cfg, *prompts[3:])) # type: ignore + (cvt_method(cvt_mid, cvt_cfg, *prompts[3:])) # type: ignore if output_file_format == 0 else ( - to_BDX_file_in_score(cvt_mid, cvt_cfg, *prompts[3:]) - if player_format == 1 - else to_BDX_file_in_delay(cvt_mid, cvt_cfg, *prompts[3:]) + ( + to_BDX_file_in_score(cvt_mid, cvt_cfg, *prompts[3:]) + if player_format == 1 + else to_BDX_file_in_delay(cvt_mid, cvt_cfg, *prompts[3:]) + ) + if output_file_format == 1 + else (cvt_method(cvt_mid, cvt_cfg, *prompts[3:])) # type: ignore ) ) prt( - f" 指令总长:{conversion_result[0]},播放刻数:{conversion_result[1]}{f''',结构大小:{conversion_result[2]},末点坐标:{conversion_result[3]}''' if output_file_format == 1 else ''}" # type: ignore + f" 结构大小:{conversion_result[0]},播放刻数:{conversion_result[1]}" + if output_file_format == 2 + else f" 指令总长:{conversion_result[0]},播放刻数:{conversion_result[1]}{f''',结构大小:{conversion_result[2]},末点坐标:{conversion_result[3]}''' if output_file_format == 1 else ''}" # type: ignore ) exitSth = ipt("结束。换行以退出程序。") diff --git a/llc_spec_Creeper.py b/llc_spec_Creeper.py index 3e305d4..4c15e81 100644 --- a/llc_spec_Creeper.py +++ b/llc_spec_Creeper.py @@ -7,7 +7,7 @@ 伶伦转换器暨模组特用奇巧 Linglun Converter for Special Use with addons -版权所有 © 2024 金羿 & 睿穆开发组 +版权所有 © 2024 金羿 & 睿乐开发组 Copyright © 2024 EillesWan & TriM Org. 开源相关声明请见 ./License.md diff --git a/llc_win_wxPython.py b/llc_win_wxPython.py index d912b51..108dee4 100644 --- a/llc_win_wxPython.py +++ b/llc_win_wxPython.py @@ -4,7 +4,7 @@ 伶伦转换器 WXGUI Linglun Converter WxPython GUI -版权所有 © 2024 金羿 & 睿穆开发组 +版权所有 © 2024 金羿 & 睿乐开发组 Copyright © 2024 EillesWan & TriM Org. 开源相关声明请见 ./License.md @@ -16,6 +16,9 @@ Terms & Conditions: ./Lisense.md import os import random import sys +from types import ModuleType + +import requests if sys.argv: if "-l" in sys.argv: @@ -27,7 +30,8 @@ if sys.argv: exit() import Musicreater -import Musicreater.experiment +import Musicreater.experiment as Musicreater_experiment +import Musicreater.plugin as Musicreater_plugin from Musicreater.plugin import ConvertConfig from Musicreater.plugin.addonpack import ( to_addon_pack_in_delay, @@ -40,33 +44,221 @@ import wx import wx.xrc import wx.propgrid as pg -from utils.io import myWords, logger, object_constants # , TrimLog, is_logging -from utils.update_check import check_update -from utils.packdata import enpack_llc_pack, unpack_llc_pack +from utils.io import ( + myWords, + logger, + object_constants, + log__init__, + TrimLog, + Tuple, + Any, + Union, + Callable, + Literal, +) +from utils.update_check import check_update_repo, check_update_release +from utils.packdata import enpack_llc_pack, unpack_llc_pack, load_msct_packed_data +from utils.webview import go_update_tip -logger.info("注册全局变量……") +logger.info("注册变量并读取内容……") WHITE = (242, 244, 246) # F2F4F6 +WHITE2 = (248, 252, 255) +# WHITE3 = (233, 236, 240) BLACK = (18, 17, 16) # 121110 +BLACK2 = (9, 12, 14) +# BLACK3 = (0, 2, 6) + +# WHITE = (18, 17, 16) # F2F4F6 +# WHITE2 = (9, 12, 14) +# BLACK = (242, 244, 246) # 121110 +# BLACK2 = (248, 252, 255) __appname__ = "伶伦转换器" -__version__ = "WXGUI 1.0.0" -__zhver__ = "WX图形界面 初代预版第〇次修订" +__version__ = "WXGUI 1.1.0" +__zhver__ = "WX图形界面 初代首版第〇次修订" yanlun_length = len(myWords) +msct_main = msct_plugin = msct_plugin_function = None -# global pgb_style -# global on_exit_saving -# global ignore_midi_mismatch_error -# global convert_tables -# global convert_table_selection -# global ConvertClass +if os.path.exists("./MSCT/Musicreater.llc.pack"): + logger.info("已发现音·创本地包,读取中") + # unpacked_data_msct: Union[ + # Any, + # Tuple[ + # Tuple[ModuleType, ModuleType, ModuleType], + # Tuple[ModuleType], + # Tuple[ + # Callable[ + # [ + # Musicreater.MidiConvert, + # Musicreater_plugin.ConvertConfig, + # str, + # int, + # ], + # Tuple[int, int], + # ], + # Callable[ + # [ + # Musicreater.MidiConvert, + # Musicreater_plugin.ConvertConfig, + # str, + # int, + # ], + # Tuple[int, int], + # ], + # Callable[ + # [ + # Musicreater.MidiConvert, + # Musicreater_plugin.ConvertConfig, + # str, + # bool, + # ], + # Tuple[int, int], + # ], + # Callable[ + # [ + # Musicreater.MidiConvert, + # Musicreater_plugin.ConvertConfig, + # str, + # int, + # ], + # Tuple[Tuple[int, int, int], int], + # ], + # Callable[ + # [ + # Musicreater.MidiConvert, + # Musicreater_plugin.ConvertConfig, + # str, + # Literal["z+", "z-", "Z+", "Z-", "x+", "x-", "X+", "X-"], + # str, + # ], + # Tuple[Tuple[int, int, int], int], + # ], + # Callable[ + # [ + # Musicreater.MidiConvert, + # Musicreater_plugin.ConvertConfig, + # str, + # bool, + # int, + # ], + # Tuple[Tuple[int, int, int], int, int], + # ], + # Callable[ + # [ + # Musicreater.MidiConvert, + # Musicreater_plugin.ConvertConfig, + # str, + # str, + # int, + # ], + # Tuple[int, int, Tuple[int, int, int], Tuple[int, int, int]], + # ], + # Callable[ + # [ + # Musicreater.MidiConvert, + # Musicreater_plugin.ConvertConfig, + # str, + # bool, + # str, + # int, + # ], + # Tuple[int, int, Tuple[int, int, int], Tuple[int, int, int]], + # ], + # ], + # ], + # ] = unpack_llc_pack("./MSCT/Musicreater.llc.pack", False) + unpacked_data_msct = unpack_llc_pack("./MSCT/Musicreater.llc.pack", False) + if isinstance(unpacked_data_msct, Exception): + logger.warning("读取内核文件失败:{};即将从互联网下载 音·创。") + else: + (msct_main, msct_plugin, msct_plugin_function) = unpacked_data_msct + ( + Musicreater, + Musicreater_experiment, + Musicreater_previous, + ) = msct_main + Musicreater_plugin = msct_plugin + ( + to_addon_pack_in_delay, + to_addon_pack_in_repeater, + to_addon_pack_in_score, + to_mcstructure_file_in_delay, + to_mcstructure_file_in_repeater, + to_mcstructure_file_in_score, + to_BDX_file_in_delay, + to_BDX_file_in_score, + ) = msct_plugin_function + # with open(, "rb") as f: + # f.write("MSCT_MAIN:\n") + # f.write(enpack_msct_pack(MSCT_MAIN, "./Packer/MSCT_MAIN.MPK").hexdigest()) + # f.write("\nMSCT_PLUGIN:\n") + # f.write(enpack_msct_pack(MSCT_PLUGIN, "./Packer/MSCT_PLUGIN.MPK").hexdigest()) + # f.write("\nMSCT_PLUGIN_FUNCTION:\n") + # f.write( + # enpack_msct_pack( + # MSCT_PLUGIN_FUNCTION, "./Packer/MSCT_PLUGIN_FUNCTION.MPK" + # ).hexdigest() + # ) -pgb_style: Musicreater.ProgressBarStyle = Musicreater.DEFAULT_PROGRESSBAR_STYLE.copy() + +logger.info("启用音·创更新检查") + +down_paths = check_update_release( + "音·创", + "https://gitee.com/TriM-Organization/Musicreater/releases/latest", + Musicreater.__version__, + go_update_tip, + logger, + "!转换器内核已经更新!\n新版本 {app} {latest} 可用,当前仍是 {current}\n是否更新?", +) + +logger.info("获取到版本检查信息:{}".format(down_paths)) + +if down_paths: + + os.remove("save.llc.config") + + unpacked_data_msct = [] + if not os.path.exists("./MSCT/"): + os.makedirs("./MSCT/") + chk_md5 = requests.get("https://gitee.com" + down_paths["checksum.txt"]).text.split( + "\r\n" + ) + for fn, lk in down_paths.items(): + if fn == "checksum.txt": + continue + unpacked_data_msct.append( + load_msct_packed_data( + requests.get("https://gitee.com" + lk).content, + chk_md5[chk_md5.index("{}:".format(os.path.splitext(fn)[0])) + 1], + ) + ) + enpack_llc_pack(tuple(unpacked_data_msct), "./MSCT/Musicreater.llc.pack") + (msct_main, msct_plugin, msct_plugin_function) = unpacked_data_msct + ( + Musicreater, + Musicreater_experiment, + Musicreater_previous, + ) = msct_main + Musicreater_plugin = msct_plugin + ( + to_addon_pack_in_delay, + to_addon_pack_in_repeater, + to_addon_pack_in_score, + to_mcstructure_file_in_delay, + to_mcstructure_file_in_repeater, + to_mcstructure_file_in_score, + to_BDX_file_in_delay, + to_BDX_file_in_score, + ) = msct_plugin_function + +pgb_style: Musicreater.ProgressBarStyle = Musicreater.DEFAULT_PROGRESSBAR_STYLE.copy() # type: ignore on_exit_saving: bool = True ignore_midi_mismatch_error: bool = True convert_tables = { @@ -104,9 +296,19 @@ osc = object_constants.ObjectStateConstant( logging_project_name=__appname__, logging_project_version=__version__, logging_exit_exec=lambda sth: wx.MessageDialog( - None, sth, "崩溃", wx.YES_DEFAULT | wx.ICON_STOP + None, + sth + "\n问题不大吧?有问题拜托请报给开发者!谢谢!", + "崩溃", + wx.YES_DEFAULT | wx.ICON_STOP, ).ShowModal(), + # is_this_a_release=True, ) +# print(osc.exit_execution) +osc.set_console(logger.console) + +log__init__(osc, TrimLog.PipManage(True, True, 40), True) + + logger.printing = not osc.is_release @@ -253,6 +455,9 @@ class LingLunMainFrame(wx.Frame): ) ) + self.mian_notebook.SetForegroundColour(BLACK) + self.mian_notebook.SetBackgroundColour(WHITE) + self.convert_page = ConvertPagePanel( self.mian_notebook, wx.ID_ANY, @@ -328,12 +533,13 @@ logger.info("加载分页……") class ConvertPagePanel(wx.Panel): + def __init__( self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, - size=wx.Size(565, 540), + size=wx.Size(652, 588), style=wx.TAB_TRAVERSAL, name=wx.EmptyString, ): @@ -341,12 +547,15 @@ class ConvertPagePanel(wx.Panel): self, parent, id=id, pos=pos, size=size, style=style, name=name ) - self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW)) + self.SetBackgroundColour(WHITE2) + self.SetForegroundColour(BLACK2) main_page_sizer = wx.BoxSizer(wx.VERTICAL) s_midiChooseSizer = wx.BoxSizer(wx.HORIZONTAL) + MidiChooser_Delete_and_Tips_bSizer15 = wx.BoxSizer(wx.VERTICAL) + self.m_ChooseMidiTips_staticText3 = wx.StaticText( self, wx.ID_ANY, @@ -357,31 +566,54 @@ class ConvertPagePanel(wx.Panel): ) self.m_ChooseMidiTips_staticText3.Wrap(-1) + MidiChooser_Delete_and_Tips_bSizer15.Add( + self.m_ChooseMidiTips_staticText3, 0, wx.ALL | wx.ALIGN_CENTER_HORIZONTAL, 5 + ) + + self.m_done_then_remove_checkBox6 = wx.CheckBox( + self, wx.ID_ANY, "完成后移除", wx.DefaultPosition, wx.DefaultSize, 0 + ) + MidiChooser_Delete_and_Tips_bSizer15.Add( + self.m_done_then_remove_checkBox6, 0, wx.ALL, 5 + ) + s_midiChooseSizer.Add( - self.m_ChooseMidiTips_staticText3, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5 + MidiChooser_Delete_and_Tips_bSizer15, 0, wx.SHAPED | wx.EXPAND, 0 ) ss_MidiChooserSizer_bSizer9 = wx.BoxSizer(wx.VERTICAL) + self.midiFilesList = set() self.m_midiFilesList_listBox2 = wx.ListBox( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, - [], + list(self.midiFilesList), wx.LB_HSCROLL | wx.LB_SORT, ) - ss_MidiChooserSizer_bSizer9.Add(self.m_midiFilesList_listBox2, 0, wx.EXPAND, 0) + ss_MidiChooserSizer_bSizer9.Add(self.m_midiFilesList_listBox2, 1, wx.EXPAND, 0) s_midiChooseSizer.Add(ss_MidiChooserSizer_bSizer9, 1, wx.EXPAND, 5) + MidiChooser_Open_and_Clear_Buttons_bSizer16 = wx.BoxSizer(wx.VERTICAL) + self.m_midiBroseButton_button21 = wx.Button( self, wx.ID_ANY, "打开…", wx.DefaultPosition, wx.DefaultSize, 0 ) - s_midiChooseSizer.Add( - self.m_midiBroseButton_button21, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5 + MidiChooser_Open_and_Clear_Buttons_bSizer16.Add( + self.m_midiBroseButton_button21, 0, wx.ALL | wx.EXPAND, 5 ) + self.m_midiChooser_Clear_button3 = wx.Button( + self, wx.ID_ANY, "清空文件", wx.DefaultPosition, wx.DefaultSize, 0 + ) + MidiChooser_Open_and_Clear_Buttons_bSizer16.Add( + self.m_midiChooser_Clear_button3, 0, wx.ALL | wx.EXPAND, 5 + ) + + s_midiChooseSizer.Add(MidiChooser_Open_and_Clear_Buttons_bSizer16, 0, wx.ALL, 5) + main_page_sizer.Add(s_midiChooseSizer, 0, wx.EXPAND, 5) s_formatChooseSizer = wx.BoxSizer(wx.HORIZONTAL) @@ -419,7 +651,7 @@ class ConvertPagePanel(wx.Panel): m_playerChoice_choice2Choices, 0, ) - self.m_playerChoice_choice2.SetSelection(0) + self.m_playerChoice_choice2.SetSelection(2) ss_playerChooseSizer.Add(self.m_playerChoice_choice2, 0, wx.ALL | wx.EXPAND, 5) s_formatChooseSizer.Add(ss_playerChooseSizer, 1, wx.ALL | wx.EXPAND, 5) @@ -467,10 +699,7 @@ class ConvertPagePanel(wx.Panel): ) ss_regularPromoptsEnteringSizer1.Add( - sss_VolumnPersentageEnteringSizer, - 0, - wx.ALL | wx.EXPAND | wx.SHAPED | wx.ALIGN_CENTER_VERTICAL, - 5, + sss_VolumnPersentageEnteringSizer, 0, wx.ALL | wx.EXPAND, 5 ) sss_SpeedEnteringSizer = wx.StaticBoxSizer( @@ -506,10 +735,7 @@ class ConvertPagePanel(wx.Panel): sss_SpeedEnteringSizer.Add(self.m_speed_spinCtrlDouble, 0, wx.ALL, 5) ss_regularPromoptsEnteringSizer1.Add( - sss_SpeedEnteringSizer, - 0, - wx.ALL | wx.EXPAND | wx.SHAPED | wx.ALIGN_CENTER_VERTICAL, - 5, + sss_SpeedEnteringSizer, 0, wx.ALL | wx.EXPAND, 5 ) s_promptSizer.Add(ss_regularPromoptsEnteringSizer1, 0, wx.EXPAND, 5) @@ -751,17 +977,62 @@ class ConvertPagePanel(wx.Panel): s_promptSizer.Add(ss_HideAndSeekSizer_bSizer15, 0, wx.EXPAND, 5) - main_page_sizer.Add( - s_promptSizer, 0, wx.SHAPED | wx.EXPAND | wx.ALIGN_CENTER_HORIZONTAL, 5 - ) + main_page_sizer.Add(s_promptSizer, 0, wx.ALL | wx.EXPAND | wx.SHAPED, 5) s_StartSizer_sbSizer18 = wx.StaticBoxSizer( wx.StaticBox(self, wx.ID_ANY, "开始转换"), wx.HORIZONTAL ) s_StartSizer_sbSizer18.SetMinSize(wx.Size(-1, 100)) + ss_Midi_Convert_distPath_bSizer17 = wx.BoxSizer(wx.VERTICAL) - s_StartSizer_sbSizer18.Add((0, 0), 1, wx.EXPAND, 5) + ss_Dest_chooser_Sizer_in_bSizer18 = wx.BoxSizer(wx.HORIZONTAL) + + self.m_tip_Change_Dest_staticText7 = wx.StaticText( + s_StartSizer_sbSizer18.GetStaticBox(), + wx.ID_ANY, + "指定输出路径", + wx.DefaultPosition, + wx.DefaultSize, + 0, + ) + self.m_tip_Change_Dest_staticText7.Wrap(-1) + + ss_Dest_chooser_Sizer_in_bSizer18.Add( + self.m_tip_Change_Dest_staticText7, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5 + ) + + self.m_Convertion_Destination_Picker_dirPicker1 = wx.DirPickerCtrl( + s_StartSizer_sbSizer18.GetStaticBox(), + wx.ID_ANY, + "./", + "选择目标目录", + wx.DefaultPosition, + wx.DefaultSize, + wx.DIRP_DEFAULT_STYLE, + ) + ss_Dest_chooser_Sizer_in_bSizer18.Add( + self.m_Convertion_Destination_Picker_dirPicker1, 1, wx.ALL | wx.EXPAND, 5 + ) + + ss_Midi_Convert_distPath_bSizer17.Add( + ss_Dest_chooser_Sizer_in_bSizer18, 0, wx.ALL | wx.EXPAND, 5 + ) + + self.m_Check_Every_Their_Path_checkBox7 = wx.CheckBox( + s_StartSizer_sbSizer18.GetStaticBox(), + wx.ID_ANY, + "输出到每个文件所在目录", + wx.DefaultPosition, + wx.DefaultSize, + 0, + ) + self.m_Check_Every_Their_Path_checkBox7.SetValue(True) + ss_Midi_Convert_distPath_bSizer17.Add( + self.m_Check_Every_Their_Path_checkBox7, 0, wx.ALL, 5 + ) + + s_StartSizer_sbSizer18.Add(ss_Midi_Convert_distPath_bSizer17, 1, wx.EXPAND, 5) self.m_start_button2 = wx.Button( s_StartSizer_sbSizer18.GetStaticBox(), @@ -773,23 +1044,24 @@ class ConvertPagePanel(wx.Panel): ) s_StartSizer_sbSizer18.Add(self.m_start_button2, 0, wx.ALIGN_CENTER | wx.ALL, 5) - main_page_sizer.Add( - s_StartSizer_sbSizer18, - 1, - wx.ALL | wx.EXPAND | wx.RESERVE_SPACE_EVEN_IF_HIDDEN, - 5, - ) + main_page_sizer.Add(s_StartSizer_sbSizer18, 1, wx.ALL | wx.EXPAND, 5) self.SetSizer(main_page_sizer) self.Layout() # Connect Events self.m_ChooseMidiTips_staticText3.Bind(wx.EVT_LEFT_DCLICK, self.MidiEasterEgg) + self.m_done_then_remove_checkBox6.Bind( + wx.EVT_CHECKBOX, self.on_Done_Then_Remove_Clicked + ) self.m_midiFilesList_listBox2.Bind(wx.EVT_LISTBOX, self.onFileListUpdated) self.m_midiFilesList_listBox2.Bind( wx.EVT_LISTBOX_DCLICK, self.onFileDoubleClicked ) self.m_midiBroseButton_button21.Bind(wx.EVT_BUTTON, self.openFile) + self.m_midiChooser_Clear_button3.Bind( + wx.EVT_BUTTON, self.on_Chooer_Clear_Button_Pressed + ) self.m_outformatChoice_choice1.Bind(wx.EVT_CHOICE, self.onOutputFormatChosen) self.m_playerChoice_choice2.Bind(wx.EVT_CHOICE, self.onPlayerChosen) self.m_volumn_slider.Bind(wx.EVT_SCROLL, self.onVolumeScrolling) @@ -819,13 +1091,18 @@ class ConvertPagePanel(wx.Panel): self.m_EnteringBDXfileSignName_textCtrl12.Bind( wx.EVT_TEXT, self.onBDXfileSignNameUpdating ) + self.m_tip_Change_Dest_staticText7.Bind( + wx.EVT_LEFT_DCLICK, self.on_Change_to_Default_Path + ) + self.m_Convertion_Destination_Picker_dirPicker1.Bind( + wx.EVT_DIRPICKER_CHANGED, self.on_Convert_Dest_Changed + ) + self.m_Check_Every_Their_Path_checkBox7.Bind( + wx.EVT_CHECKBOX, self.On_Their_Path_Checked + ) self.m_start_button2.Bind(wx.EVT_BUTTON, self.onStartButtonPressed) - self.m_EnteringBDXfileSignName_textCtrl12.Enable(False) - - self.m_PlayerSelectorEntering_comboBox1.Enable(False) - self.m_StructureHeight_slider7.Enable(False) - self.m_enteringStructureMaxHeight_spinCtrl1.Enable(False) + self.m_Convertion_Destination_Picker_dirPicker1.Enable(False) def __del__(self): pass @@ -836,6 +1113,9 @@ class ConvertPagePanel(wx.Panel): self.midiFilesList.add("诸葛亮与八卦阵-山水千年") self.m_midiFilesList_listBox2.Append("诸葛亮与八卦阵-山水千年") + def on_Done_Then_Remove_Clicked(self, event): + event.Skip() + def onFileListUpdated(self, event): # prt(self.m_ChooseMIDI_filePicker1.GetTextCtrl().Value) # self.midi_cvt = Musicreater.MidiConvert.from_midi_file(self.m_ChooseMIDI_filePicker1.GetLabel(),self.m_oldExeFormatChecker_checkBox3.GetValue()) @@ -862,6 +1142,10 @@ class ConvertPagePanel(wx.Panel): fileDialog.Destroy() + def on_Chooer_Clear_Button_Pressed(self, event): + self.midiFilesList.clear() + self.m_midiFilesList_listBox2.Clear() + def onOutputFormatChosen(self, event): # 0: 附加包 # 1: BDX @@ -963,6 +1247,18 @@ class ConvertPagePanel(wx.Panel): def onBDXfileSignNameUpdating(self, event): event.Skip() + def on_Change_to_Default_Path(self, event): + event.Skip() + + def on_Convert_Dest_Changed(self, event): + event.Skip() + + def On_Their_Path_Checked(self, event): + if self.m_Check_Every_Their_Path_checkBox7.GetValue(): + self.m_Convertion_Destination_Picker_dirPicker1.Enable(False) + else: + self.m_Convertion_Destination_Picker_dirPicker1.Enable(True) + def onStartButtonPressed(self, event): global pgb_style for file_name in self.m_midiFilesList_listBox2.GetStrings(): @@ -983,7 +1279,11 @@ class ConvertPagePanel(wx.Panel): ) cvt_cfg = ConvertConfig( - os.path.split(file_name)[0], + ( + os.path.split(file_name)[0] + if self.m_Check_Every_Their_Path_checkBox7.GetValue() + else self.m_Convertion_Destination_Picker_dirPicker1.GetTextCtrl().GetValue() + ), self.m_volumn_spinCtrlDouble1.GetValue() / 100, self.m_speed_spinCtrlDouble.GetValue(), progressbar=pgb_style, @@ -1072,6 +1372,11 @@ class ConvertPagePanel(wx.Panel): ).ShowModal() return + if self.m_done_then_remove_checkBox6.GetValue(): + self.m_midiFilesList_listBox2.Delete( + self.m_midiFilesList_listBox2.FindString(file_name) + ) + ########################################################################### ## Class setting_page_pannel @@ -1092,6 +1397,9 @@ class SettingPagePannel(wx.Panel): self, parent, id=id, pos=pos, size=size, style=style, name=name ) + self.SetBackgroundColour(WHITE2) + self.SetForegroundColour(BLACK2) + setting_page_sizer = wx.BoxSizer(wx.VERTICAL) self.setting_notebook = wx.Notebook( @@ -1111,9 +1419,8 @@ class SettingPagePannel(wx.Panel): "@OPPOSans R", ) ) - self.setting_notebook.SetBackgroundColour( - wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW) - ) + self.setting_notebook.SetBackgroundColour(WHITE2) + self.setting_notebook.SetForegroundColour(BLACK2) self.setting_page1 = wx.Panel( self.setting_notebook, @@ -1537,9 +1844,9 @@ class SettingPagePannel(wx.Panel): case 0: ConvertClass = (Musicreater.MidiConvert, "常规转换") case 1: - ConvertClass = (Musicreater.experiment.FutureMidiConvertM4, "长音插值") + ConvertClass = (Musicreater_experiment.FutureMidiConvertM4, "长音插值") case 2: - ConvertClass = (Musicreater.experiment.FutureMidiConvertM5, "同刻偏移") + ConvertClass = (Musicreater_experiment.FutureMidiConvertM5, "同刻偏移") def onMidiFaultIgnoranceChecking(self, event): global ignore_midi_mismatch_error @@ -1649,7 +1956,7 @@ logger.info("执行应用。") if __name__ == "__main__": logger.info("检查更新:") - check_update( + check_update_repo( __appname__, "https://gitee.com/TriM-Organization/Linglun-Converter/raw/master/llc_win_wxPython.py", __version__, diff --git a/requirements.txt b/requirements.txt index 22bc493..48def2d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ -Musicreater>=1.7.2 +Musicreater>=1.7.2.1 TrimLog>=0.8.3 +requests>=2.0.0 \ No newline at end of file diff --git a/utils/io.py b/utils/io.py index dcee6e6..70a3a5a 100644 --- a/utils/io.py +++ b/utils/io.py @@ -4,7 +4,7 @@ 伶伦转换器 命令行组件 Linglun Converter Command Line IO Component -版权所有 © 2024 金羿 & 睿穆开发组 +版权所有 © 2024 金羿 & 睿乐开发组 Copyright © 2024 EillesWan & TriM Org. 开源相关声明请见 ./License.md @@ -12,8 +12,7 @@ Terms & Conditions: ./Lisense.md """ -import urllib.error -import urllib.request +import requests from typing import ( Any, Callable, @@ -26,31 +25,28 @@ from typing import ( Tuple, Iterable, Sequence, + Union, ) import TrimLog -from TrimLog import object_constants, logger +from TrimLog import object_constants, logger, log__init__ -is_logging: bool = True - -MainConsole = logger.console logger.is_logging = True logger.suffix = ".llc" logger.is_tips = True +logger.info("读取 言·论 信息……") try: myWords = ( - urllib.request.urlopen( - "https://gitee.com/TriM-Organization/LinglunStudio/raw/master/resources/myWords.txt" - ) - .read() - .decode("utf-8") + requests.get( + "https://gitee.com/TriM-Organization/LinglunStudio/raw/master/resources/myWords.txt", + ).text .strip("\n") .split("\n") ) -except (ConnectionError, urllib.error.HTTPError) as E: +except (ConnectionError, requests.HTTPError, requests.RequestException) as E: logger.warning(f"读取言·论信息发生 互联网连接 错误:\n{E}") myWords = ["以梦想为驱使 创造属于自己的未来"] # noinspection PyBroadException @@ -59,6 +55,9 @@ except BaseException as E: myWords = ["灵光焕发 深艺献心"] + +logger.info("注册出入方法……") + JustifyMethod = Literal["default", "left", "center", "right", "full"] OverflowMethod = Literal["fold", "crop", "ellipsis", "ignore"] @@ -98,7 +97,7 @@ def prt( soft_wrap (bool, 可选): 启用软包装模式,禁止文字包装和裁剪,或`None``用于 控制台默认值。默认为`None`。 new_line_start (bool, False): 如果输出包含多行,在开始时插入一个新行。默认值为`False`。 """ - MainConsole.print( + logger.console.print( *objects, sep=sep, end=end, @@ -159,7 +158,7 @@ def ipt( Returns: str: 从stdin读取的字符串 """ - MainConsole.print( + logger.console.print( *objects, sep=sep, end="", @@ -177,7 +176,7 @@ def ipt( new_line_start=new_line_start, ) - return MainConsole.input(password=password, stream=stream) + return logger.console.input(password=password, stream=stream) def format_ipt( @@ -213,61 +212,57 @@ def isin(sth: str, range_list: dict): for bool_value, res_list in range_list.items(): if sth in res_list: return bool_value - raise ValueError + raise ValueError( + "不在可选范围内:{}".format([j for i in range_list.values() for j in i]) + ) # 真假字符串判断 def bool_str(sth: str): try: return bool(float(sth)) - except: + except ValueError: if str(sth).lower() in ("true", "真", "是", "y", "t"): return True elif str(sth).lower() in ("false", "假", "否", "f", "n"): return False else: - raise ValueError + raise ValueError("非法逻辑字串") def float_str(sth: str): try: return float(sth) except ValueError: - try: - return float( - sth.replace("壹", "1") - .replace("贰", "2") - .replace("叁", "3") - .replace("肆", "4") - .replace("伍", "5") - .replace("陆", "6") - .replace("柒", "7") - .replace("捌", "8") - .replace("玖", "9") - .replace("零", "0") - .replace("一", "1") - .replace("二", "2") - .replace("三", "3") - .replace("四", "4") - .replace("五", "5") - .replace("六", "6") - .replace("七", "7") - .replace("八", "8") - .replace("九", "9") - .replace("〇", "0") - .replace("洞", "0") - .replace("幺", "1") - .replace("俩", "2") - .replace("两", "2") - .replace("拐", "7") - .replace("点", ".") - ) - except: - raise ValueError + return float( + sth.replace("壹", "1") + .replace("贰", "2") + .replace("叁", "3") + .replace("肆", "4") + .replace("伍", "5") + .replace("陆", "6") + .replace("柒", "7") + .replace("捌", "8") + .replace("玖", "9") + .replace("零", "0") + .replace("一", "1") + .replace("二", "2") + .replace("三", "3") + .replace("四", "4") + .replace("五", "5") + .replace("六", "6") + .replace("七", "7") + .replace("八", "8") + .replace("九", "9") + .replace("〇", "0") + .replace("洞", "0") + .replace("幺", "1") + .replace("俩", "2") + .replace("两", "2") + .replace("拐", "7") + .replace("点", ".") + ) def int_str(sth: str): - try: - return int(float_str(sth)) - except ValueError: - raise ValueError + return int(float_str(sth)) diff --git a/utils/localize.py b/utils/localize.py index 051d430..e2b10ec 100644 --- a/utils/localize.py +++ b/utils/localize.py @@ -4,7 +4,7 @@ 伶伦转换器 本地化组件 Linglun Converter Language Localization Component -版权所有 © 2024 金羿 & 睿穆开发组 +版权所有 © 2024 金羿 & 睿乐开发组 Copyright © 2024 EillesWan & TriM Org. 开源相关声明请见 ./License.md diff --git a/utils/packdata.py b/utils/packdata.py index b14b0f7..7224708 100644 --- a/utils/packdata.py +++ b/utils/packdata.py @@ -4,7 +4,7 @@ 伶伦转换器 打包存档组件 Linglun Converter Language Localization Component -版权所有 © 2024 金羿 & 睿穆开发组 +版权所有 © 2024 金羿 & 睿乐开发组 Copyright © 2024 EillesWan & TriM Org. 开源相关声明请见 ./License.md @@ -12,7 +12,6 @@ Terms & Conditions: ./Lisense.md """ - import hashlib import dill @@ -62,3 +61,60 @@ def enpack_llc_pack(sth: Any, to_dist: str): f.write(md5_value) f.write(b" | \n") f.write(packing_bytes) + + +def enpack_msct_pack(sth, to_dist: str): + packing_bytes = brotli.compress( + dill.dumps( + sth, + ) + ) + with open( + to_dist, + "wb", + ) as f: + f.write(packing_bytes) + + return hashlib.sha256(packing_bytes) + + +def unpack_msct_pack(from_dist: str, hash_value: str, raise_error: bool = True): + with open(from_dist, "rb") as f: + packed_data = f.read() + now_hash = hashlib.sha256(packed_data).hexdigest() + if now_hash == hash_value: + return dill.loads(brotli.decompress(packed_data)) + else: + if raise_error: + raise ValueError( + "文件读取失败:\n传入:{}\n需求:{}\n签名不一致,可能存在注入风险。".format( + now_hash, hash_value + ) + ) + else: + return ValueError( + "文件读取失败:\n传入:{}\n需求:{}\n签名不一致,可能存在注入风险。".format( + now_hash, hash_value + ) + ) + + +def load_msct_packed_data( + packed_data: bytes, hash_value: str, raise_error: bool = True +): + now_hash = hashlib.sha256(packed_data).hexdigest() + if now_hash == hash_value: + return dill.loads(brotli.decompress(packed_data)) + else: + if raise_error: + raise ValueError( + "文件读取失败:\n传入:{}\n需求:{}\n签名不一致,可能存在注入风险。".format( + now_hash, hash_value + ) + ) + else: + return ValueError( + "文件读取失败:\n传入:{}\n需求:{}\n签名不一致,可能存在注入风险。".format( + now_hash, hash_value + ) + ) diff --git a/utils/update_check.py b/utils/update_check.py index 5003c56..6060520 100644 --- a/utils/update_check.py +++ b/utils/update_check.py @@ -4,14 +4,14 @@ 伶伦转换器 版本检查组件 Linglun Converter Version Checking Component -版权所有 © 2024 金羿 & 睿穆开发组 +版权所有 © 2024 金羿 & 睿乐开发组 Copyright © 2024 EillesWan & TriM Org. 开源相关声明请见 ./License.md Terms & Conditions: ./Lisense.md """ -from .io import TrimLog, urllib, Sequence, Iterable, Callable, Optional +from .io import TrimLog, requests, Sequence, Iterable, Callable, Optional, Dict, Union def is_ver_char(text: str) -> bool: @@ -64,20 +64,21 @@ def is_ver_bigger(ver_1: Sequence[int], ver_2: Sequence[int]) -> bool: return len_v1 > len_v2 -def check_update( +def check_update_repo( appname: str, get_text_url: str, version_now: str, message_show_fun: Callable, logger: TrimLog.Logger, version_disp: Optional[str] = None, + version_renew_tip: str = "!有新版本!\n最新的 {app} 已经是 {latest} 版本,当前您正在使用的仍是 {current} 版本,您可以前往下载地址更新。", ): if not version_disp: version_disp = version_now - logger.info("当前版本信息:{}".format(version_now)) + logger.info("当前 {} 版本:{}".format(appname,version_now)) try: - code_content: str = urllib.request.urlopen(get_text_url).read().decode("utf-8") + code_content: str = requests.get(get_text_url).text except Exception as E: # noinspection PyBroadException logger.warning("无法获取更新版本信息:{}".format(E)) return @@ -86,7 +87,7 @@ def check_update( code_content = code_content[code_content.find('"') + 1 :] version_content = code_content[: code_content.find('"')] - logger.info("已获取更新版本信息:{}".format(version_content)) + logger.info("已获取 {} 新版本信息:{}".format(appname,version_content)) if is_ver_bigger( [int(v) for v in cut_ver_str(version_content).split(".")], @@ -98,7 +99,7 @@ def check_update( version_content = code_content[: code_content.find('"')] message_show_fun( - "!有新版本!\n最新的 {app} 已经是 {latest} 版本,当前您正在使用的仍是 {current} 版本,您可以前往下载地址更新。".format( + version_renew_tip.format( app=appname, latest=version_content, current=version_disp ) ) @@ -116,3 +117,42 @@ def check_update( # return version_content[i:j] # "".join([version_content[i] for i in range(version_content.__len__()) if is_ver_char(version_content[i]) and ((version_content[i-1] if i > 0 else False) or (version_content[i+1] if i < version_content.__len__() else False))]).split('.') + + +def check_update_release( + appname: str, + get_release_url: str, + version_now: str, + notice_fun: Callable[[str, str], bool], + logger: TrimLog.Logger, + version_renew_tip: str = "!有新版本!\n最新的 {app} 已经是 {latest} 版本,当前您正在使用的仍是 {current} 版本,是否更新?", +) -> Union[None, Dict[str, str]]: + + logger.info("当前 {} 版本:{}".format(appname,version_now)) + try: + code_content: Dict = requests.get(get_release_url).json() + except Exception as E: # noinspection PyBroadException + logger.warning("无法获取更新版本信息:{}".format(E)) + return + + version_content = code_content["release"]["tag"]["name"] + + logger.info("已获取 {} 新版本信息:{}".format(appname,version_content)) + + if is_ver_bigger( + [int(v) for v in cut_ver_str(version_content).split(".")], + [int(v) for v in cut_ver_str(version_now).split(".")], + ): + + if notice_fun( + version_renew_tip.format( + app=appname, latest=version_content, current=version_now + ), + code_content["release"]["release"]["description"], + ): + return dict( + [ + (d["name"], d["download_url"]) + for d in code_content["release"]["release"]["attach_files"] + ] + ) diff --git a/utils/webview.py b/utils/webview.py new file mode 100644 index 0000000..cbf0eb5 --- /dev/null +++ b/utils/webview.py @@ -0,0 +1,147 @@ +import wx +import wx.html + + +class HTMLFrame(wx.Frame): + """桌面程序主窗口类""" + + def __init__( + self, + parent, + tip_text, + web_text, + window_title: str = "新版本已发布", + bg_colour: tuple = (0, 0, 0), + window_size: tuple = (800, 480), + ): + """构造函数""" + + wx.Frame.__init__( + self, + parent, + id=wx.ID_ANY, + title=window_title, + pos=wx.DefaultPosition, + size=window_size, + style=wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL, + ) + + # self.SetIcon(wx.Icon('', wx.BITMAP_TYPE_ICO)) + self.SetBackgroundColour(bg_colour) + self.Center() + + self.SetSizeHints(wx.DefaultSize, wx.DefaultSize) + + bSizer1 = wx.BoxSizer(wx.VERTICAL) + + self.m_staticText1 = wx.StaticText( + self, + wx.ID_ANY, + tip_text, + wx.DefaultPosition, + wx.DefaultSize, + wx.ALIGN_CENTER_HORIZONTAL, + ) + self.m_staticText1.Wrap(-1) + + self.m_staticText1.SetFont( + wx.Font( + wx.NORMAL_FONT.GetPointSize() * 2, + wx.FONTFAMILY_DEFAULT, + wx.FONTSTYLE_NORMAL, + wx.FONTWEIGHT_NORMAL, + False, + "OPPOSans M", + ) + ) + + bSizer1.Add(self.m_staticText1, 3, wx.ALL | wx.ALIGN_CENTER_HORIZONTAL, 5) + + self.m_htmlWin1 = wx.html.HtmlWindow( + self, + wx.ID_ANY, + wx.DefaultPosition, + wx.DefaultSize, + wx.html.HW_SCROLLBAR_AUTO, + ) + self.m_htmlWin1.SetFont( + wx.Font( + wx.NORMAL_FONT.GetPointSize(), + wx.FONTFAMILY_DEFAULT, + wx.FONTSTYLE_NORMAL, + wx.FONTWEIGHT_NORMAL, + False, + "OPPOSans R", + ) + ) + self.m_htmlWin1.SetStandardFonts(normal_face="OPPOSans R") + + bSizer1.Add(self.m_htmlWin1, 5, wx.EXPAND | wx.RESERVE_SPACE_EVEN_IF_HIDDEN, 5) + + bSizer2 = wx.BoxSizer(wx.HORIZONTAL) + + self.m_button1 = wx.Button( + self, wx.ID_ANY, "取消", wx.DefaultPosition, wx.DefaultSize, 0 + ) + bSizer2.Add(self.m_button1, 0, wx.ALL, 5) + + self.m_button2 = wx.Button( + self, wx.ID_ANY, "更新", wx.DefaultPosition, wx.DefaultSize, 0 + ) + bSizer2.Add(self.m_button2, 0, wx.ALL, 5) + + bSizer1.Add(bSizer2, 0, wx.ALIGN_RIGHT, 5) + + self.SetSizer(bSizer1) + self.Layout() + + self.Centre(wx.BOTH) + + self.m_htmlWin1.SetPage(web_text) + + # Connect Events + self.m_button1.Bind(wx.EVT_BUTTON, self.on_Cancel_Click) + self.m_button2.Bind(wx.EVT_BUTTON, self.on_Update_Click) + + self.ok = False + + def __del__(self): + # return self.ok + pass + + def getok(self) -> bool: + return self.ok + + # Virtual event handlers, override them in your derived class + def on_Cancel_Click(self, event): + self.ok = False + self.Destroy() + + def on_Update_Click(self, event): + self.ok = True + self.Destroy() + + +def go_update_tip(tip_text: str, html_context: str) -> bool: + app = wx.App() + frame = HTMLFrame( + None, + tip_text, + html_context, + bg_colour=wx.SystemSettings.GetColour(wx.SYS_COLOUR_MENU), + ) + frame.Show() + app.MainLoop() + return frame.getok() + + +if __name__ == "__main__": + go_update_tip( + "!有新版本!\n最新的 {app} 已经是 {latest} 版本,当前您正在使用的仍是 {current} 版本,是否更新?", + '
我们使用Python库 dill
和 Brotli
对整个库的包体进行打包,方式如下:
packing_bytes = brotli.compress(dill.dumps(sth,))\n
\n\n每个包中的内容为:
\nMSCT_MAIN = (\n Musicreater,\n Musicreater.experiment,\n Musicreater.previous,\n)\n\nMSCT_PLUGIN = (Musicreater.plugin,)\n\nMSCT_PLUGIN_FUNCTION = (\n to_addon_pack_in_delay,\n to_addon_pack_in_repeater,\n to_addon_pack_in_score,\n to_mcstructure_file_in_delay,\n to_mcstructure_file_in_repeater,\n to_mcstructure_file_in_score,\n to_BDX_file_in_delay,\n to_BDX_file_in_score,\n)\n
\n\n