pygpt-net 2.4.37__py3-none-any.whl → 2.4.42__py3-none-any.whl

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 (340) hide show
  1. CHANGELOG.md +37 -0
  2. README.md +176 -182
  3. pygpt_net/CHANGELOG.txt +37 -0
  4. pygpt_net/__init__.py +3 -3
  5. pygpt_net/app.py +3 -1
  6. pygpt_net/controller/__init__.py +7 -3
  7. pygpt_net/controller/access/control.py +1 -1
  8. pygpt_net/controller/access/voice.py +11 -5
  9. pygpt_net/controller/agent/experts.py +11 -6
  10. pygpt_net/controller/agent/legacy.py +8 -6
  11. pygpt_net/controller/agent/llama.py +4 -2
  12. pygpt_net/controller/assistant/__init__.py +9 -4
  13. pygpt_net/controller/assistant/batch.py +38 -21
  14. pygpt_net/controller/assistant/editor.py +7 -6
  15. pygpt_net/controller/assistant/files.py +23 -7
  16. pygpt_net/controller/assistant/store.py +20 -7
  17. pygpt_net/controller/assistant/threads.py +34 -8
  18. pygpt_net/controller/attachment.py +29 -10
  19. pygpt_net/controller/audio/__init__.py +26 -5
  20. pygpt_net/controller/calendar/__init__.py +23 -4
  21. pygpt_net/controller/calendar/note.py +57 -11
  22. pygpt_net/controller/camera.py +4 -12
  23. pygpt_net/controller/chat/__init__.py +5 -3
  24. pygpt_net/controller/chat/attachment.py +34 -7
  25. pygpt_net/controller/chat/audio.py +2 -2
  26. pygpt_net/controller/chat/command.py +4 -2
  27. pygpt_net/controller/chat/common.py +11 -4
  28. pygpt_net/controller/chat/files.py +10 -3
  29. pygpt_net/controller/chat/image.py +17 -5
  30. pygpt_net/controller/chat/input.py +10 -7
  31. pygpt_net/controller/chat/output.py +21 -6
  32. pygpt_net/controller/chat/render.py +100 -21
  33. pygpt_net/controller/chat/response.py +34 -7
  34. pygpt_net/controller/chat/stream.py +4 -2
  35. pygpt_net/controller/chat/text.py +6 -4
  36. pygpt_net/controller/command.py +11 -3
  37. pygpt_net/controller/config/__init__.py +34 -6
  38. pygpt_net/controller/config/field/checkbox.py +7 -4
  39. pygpt_net/controller/config/field/cmd.py +7 -5
  40. pygpt_net/controller/config/field/combo.py +14 -6
  41. pygpt_net/controller/config/field/dictionary.py +14 -11
  42. pygpt_net/controller/config/field/input.py +9 -6
  43. pygpt_net/controller/config/field/slider.py +11 -8
  44. pygpt_net/controller/config/field/textarea.py +8 -5
  45. pygpt_net/controller/config/placeholder.py +66 -21
  46. pygpt_net/controller/ctx/__init__.py +138 -49
  47. pygpt_net/controller/ctx/common.py +15 -4
  48. pygpt_net/controller/ctx/extra.py +11 -3
  49. pygpt_net/controller/ctx/summarizer.py +24 -5
  50. pygpt_net/controller/debug/__init__.py +27 -6
  51. pygpt_net/controller/dialogs/confirm.py +34 -7
  52. pygpt_net/controller/dialogs/debug.py +4 -2
  53. pygpt_net/controller/dialogs/info.py +7 -2
  54. pygpt_net/controller/files.py +48 -10
  55. pygpt_net/controller/finder.py +11 -5
  56. pygpt_net/controller/idx/__init__.py +10 -3
  57. pygpt_net/controller/idx/common.py +4 -2
  58. pygpt_net/controller/idx/indexer.py +25 -17
  59. pygpt_net/controller/idx/settings.py +9 -3
  60. pygpt_net/controller/kernel/__init__.py +34 -8
  61. pygpt_net/controller/kernel/reply.py +12 -3
  62. pygpt_net/controller/kernel/stack.py +5 -3
  63. pygpt_net/controller/lang/custom.py +2 -7
  64. pygpt_net/controller/lang/mapping.py +5 -3
  65. pygpt_net/controller/layout.py +2 -2
  66. pygpt_net/controller/mode.py +16 -4
  67. pygpt_net/controller/model/__init__.py +14 -3
  68. pygpt_net/controller/model/editor.py +8 -3
  69. pygpt_net/controller/notepad.py +26 -12
  70. pygpt_net/controller/painter/capture.py +23 -4
  71. pygpt_net/controller/painter/common.py +9 -7
  72. pygpt_net/controller/plugins/__init__.py +19 -5
  73. pygpt_net/controller/plugins/presets.py +15 -6
  74. pygpt_net/controller/plugins/settings.py +9 -3
  75. pygpt_net/controller/presets/__init__.py +55 -16
  76. pygpt_net/controller/presets/editor.py +26 -10
  77. pygpt_net/controller/settings/__init__.py +3 -2
  78. pygpt_net/controller/settings/editor.py +29 -7
  79. pygpt_net/controller/settings/profile.py +22 -5
  80. pygpt_net/controller/theme/__init__.py +54 -12
  81. pygpt_net/controller/theme/common.py +24 -2
  82. pygpt_net/controller/theme/markdown.py +32 -16
  83. pygpt_net/controller/theme/menu.py +26 -5
  84. pygpt_net/controller/theme/nodes.py +2 -5
  85. pygpt_net/controller/tools/__init__.py +40 -2
  86. pygpt_net/controller/ui/__init__.py +4 -6
  87. pygpt_net/controller/ui/mode.py +16 -21
  88. pygpt_net/controller/ui/tabs.py +363 -65
  89. pygpt_net/core/access/actions.py +6 -4
  90. pygpt_net/core/access/shortcuts.py +4 -3
  91. pygpt_net/core/access/voice.py +6 -5
  92. pygpt_net/core/agents/legacy.py +4 -2
  93. pygpt_net/core/agents/memory.py +7 -2
  94. pygpt_net/core/agents/observer/evaluation.py +15 -7
  95. pygpt_net/core/agents/provider.py +9 -4
  96. pygpt_net/core/agents/runner.py +61 -15
  97. pygpt_net/core/agents/tools.py +23 -5
  98. pygpt_net/core/assistants/__init__.py +6 -4
  99. pygpt_net/core/assistants/files.py +35 -12
  100. pygpt_net/core/assistants/store.py +20 -10
  101. pygpt_net/core/attachments/__init__.py +54 -15
  102. pygpt_net/core/attachments/context.py +92 -29
  103. pygpt_net/core/audio/__init__.py +74 -3
  104. pygpt_net/core/audio/context.py +7 -2
  105. pygpt_net/core/audio/whisper.py +37 -0
  106. pygpt_net/core/bridge/__init__.py +22 -6
  107. pygpt_net/core/bridge/context.py +5 -3
  108. pygpt_net/core/bridge/worker.py +2 -2
  109. pygpt_net/core/calendar/__init__.py +57 -11
  110. pygpt_net/core/chain/__init__.py +8 -2
  111. pygpt_net/core/chain/chat.py +10 -8
  112. pygpt_net/core/chain/completion.py +10 -7
  113. pygpt_net/core/command.py +62 -17
  114. pygpt_net/core/ctx/__init__.py +260 -58
  115. pygpt_net/core/ctx/bag.py +25 -4
  116. pygpt_net/core/ctx/container.py +28 -17
  117. pygpt_net/core/ctx/idx.py +45 -8
  118. pygpt_net/core/ctx/output.py +95 -74
  119. pygpt_net/core/ctx/reply.py +5 -2
  120. pygpt_net/core/db/__init__.py +8 -7
  121. pygpt_net/core/db/viewer.py +17 -11
  122. pygpt_net/core/debug/__init__.py +10 -9
  123. pygpt_net/core/debug/events.py +22 -10
  124. pygpt_net/core/debug/tabs.py +9 -3
  125. pygpt_net/core/docker/__init__.py +11 -5
  126. pygpt_net/core/docker/builder.py +11 -3
  127. pygpt_net/core/events/app.py +5 -3
  128. pygpt_net/core/events/base.py +11 -5
  129. pygpt_net/core/events/control.py +5 -3
  130. pygpt_net/core/events/event.py +17 -7
  131. pygpt_net/core/events/kernel.py +5 -3
  132. pygpt_net/core/events/render.py +5 -3
  133. pygpt_net/core/experts/__init__.py +5 -4
  134. pygpt_net/core/filesystem/__init__.py +52 -34
  135. pygpt_net/core/filesystem/actions.py +8 -5
  136. pygpt_net/core/filesystem/editor.py +13 -3
  137. pygpt_net/core/filesystem/types.py +12 -7
  138. pygpt_net/core/filesystem/url.py +7 -3
  139. pygpt_net/core/history.py +3 -2
  140. pygpt_net/core/idx/__init__.py +48 -27
  141. pygpt_net/core/idx/chat.py +51 -17
  142. pygpt_net/core/idx/context.py +6 -2
  143. pygpt_net/core/idx/indexing.py +107 -42
  144. pygpt_net/core/idx/llm.py +11 -3
  145. pygpt_net/core/idx/metadata.py +13 -3
  146. pygpt_net/core/idx/types/ctx.py +32 -6
  147. pygpt_net/core/idx/types/external.py +41 -7
  148. pygpt_net/core/idx/types/files.py +31 -6
  149. pygpt_net/core/image.py +15 -4
  150. pygpt_net/core/installer.py +2 -4
  151. pygpt_net/core/llm/__init__.py +13 -3
  152. pygpt_net/core/locale.py +34 -8
  153. pygpt_net/core/models.py +63 -17
  154. pygpt_net/core/modes.py +11 -13
  155. pygpt_net/core/notepad.py +10 -5
  156. pygpt_net/core/plugins.py +31 -19
  157. pygpt_net/core/presets.py +37 -17
  158. pygpt_net/core/profile.py +21 -7
  159. pygpt_net/core/prompt/__init__.py +10 -3
  160. pygpt_net/core/prompt/custom.py +7 -6
  161. pygpt_net/core/prompt/template.py +9 -3
  162. pygpt_net/core/render/base.py +117 -22
  163. pygpt_net/core/render/markdown/body.py +27 -7
  164. pygpt_net/core/render/markdown/renderer.py +119 -22
  165. pygpt_net/core/render/plain/body.py +22 -5
  166. pygpt_net/core/render/plain/renderer.py +97 -21
  167. pygpt_net/core/render/web/body.py +75 -25
  168. pygpt_net/core/render/web/parser.py +3 -1
  169. pygpt_net/core/render/web/renderer.py +313 -63
  170. pygpt_net/core/settings.py +10 -5
  171. pygpt_net/core/tabs/__init__.py +290 -103
  172. pygpt_net/core/tabs/tab.py +26 -5
  173. pygpt_net/core/tokens.py +47 -12
  174. pygpt_net/core/updater/__init__.py +20 -7
  175. pygpt_net/core/vision/analyzer.py +29 -6
  176. pygpt_net/core/{web.py → web/__init__.py} +29 -7
  177. pygpt_net/core/web/helpers.py +237 -0
  178. pygpt_net/data/config/config.json +15 -4
  179. pygpt_net/data/config/models.json +3 -3
  180. pygpt_net/data/config/modes.json +3 -3
  181. pygpt_net/data/config/settings.json +55 -10
  182. pygpt_net/data/config/settings_section.json +3 -0
  183. pygpt_net/data/css/style.light.css +1 -0
  184. pygpt_net/data/css/{web.css → web-blocks.css} +162 -133
  185. pygpt_net/data/css/{web.light.css → web-blocks.light.css} +7 -0
  186. pygpt_net/data/css/web-chatgpt.css +350 -0
  187. pygpt_net/data/css/web-chatgpt.dark.css +64 -0
  188. pygpt_net/data/css/web-chatgpt.light.css +75 -0
  189. pygpt_net/data/css/web-chatgpt_wide.css +350 -0
  190. pygpt_net/data/css/web-chatgpt_wide.dark.css +64 -0
  191. pygpt_net/data/css/web-chatgpt_wide.light.css +75 -0
  192. pygpt_net/data/icons/split_screen.svg +1 -0
  193. pygpt_net/data/locale/locale.de.ini +12 -0
  194. pygpt_net/data/locale/locale.en.ini +18 -2
  195. pygpt_net/data/locale/locale.es.ini +12 -0
  196. pygpt_net/data/locale/locale.fr.ini +12 -0
  197. pygpt_net/data/locale/locale.it.ini +12 -0
  198. pygpt_net/data/locale/locale.pl.ini +12 -0
  199. pygpt_net/data/locale/locale.uk.ini +12 -0
  200. pygpt_net/data/locale/locale.zh.ini +12 -0
  201. pygpt_net/data/locale/plugin.cmd_web.de.ini +2 -0
  202. pygpt_net/data/locale/plugin.cmd_web.en.ini +22 -10
  203. pygpt_net/data/locale/plugin.cmd_web.es.ini +2 -0
  204. pygpt_net/data/locale/plugin.cmd_web.fr.ini +2 -0
  205. pygpt_net/data/locale/plugin.cmd_web.it.ini +2 -0
  206. pygpt_net/data/locale/plugin.cmd_web.pl.ini +2 -0
  207. pygpt_net/data/locale/plugin.cmd_web.uk.ini +2 -0
  208. pygpt_net/data/locale/plugin.cmd_web.zh.ini +2 -0
  209. pygpt_net/data/locale/plugin.mailer.en.ini +21 -0
  210. pygpt_net/icons.qrc +1 -0
  211. pygpt_net/icons_rc.py +165 -136
  212. pygpt_net/item/ctx.py +58 -25
  213. pygpt_net/plugin/agent/__init__.py +7 -2
  214. pygpt_net/plugin/audio_input/simple.py +21 -5
  215. pygpt_net/plugin/audio_output/__init__.py +9 -1
  216. pygpt_net/plugin/base/config.py +4 -2
  217. pygpt_net/plugin/base/plugin.py +75 -23
  218. pygpt_net/plugin/base/worker.py +42 -11
  219. pygpt_net/plugin/cmd_code_interpreter/__init__.py +39 -37
  220. pygpt_net/plugin/cmd_code_interpreter/runner.py +25 -12
  221. pygpt_net/plugin/cmd_history/config.py +2 -2
  222. pygpt_net/plugin/cmd_web/__init__.py +48 -9
  223. pygpt_net/plugin/cmd_web/config.py +135 -41
  224. pygpt_net/plugin/cmd_web/websearch.py +74 -33
  225. pygpt_net/plugin/cmd_web/worker.py +142 -13
  226. pygpt_net/plugin/idx_llama_index/config.py +3 -3
  227. pygpt_net/plugin/mailer/__init__.py +123 -0
  228. pygpt_net/plugin/mailer/config.py +149 -0
  229. pygpt_net/plugin/mailer/runner.py +285 -0
  230. pygpt_net/plugin/mailer/worker.py +123 -0
  231. pygpt_net/provider/agents/base.py +5 -2
  232. pygpt_net/provider/agents/openai.py +4 -2
  233. pygpt_net/provider/agents/openai_assistant.py +4 -2
  234. pygpt_net/provider/agents/planner.py +4 -2
  235. pygpt_net/provider/agents/react.py +4 -2
  236. pygpt_net/provider/audio_output/openai_tts.py +5 -11
  237. pygpt_net/provider/core/assistant/base.py +5 -3
  238. pygpt_net/provider/core/assistant/json_file.py +8 -5
  239. pygpt_net/provider/core/assistant_file/base.py +4 -3
  240. pygpt_net/provider/core/assistant_file/db_sqlite/__init__.py +4 -3
  241. pygpt_net/provider/core/assistant_file/db_sqlite/storage.py +3 -2
  242. pygpt_net/provider/core/assistant_store/base.py +6 -4
  243. pygpt_net/provider/core/assistant_store/db_sqlite/__init__.py +5 -4
  244. pygpt_net/provider/core/assistant_store/db_sqlite/storage.py +5 -3
  245. pygpt_net/provider/core/attachment/base.py +5 -3
  246. pygpt_net/provider/core/attachment/json_file.py +4 -3
  247. pygpt_net/provider/core/calendar/base.py +5 -3
  248. pygpt_net/provider/core/calendar/db_sqlite/__init__.py +6 -5
  249. pygpt_net/provider/core/calendar/db_sqlite/storage.py +5 -4
  250. pygpt_net/provider/core/config/base.py +8 -6
  251. pygpt_net/provider/core/config/json_file.py +9 -7
  252. pygpt_net/provider/core/config/patch.py +43 -1
  253. pygpt_net/provider/core/ctx/base.py +30 -25
  254. pygpt_net/provider/core/ctx/db_sqlite/__init__.py +59 -34
  255. pygpt_net/provider/core/ctx/db_sqlite/storage.py +62 -30
  256. pygpt_net/provider/core/ctx/db_sqlite/utils.py +11 -9
  257. pygpt_net/provider/core/index/base.py +129 -23
  258. pygpt_net/provider/core/index/db_sqlite/__init__.py +130 -23
  259. pygpt_net/provider/core/index/db_sqlite/storage.py +130 -23
  260. pygpt_net/provider/core/index/db_sqlite/utils.py +4 -2
  261. pygpt_net/provider/core/mode/base.py +5 -3
  262. pygpt_net/provider/core/mode/json_file.py +7 -6
  263. pygpt_net/provider/core/model/base.py +6 -4
  264. pygpt_net/provider/core/model/json_file.py +9 -7
  265. pygpt_net/provider/core/notepad/base.py +5 -3
  266. pygpt_net/provider/core/notepad/db_sqlite/__init__.py +5 -4
  267. pygpt_net/provider/core/notepad/db_sqlite/storage.py +4 -3
  268. pygpt_net/provider/core/plugin_preset/base.py +4 -2
  269. pygpt_net/provider/core/plugin_preset/json_file.py +5 -3
  270. pygpt_net/provider/core/preset/base.py +6 -4
  271. pygpt_net/provider/core/preset/json_file.py +9 -9
  272. pygpt_net/provider/core/prompt/base.py +6 -3
  273. pygpt_net/provider/core/prompt/json_file.py +11 -6
  274. pygpt_net/provider/gpt/assistants.py +21 -11
  275. pygpt_net/provider/gpt/audio.py +6 -5
  276. pygpt_net/provider/gpt/chat.py +10 -7
  277. pygpt_net/provider/gpt/completion.py +11 -5
  278. pygpt_net/provider/gpt/image.py +9 -2
  279. pygpt_net/provider/gpt/store.py +53 -18
  280. pygpt_net/provider/gpt/vision.py +17 -11
  281. pygpt_net/provider/llms/anthropic.py +7 -2
  282. pygpt_net/provider/llms/azure_openai.py +26 -5
  283. pygpt_net/provider/llms/base.py +47 -9
  284. pygpt_net/provider/llms/google.py +7 -2
  285. pygpt_net/provider/llms/hugging_face.py +13 -3
  286. pygpt_net/provider/llms/hugging_face_api.py +18 -4
  287. pygpt_net/provider/llms/local.py +7 -2
  288. pygpt_net/provider/llms/ollama.py +30 -6
  289. pygpt_net/provider/llms/openai.py +32 -6
  290. pygpt_net/provider/vector_stores/__init__.py +45 -14
  291. pygpt_net/provider/vector_stores/base.py +35 -8
  292. pygpt_net/provider/vector_stores/chroma.py +13 -3
  293. pygpt_net/provider/vector_stores/ctx_attachment.py +31 -12
  294. pygpt_net/provider/vector_stores/elasticsearch.py +12 -3
  295. pygpt_net/provider/vector_stores/pinecode.py +12 -3
  296. pygpt_net/provider/vector_stores/redis.py +12 -3
  297. pygpt_net/provider/vector_stores/simple.py +12 -3
  298. pygpt_net/provider/vector_stores/temp.py +16 -4
  299. pygpt_net/provider/web/base.py +10 -3
  300. pygpt_net/provider/web/google_custom_search.py +9 -3
  301. pygpt_net/provider/web/microsoft_bing.py +9 -3
  302. pygpt_net/tools/__init__.py +20 -4
  303. pygpt_net/tools/audio_transcriber/__init__.py +4 -3
  304. pygpt_net/tools/base.py +28 -7
  305. pygpt_net/tools/code_interpreter/__init__.py +177 -77
  306. pygpt_net/tools/code_interpreter/ui/dialogs.py +21 -103
  307. pygpt_net/tools/code_interpreter/ui/widgets.py +284 -9
  308. pygpt_net/tools/html_canvas/__init__.py +81 -25
  309. pygpt_net/tools/html_canvas/ui/dialogs.py +46 -62
  310. pygpt_net/tools/html_canvas/ui/widgets.py +96 -3
  311. pygpt_net/tools/image_viewer/__init__.py +10 -4
  312. pygpt_net/tools/indexer/__init__.py +8 -7
  313. pygpt_net/tools/media_player/__init__.py +4 -3
  314. pygpt_net/tools/text_editor/__init__.py +36 -10
  315. pygpt_net/ui/base/context_menu.py +2 -2
  316. pygpt_net/ui/layout/chat/input.py +10 -18
  317. pygpt_net/ui/layout/chat/output.py +27 -45
  318. pygpt_net/ui/layout/ctx/ctx_list.py +13 -4
  319. pygpt_net/ui/layout/toolbox/footer.py +18 -2
  320. pygpt_net/ui/main.py +2 -2
  321. pygpt_net/ui/menu/audio.py +12 -1
  322. pygpt_net/ui/menu/config.py +7 -11
  323. pygpt_net/ui/menu/debug.py +11 -1
  324. pygpt_net/ui/menu/theme.py +9 -2
  325. pygpt_net/ui/widget/filesystem/explorer.py +2 -2
  326. pygpt_net/ui/widget/lists/context.py +27 -5
  327. pygpt_net/ui/widget/tabs/Input.py +2 -2
  328. pygpt_net/ui/widget/tabs/body.py +2 -1
  329. pygpt_net/ui/widget/tabs/layout.py +195 -0
  330. pygpt_net/ui/widget/tabs/output.py +218 -55
  331. pygpt_net/ui/widget/textarea/html.py +11 -1
  332. pygpt_net/ui/widget/textarea/output.py +10 -1
  333. pygpt_net/ui/widget/textarea/search_input.py +4 -1
  334. pygpt_net/ui/widget/textarea/web.py +49 -9
  335. {pygpt_net-2.4.37.dist-info → pygpt_net-2.4.42.dist-info}/METADATA +177 -183
  336. {pygpt_net-2.4.37.dist-info → pygpt_net-2.4.42.dist-info}/RECORD +340 -325
  337. /pygpt_net/data/css/{web.dark.css → web-blocks.dark.css} +0 -0
  338. {pygpt_net-2.4.37.dist-info → pygpt_net-2.4.42.dist-info}/LICENSE +0 -0
  339. {pygpt_net-2.4.37.dist-info → pygpt_net-2.4.42.dist-info}/WHEEL +0 -0
  340. {pygpt_net-2.4.37.dist-info → pygpt_net-2.4.42.dist-info}/entry_points.txt +0 -0
@@ -6,36 +6,46 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2024.11.11 23:00:00 #
9
+ # Updated Date: 2024.12.14 22:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import os
13
+ from typing import Dict
13
14
 
14
- from PySide6.QtCore import QTimer, Slot, QUrl
15
+ from PySide6.QtCore import QTimer, Slot
15
16
  from PySide6.QtGui import QAction, QIcon
16
- from PySide6.QtWidgets import QFileDialog
17
+ from PySide6.QtWidgets import QFileDialog, QWidget
17
18
 
19
+ from pygpt_net.core.tabs.tab import Tab
18
20
  from pygpt_net.core.text.utils import output_clean_html, output_html2text
19
21
  from pygpt_net.tools.base import BaseTool
20
- from pygpt_net.tools.html_canvas.ui.dialogs import Canvas
21
22
  from pygpt_net.utils import trans
22
23
 
24
+ from .ui.dialogs import Tool
25
+ from .ui.widgets import ToolWidget, ToolSignals
26
+
23
27
 
24
28
  class HtmlCanvas(BaseTool):
25
29
  def __init__(self, *args, **kwargs):
26
30
  """
27
- HTML/JS canvas
31
+ HTML/JS Canvas
28
32
 
29
33
  :param window: Window instance
30
34
  """
31
35
  super(HtmlCanvas, self).__init__(*args, **kwargs)
32
36
  self.id = "html_canvas"
37
+ self.dialog_id = "html_canvas"
38
+ self.has_tab = True
39
+ self.tab_title = "menu.tools.html_canvas"
40
+ self.tab_icon = ":/icons/code.svg"
33
41
  self.opened = False
34
42
  self.is_edit = False
35
43
  self.auto_clear = True
36
44
  self.dialog = None
37
45
  self.is_edit = False
46
+ self.auto_opened = False
38
47
  self.file_output = ".canvas.html"
48
+ self.signals = ToolSignals()
39
49
 
40
50
  def setup(self):
41
51
  """Setup"""
@@ -50,16 +60,19 @@ class HtmlCanvas(BaseTool):
50
60
  """Update menu"""
51
61
  self.update_menu()
52
62
 
53
- def toggle_edit(self):
54
- """Toggle edit mode"""
63
+ def toggle_edit(self, widget: ToolWidget):
64
+ """
65
+ Toggle edit mode
66
+
67
+ :param widget: Canvas widget
68
+ """
55
69
  current = self.is_edit
56
70
  self.is_edit = not self.is_edit
57
- self.window.ui.nodes['html_canvas.edit'].setVisible(self.is_edit)
58
- self.window.ui.nodes['html_canvas.output'].setVisible(not self.is_edit)
71
+ widget.edit.setVisible(self.is_edit)
72
+ widget.output.setVisible(not self.is_edit)
59
73
  if current:
60
- self.set_output(self.window.ui.nodes['html_canvas.edit'].toPlainText())
74
+ self.set_output(widget.edit.toPlainText())
61
75
  self.save_output()
62
- self.window.ui.nodes['html_canvas.btn.edit'].setChecked(self.is_edit)
63
76
 
64
77
  def update_menu(self):
65
78
  """Update menu"""
@@ -78,18 +91,26 @@ class HtmlCanvas(BaseTool):
78
91
  """
79
92
  return os.path.join(self.window.core.config.get_user_dir("data"), self.file_output)
80
93
 
94
+ def get_dialog_id(self) -> str:
95
+ """
96
+ Get dialog ID
97
+
98
+ :return: Dialog ID
99
+ """
100
+ return self.dialog_id
101
+
81
102
  def set_output(self, output: str):
82
103
  """
83
104
  Set output HTML
84
105
 
85
106
  :param output: Output HTML code
86
107
  """
87
- path = os.path.join(self.window.core.config.get_user_dir("data"), self.file_output)
108
+ path = self.get_current_path()
88
109
  with open(path, "w", encoding="utf-8") as f:
89
110
  f.write(output)
90
111
  if os.path.exists(path):
91
- self.window.ui.nodes['html_canvas.output'].setUrl(QUrl().fromLocalFile(path))
92
- self.window.ui.nodes['html_canvas.edit'].setPlainText(output)
112
+ self.signals.reload.emit(path)
113
+ self.signals.update.emit(output)
93
114
 
94
115
  def reload_output(self):
95
116
  """Reload output data"""
@@ -102,11 +123,16 @@ class HtmlCanvas(BaseTool):
102
123
 
103
124
  :return: Output data
104
125
  """
105
- return self.window.ui.nodes['html_canvas.edit'].toPlainText()
126
+ path = self.get_current_path()
127
+ data = ""
128
+ if os.path.exists(path):
129
+ with open(path, "r", encoding="utf-8") as f:
130
+ data = f.read()
131
+ return data
106
132
 
107
133
  def load_output(self):
108
134
  """Load output data from file"""
109
- path = os.path.join(self.window.core.config.get_user_dir("data"), self.file_output)
135
+ path = self.get_current_path()
110
136
  data = ""
111
137
  if os.path.exists(path):
112
138
  with open(path, "r", encoding="utf-8") as f:
@@ -115,14 +141,14 @@ class HtmlCanvas(BaseTool):
115
141
 
116
142
  def save_output(self):
117
143
  """Save output data to file"""
118
- path = os.path.join(self.window.core.config.get_user_dir("data"), self.file_output)
144
+ path = self.get_current_path()
119
145
  data = self.get_output()
120
146
  with open(path, "w", encoding="utf-8") as f:
121
147
  f.write(data)
122
148
 
123
149
  def clear_output(self):
124
150
  """Clear output"""
125
- path = os.path.join(self.window.core.config.get_user_dir("data"), self.file_output)
151
+ path = self.get_current_path()
126
152
  if os.path.exists(path):
127
153
  os.remove(path)
128
154
  self.set_output("")
@@ -151,9 +177,17 @@ class HtmlCanvas(BaseTool):
151
177
  if not self.opened:
152
178
  self.opened = True
153
179
  self.load_output()
154
- self.window.ui.dialogs.open('html_canvas', width=800, height=600)
180
+ self.window.ui.dialogs.open(self.dialog_id, width=800, height=600)
155
181
  self.update()
156
182
 
183
+ def auto_open(self):
184
+ """Auto open canvas dialog"""
185
+ if self.window.controller.ui.tabs.is_current_tool(self.id):
186
+ return # do not open if already opened in tab
187
+ if not self.auto_opened:
188
+ self.auto_opened = True
189
+ self.open()
190
+
157
191
  def open_file(self):
158
192
  """Open file dialog"""
159
193
  last_dir = self.window.core.config.get_last_used_dir()
@@ -172,7 +206,7 @@ class HtmlCanvas(BaseTool):
172
206
  def close(self):
173
207
  """Close HTML canvas dialog"""
174
208
  self.opened = False
175
- self.window.ui.dialogs.close('html_canvas')
209
+ self.window.ui.dialogs.close(self.dialog_id)
176
210
  self.update()
177
211
 
178
212
  def toggle(self):
@@ -193,13 +227,21 @@ class HtmlCanvas(BaseTool):
193
227
  else:
194
228
  self.close()
195
229
 
230
+ def get_toolbar_icon(self) -> QWidget:
231
+ """
232
+ Get toolbar icon
233
+
234
+ :return: QWidget
235
+ """
236
+ return self.window.ui.nodes['icon.html_canvas']
237
+
196
238
  def toggle_icon(self, state: bool):
197
239
  """
198
240
  Toggle canvas icon
199
241
 
200
242
  :param state: State
201
243
  """
202
- self.window.ui.nodes['icon.html_canvas'].setVisible(state)
244
+ self.get_toolbar_icon().setVisible(state)
203
245
 
204
246
  def get_current_output(self) -> str:
205
247
  """
@@ -207,7 +249,7 @@ class HtmlCanvas(BaseTool):
207
249
 
208
250
  :return: Output data
209
251
  """
210
- return self.window.ui.nodes['html_canvas.output'].get_html_content()
252
+ return self.get_output()
211
253
 
212
254
  @Slot(str, str)
213
255
  def handle_save_as(self, text: str, type: str = 'txt'):
@@ -224,7 +266,7 @@ class HtmlCanvas(BaseTool):
224
266
  # fix: QTimer required here to prevent crash if signal emitted from WebEngine window
225
267
  QTimer.singleShot(0, lambda: self.window.controller.chat.common.save_text(text, type))
226
268
 
227
- def setup_menu(self) -> dict:
269
+ def setup_menu(self) -> Dict[str, QAction]:
228
270
  """
229
271
  Setup main menu
230
272
 
@@ -242,16 +284,30 @@ class HtmlCanvas(BaseTool):
242
284
  )
243
285
  return actions
244
286
 
287
+ def as_tab(self, tab: Tab) -> QWidget:
288
+ """
289
+ Spawn and return tab instance
290
+
291
+ :param tab: Parent Tab instance
292
+ :return: Tab widget instance
293
+ """
294
+ canvas = Tool(window=self.window, tool=self)
295
+ layout = canvas.widget.setup()
296
+ widget = QWidget()
297
+ widget.setLayout(layout)
298
+ self.load_output()
299
+ return widget
300
+
245
301
  def setup_dialogs(self):
246
302
  """Setup dialogs (static)"""
247
- self.dialog = Canvas(self.window)
303
+ self.dialog = Tool(window=self.window, tool=self)
248
304
  self.dialog.setup()
249
305
 
250
306
  def setup_theme(self):
251
307
  """Setup theme"""
252
308
  pass
253
309
 
254
- def get_lang_mappings(self) -> dict:
310
+ def get_lang_mappings(self) -> Dict[str, Dict]:
255
311
  """
256
312
  Get language mappings
257
313
 
@@ -6,29 +6,32 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2024.11.11 23:00:00 #
9
+ # Updated Date: 2024.12.09 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import re
13
13
 
14
14
  from PySide6.QtCore import Qt
15
15
  from PySide6.QtGui import QAction, QIcon
16
- from PySide6.QtWidgets import QHBoxLayout, QVBoxLayout, QCheckBox, QMenuBar
16
+ from PySide6.QtWidgets import QMenuBar, QVBoxLayout
17
17
 
18
- from pygpt_net.tools.html_canvas.ui.widgets import CanvasOutput, CanvasEdit
19
18
  from pygpt_net.ui.widget.dialog.base import BaseDialog
20
- from pygpt_net.ui.widget.element.labels import HelpLabel
21
- from pygpt_net.ui.widget.textarea.html import CustomWebEnginePage
22
19
  from pygpt_net.utils import trans
23
20
 
24
- class Canvas:
25
- def __init__(self, window=None):
21
+ from .widgets import ToolWidget
22
+
23
+ class Tool:
24
+ def __init__(self, window=None, tool=None):
26
25
  """
27
26
  HTML/JS canvas dialog
28
27
 
29
28
  :param window: Window instance
29
+ :param tool: Tool instance
30
30
  """
31
31
  self.window = window
32
+ self.tool = tool # tool instance
33
+ self.widget = ToolWidget(window, tool)
34
+ self.layout = None
32
35
  self.menu_bar = None
33
36
  self.menu = {}
34
37
  self.actions = {} # menu actions
@@ -45,20 +48,20 @@ class Canvas:
45
48
 
46
49
  self.actions["file.open"] = QAction(QIcon(":/icons/folder.svg"), trans("tool.html_canvas.menu.file.open"))
47
50
  self.actions["file.open"].triggered.connect(
48
- lambda: self.window.tools.get("html_canvas").open_file()
51
+ lambda: self.tool.open_file()
49
52
  )
50
53
  self.actions["file.save_as"] = QAction(QIcon(":/icons/save.svg"), trans("tool.html_canvas.menu.file.save_as"))
51
54
  self.actions["file.save_as"].triggered.connect(
52
- lambda: self.window.ui.nodes['html_canvas.output'].signals.save_as.emit(
53
- re.sub(r'\n{2,}', '\n\n', self.window.ui.nodes['html_canvas.output'].html_content), 'html')
55
+ lambda: self.widget.output.signals.save_as.emit(
56
+ re.sub(r'\n{2,}', '\n\n', self.widget.output.html_content), 'html')
54
57
  )
55
58
  self.actions["file.reload"] = QAction(QIcon(":/icons/reload.svg"), trans("tool.html_canvas.menu.file.reload"))
56
59
  self.actions["file.reload"].triggered.connect(
57
- lambda: self.window.tools.get("html_canvas").reload_output()
60
+ lambda: self.tool.reload_output()
58
61
  )
59
62
  self.actions["file.clear"] = QAction(QIcon(":/icons/close.svg"), trans("tool.html_canvas.menu.file.clear"))
60
63
  self.actions["file.clear"].triggered.connect(
61
- lambda: self.window.tools.get("html_canvas").clear()
64
+ lambda: self.tool.clear()
62
65
  )
63
66
 
64
67
  # add actions
@@ -70,61 +73,44 @@ class Canvas:
70
73
 
71
74
  def setup(self):
72
75
  """Setup canvas dialog"""
73
- self.window.ui.nodes['html_canvas.output'] = CanvasOutput(self.window)
74
- self.window.ui.nodes['html_canvas.output'].setPage(
75
- CustomWebEnginePage(self.window, self.window.ui.nodes['html_canvas.output'])
76
- )
77
- self.window.ui.nodes['html_canvas.edit'] = CanvasEdit(self.window)
78
- self.window.ui.nodes['html_canvas.edit'].setVisible(False)
79
- self.window.ui.nodes['html_canvas.edit'].textChanged.connect(
80
- lambda: self.window.tools.get("html_canvas").save_output()
81
- )
82
-
83
- # edit checkbox
84
- self.window.ui.nodes['html_canvas.btn.edit'] = QCheckBox(trans("html_canvas.btn.edit"))
85
- self.window.ui.nodes['html_canvas.btn.edit'].stateChanged.connect(
86
- lambda: self.window.tools.get("html_canvas").toggle_edit()
87
- )
88
-
89
- path = self.window.tools.get("html_canvas").get_current_path()
90
- path_label = HelpLabel(path)
91
- path_label.setMaximumHeight(30)
92
- path_label.setAlignment(Qt.AlignRight)
76
+ self.layout = self.widget.setup()
77
+ self.layout.setMenuBar(self.setup_menu()) # add menu bar
93
78
 
94
- bottom_layout = QHBoxLayout()
95
- bottom_layout.addWidget(self.window.ui.nodes['html_canvas.btn.edit'])
96
- bottom_layout.addWidget(path_label)
79
+ id = self.tool.get_dialog_id()
80
+ dialog = ToolDialog(window=self.window, tool=self.tool)
81
+ dialog.setLayout(self.layout)
82
+ dialog.setWindowTitle(trans("dialog.html_canvas.title"))
83
+ dialog.resize(800, 500)
84
+ self.window.ui.dialog[id] = dialog
97
85
 
98
- output_layout = QVBoxLayout()
99
- output_layout.addWidget(self.window.ui.nodes['html_canvas.output'])
100
- output_layout.addWidget(self.window.ui.nodes['html_canvas.edit'])
101
- output_layout.setContentsMargins(0, 0, 0, 0)
86
+ def get_widget(self) -> ToolWidget:
87
+ """
88
+ Get widget
102
89
 
103
- # connect signals
104
- self.window.ui.nodes['html_canvas.output'].signals.save_as.connect(self.window.tools.get("html_canvas").handle_save_as)
105
- self.window.ui.nodes['html_canvas.output'].signals.audio_read.connect(self.window.controller.chat.render.handle_audio_read)
90
+ :return: ToolWidget
91
+ """
92
+ return self.widget
106
93
 
107
- layout = QVBoxLayout()
108
- layout.setMenuBar(self.setup_menu()) # add menu bar
109
- layout.addLayout(output_layout)
110
- layout.addLayout(bottom_layout)
94
+ def get_tab(self) -> QVBoxLayout:
95
+ """
96
+ Get layout
111
97
 
112
- self.window.ui.dialog['html_canvas'] = CanvasDialog(self.window)
113
- self.window.ui.dialog['html_canvas'].setLayout(layout)
114
- self.window.ui.dialog['html_canvas'].setWindowTitle(trans("dialog.html_canvas.title"))
115
- self.window.ui.dialog['html_canvas'].resize(800, 500)
98
+ :return: QVBoxLayout
99
+ """
100
+ return self.layout
116
101
 
117
102
 
118
- class CanvasDialog(BaseDialog):
119
- def __init__(self, window=None, id="html_canvas"):
103
+ class ToolDialog(BaseDialog):
104
+ def __init__(self, window=None, id="html_canvas", tool=None):
120
105
  """
121
106
  HTML canvas dialog
122
107
 
123
108
  :param window: main window
124
109
  :param id: logger id
125
110
  """
126
- super(CanvasDialog, self).__init__(window, id)
111
+ super(ToolDialog, self).__init__(window, id)
127
112
  self.window = window
113
+ self.tool = tool
128
114
 
129
115
  def closeEvent(self, event):
130
116
  """
@@ -133,7 +119,7 @@ class CanvasDialog(BaseDialog):
133
119
  :param event: close event
134
120
  """
135
121
  self.cleanup()
136
- super(CanvasDialog, self).closeEvent(event)
122
+ super(ToolDialog, self).closeEvent(event)
137
123
 
138
124
  def keyPressEvent(self, event):
139
125
  """
@@ -145,14 +131,12 @@ class CanvasDialog(BaseDialog):
145
131
  self.cleanup()
146
132
  self.close() # close dialog when the Esc key is pressed.
147
133
  else:
148
- super(CanvasDialog, self).keyPressEvent(event)
134
+ super(ToolDialog, self).keyPressEvent(event)
149
135
 
150
136
  def cleanup(self):
151
- """
152
- Cleanup on close
153
- """
154
- if self.window is None:
137
+ """Cleanup on close"""
138
+ if self.window is None or self.tool is None:
155
139
  return
156
- self.window.tools.get("html_canvas").opened = False
157
- self.window.tools.get("html_canvas").close()
158
- self.window.tools.get("html_canvas").update()
140
+ self.tool.opened = False
141
+ self.tool.close()
142
+ self.tool.update()
@@ -6,13 +6,101 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2024.11.11 23:00:00 #
9
+ # Updated Date: 2024.12.09 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
+ from PySide6.QtCore import Qt, Slot, QUrl, QObject, Signal
13
+ from PySide6.QtWidgets import QVBoxLayout, QCheckBox, QHBoxLayout
14
+
15
+ from pygpt_net.ui.widget.element.labels import HelpLabel
12
16
  from pygpt_net.ui.widget.textarea.editor import BaseCodeEditor
13
- from pygpt_net.ui.widget.textarea.html import HtmlOutput
17
+ from pygpt_net.ui.widget.textarea.html import HtmlOutput, CustomWebEnginePage
14
18
 
15
19
  import pygpt_net.icons_rc
20
+ from pygpt_net.utils import trans
21
+
22
+
23
+ class ToolWidget:
24
+ def __init__(self, window=None, tool=None):
25
+ """
26
+ HTML/JS canvas widget
27
+
28
+ :param window: Window instance
29
+ :param tool: Tool instance
30
+ """
31
+ self.window = window
32
+ self.tool = tool # tool instance
33
+ self.output = None # canvas output
34
+ self.edit = None # canvas edit
35
+ self.btn_edit = None # edit checkbox
36
+
37
+ def setup(self) -> QVBoxLayout:
38
+ """
39
+ Setup widget body
40
+
41
+ :return: QVBoxLayout
42
+ """
43
+ self.output = CanvasOutput(self.window)
44
+ self.output.setPage(
45
+ CustomWebEnginePage(self.window, self.output)
46
+ )
47
+ self.edit = CanvasEdit(self.window)
48
+ self.edit.setVisible(False)
49
+ self.edit.textChanged.connect(
50
+ lambda: self.tool.save_output()
51
+ )
52
+
53
+ # edit checkbox
54
+ self.btn_edit = QCheckBox(trans("html_canvas.btn.edit"))
55
+ self.btn_edit.stateChanged.connect(
56
+ lambda: self.tool.toggle_edit(self)
57
+ )
58
+
59
+ path = self.tool.get_current_path()
60
+ path_label = HelpLabel(path)
61
+ path_label.setMaximumHeight(30)
62
+ path_label.setAlignment(Qt.AlignRight)
63
+
64
+ bottom_layout = QHBoxLayout()
65
+ bottom_layout.addWidget(self.btn_edit)
66
+ bottom_layout.addWidget(path_label)
67
+
68
+ output_layout = QVBoxLayout()
69
+ output_layout.addWidget(self.output)
70
+ output_layout.addWidget(self.edit)
71
+ output_layout.setContentsMargins(0, 0, 0, 0)
72
+
73
+ # connect signals
74
+ self.output.signals.save_as.connect(
75
+ self.tool.handle_save_as)
76
+ self.output.signals.audio_read.connect(
77
+ self.window.controller.chat.render.handle_audio_read)
78
+
79
+ self.tool.signals.update.connect(self.set_output)
80
+ self.tool.signals.reload.connect(self.load_output)
81
+
82
+ layout = QVBoxLayout()
83
+ layout.addLayout(output_layout)
84
+ layout.addLayout(bottom_layout)
85
+ return layout
86
+
87
+ @Slot(str)
88
+ def set_output(self, content: str):
89
+ """
90
+ Set output content
91
+
92
+ :param content: Content
93
+ """
94
+ self.edit.setPlainText(content)
95
+
96
+ @Slot(str)
97
+ def load_output(self, path: str):
98
+ """
99
+ Load output content
100
+
101
+ :param path: Content
102
+ """
103
+ self.output.setUrl(QUrl().fromLocalFile(path))
16
104
 
17
105
  class CanvasOutput(HtmlOutput):
18
106
  def __init__(self, window=None):
@@ -39,4 +127,9 @@ class CanvasEdit(BaseCodeEditor):
39
127
  self.min_font_size = 8
40
128
  self.setProperty('class', 'interpreter-output')
41
129
  self.default_stylesheet = ""
42
- self.setStyleSheet(self.default_stylesheet)
130
+ self.setStyleSheet(self.default_stylesheet)
131
+
132
+
133
+ class ToolSignals(QObject):
134
+ update = Signal(str) # data
135
+ reload = Signal(str) # path
@@ -6,12 +6,13 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2024.11.20 21:00:00 #
9
+ # Updated Date: 2024.12.14 22:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import hashlib
13
13
  import os
14
14
  import shutil
15
+ from typing import Dict, Optional
15
16
 
16
17
  from PySide6 import QtGui, QtCore
17
18
  from PySide6.QtGui import QAction, QIcon
@@ -19,6 +20,7 @@ from PySide6.QtWidgets import QFileDialog
19
20
 
20
21
  from pygpt_net.tools.base import BaseTool
21
22
  from pygpt_net.tools.image_viewer.ui.dialogs import DialogSpawner
23
+ from pygpt_net.ui.widget.dialog.base import BaseDialog
22
24
  from pygpt_net.utils import trans
23
25
 
24
26
 
@@ -255,7 +257,7 @@ class ImageViewer(BaseTool):
255
257
  except Exception as e:
256
258
  self.window.core.debug.log(e)
257
259
 
258
- def setup_menu(self) -> dict:
260
+ def setup_menu(self) -> Dict[str, QAction]:
259
261
  """
260
262
  Setup main menu
261
263
 
@@ -273,7 +275,11 @@ class ImageViewer(BaseTool):
273
275
  )
274
276
  return actions
275
277
 
276
- def get_instance(self, type_id: str, dialog_id: str = None):
278
+ def get_instance(
279
+ self,
280
+ type_id: str,
281
+ dialog_id: Optional[str] = None
282
+ ) -> Optional[BaseDialog]:
277
283
  """
278
284
  Spawn and return dialog instance
279
285
 
@@ -284,7 +290,7 @@ class ImageViewer(BaseTool):
284
290
  if type_id == "image_viewer":
285
291
  return self.spawner.setup(dialog_id)
286
292
 
287
- def get_lang_mappings(self) -> dict:
293
+ def get_lang_mappings(self) -> Dict[str, Dict]:
288
294
  """
289
295
  Get language mappings
290
296
 
@@ -6,11 +6,12 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2024.08.20 19:00:00 #
9
+ # Updated Date: 2024.12.14 22:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import datetime
13
13
  import json
14
+ from typing import Dict, Any, List
14
15
 
15
16
  from PySide6.QtCore import Slot
16
17
  from PySide6.QtGui import QAction, QIcon, QTextCursor
@@ -200,7 +201,7 @@ class IndexerTool(BaseTool):
200
201
  last_str = datetime.datetime.fromtimestamp(last_ts).strftime('%Y-%m-%d %H:%M:%S')
201
202
  self.window.ui.nodes['tool.indexer.ctx.last_auto'].setText(last_str)
202
203
 
203
- def update_tab_files(self):
204
+ def update_tab_files(self) -> List[str]:
204
205
  """
205
206
  Update files tab
206
207
 
@@ -420,7 +421,7 @@ class IndexerTool(BaseTool):
420
421
  self.refresh()
421
422
 
422
423
  @Slot(object)
423
- def handle_log(self, data: any):
424
+ def handle_log(self, data: Any):
424
425
  """
425
426
  Handle log message
426
427
 
@@ -428,7 +429,7 @@ class IndexerTool(BaseTool):
428
429
  """
429
430
  self.log(data)
430
431
 
431
- def log(self, data: any):
432
+ def log(self, data: Any):
432
433
  """
433
434
  Log message to console or logger window
434
435
 
@@ -451,7 +452,7 @@ class IndexerTool(BaseTool):
451
452
  """Clear log"""
452
453
  self.window.ui.nodes["tool.indexer.status"].clear()
453
454
 
454
- def get_tables(self) -> dict:
455
+ def get_tables(self) -> Dict[str, Dict]:
455
456
  """
456
457
  Get tables configuration
457
458
 
@@ -513,7 +514,7 @@ class IndexerTool(BaseTool):
513
514
  }
514
515
  return tables
515
516
 
516
- def setup_menu(self) -> dict:
517
+ def setup_menu(self) -> Dict[str, QAction]:
517
518
  """
518
519
  Setup main menu (Tools)
519
520
 
@@ -536,7 +537,7 @@ class IndexerTool(BaseTool):
536
537
  self.dialog = DialogBuilder(self.window)
537
538
  self.dialog.setup()
538
539
 
539
- def get_lang_mappings(self) -> dict:
540
+ def get_lang_mappings(self) -> Dict[str, Dict]:
540
541
  """
541
542
  Get language mappings
542
543