ok-script 2.0.0b4__tar.gz → 2.0.0b5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (358) hide show
  1. {ok_script-2.0.0b4/ok_script.egg-info → ok_script-2.0.0b5}/PKG-INFO +1 -1
  2. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/MainWindow.py +37 -1
  3. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/about/AboutTab.py +36 -24
  4. ok_script-2.0.0b5/ok/ui/qt/about/UpdateCard.py +313 -0
  5. ok_script-2.0.0b5/ok/ui/qt/about/VersionCard.py +16 -0
  6. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/common/design_system.py +1 -1
  7. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/i18n/en_US.qm +0 -0
  8. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/i18n/en_US.ts +159 -0
  9. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/i18n/es_ES.qm +0 -0
  10. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/i18n/es_ES.ts +159 -0
  11. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/i18n/ja_JP.qm +0 -0
  12. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/i18n/ja_JP.ts +159 -0
  13. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/i18n/ko_KR.qm +0 -0
  14. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/i18n/ko_KR.ts +159 -0
  15. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/i18n/zh_CN.qm +0 -0
  16. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/i18n/zh_CN.ts +159 -0
  17. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/i18n/zh_TW.qm +0 -0
  18. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/i18n/zh_TW.ts +159 -0
  19. ok_script-2.0.0b5/ok/ui/qt/resources.py +19337 -0
  20. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/tasks/EditTaskTab.py +2 -0
  21. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/tasks/TemplateTab.py +2 -2
  22. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/widget/ExpandCardLayout.py +4 -0
  23. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/web/app.py +114 -0
  24. ok_script-2.0.0b5/ok/ui/web/static/app.js +11 -0
  25. ok_script-2.0.0b5/ok/ui/web/static/index.css +1 -0
  26. {ok_script-2.0.0b4 → ok_script-2.0.0b5/ok_script.egg-info}/PKG-INFO +1 -1
  27. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok_script.egg-info/SOURCES.txt +2 -0
  28. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_expand_card_layout.py +10 -0
  29. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_main_window_startup_tab.py +20 -1
  30. ok_script-2.0.0b5/tests/test_pyappify_startup_update.py +483 -0
  31. ok_script-2.0.0b5/tests/test_qt_page_layout.py +45 -0
  32. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_task_ui.py +5 -0
  33. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_template_tab.py +10 -0
  34. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_web_ui_pages.py +52 -0
  35. ok_script-2.0.0b4/ok/ui/qt/about/VersionCard.py +0 -33
  36. ok_script-2.0.0b4/ok/ui/qt/resources.py +0 -15570
  37. ok_script-2.0.0b4/ok/ui/web/static/app.js +0 -11
  38. ok_script-2.0.0b4/ok/ui/web/static/index.css +0 -1
  39. ok_script-2.0.0b4/tests/test_pyappify_startup_update.py +0 -202
  40. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/LICENSE.txt +0 -0
  41. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/MANIFEST.in +0 -0
  42. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/README.md +0 -0
  43. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/diagnostics/qq_trace.py +0 -0
  44. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/__init__.py +0 -0
  45. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/__main__.py +0 -0
  46. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/alas/__init__.py +0 -0
  47. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/alas/emulator_base.py +0 -0
  48. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/alas/emulator_windows.py +0 -0
  49. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/alas/platform_windows.py +0 -0
  50. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/alas/utils.py +0 -0
  51. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/capture/__init__.py +0 -0
  52. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/capture/adb/__init__.py +0 -0
  53. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/capture/adb/deep.py +0 -0
  54. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/capture/adb/minitouch.py +0 -0
  55. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/capture/adb/nemu_ipc.py +0 -0
  56. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/capture/adb/nemu_utils.py +0 -0
  57. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/capture/adb/pool.py +0 -0
  58. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/capture/adb/timer.py +0 -0
  59. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/capture/adb/util.py +0 -0
  60. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/capture/windows/__init__.py +0 -0
  61. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/capture/windows/d3d11.py +0 -0
  62. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/capture/windows/dump.py +0 -0
  63. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/cli.py +0 -0
  64. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/core/__init__.py +0 -0
  65. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/core/config_schema.py +0 -0
  66. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/core/downloads.py +0 -0
  67. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/core/events.py +0 -0
  68. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/core/icons.py +0 -0
  69. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/core/notifications.py +0 -0
  70. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/core/screenshot.py +0 -0
  71. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/core/script_editing.py +0 -0
  72. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/core/script_packager.py +0 -0
  73. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/core/script_templates.py +0 -0
  74. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/core/start_controller.py +0 -0
  75. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/core/task_manager.py +0 -0
  76. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/core/template_store.py +0 -0
  77. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/core/translation.py +0 -0
  78. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/core/ui_config.py +0 -0
  79. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/device/DeviceManager.py +0 -0
  80. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/device/__init__.py +0 -0
  81. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/device/capture.py +0 -0
  82. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/device/capture_methods/__init__.py +0 -0
  83. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/device/capture_methods/adb.py +0 -0
  84. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/device/capture_methods/base.py +0 -0
  85. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/device/capture_methods/bitblt.py +0 -0
  86. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/device/capture_methods/bitblt_utils.py +0 -0
  87. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/device/capture_methods/browser.py +0 -0
  88. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/device/capture_methods/desktop_duplication.py +0 -0
  89. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/device/capture_methods/hwnd_window.py +0 -0
  90. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/device/capture_methods/image.py +0 -0
  91. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/device/capture_methods/nemu_ipc.py +0 -0
  92. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/device/capture_methods/types.py +0 -0
  93. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/device/capture_methods/update.py +0 -0
  94. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/device/capture_methods/windows_graphics.py +0 -0
  95. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/device/interaction.py +0 -0
  96. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/device/interaction_methods/__init__.py +0 -0
  97. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/device/interaction_methods/adb.py +0 -0
  98. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/device/interaction_methods/base.py +0 -0
  99. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/device/interaction_methods/browser.py +0 -0
  100. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/device/interaction_methods/do_nothing.py +0 -0
  101. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/device/interaction_methods/foreground_post_message.py +0 -0
  102. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/device/interaction_methods/genshin.py +0 -0
  103. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/device/interaction_methods/keys.py +0 -0
  104. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/device/interaction_methods/post_message.py +0 -0
  105. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/device/interaction_methods/pydirect.py +0 -0
  106. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/device/interaction_methods/pynput.py +0 -0
  107. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/device/interaction_methods/swipe.py +0 -0
  108. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/device/intercation.py +0 -0
  109. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/feature/Box.py +0 -0
  110. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/feature/Feature.py +0 -0
  111. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/feature/FeatureSet.py +0 -0
  112. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/feature/__init__.py +0 -0
  113. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/gui/__init__.py +0 -0
  114. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/gui/util/pyappify_startup.py +0 -0
  115. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/notification/__init__.py +0 -0
  116. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/notification/manager.py +0 -0
  117. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/notification/messenger_images.py +0 -0
  118. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/notification/pipeline.py +0 -0
  119. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/notification/ppocr.py +0 -0
  120. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/notification/providers.py +0 -0
  121. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/notification/system.py +0 -0
  122. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/notification/windows_messenger.py +0 -0
  123. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ocr/__init__.py +0 -0
  124. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ocr/download_paddle_model.py +0 -0
  125. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/rotypes/Windows/Foundation/Collections.py +0 -0
  126. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/rotypes/Windows/Foundation/__init__.py +0 -0
  127. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/rotypes/Windows/Globalization/__init__.py +0 -0
  128. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/rotypes/Windows/Graphics/Capture/__init__.py +0 -0
  129. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/rotypes/Windows/Graphics/DirectX/Direct3D11/__init__.py +0 -0
  130. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/rotypes/Windows/Graphics/DirectX/__init__.py +0 -0
  131. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/rotypes/Windows/Graphics/Imaging/__init__.py +0 -0
  132. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/rotypes/Windows/Graphics/__init__.py +0 -0
  133. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/rotypes/Windows/Media/Ocr/__init__.py +0 -0
  134. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/rotypes/Windows/Media/__init__.py +0 -0
  135. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/rotypes/Windows/Security/Cryptography/__init__.py +0 -0
  136. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/rotypes/Windows/Security/__init__.py +0 -0
  137. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/rotypes/Windows/Storage/Streams/__init__.py +0 -0
  138. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/rotypes/Windows/Storage/__init__.py +0 -0
  139. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/rotypes/Windows/UI/ViewManagement/__init__.py +0 -0
  140. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/rotypes/Windows/UI/__init__.py +0 -0
  141. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/rotypes/Windows/__init__.py +0 -0
  142. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/rotypes/__init__.py +0 -0
  143. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/rotypes/delegate.py +0 -0
  144. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/rotypes/export.py +0 -0
  145. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/rotypes/idldsl.py +0 -0
  146. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/rotypes/inspectable.py +0 -0
  147. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/rotypes/roapi.py +0 -0
  148. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/rotypes/types.py +0 -0
  149. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/rotypes/winstring.py +0 -0
  150. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/task/DiagnosisTask.py +0 -0
  151. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/task/TaskExecutor.py +0 -0
  152. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/task/__init__.py +0 -0
  153. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/task/exceptions.py +0 -0
  154. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/task/task.py +0 -0
  155. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/task/web.py +0 -0
  156. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/test/OKTestRunner.py +0 -0
  157. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/test/RunTests.py +0 -0
  158. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/test/TaskTestCase.py +0 -0
  159. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/test/__init__.py +0 -0
  160. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/third_party/__init__.py +0 -0
  161. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/third_party/paperclip.py +0 -0
  162. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/__init__.py +0 -0
  163. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/overlay/__init__.py +0 -0
  164. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/overlay/win32_gdi.py +0 -0
  165. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/Communicate.py +0 -0
  166. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/MessageWindow.py +0 -0
  167. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/StartController.py +0 -0
  168. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/TabTitles.py +0 -0
  169. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/__init__.py +0 -0
  170. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/about/HttpTextEdit.py +0 -0
  171. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/about/LinksBar.py +0 -0
  172. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/about/ProjectCard.py +0 -0
  173. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/about/__init__.py +0 -0
  174. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/common/OKIcon.py +0 -0
  175. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/common/__init__.py +0 -0
  176. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/common/accent_color.py +0 -0
  177. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/common/config.py +0 -0
  178. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/common/icons.py +0 -0
  179. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/common/style_sheet.py +0 -0
  180. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/debug/DebugTab.py +0 -0
  181. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/debug/OverlayWidget.py +0 -0
  182. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/debug/RunCodeTab.py +0 -0
  183. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/debug/Screenshot.py +0 -0
  184. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/debug/__init__.py +0 -0
  185. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/events.py +0 -0
  186. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/i18n/GettextTranslator.py +0 -0
  187. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/i18n/__init__.py +0 -0
  188. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/i18n/path.py +0 -0
  189. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/i18n/update.py +0 -0
  190. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/overlay/OverlayWindow.py +0 -0
  191. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/overlay/__init__.py +0 -0
  192. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/qss/__init__.py +0 -0
  193. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/qss/dark/card.qss +0 -0
  194. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/qss/dark/discord.svg +0 -0
  195. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/qss/dark/heart.svg +0 -0
  196. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/qss/dark/message_window.qss +0 -0
  197. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/qss/dark/setting_interface.qss +0 -0
  198. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/qss/dark/status_bar.qss +0 -0
  199. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/qss/dark/stop.svg +0 -0
  200. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/qss/dark/tab.qss +0 -0
  201. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/qss/light/card.qss +0 -0
  202. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/qss/light/discord.svg +0 -0
  203. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/qss/light/heart.svg +0 -0
  204. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/qss/light/message_window.qss +0 -0
  205. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/qss/light/setting_interface.qss +0 -0
  206. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/qss/light/status_bar.qss +0 -0
  207. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/qss/light/stop.svg +0 -0
  208. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/qss/light/tab.qss +0 -0
  209. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/qt.qrc +0 -0
  210. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/settings/GlobalConfigCard.py +0 -0
  211. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/settings/GlobalConfigTab.py +0 -0
  212. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/settings/SettingTab.py +0 -0
  213. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/settings/__init__.py +0 -0
  214. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/start/LogWindow.py +0 -0
  215. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/start/SelectCaptureListView.py +0 -0
  216. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/start/SelectInteractionListView.py +0 -0
  217. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/start/StartCard.py +0 -0
  218. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/start/StartTab.py +0 -0
  219. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/start/__init__.py +0 -0
  220. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/tasks/ConfigCard.py +0 -0
  221. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/tasks/ConfigItemFactory.py +0 -0
  222. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/tasks/ConfigLabelAndWidget.py +0 -0
  223. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/tasks/LabelAndButtons.py +0 -0
  224. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/tasks/LabelAndDoubleSpinBox.py +0 -0
  225. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/tasks/LabelAndDropDown.py +0 -0
  226. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/tasks/LabelAndFileSelector.py +0 -0
  227. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/tasks/LabelAndGlobal.py +0 -0
  228. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/tasks/LabelAndLineEdit.py +0 -0
  229. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/tasks/LabelAndList.py +0 -0
  230. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/tasks/LabelAndMultiSelection.py +0 -0
  231. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/tasks/LabelAndSpinBox.py +0 -0
  232. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/tasks/LabelAndSwitchButton.py +0 -0
  233. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/tasks/LabelAndTextEdit.py +0 -0
  234. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/tasks/LabelAndWidget.py +0 -0
  235. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/tasks/MarkUpWindow.py +0 -0
  236. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/tasks/ModifyListDialog.py +0 -0
  237. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/tasks/ModifyListItem.py +0 -0
  238. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/tasks/OneTimeTaskTab.py +0 -0
  239. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/tasks/PythonHighlighter.py +0 -0
  240. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/tasks/RecordScript.py +0 -0
  241. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/tasks/ScheduleTaskTab.py +0 -0
  242. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/tasks/ScriptPackager.py +0 -0
  243. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/tasks/StartButton.py +0 -0
  244. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/tasks/TaskCard.py +0 -0
  245. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/tasks/TaskManger.py +0 -0
  246. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/tasks/TaskOpButton.py +0 -0
  247. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/tasks/TaskTab.py +0 -0
  248. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/tasks/TemplateFactory.py +0 -0
  249. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/tasks/TooltipTableWidget.py +0 -0
  250. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/tasks/TriggerTaskTab.py +0 -0
  251. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/tasks/__init__.py +0 -0
  252. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/util/Alert.py +0 -0
  253. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/util/InitWorker.py +0 -0
  254. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/util/__init__.py +0 -0
  255. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/util/app.py +0 -0
  256. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/util/download.py +0 -0
  257. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/util/pip_util.py +0 -0
  258. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/util/pyappify_startup.py +0 -0
  259. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/util/touch_scroll.py +0 -0
  260. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/util/windows_thumbnail.py +0 -0
  261. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/widget/BaseLoading.py +0 -0
  262. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/widget/BaseWindow.py +0 -0
  263. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/widget/Card.py +0 -0
  264. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/widget/CustomTab.py +0 -0
  265. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/widget/EmptyCard.py +0 -0
  266. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/widget/FlowLayout.py +0 -0
  267. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/widget/FramelessDialog.py +0 -0
  268. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/widget/ImageWidget.py +0 -0
  269. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/widget/ListTableWidgetItem.py +0 -0
  270. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/widget/NumericTableWidgetItem.py +0 -0
  271. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/widget/OkCompactSpinBox.py +0 -0
  272. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/widget/SortingTableWidgetItem.py +0 -0
  273. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/widget/StartLoadingDialog.py +0 -0
  274. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/widget/StatusBar.py +0 -0
  275. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/widget/Tab.py +0 -0
  276. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/widget/TabWidget.py +0 -0
  277. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/widget/UpdateConfigWidgetItem.py +0 -0
  278. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/widget/WidgetWithVLabel.py +0 -0
  279. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/widget/YesNonWidgetItem.py +0 -0
  280. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/qt/widget/__init__.py +0 -0
  281. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/web/__init__.py +0 -0
  282. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/web/requirements.py +0 -0
  283. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/web/server.py +0 -0
  284. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/web/static/chunk-fluent.js +0 -0
  285. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/web/static/chunk-react.js +0 -0
  286. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/ui/web/static/index.html +0 -0
  287. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/update/__init__.py +0 -0
  288. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/update/copy_ok_folder.py +0 -0
  289. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/update/inline_ok_requirements.py +0 -0
  290. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/util/Analytics.py +0 -0
  291. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/util/GlobalConfig.py +0 -0
  292. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/util/__init__.py +0 -0
  293. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/util/blur.py +0 -0
  294. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/util/clazz.py +0 -0
  295. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/util/collection.py +0 -0
  296. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/util/color.py +0 -0
  297. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/util/config.py +0 -0
  298. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/util/explorer.py +0 -0
  299. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/util/file.py +0 -0
  300. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/util/gpu_driver_settings.py +0 -0
  301. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/util/handler.py +0 -0
  302. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/util/i18n.py +0 -0
  303. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/util/logger.py +0 -0
  304. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/util/partial_sync_repo.py +0 -0
  305. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/util/print_hwnd.py +0 -0
  306. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/util/process.py +0 -0
  307. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/util/window.py +0 -0
  308. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok/util/windows_schedule.py +0 -0
  309. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok_script.egg-info/dependency_links.txt +0 -0
  310. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok_script.egg-info/entry_points.txt +0 -0
  311. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok_script.egg-info/not-zip-safe +0 -0
  312. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok_script.egg-info/requires.txt +0 -0
  313. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/ok_script.egg-info/top_level.txt +0 -0
  314. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/pyproject.toml +0 -0
  315. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/scripts/generate_web_i18n.py +0 -0
  316. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/setup.cfg +0 -0
  317. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/setup.py +0 -0
  318. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_accent_color.py +0 -0
  319. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_app.py +0 -0
  320. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_base_interaction.py +0 -0
  321. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_blur.py +0 -0
  322. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_box.py +0 -0
  323. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_capture_update.py +0 -0
  324. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_cli.py +0 -0
  325. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_config_card.py +0 -0
  326. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_core_events.py +0 -0
  327. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_core_ui_services.py +0 -0
  328. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_device_manager.py +0 -0
  329. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_explorer.py +0 -0
  330. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_global_config.py +0 -0
  331. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_gpu_driver_settings.py +0 -0
  332. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_headless_imports.py +0 -0
  333. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_inline_ok_requirements.py +0 -0
  334. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_logger.py +0 -0
  335. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_main_window_notifications.py +0 -0
  336. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_main_window_system_theme.py +0 -0
  337. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_missing_frame.py +0 -0
  338. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_navigation_state.py +0 -0
  339. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_nemu_ipc_capture.py +0 -0
  340. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_notifications.py +0 -0
  341. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_ok_mutex.py +0 -0
  342. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_overlay_custom_draw.py +0 -0
  343. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_package_metadata.py +0 -0
  344. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_process.py +0 -0
  345. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_qt_events.py +0 -0
  346. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_qt_legacy_imports.py +0 -0
  347. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_runtime_startup.py +0 -0
  348. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_start_controller.py +0 -0
  349. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_task_executor_queue.py +0 -0
  350. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_touch_scroll.py +0 -0
  351. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_translation_fallback.py +0 -0
  352. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_ui_config.py +0 -0
  353. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_web_app.py +0 -0
  354. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_web_i18n.py +0 -0
  355. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_web_server.py +0 -0
  356. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_web_task_tabs.py +0 -0
  357. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_web_ui_tasks.py +0 -0
  358. {ok_script-2.0.0b4 → ok_script-2.0.0b5}/tests/test_windows_graphics_capture.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ok-script
3
- Version: 2.0.0b4
3
+ Version: 2.0.0b5
4
4
  Summary: Automation with Computer Vision for Python
5
5
  Author-email: ok-oldking <firedcto@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/ok-oldking/ok-script
@@ -6,7 +6,8 @@ from PySide6.QtCore import QCoreApplication, QEvent, QSize, Qt, QTimer
6
6
  from PySide6.QtGui import QColor, QScreen
7
7
  from PySide6.QtWidgets import QMenu, QSystemTrayIcon, QApplication
8
8
  from qfluentwidgets import qconfig, FluentIcon, NavigationItemPosition, MessageBox, InfoBar, \
9
- InfoBarPosition, MessageBoxBase, FluentWindow, NavigationDisplayMode, isDarkTheme, Theme
9
+ InfoBarPosition, MessageBoxBase, FluentWindow, NavigationDisplayMode, isDarkTheme, Theme, \
10
+ DotInfoBadge, InfoBadgePosition
10
11
  from qfluentwidgets.components.widgets.scroll_bar import ScrollBarHandleDisplayMode
11
12
  from qfluentwidgets.common.style_sheet import updateStyleSheet
12
13
 
@@ -47,6 +48,10 @@ NAVIGATION_EXPAND_MAX_WIDTH = 240
47
48
  NAVIGATION_EXPAND_FIT_PADDING = 23
48
49
 
49
50
 
51
+ def update_check_delay_ms():
52
+ return 10_000 if "PYAPPIFY_PYTHON_TEST" in os.environ else 30_000
53
+
54
+
50
55
  class MainWindow(FluentWindow):
51
56
 
52
57
  def __init__(self, app, config, ok_config, icon, title, version, debug=False, about=None, exit_event=None,
@@ -210,6 +215,11 @@ class MainWindow(FluentWindow):
210
215
  self.about_tab = AboutTab(config)
211
216
  self.addSubInterface(self.about_tab, FluentIcon.QUESTION, self.tr('About'),
212
217
  position=NavigationItemPosition.BOTTOM)
218
+ self.about_update_badge = None
219
+ self.update_check_timer = None
220
+ if self.about_tab.update_card is not None:
221
+ self.about_tab.update_card.update_available_changed.connect(self._set_about_update_available)
222
+ self.about_tab.update_card.check_started.connect(self._cancel_scheduled_update_check)
213
223
 
214
224
  dev = self.tr('Debug')
215
225
  profile = config.get('profile', "")
@@ -243,6 +253,31 @@ class MainWindow(FluentWindow):
243
253
 
244
254
  logger.info('main window __init__ done')
245
255
 
256
+ def _set_about_update_available(self, available):
257
+ if available and self.about_update_badge is None:
258
+ about_navigation_item = self.navigationInterface.widget(self.about_tab.objectName())
259
+ self.about_update_badge = DotInfoBadge.error(
260
+ self, target=about_navigation_item, position=InfoBadgePosition.NAVIGATION_ITEM
261
+ )
262
+ if self.about_update_badge is not None:
263
+ self.about_update_badge.setVisible(available)
264
+
265
+ def _schedule_update_check(self):
266
+ if self.about_tab.update_card is None:
267
+ return
268
+ if self.update_check_timer is None:
269
+ self.update_check_timer = QTimer(self)
270
+ self.update_check_timer.setSingleShot(True)
271
+ self.update_check_timer.timeout.connect(self.about_tab.check_for_updates)
272
+ update_delay = update_check_delay_ms()
273
+ logger.info(f'schedule pyappify update check in {update_delay}ms')
274
+ self.update_check_timer.start(update_delay)
275
+
276
+ def _cancel_scheduled_update_check(self):
277
+ if self.update_check_timer is not None and self.update_check_timer.isActive():
278
+ logger.info('cancel scheduled pyappify update check because a check has started')
279
+ self.update_check_timer.stop()
280
+
246
281
  @staticmethod
247
282
  def _get_dwm_accent_color():
248
283
  """Return the DWM accent color as a compatibility fallback."""
@@ -513,6 +548,7 @@ class MainWindow(FluentWindow):
513
548
  if first_show:
514
549
  QTimer.singleShot(0, self.bring_to_front)
515
550
  QTimer.singleShot(250, self.show_startup_version_change_notice)
551
+ self._schedule_update_check()
516
552
 
517
553
  def set_window_size(self, width, height, min_width, min_height):
518
554
  screen = QScreen.availableGeometry(self.screen())
@@ -1,32 +1,56 @@
1
1
  from PySide6.QtCore import Qt
2
2
  from PySide6.QtWidgets import QGridLayout, QWidget, QSizePolicy
3
- from qfluentwidgets import BodyLabel, SettingCardGroup
3
+ from qfluentwidgets import BodyLabel
4
4
 
5
5
  from ok.ui.qt.about.ProjectCard import ProjectCard
6
6
  from ok.ui.qt.about.VersionCard import VersionCard
7
+ from ok.ui.qt.about.UpdateCard import ChangeLogView, UpdateCard
7
8
  from ok.ui.qt.util.app import get_localized_app_config
8
9
  from ok.ui.qt.util.pyappify_startup import get_startup_version_change
9
10
  from ok.ui.qt.widget.Tab import Tab
10
11
  from ok.util.file import get_path_relative_to_exe
12
+ from ok.util.logger import Logger
13
+
14
+
15
+ logger = Logger.get_logger(__name__)
11
16
 
12
17
 
13
18
  class AboutTab(Tab):
14
- def __init__(self, config):
19
+ def __init__(self, config, pyappify_module=None):
15
20
  super().__init__()
21
+ if pyappify_module is None:
22
+ import pyappify as pyappify_module
16
23
  self.version_card = VersionCard(config, get_path_relative_to_exe(config.get('gui_icon')),
17
24
  config.get('gui_title'), config.get('version'),
18
25
  config.get('debug'), self)
19
26
  # The About page uses the same section rhythm as the rest of the app.
20
27
  self.add_widget(self.version_card)
21
28
 
22
- if version_change := get_startup_version_change():
23
- update_note_label = BodyLabel()
24
- update_note_label.setText(version_change.content)
25
- update_note_label.setWordWrap(True)
26
- update_note_label.setTextInteractionFlags(Qt.TextInteractionFlag.TextSelectableByMouse)
29
+ self.update_card = None
30
+ if callable(getattr(pyappify_module, 'get_version_list', None)):
31
+ self.update_card = UpdateCard(config.get('version'), pyappify_module, self)
32
+ self.add_card(self.tr("App update"), self.update_card)
33
+ else:
34
+ logger.warning(
35
+ "pyappify.get_version_list is unavailable; update controls are disabled. "
36
+ f"Loaded module: {getattr(pyappify_module, '__file__', type(pyappify_module).__name__)!r}"
37
+ )
38
+
39
+ if version_change := get_startup_version_change(pyappify_module):
40
+ update_note_label = ChangeLogView(version_change.content)
27
41
  update_note_label.setContentsMargins(0, 0, 0, 0)
28
42
  self.add_card(self._startup_version_change_title(version_change), update_note_label)
29
43
 
44
+ if about := config.get('about'):
45
+ about_label = BodyLabel()
46
+ about_label.setText(about)
47
+ about_label.setWordWrap(True)
48
+ about_label.setOpenExternalLinks(True)
49
+ about_label.setTextInteractionFlags(Qt.TextBrowserInteraction)
50
+ about_label.setContentsMargins(0, 0, 0, 0)
51
+
52
+ self.add_card(self.tr("Disclaimer"), about_label)
53
+
30
54
  projects = [
31
55
  {"name": self.tr("ok-py Automation Tool"), "url": "https://github.com/ok-oldking/ok-py"},
32
56
  {"name": self.tr("ok-script App Template"), "url": "https://github.com/ok-oldking/ok-script-app"},
@@ -49,10 +73,6 @@ class AboutTab(Tab):
49
73
  filtered_projects = [p for p in projects if normalize_url(p['url']) != current_github_norm]
50
74
 
51
75
  if filtered_projects:
52
- self.group = SettingCardGroup(self.tr("Other Projects"), self)
53
-
54
- self.group.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
55
-
56
76
  grid_widget = QWidget()
57
77
  grid_widget.setSizePolicy(grid_widget.sizePolicy().horizontalPolicy(), QSizePolicy.Fixed)
58
78
 
@@ -66,22 +86,14 @@ class AboutTab(Tab):
66
86
  card = ProjectCard(project['name'], project['url'], grid_widget)
67
87
  grid_layout.addWidget(card, i // 2, i % 2)
68
88
 
69
- self.group.addSettingCard(grid_widget)
70
- self.group.setContentsMargins(0, 0, 0, 0)
71
- self.add_widget(self.group)
72
-
73
- if about := config.get('about'):
74
- about_label = BodyLabel()
75
- about_label.setText(about)
76
- about_label.setWordWrap(True)
77
- about_label.setOpenExternalLinks(True)
78
- about_label.setTextInteractionFlags(Qt.TextBrowserInteraction)
79
- about_label.setContentsMargins(0, 0, 0, 0)
80
-
81
- self.add_card(None, about_label)
89
+ self.group = self.add_card(self.tr("Other Projects"), grid_widget)
82
90
 
83
91
  self.vBoxLayout.addStretch(1)
84
92
 
93
+ def check_for_updates(self):
94
+ if self.update_card is not None:
95
+ self.update_card.check_for_updates()
96
+
85
97
  def _startup_version_change_title(self, version_change):
86
98
  if version_change.action == "update":
87
99
  title = self.tr("Update success {from_version} -> {to_version}")
@@ -0,0 +1,313 @@
1
+ import os
2
+ import threading
3
+
4
+ from PySide6.QtCore import QEvent, Signal, Qt
5
+ from PySide6.QtGui import QFontMetrics, QIcon, QPixmap
6
+ from PySide6.QtWidgets import QHBoxLayout, QSizePolicy, QVBoxLayout, QWidget
7
+ from qfluentwidgets import BodyLabel, CheckBox, ComboBox, FluentIcon, IndeterminateProgressRing, \
8
+ PrimaryPushButton, PushButton
9
+
10
+ from ok.util.logger import Logger
11
+
12
+
13
+ logger = Logger.get_logger(__name__)
14
+
15
+
16
+ def _is_numeric_version(version):
17
+ try:
18
+ return bool(version) and all(part.isdigit() for part in version.lstrip("v").split("."))
19
+ except AttributeError:
20
+ return False
21
+
22
+
23
+ class ChangeLogView(BodyLabel):
24
+ """A non-interactive, word-wrapped changelog that follows its text height."""
25
+
26
+ def __init__(self, text="", parent=None):
27
+ super().__init__(parent)
28
+ self.setText(text)
29
+ self.setWordWrap(True)
30
+ self.setTextFormat(Qt.TextFormat.PlainText)
31
+ self.setTextInteractionFlags(Qt.TextInteractionFlag.NoTextInteraction)
32
+ self.setAlignment(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignTop)
33
+ size_policy = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
34
+ size_policy.setHeightForWidth(True)
35
+ self.setSizePolicy(size_policy)
36
+
37
+ def setPlainText(self, text):
38
+ self.setText(text)
39
+
40
+ def toPlainText(self):
41
+ return self.text()
42
+
43
+
44
+ class UpdateCard(QWidget):
45
+ """Version picker and release-note viewer backed by the PyAppify launcher API."""
46
+
47
+ update_available_changed = Signal(bool)
48
+ check_started = Signal()
49
+ _versions_loaded = Signal(object)
50
+ _update_finished = Signal(object)
51
+ VERSION_COMBO_MIN_WIDTH = 100
52
+ VERSION_COMBO_MAX_WIDTH = 240
53
+
54
+ def __init__(self, current_version, pyappify_module, parent=None):
55
+ super().__init__(parent)
56
+ self.current_version = current_version or getattr(pyappify_module, "app_version", None) or ""
57
+ if "PYAPPIFY_PYTHON_TEST" in os.environ and not _is_numeric_version(self.current_version):
58
+ logger.info(f"using v0.0.0 for nonnumeric test version {self.current_version!r}")
59
+ self.current_version = "v0.0.0"
60
+ self.pyappify_module = pyappify_module
61
+ self.versions = []
62
+ self._busy = False
63
+ logger.info(
64
+ f"initialized current_version={self.current_version!r}, "
65
+ f"pyappify_module={getattr(pyappify_module, '__file__', type(pyappify_module).__name__)!r}, "
66
+ f"pyappify_app_version={getattr(pyappify_module, 'app_version', None)!r}, "
67
+ f"test_mode={'PYAPPIFY_PYTHON_TEST' in os.environ}"
68
+ )
69
+
70
+ self.version_combo = ComboBox(self)
71
+ self.version_combo.setFixedWidth(self.VERSION_COMBO_MIN_WIDTH)
72
+ self.version_combo.currentIndexChanged.connect(self._selection_changed)
73
+
74
+ self.test_version_checkbox = CheckBox(self.tr("Check Test Version"), self)
75
+ self.test_version_checkbox.setChecked(False)
76
+ self.check_button = PushButton(FluentIcon.SYNC, self.tr("Check for updates"), self)
77
+ loading_icon_pixmap = QPixmap(16, 16)
78
+ loading_icon_pixmap.fill(Qt.GlobalColor.transparent)
79
+ self._loading_placeholder_icon = QIcon(loading_icon_pixmap)
80
+ self.check_progress = IndeterminateProgressRing(self.check_button, start=False)
81
+ self.check_progress.setFixedSize(16, 16)
82
+ self.check_progress.setStrokeWidth(2)
83
+ self.check_progress.hide()
84
+ self.check_button.setMinimumWidth(self.check_button.sizeHint().width())
85
+ self.check_button.installEventFilter(self)
86
+ self.check_button.clicked.connect(self.check_for_updates)
87
+ self.update_button = PrimaryPushButton(FluentIcon.UPDATE, self.tr("Update"), self)
88
+ self.update_button.clicked.connect(self.update_to_selected_version)
89
+ self.update_button.setEnabled(False)
90
+
91
+ self.controls_layout = QHBoxLayout()
92
+ self.controls_layout.setContentsMargins(0, 0, 0, 0)
93
+ self.version_label = BodyLabel(self.tr("Version"), self)
94
+ self.status_label = BodyLabel(self.tr("Click to check for updates"), self)
95
+ self.controls_layout.addWidget(self.version_label)
96
+ self.controls_layout.addWidget(self.version_combo)
97
+ self.controls_layout.addWidget(self.status_label)
98
+ self.controls_layout.addStretch(1)
99
+ self.controls_layout.addWidget(self.test_version_checkbox)
100
+ self.controls_layout.addWidget(self.check_button)
101
+ self.controls_layout.addWidget(self.update_button)
102
+ self._set_version_controls_visible(False)
103
+
104
+ self.notes_edit = ChangeLogView("", self)
105
+ self.notes_edit.hide()
106
+
107
+ layout = QVBoxLayout(self)
108
+ layout.setContentsMargins(0, 0, 0, 0)
109
+ layout.setSpacing(12)
110
+ layout.addLayout(self.controls_layout)
111
+ layout.addWidget(self.notes_edit)
112
+
113
+ self._versions_loaded.connect(self._apply_versions)
114
+ self._update_finished.connect(self._apply_update_result)
115
+
116
+ def check_for_updates(self):
117
+ if self._busy:
118
+ return
119
+ get_versions = getattr(self.pyappify_module, "get_version_list", None)
120
+ if not callable(get_versions):
121
+ self._show_error(self.tr("Update checking is not supported by this PyAppify version."))
122
+ return
123
+ self._set_busy(True, checking=True)
124
+ self.check_started.emit()
125
+ self._set_status(self.tr("Checking for updates…"))
126
+ release_only = not self.test_version_checkbox.isChecked()
127
+ self._run_in_background(
128
+ lambda: get_versions(release_only=release_only),
129
+ self._versions_loaded,
130
+ f"pyappify.get_version_list(release_only={release_only})",
131
+ )
132
+
133
+ def update_to_selected_version(self):
134
+ if self._busy or self.version_combo.currentIndex() < 0:
135
+ return
136
+ update_to_version = getattr(self.pyappify_module, "update_to_version", None)
137
+ if not callable(update_to_version):
138
+ self._show_error(self.tr("Updating is not supported by this PyAppify version."))
139
+ return
140
+ version = self.version_combo.currentText()
141
+ self._set_busy(True)
142
+ self._set_status(self.tr("Starting change to {version}…").format(version=version))
143
+ self._run_in_background(
144
+ lambda: update_to_version(version),
145
+ self._update_finished,
146
+ f"pyappify.update_to_version({version!r})",
147
+ )
148
+
149
+ def _run_in_background(self, operation, signal, operation_name):
150
+ def run():
151
+ logger.info(f"calling {operation_name}")
152
+ try:
153
+ result = operation()
154
+ logger.info(f"{operation_name} result={result!r}")
155
+ signal.emit((True, result))
156
+ except Exception as error:
157
+ logger.error(f"{operation_name} failed: {error}", error)
158
+ signal.emit((False, str(error)))
159
+
160
+ threading.Thread(target=run, daemon=True, name="pyappify-update").start()
161
+
162
+ def _apply_versions(self, result):
163
+ self._set_busy(False, refresh_selection=False)
164
+ successful, value = result
165
+ if not successful:
166
+ self.versions = []
167
+ self.version_combo.clear()
168
+ self._set_version_controls_visible(False)
169
+ self.update_available_changed.emit(False)
170
+ self._show_error(self.tr("Failed to check for updates: {error}").format(error=value))
171
+ return
172
+
173
+ self.versions = [item for item in value if isinstance(item, dict) and item.get("version")]
174
+ self.version_combo.blockSignals(True)
175
+ self.version_combo.clear()
176
+ self.version_combo.addItems([str(item["version"]) for item in self.versions])
177
+ self.version_combo.blockSignals(False)
178
+ self._resize_version_combo()
179
+ logger.info(
180
+ f"loaded {len(self.versions)} valid versions into selector: "
181
+ f"{[item['version'] for item in self.versions]!r}"
182
+ )
183
+
184
+ newest_update = next(
185
+ (index for index, item in enumerate(self.versions)
186
+ if self._compare_versions(str(item["version"]), self.current_version) > 0),
187
+ None,
188
+ )
189
+ self.update_available_changed.emit(newest_update is not None)
190
+ logger.info(
191
+ f"update_available={newest_update is not None}, current_version={self.current_version!r}, "
192
+ f"newest_update_index={newest_update!r}"
193
+ )
194
+ if not self.versions:
195
+ self._set_version_controls_visible(False)
196
+ self._set_notes("")
197
+ self._set_status(self.tr("No versions are available."))
198
+ self.update_button.setEnabled(False)
199
+ return
200
+ self._set_version_controls_visible(True)
201
+ self._set_status("" if newest_update is not None else self.tr("No updates available."))
202
+ self.version_combo.setCurrentIndex(0)
203
+ self._selection_changed()
204
+
205
+ def _selection_changed(self, _index=None):
206
+ index = self.version_combo.currentIndex()
207
+ if index < 0 or index >= len(self.versions):
208
+ self.update_button.setEnabled(False)
209
+ return
210
+ selected = self.versions[index]
211
+ target = str(selected["version"])
212
+ direction = self._compare_versions(target, self.current_version)
213
+ logger.debug(
214
+ f"selected version={target!r}, current_version={self.current_version!r}, direction={direction}"
215
+ )
216
+ self.update_button.setEnabled(direction != 0 and not self._busy)
217
+ self.update_button.setText(self.tr("Update") if direction > 0 else self.tr("Downgrade"))
218
+
219
+ if direction == 0:
220
+ self.update_button.setText(self.tr("Current version"))
221
+
222
+ calculate_notes = getattr(self.pyappify_module, "calculate_update_notes", None)
223
+ if not callable(calculate_notes):
224
+ self._set_notes("")
225
+ self._set_status(self.tr("Update-note calculation is not supported."), error=True)
226
+ return
227
+ try:
228
+ notes = calculate_notes(self.versions, self.current_version, target)
229
+ self._set_notes(
230
+ "\n".join(f"• {note}" for note in notes) or self.tr("No release notes.")
231
+ )
232
+ except Exception as error:
233
+ logger.error(f"pyappify.calculate_update_notes failed: {error}", error)
234
+ self._set_notes("")
235
+ self._set_status(self.tr("Failed to calculate update notes: {error}").format(error=error), error=True)
236
+
237
+ def _resize_version_combo(self):
238
+ font_metrics = QFontMetrics(self.version_combo.font())
239
+ text_width = max(
240
+ (font_metrics.horizontalAdvance(str(item["version"])) for item in self.versions),
241
+ default=0,
242
+ )
243
+ content_width = text_width + 48
244
+ width = max(self.VERSION_COMBO_MIN_WIDTH, min(self.VERSION_COMBO_MAX_WIDTH, content_width))
245
+ self.version_combo.setFixedWidth(width)
246
+
247
+ def _set_version_controls_visible(self, visible):
248
+ self.version_label.setVisible(visible)
249
+ self.version_combo.setVisible(visible)
250
+
251
+ def _set_notes(self, text):
252
+ self.notes_edit.setPlainText(text)
253
+ self.notes_edit.setVisible(bool(text))
254
+
255
+ def _set_check_loading(self, loading):
256
+ if loading:
257
+ self.check_button.setIcon(self._loading_placeholder_icon)
258
+ self.check_progress.show()
259
+ self.check_progress.start()
260
+ else:
261
+ self.check_progress.stop()
262
+ self.check_progress.hide()
263
+ self.check_button.setIcon(FluentIcon.SYNC)
264
+ self._position_check_progress()
265
+
266
+ def _position_check_progress(self):
267
+ minimum_width = self.check_button.minimumSizeHint().width()
268
+ x = 12 + max(0, (self.check_button.width() - minimum_width) // 2)
269
+ self.check_progress.move(x, (self.check_button.height() - self.check_progress.height()) // 2)
270
+
271
+ def eventFilter(self, watched, event):
272
+ if watched is self.check_button and event.type() == QEvent.Type.Resize:
273
+ self._position_check_progress()
274
+ return super().eventFilter(watched, event)
275
+
276
+ def _apply_update_result(self, result):
277
+ self._set_busy(False)
278
+ successful, value = result
279
+ if successful:
280
+ self._set_status(self.tr("Update request accepted. The app will restart to apply it."))
281
+ else:
282
+ self._show_error(self.tr("Failed to change version: {error}").format(error=value))
283
+
284
+ def _set_busy(self, busy, checking=False, refresh_selection=True):
285
+ self._busy = busy
286
+ self.check_button.setEnabled(not busy)
287
+ self._set_check_loading(busy and checking)
288
+ self.test_version_checkbox.setEnabled(not busy)
289
+ self.version_combo.setEnabled(not busy)
290
+ if busy:
291
+ self.update_button.setEnabled(False)
292
+ elif refresh_selection:
293
+ self._selection_changed()
294
+
295
+ def _show_error(self, message):
296
+ self._set_busy(False, refresh_selection=False)
297
+ self._set_notes("")
298
+ self._set_status(message, error=True)
299
+
300
+ def _set_status(self, message, error=False):
301
+ self.status_label.setText(message)
302
+ self.status_label.setStyleSheet("color: #d13438;" if error else "")
303
+
304
+ def _compare_versions(self, left, right):
305
+ if left == right:
306
+ return 0
307
+ is_greater = getattr(self.pyappify_module, "is_greater_version", None)
308
+ if callable(is_greater):
309
+ if is_greater(left, right):
310
+ return 1
311
+ if is_greater(right, left):
312
+ return -1
313
+ return 0
@@ -0,0 +1,16 @@
1
+ from qfluentwidgets import SettingCard
2
+
3
+ from ok.ui.qt.about.LinksBar import LinksBar
4
+
5
+
6
+ class VersionCard(SettingCard):
7
+ """ Sample card """
8
+
9
+ def __init__(self, config, icon, title, version, debug, parent=None):
10
+ super().__init__(icon, title, f'{version} {self.get_type(debug)}')
11
+ links_bar = LinksBar(config)
12
+ self.iconLabel.setFixedSize(36, 36)
13
+ self.hBoxLayout.addWidget(links_bar)
14
+
15
+ def get_type(self, debug=None):
16
+ return self.tr('Debug') if debug else self.tr('Release')
@@ -11,7 +11,7 @@ from PySide6.QtWidgets import QLayout, QWidget
11
11
  class DesignToken:
12
12
  """The app's 8-point-grid-derived layout and sizing tokens."""
13
13
 
14
- PAGE_MARGIN = 24
14
+ PAGE_MARGIN = 16
15
15
  PAGE_SPACING = 12
16
16
 
17
17
  SECTION_SPACING = 12