{"repo": "aarongig/pdf2zh-desktop", "files": {"ui/main_window.py": {"ead24a4b52b86c4f7b59958f51c5d72d2641064a": {"t": 1785674187.8725162, "n": 266583, "h": "6380f23012856569", "c": "\"\"\"\npdf2zh for Mac — 完整版主窗口\n全功能适配: 三种预览模式 / 分块翻译 / 页码范围 / 历史记录 / 20+翻译服务\n\"\"\"\n\nimport sys\nimport os\nimport json\nimport webbrowser\nimport time\nfrom pathlib import Path\nimport fitz\n\n\ndef _install_pdf2zh_color_fix():\n \"\"\"v2.3.3 运行时热补丁 (import hook, 不改 pdf2zh 模块本身):\n 修复某些期刊 PDF(ICC 颜色空间) 白色矩形 '1 1 1 scn' 被截断成 '1 scn' → 渲染成红色,\n 以及译文文字继承颜色导致变红。在 pdf2zh.pdfinterp / pdf2zh.converter 被导入时自动打补丁。\n \"\"\"\n import sys as _sys\n import importlib.util as _ilu\n from importlib.abc import MetaPathFinder\n\n _patched = set()\n\n def _patch_pdfinterp(mod):\n for cn in (\"PDFPageInterpreterEx\", \"PDFPageInterpreter\"):\n cls = getattr(mod, cn, None)\n if not cls or getattr(cls, \"_p2z_scn_fixed\", False):\n continue\n\n def _mk(is_stroke):\n attr = \"scs\" if is_stroke else \"ncs\"\n cattr = \"scolor\" if is_stroke else \"ncolor\"\n\n def _f(self):\n cs = getattr(self.graphicstate, attr, None) or getattr(self, attr, None)\n n = cs.ncomponents if cs else 1\n _num = 0\n for _v in reversed(self.argstack):\n if isinstance(_v, (int, float)):\n _num += 1\n else:\n break\n if _num > n:\n n = _num\n a = self.pop(n)\n setattr(self.graphicstate, cattr, a)\n return a\n\n return _f\n\n cls.do_scn = _mk(False)\n cls.do_sc = cls.do_scn\n cls.do_SCN = _mk(True)\n cls.do_SC = cls.do_SCN\n cls._p2z_scn_fixed = True\n\n def _patch_converter(mod):\n tc = getattr(mod, \"TranslateConverter\", None)\n if not tc or getattr(tc, \"_p2z_color_fixed\", False):\n return\n _orig = tc.receive_layout\n\n def _wrapped(self, ltpage):\n ops = _orig(self, ltpage)\n if isinstance(ops, str) and ops:\n return \"0 g 0 G \" + ops\n return ops\n\n tc.receive_layout = _wrapped\n tc._p2z_color_fixed = True\n\n def _patch_translator(mod):\n import re as _re\n dt = getattr(mod, \"DeepseekTranslator\", None)\n ot = getattr(mod, \"OpenAITranslator\", None)\n\n # v2.3.5: DeepSeek V4(v4-flash/v4-pro, 及已映射到 v4 的 deepseek-chat 别名)是混合推理模型,\n # 裸调默认走\"思考模式\" → 逐段先推理再输出 → 翻译极慢/偶发漏译/(经代理时)推理泄漏进译文。\n # 对这些实例注入 thinking:disabled 退回直出; deepseek-reasoner 纯推理不动。\n if dt is not None and not getattr(dt, \"_p2z_thinking_fixed\", False):\n _orig_init = dt.__init__\n\n def _new_init(self, *a, **kw):\n _orig_init(self, *a, **kw)\n try:\n _m = (getattr(self, \"model\", \"\") or \"\").lower()\n if (\"v4\" in _m) or (\"chat\" in _m):\n if not getattr(self, \"options\", None):\n self.options = {}\n self.options[\"extra_body\"] = {\"thinking\": {\"type\": \"disabled\"}}\n except Exception:\n pass\n\n dt.__init__ = _new_init\n dt._p2z_thinking_fixed = True\n\n # v2.3.6: 弱模型/推理模型往译文里加译者注(注:...)/前言/思考块(见 issue #27)。\n # A 强约束 system prompt(所有 OpenAI 兼容服务) + B 输出兜底清洗。\n if ot is not None and not getattr(ot, \"_p2z_mt_clean\", False):\n _NOTE = _re.compile(\n r\"\\s*[((]\\s*(注|註|译者注|譯者註|译注|譯注|Note|N\\.?B\\.?)\\s*[::].*$\",\n _re.DOTALL | _re.IGNORECASE,\n )\n _PRE = _re.compile(\n r\"^\\s*(译文|译|翻译|Translation|Translated text)\\s*[::]\\s*\", _re.IGNORECASE\n )\n _THK = _re.compile(r\"\\1', text)\n # 列表项 (- item)\n text = _re.sub(r'^- (.+)$', r'
\\1', text)\n # 列表项 (- item)\n text = _re.sub(r'^- (.+)$', r'\\1', text)\n # 列表项 (- item)\n text = _re.sub(r'^- (.+)$', r'\\1', text)\n # 列表项 (- item)\n text = _re.sub(r'^- (.+)$', r'