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,7 +6,7 @@
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.22 17:00:00 #
9
+ # Updated Date: 2024.12.12 04:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import datetime
@@ -402,11 +402,32 @@ class ImportantItemDelegate(QtWidgets.QStyledItemDelegate):
402
402
  super(ImportantItemDelegate, self).paint(painter, option, index)
403
403
 
404
404
  # pin (>= 10)
405
- if index.data(QtCore.Qt.ItemDataRole.UserRole) and index.data(QtCore.Qt.ItemDataRole.UserRole) > 0:
406
- label = index.data(QtCore.Qt.ItemDataRole.UserRole)
405
+ if index.data(QtCore.Qt.ItemDataRole.UserRole):
406
+ data = index.data(QtCore.Qt.ItemDataRole.UserRole)
407
+ label = 0
408
+ is_important = False
409
+ is_attachment = False
410
+ if "label" in data:
411
+ label = data["label"]
412
+ if "is_important" in data and data["is_important"]:
413
+ is_important = True
414
+ if "is_attachment" in data and data["is_attachment"]:
415
+ is_attachment = True
416
+
407
417
  painter.save()
408
418
 
409
- if label >= 10:
419
+ if is_attachment:
420
+ icon = QtGui.QIcon(":/icons/attachment.svg")
421
+ icon_size = option.decorationSize or QtCore.QSize(16, 16)
422
+ icon_rect = QtCore.QRect(
423
+ option.rect.right() - icon_size.width(),
424
+ option.rect.top() + (option.rect.height() - icon_size.height()) / 2,
425
+ icon_size.width(),
426
+ icon_size.height()
427
+ )
428
+ icon.paint(painter, icon_rect, QtCore.Qt.AlignCenter)
429
+
430
+ if is_important:
410
431
  color = self.get_color_for_status(3)
411
432
  square_size = 3
412
433
  square_margin = 0
@@ -426,7 +447,7 @@ class ImportantItemDelegate(QtWidgets.QStyledItemDelegate):
426
447
  )
427
448
  painter.drawRect(square_rect)
428
449
 
429
- label = label - 10 # remove pin status
450
+ #label = label - 10 # remove pin status
430
451
 
431
452
  # label (0-9)
432
453
  if label > 0:
@@ -494,3 +515,4 @@ class SectionItem(QStandardItem):
494
515
  self.setTextAlignment(QtCore.Qt.AlignRight)
495
516
  font = self.font()
496
517
  font.setBold(True)
518
+ self.setFont(font)
@@ -6,7 +6,7 @@
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.01.29 14:00:00 #
9
+ # Updated Date: 2024.12.09 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtWidgets import QTabWidget, QMenu
@@ -40,7 +40,7 @@ class InputTabs(QTabWidget):
40
40
 
41
41
  :param global_pos: QPoint
42
42
  """
43
- context_menu = QMenu()
43
+ context_menu = QMenu(self)
44
44
  actions = {}
45
45
  actions['clear'] = QAction(QIcon(":/icons/delete.svg"), trans('attachments.btn.clear'), self)
46
46
  actions['clear'].triggered.connect(
@@ -6,10 +6,11 @@
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.05 23:00:00 #
9
+ # Updated Date: 2024.12.09 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtWidgets import QTabWidget
13
+
13
14
  from pygpt_net.core.tabs.tab import Tab
14
15
 
15
16
 
@@ -0,0 +1,195 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ # ================================================== #
4
+ # This file is a part of PYGPT package #
5
+ # Website: https://pygpt.net #
6
+ # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
+ # MIT License #
8
+ # Created By : Marcin Szczygliński #
9
+ # Updated Date: 2024.12.09 03:00:00 #
10
+ # ================================================== #
11
+
12
+ from PySide6.QtCore import Qt, QObject, QEvent
13
+ from PySide6.QtWidgets import QTabWidget, QWidget, QVBoxLayout, QSplitter, QSizePolicy
14
+
15
+ from pygpt_net.ui.widget.tabs.output import OutputTabs
16
+
17
+
18
+ class OutputColumn(QWidget):
19
+ def __init__(self, window=None):
20
+ """
21
+ Output column
22
+
23
+ :param window: window instance
24
+ """
25
+ super(OutputColumn, self).__init__(window)
26
+ self.window = window
27
+ self.idx = -1
28
+ self.tabs = OutputTabs(self.window, column=self)
29
+ self.layout = QVBoxLayout()
30
+ self.layout.addWidget(self.tabs)
31
+ self.layout.setContentsMargins(0, 0, 0, 0)
32
+ self.setLayout(self.layout)
33
+ self.filter = FocusEventFilter(self, self.on_focus)
34
+ self.installEventFilter(self.filter)
35
+ self.setFocusPolicy(Qt.StrongFocus)
36
+
37
+ def on_focus(self, widget):
38
+ """
39
+ On widget clicked
40
+
41
+ :param widget: widget
42
+ """
43
+ self.window.controller.ui.tabs.on_column_focus(self.idx)
44
+ widget.setFocus()
45
+
46
+ def set_idx(self, idx: int):
47
+ """
48
+ Set index
49
+
50
+ :param idx: int
51
+ """
52
+ self.idx = idx
53
+
54
+ def get_idx(self) -> int:
55
+ """
56
+ Get index
57
+
58
+ :return: int
59
+ """
60
+ return self.idx
61
+
62
+ def set_tabs(self, tabs: QTabWidget):
63
+ """
64
+ Set tabs widget
65
+
66
+ :param tabs: QTabWidget
67
+ """
68
+ self.tabs = tabs
69
+
70
+ def get_tabs(self) -> OutputTabs:
71
+ """
72
+ Get tabs
73
+
74
+ :return: OutputTabs
75
+ """
76
+ return self.tabs
77
+
78
+
79
+ class OutputLayout(QWidget):
80
+ def __init__(self, window=None):
81
+ """
82
+ Output layout
83
+
84
+ :param window: window instance
85
+ """
86
+ super(OutputLayout, self).__init__(window)
87
+ self.window = window
88
+ self.columns = []
89
+
90
+ column1 = OutputColumn(self.window)
91
+ column2 = OutputColumn(self.window)
92
+ self.add_column(column1)
93
+ self.add_column(column2)
94
+
95
+ self.splitter = QSplitter(Qt.Horizontal)
96
+ self.splitter.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
97
+ for column in self.columns:
98
+ self.splitter.addWidget(column)
99
+
100
+ self.window.ui.splitters['columns'] = self.splitter
101
+
102
+ self.layout = QVBoxLayout()
103
+ self.layout.addWidget(self.splitter, stretch=1)
104
+ self.layout.setContentsMargins(0, 0, 0, 0)
105
+ self.setLayout(self.layout)
106
+
107
+ def get_next_idx(self) -> int:
108
+ """
109
+ Get next index
110
+
111
+ :return: int
112
+ """
113
+ return len(self.columns)
114
+
115
+ def add_column(self, column: OutputColumn):
116
+ """
117
+ Add column
118
+
119
+ :param column: OutputColumn
120
+ """
121
+ idx = self.get_next_idx()
122
+ column.set_idx(idx)
123
+ self.columns.append(column)
124
+
125
+ def get_tabs_by_idx(self, idx: int) -> OutputTabs:
126
+ """
127
+ Get tabs by column index
128
+
129
+ :param idx: int
130
+ :return: OutputTabs
131
+ """
132
+ for column in self.columns:
133
+ if column.idx == idx:
134
+ return column.tabs
135
+ return None
136
+
137
+ def get_active_tabs(self) -> OutputTabs:
138
+ """
139
+ Get active tabs
140
+
141
+ :return: OutputTabs
142
+ """
143
+ current = self.window.controller.ui.tabs.get_current_column_idx()
144
+ for column in self.columns:
145
+ if column.idx == current:
146
+ return column.tabs
147
+
148
+ def get_column_by_idx(self, idx: int) -> OutputColumn:
149
+ """
150
+ Get column by index
151
+
152
+ :param idx: int
153
+ :return: OutputColumn
154
+ """
155
+ for column in self.columns:
156
+ if column.idx == idx:
157
+ return column
158
+ return None
159
+
160
+ def get_active_column(self) -> OutputColumn:
161
+ """
162
+ Get active column
163
+
164
+ :return: OutputColumn
165
+ """
166
+ current = self.window.controller.ui.tabs.get_current_column_idx()
167
+ for column in self.columns:
168
+ if column.idx == current:
169
+ return column
170
+
171
+ class FocusEventFilter(QObject):
172
+ def __init__(self, column, callback):
173
+ """
174
+ Column event filter
175
+
176
+ :param column: parent column
177
+ :param callback: callback
178
+ """
179
+ super().__init__()
180
+ self.column = column
181
+ self.callback = callback
182
+
183
+ def eventFilter(self, obj, event):
184
+ """
185
+ Click event filter
186
+
187
+ :param obj: object
188
+ :param event: event
189
+ """
190
+ if event.type() == QEvent.MouseButtonPress or event.type() == QEvent.FocusIn:
191
+ widget = obj
192
+ if widget is not None:
193
+ self.callback(widget)
194
+ return False
195
+ return False
@@ -6,10 +6,10 @@
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.05 23:00:00 #
9
+ # Updated Date: 2024.12.14 07:00:00 #
10
10
  # ================================================== #
11
11
 
12
- from PySide6.QtWidgets import QTabWidget, QMenu
12
+ from PySide6.QtWidgets import QTabWidget, QMenu, QPushButton
13
13
  from PySide6.QtCore import Qt, Slot
14
14
  from PySide6.QtGui import QAction, QIcon
15
15
 
@@ -18,17 +18,128 @@ from pygpt_net.utils import trans
18
18
  import pygpt_net.icons_rc
19
19
 
20
20
 
21
+ class AddButton(QPushButton):
22
+ def __init__(self, window=None, column=None, tabs=None):
23
+ super(AddButton, self).__init__(QIcon(":/icons/add.svg"), "", window)
24
+ self.window = window
25
+ self.column = column
26
+ self.tabs = tabs
27
+ self.setFixedSize(30, 25)
28
+ self.setFlat(True)
29
+ self.clicked.connect(
30
+ lambda: self.window.controller.ui.tabs.new_tab(self.column.get_idx())
31
+ )
32
+ self.setObjectName('tab-add')
33
+ self.setProperty('tabAdd', True)
34
+ self.setToolTip(trans('action.tab.add.chat'))
35
+
36
+ def mousePressEvent(self, event):
37
+ """
38
+ Mouse press event
39
+
40
+ :param event: event
41
+ """
42
+ if event.button() == Qt.RightButton:
43
+ idx = 0
44
+ column_idx = self.column.get_idx()
45
+ self.show_menu(idx, column_idx, event.globalPos())
46
+ super(AddButton, self).mousePressEvent(event)
47
+
48
+ def show_menu(self, index: int, column_idx: int, global_pos):
49
+ """
50
+ Show context menu
51
+
52
+ :param index: index
53
+ :param column_idx: column index
54
+ :param global_pos: global position
55
+ """
56
+ context_menu = self.prepare_menu(index, column_idx)
57
+ context_menu.exec(global_pos)
58
+
59
+ def prepare_menu(self, index: int, column_idx: int) -> QMenu:
60
+ """
61
+ Prepare and return context menu
62
+
63
+ :param index: index
64
+ :param column_idx: column index
65
+ :return: menu
66
+ """
67
+ menu = QMenu(self)
68
+
69
+ actions = {}
70
+ actions['add_chat'] = QAction(QIcon(":/icons/add.svg"), trans('action.tab.add.chat'), self)
71
+ actions['add_chat'].triggered.connect(
72
+ lambda: self.tabs.add_tab(index, column_idx, Tab.TAB_CHAT)
73
+ )
74
+ actions['add_notepad'] = QAction(QIcon(":/icons/add.svg"), trans('action.tab.add.notepad'), self)
75
+ actions['add_notepad'].triggered.connect(
76
+ lambda: self.tabs.add_tab(index, column_idx, Tab.TAB_NOTEPAD)
77
+ )
78
+
79
+ # add chat, add notepad
80
+ menu.addAction(actions['add_chat'])
81
+ menu.addAction(actions['add_notepad'])
82
+
83
+ # add tools submenu
84
+ self.window.controller.tools.append_tab_menu(self, menu, index, column_idx)
85
+
86
+ return menu
87
+
21
88
  class OutputTabs(QTabWidget):
22
- def __init__(self, window=None):
89
+ def __init__(self, window=None, column=None):
23
90
  super(OutputTabs, self).__init__(window)
24
91
  self.window = window
92
+ self.active = True
93
+ self.column = column
25
94
  self.setMinimumHeight(1)
26
95
  self.owner = None
27
96
  self.setMovable(True)
97
+ self.init()
98
+
99
+ def set_active(self, active: bool):
100
+ """Set the active state of the tab bar."""
101
+ self.active = active
102
+ if self.active:
103
+ self.setStyleSheet("QTabBar::tab { border-bottom-width: 2px; }")
104
+ else:
105
+ self.setStyleSheet("QTabBar::tab { border-bottom-width: 0px; }")
106
+
107
+ def init(self):
108
+ """Initialize"""
109
+ # create the [+] button
110
+ add_button = AddButton(self.window, self.column, self)
111
+
112
+ # add the button to the top right corner of the tab bar
113
+ self.setCornerWidget(add_button, corner=Qt.TopRightCorner)
114
+
115
+ # connect signals
116
+ self.currentChanged.connect(
117
+ lambda: self.window.controller.ui.tabs.on_tab_changed(self.currentIndex(), self.column.get_idx())
118
+ )
119
+ self.tabBarClicked.connect(
120
+ lambda: self.window.controller.ui.tabs.on_tab_clicked(self.currentIndex(), self.column.get_idx())
121
+ )
122
+ self.tabBarDoubleClicked.connect(
123
+ lambda: self.window.controller.ui.tabs.on_tab_dbl_clicked(self.currentIndex(), self.column.get_idx())
124
+ )
125
+ self.tabCloseRequested.connect(
126
+ lambda: self.window.controller.ui.tabs.on_tab_closed(self.currentIndex(), self.column.get_idx())
127
+ )
128
+ self.tabBar().tabMoved.connect(
129
+ lambda: self.window.controller.ui.tabs.on_tab_moved(self.currentIndex(), self.column.get_idx())
130
+ )
131
+
132
+ def get_column(self):
133
+ """
134
+ Get column
135
+
136
+ :return: OutputColumn
137
+ """
138
+ return self.column
28
139
 
29
140
  def setOwner(self, owner: Tab):
30
141
  """
31
- Set parent
142
+ Set internal tab instance
32
143
 
33
144
  :param owner: parent tab instance
34
145
  """
@@ -42,158 +153,210 @@ class OutputTabs(QTabWidget):
42
153
  """
43
154
  if event.button() == Qt.RightButton:
44
155
  idx = self.tabBar().tabAt(event.pos())
45
- tab = self.window.core.tabs.get_tab_by_index(idx)
156
+ column_idx = self.column.get_idx()
157
+ tab = self.window.core.tabs.get_tab_by_index(idx, column_idx)
46
158
  if tab is not None:
47
159
  if tab.type == Tab.TAB_NOTEPAD:
48
- self.show_notepad_menu(idx, event.globalPos()) # notepad
160
+ self.show_notepad_menu(idx, column_idx, event.globalPos()) # notepad
49
161
  elif tab.type == Tab.TAB_CHAT:
50
- self.show_chat_menu(idx, event.globalPos()) # chat
162
+ self.show_chat_menu(idx, column_idx, event.globalPos()) # chat
51
163
  elif tab.type == Tab.TAB_FILES:
52
- self.show_files_menu(idx, event.globalPos()) # files
164
+ self.show_files_menu(idx, column_idx, event.globalPos()) # files
165
+ elif tab.type == Tab.TAB_TOOL:
166
+ self.show_tool_menu(idx, column_idx, event.globalPos()) # tool
53
167
  else:
54
- self.show_default_menu(idx, event.globalPos()) # default
168
+ self.show_default_menu(idx, column_idx, event.globalPos()) # default
55
169
  super(OutputTabs, self).mousePressEvent(event)
56
170
 
57
- def get_common_actions(self, index):
171
+ def prepare_menu(self, index: int, column_idx: int) -> QMenu:
58
172
  """
59
- Get common actions
173
+ Prepare and return context menu
60
174
 
61
175
  :param index: index
62
- :return: dict
176
+ :param column_idx: column index
177
+ :return: menu
63
178
  """
179
+ menu = QMenu(self)
180
+
64
181
  actions = {}
65
182
  actions['add_chat'] = QAction(QIcon(":/icons/add.svg"), trans('action.tab.add.chat'), self)
66
183
  actions['add_chat'].triggered.connect(
67
- lambda: self.add_tab(index, Tab.TAB_CHAT)
184
+ lambda: self.add_tab(index, column_idx, Tab.TAB_CHAT)
68
185
  )
69
186
  actions['add_notepad'] = QAction(QIcon(":/icons/add.svg"), trans('action.tab.add.notepad'), self)
70
187
  actions['add_notepad'].triggered.connect(
71
- lambda: self.add_tab(index, Tab.TAB_NOTEPAD)
188
+ lambda: self.add_tab(index, column_idx, Tab.TAB_NOTEPAD)
72
189
  )
73
190
  actions['edit'] = QAction(QIcon(":/icons/edit.svg"), trans('action.rename'), self)
74
191
  actions['edit'].triggered.connect(
75
- lambda: self.rename_tab(index)
192
+ lambda: self.rename_tab(index, column_idx)
193
+ )
194
+ actions['move_right'] = QAction(QIcon(":/icons/forward"), trans('action.tab.move.right'), self)
195
+ actions['move_right'].triggered.connect(
196
+ lambda: self.window.controller.ui.tabs.move_tab(index, column_idx, 1)
76
197
  )
77
- return actions
198
+ actions['move_left'] = QAction(QIcon(":/icons/back"), trans('action.tab.move.left'), self)
199
+ actions['move_left'].triggered.connect(
200
+ lambda: self.window.controller.ui.tabs.move_tab(index, column_idx, 0)
201
+ )
202
+
203
+ # add chat, add notepad
204
+ menu.addAction(actions['add_chat'])
205
+ menu.addAction(actions['add_notepad'])
206
+
207
+ # add tools submenu
208
+ self.window.controller.tools.append_tab_menu(self, menu, index, column_idx)
209
+
210
+ # rename tab
211
+ menu.addAction(actions['edit'])
212
+
213
+ # move tab left, move tab right
214
+ if column_idx != 0:
215
+ menu.addAction(actions['move_left'])
216
+ if column_idx != 1:
217
+ menu.addAction(actions['move_right'])
78
218
 
79
- def show_notepad_menu(self, index, global_pos):
219
+ return menu
220
+
221
+ def show_notepad_menu(self, index: int, column_idx: int, global_pos):
80
222
  """
81
223
  Show notepad menu
82
224
 
83
225
  :param index: index
226
+ :param column_idx: column index
84
227
  :param global_pos: global position
85
228
  """
86
- context_menu = QMenu()
87
- actions = self.get_common_actions(index)
229
+ context_menu = self.prepare_menu(index, column_idx)
230
+ actions = {}
88
231
  actions['close'] = QAction(QIcon(":/icons/close.svg"), trans('action.tab.close'), self)
89
232
  actions['close'].triggered.connect(
90
- lambda: self.close_tab(index)
233
+ lambda: self.close_tab(index, column_idx)
91
234
  )
92
235
  actions['close_all'] = QAction(QIcon(":/icons/close.svg"), trans('action.tab.close_all.notepad'), self)
93
236
  actions['close_all'].triggered.connect(
94
- lambda: self.close_all(Tab.TAB_NOTEPAD)
237
+ lambda: self.close_all(Tab.TAB_NOTEPAD, column_idx)
95
238
  )
96
- context_menu.addAction(actions['add_chat'])
97
- context_menu.addAction(actions['add_notepad'])
98
- context_menu.addAction(actions['edit'])
99
239
  context_menu.addAction(actions['close'])
100
240
 
101
241
  if self.window.core.tabs.count_by_type(Tab.TAB_NOTEPAD) > 1:
102
242
  context_menu.addAction(actions['close_all'])
243
+
103
244
  context_menu.exec(global_pos)
104
245
 
105
- def show_chat_menu(self, index, global_pos):
246
+ def show_chat_menu(self, index: int, column_idx: int, global_pos):
106
247
  """
107
248
  Show chat menu
108
249
 
109
250
  :param index: index
251
+ :param column_idx: column index
110
252
  :param global_pos: global position
111
253
  """
112
- context_menu = QMenu()
113
- actions = self.get_common_actions(index)
254
+ context_menu = self.prepare_menu(index, column_idx)
255
+ actions = {}
114
256
  actions['close'] = QAction(QIcon(":/icons/close.svg"), trans('action.tab.close'), self)
115
257
  actions['close'].triggered.connect(
116
- lambda: self.close_tab(index)
258
+ lambda: self.close_tab(index, column_idx)
117
259
  )
118
260
  actions['close_all'] = QAction(QIcon(":/icons/close.svg"), trans('action.tab.close_all.chat'), self)
119
261
  actions['close_all'].triggered.connect(
120
- lambda: self.close_all(Tab.TAB_CHAT)
262
+ lambda: self.close_all(Tab.TAB_CHAT, column_idx)
121
263
  )
122
- context_menu.addAction(actions['add_chat'])
123
- context_menu.addAction(actions['add_notepad'])
124
- context_menu.addAction(actions['edit'])
125
264
 
126
265
  # at least one chat tab must be open
127
266
  if self.window.core.tabs.count_by_type(Tab.TAB_CHAT) > 1:
128
267
  context_menu.addAction(actions['close'])
129
-
130
- if self.window.core.tabs.count_by_type(Tab.TAB_CHAT) > 1:
131
268
  context_menu.addAction(actions['close_all'])
132
269
 
133
270
  context_menu.exec(global_pos)
134
271
 
135
- def show_files_menu(self, index, global_pos):
272
+ def show_files_menu(self, index: int, column_idx: int, global_pos):
136
273
  """
137
274
  Show files menu
138
275
 
139
276
  :param index: index
277
+ :param column_idx: column index
140
278
  :param global_pos: global position
141
279
  """
142
- context_menu = QMenu()
143
- actions = self.get_common_actions(index)
280
+ context_menu = self.prepare_menu(index, column_idx)
281
+ actions = {}
144
282
  actions['refresh'] = QAction(QIcon(":/icons/reload.svg"), trans('action.refresh'), self)
145
283
  actions['refresh'].triggered.connect(
146
284
  lambda: self.window.controller.files.update_explorer()
147
285
  )
148
- context_menu.addAction(actions['add_chat'])
149
- context_menu.addAction(actions['add_notepad'])
150
286
  context_menu.addAction(actions['refresh'])
151
- context_menu.addAction(actions['edit'])
152
287
  context_menu.exec(global_pos)
153
288
 
154
- def show_default_menu(self, index, global_pos):
289
+ def show_tool_menu(self, index: int, column_idx: int, global_pos):
290
+ """
291
+ Show tool menu
292
+
293
+ :param index: index
294
+ :param column_idx: column index
295
+ :param global_pos: global position
296
+ """
297
+ context_menu = self.prepare_menu(index, column_idx)
298
+ actions = {}
299
+ actions['close'] = QAction(QIcon(":/icons/close.svg"), trans('action.tab.close'), self)
300
+ actions['close'].triggered.connect(
301
+ lambda: self.close_tab(index, column_idx)
302
+ )
303
+ context_menu.addAction(actions['close'])
304
+ context_menu.exec(global_pos)
305
+
306
+ def show_default_menu(self, index: int, column_idx: int, global_pos):
155
307
  """
156
308
  Show default menu
157
309
 
158
310
  :param index: index
311
+ :param column_idx: column index
159
312
  :param global_pos: global position
160
313
  """
161
- context_menu = QMenu()
162
- actions = self.get_common_actions(index)
163
- context_menu.addAction(actions['add_chat'])
164
- context_menu.addAction(actions['add_notepad'])
165
- context_menu.addAction(actions['edit'])
314
+ context_menu = self.prepare_menu(index, column_idx)
166
315
  context_menu.exec(global_pos)
167
316
 
168
317
  @Slot()
169
- def rename_tab(self, index):
318
+ def rename_tab(self, index: int, column_idx: int):
170
319
  """
171
320
  Rename tab
321
+
172
322
  :param index: index
323
+ :param column_idx: column index
173
324
  """
174
- self.window.controller.ui.tabs.rename(index)
325
+ self.window.controller.ui.tabs.rename(index, column_idx)
175
326
 
176
327
  @Slot()
177
- def close_tab(self, index):
328
+ def close_tab(self, index: int, column_idx: int):
178
329
  """
179
330
  Close tab
331
+
180
332
  :param index: index
333
+ :param column_idx: column index
181
334
  """
182
- self.window.controller.ui.tabs.close(index)
335
+ self.window.controller.ui.tabs.close(index, column_idx)
183
336
 
184
337
  @Slot()
185
- def close_all(self, type):
338
+ def close_all(self, type, column_idx: int):
186
339
  """
187
340
  Close all tabs
341
+
188
342
  :param type: type
343
+ :param column_idx: column index
189
344
  """
190
- self.window.controller.ui.tabs.close_all(type)
345
+ self.window.controller.ui.tabs.close_all(type, column_idx)
191
346
 
192
347
  @Slot()
193
- def add_tab(self, index, type):
348
+ def add_tab(self, index: int, column_idx: int, type: int, tool_id: str = None):
194
349
  """
195
- Add tab
350
+ Add a new tab
351
+
196
352
  :param index: index
353
+ :param column_idx: column index
197
354
  :param type: type
355
+ :param tool_id: tool id
198
356
  """
199
- self.window.controller.ui.tabs.append(type, index)
357
+ self.window.controller.ui.tabs.append(
358
+ type=type,
359
+ tool_id=tool_id,
360
+ idx=index,
361
+ column_idx=column_idx,
362
+ )