pygpt-net 2.4.39__py3-none-any.whl → 2.4.40__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.
- CHANGELOG.md +13 -0
- README.md +19 -2
- pygpt_net/CHANGELOG.txt +13 -0
- pygpt_net/__init__.py +3 -3
- pygpt_net/controller/__init__.py +5 -3
- pygpt_net/controller/audio/__init__.py +9 -1
- pygpt_net/controller/chat/input.py +2 -1
- pygpt_net/controller/chat/render.py +2 -2
- pygpt_net/controller/ctx/__init__.py +2 -2
- pygpt_net/controller/debug/__init__.py +13 -2
- pygpt_net/controller/kernel/__init__.py +2 -1
- pygpt_net/controller/notepad.py +7 -6
- pygpt_net/controller/theme/nodes.py +2 -5
- pygpt_net/controller/tools/__init__.py +37 -1
- pygpt_net/controller/ui/__init__.py +1 -5
- pygpt_net/controller/ui/tabs.py +104 -12
- pygpt_net/core/command.py +3 -1
- pygpt_net/core/ctx/__init__.py +6 -2
- pygpt_net/core/ctx/container.py +5 -5
- pygpt_net/core/debug/tabs.py +3 -1
- pygpt_net/core/render/base.py +2 -2
- pygpt_net/core/render/web/body.py +1 -1
- pygpt_net/core/render/web/renderer.py +208 -38
- pygpt_net/core/tabs/__init__.py +104 -43
- pygpt_net/core/tabs/tab.py +4 -1
- pygpt_net/core/web.py +127 -1
- pygpt_net/data/config/config.json +4 -3
- pygpt_net/data/config/models.json +3 -3
- pygpt_net/data/config/modes.json +3 -3
- pygpt_net/data/css/web-blocks.css +18 -0
- pygpt_net/data/css/web-blocks.light.css +7 -0
- pygpt_net/data/css/web-chatgpt.css +8 -0
- pygpt_net/data/css/web-chatgpt_wide.css +8 -0
- pygpt_net/data/icons/split_screen.svg +1 -0
- pygpt_net/data/locale/locale.de.ini +1 -1
- pygpt_net/data/locale/locale.en.ini +4 -2
- pygpt_net/data/locale/locale.es.ini +1 -1
- pygpt_net/data/locale/locale.fr.ini +1 -1
- pygpt_net/data/locale/locale.it.ini +1 -1
- pygpt_net/data/locale/locale.pl.ini +2 -2
- pygpt_net/data/locale/locale.uk.ini +1 -1
- pygpt_net/data/locale/locale.zh.ini +1 -1
- pygpt_net/data/locale/plugin.cmd_web.de.ini +2 -0
- pygpt_net/data/locale/plugin.cmd_web.en.ini +20 -10
- pygpt_net/data/locale/plugin.cmd_web.es.ini +2 -0
- pygpt_net/data/locale/plugin.cmd_web.fr.ini +2 -0
- pygpt_net/data/locale/plugin.cmd_web.it.ini +2 -0
- pygpt_net/data/locale/plugin.cmd_web.pl.ini +2 -0
- pygpt_net/data/locale/plugin.cmd_web.uk.ini +2 -0
- pygpt_net/data/locale/plugin.cmd_web.zh.ini +2 -0
- pygpt_net/icons.qrc +1 -0
- pygpt_net/icons_rc.py +165 -136
- pygpt_net/item/ctx.py +46 -24
- pygpt_net/plugin/audio_output/__init__.py +4 -1
- pygpt_net/plugin/base/plugin.py +18 -4
- pygpt_net/plugin/cmd_code_interpreter/__init__.py +39 -37
- pygpt_net/plugin/cmd_code_interpreter/runner.py +25 -12
- pygpt_net/plugin/cmd_web/__init__.py +46 -6
- pygpt_net/plugin/cmd_web/config.py +74 -48
- pygpt_net/plugin/cmd_web/websearch.py +61 -28
- pygpt_net/plugin/cmd_web/worker.py +79 -13
- pygpt_net/provider/core/config/patch.py +22 -1
- pygpt_net/tools/__init__.py +9 -1
- pygpt_net/tools/base.py +15 -1
- pygpt_net/tools/code_interpreter/__init__.py +174 -75
- pygpt_net/tools/code_interpreter/ui/dialogs.py +21 -103
- pygpt_net/tools/code_interpreter/ui/widgets.py +284 -9
- pygpt_net/tools/html_canvas/__init__.py +78 -23
- pygpt_net/tools/html_canvas/ui/dialogs.py +46 -62
- pygpt_net/tools/html_canvas/ui/widgets.py +96 -3
- pygpt_net/ui/base/context_menu.py +2 -2
- pygpt_net/ui/layout/ctx/ctx_list.py +13 -4
- pygpt_net/ui/layout/toolbox/footer.py +1 -1
- pygpt_net/ui/main.py +2 -2
- pygpt_net/ui/menu/debug.py +11 -1
- pygpt_net/ui/widget/filesystem/explorer.py +2 -2
- pygpt_net/ui/widget/lists/context.py +26 -5
- pygpt_net/ui/widget/tabs/Input.py +2 -2
- pygpt_net/ui/widget/tabs/body.py +2 -1
- pygpt_net/ui/widget/tabs/output.py +126 -61
- {pygpt_net-2.4.39.dist-info → pygpt_net-2.4.40.dist-info}/METADATA +20 -3
- {pygpt_net-2.4.39.dist-info → pygpt_net-2.4.40.dist-info}/RECORD +85 -84
- {pygpt_net-2.4.39.dist-info → pygpt_net-2.4.40.dist-info}/LICENSE +0 -0
- {pygpt_net-2.4.39.dist-info → pygpt_net-2.4.40.dist-info}/WHEEL +0 -0
- {pygpt_net-2.4.39.dist-info → pygpt_net-2.4.40.dist-info}/entry_points.txt +0 -0
CHANGELOG.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
## 2.4.40 (2024-12-13)
|
4
|
+
|
5
|
+
- Enhanced Split Screen mode, now promoted from beta to stable.
|
6
|
+
- Python Code Interpreter tool added to the Tabs.
|
7
|
+
- HTML/JS Canvas tool added to the Tabs.
|
8
|
+
- Added attachment icon to the context list if context has attachments.
|
9
|
+
- Improved audio playback.
|
10
|
+
- Improved web search.
|
11
|
+
- Added a thumbnail image to web search results.
|
12
|
+
- Added a new commands to web search: "extract_images" and "extract_links".
|
13
|
+
- Added the option "Use raw content (without summarization)" to the web search plugin, which provides a more detailed result to the main model.
|
14
|
+
- Extended the default maximum result characters to 50,000 in the web search plugin.
|
15
|
+
|
3
16
|
## 2.4.39 (2024-12-09)
|
4
17
|
|
5
18
|
- Added "Split Screen" mode (accessible via the switch in the bottom-right corner of the screen), which allows you to work in two windows simultaneously. It is currently experimental (beta). Future updates will include Code Interpreter and Canvas running in tabs.
|
README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
[](https://snapcraft.io/pygpt)
|
4
4
|
|
5
|
-
Release: **2.4.
|
5
|
+
Release: **2.4.40** | build: **2024.12.13** | Python: **>=3.10, <3.12**
|
6
6
|
|
7
7
|
> Official website: https://pygpt.net | Documentation: https://pygpt.readthedocs.io
|
8
8
|
>
|
@@ -1984,6 +1984,10 @@ Per-page content chunk size (max characters per chunk). *Default:* `20000`
|
|
1984
1984
|
|
1985
1985
|
Disables SSL verification when crawling web pages. *Default:* `False`
|
1986
1986
|
|
1987
|
+
- `Use raw content (without summarization)` *raw*
|
1988
|
+
|
1989
|
+
Return raw content from web search instead of summarized content. Provides more data but consumes more tokens. *Default:* `True`
|
1990
|
+
|
1987
1991
|
- `Timeout` *timeout*
|
1988
1992
|
|
1989
1993
|
Connection timeout (seconds). *Default:* `5`
|
@@ -1994,7 +1998,7 @@ User agent to use when making requests. *Default:* `Mozilla/5.0`.
|
|
1994
1998
|
|
1995
1999
|
- `Max result length` *max_result_length*
|
1996
2000
|
|
1997
|
-
Max length of summarized result (characters). *Default:* `
|
2001
|
+
Max length of the summarized or raw result (characters). *Default:* `50000`
|
1998
2002
|
|
1999
2003
|
- `Max summary tokens` *summary_max_tokens*
|
2000
2004
|
|
@@ -3873,6 +3877,19 @@ may consume additional tokens that are not displayed in the main window.
|
|
3873
3877
|
|
3874
3878
|
## Recent changes:
|
3875
3879
|
|
3880
|
+
**2.4.40 (2024-12-13)**
|
3881
|
+
|
3882
|
+
- Enhanced Split Screen mode, now promoted from beta to stable.
|
3883
|
+
- Python Code Interpreter tool added to the Tabs.
|
3884
|
+
- HTML/JS Canvas tool added to the Tabs.
|
3885
|
+
- Added attachment icon to the context list if context has attachments.
|
3886
|
+
- Improved audio playback.
|
3887
|
+
- Improved web search.
|
3888
|
+
- Added a thumbnail image to web search results.
|
3889
|
+
- Added a new commands to web search: "extract_images" and "extract_links".
|
3890
|
+
- Added the option "Use raw content (without summarization)" to the web search plugin, which provides a more detailed result to the main model.
|
3891
|
+
- Extended the default maximum result characters to 50,000 in the web search plugin.
|
3892
|
+
|
3876
3893
|
**2.4.39 (2024-12-09)**
|
3877
3894
|
|
3878
3895
|
- Added "Split Screen" mode (accessible via the switch in the bottom-right corner of the screen), which allows you to work in two windows simultaneously. It is currently experimental (beta). Future updates will include Code Interpreter and Canvas running in tabs.
|
pygpt_net/CHANGELOG.txt
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
2.4.40 (2024-12-13)
|
2
|
+
|
3
|
+
- Enhanced Split Screen mode, now promoted from beta to stable.
|
4
|
+
- Python Code Interpreter tool added to the Tabs.
|
5
|
+
- HTML/JS Canvas tool added to the Tabs.
|
6
|
+
- Added attachment icon to the context list if context has attachments.
|
7
|
+
- Improved audio playback.
|
8
|
+
- Improved web search.
|
9
|
+
- Added a thumbnail image to web search results.
|
10
|
+
- Added a new commands to web search: "extract_images" and "extract_links".
|
11
|
+
- Added the option "Use raw content (without summarization)" to the web search plugin, which provides a more detailed result to the main model.
|
12
|
+
- Extended the default maximum result characters to 50,000 in the web search plugin.
|
13
|
+
|
1
14
|
2.4.39 (2024-12-09)
|
2
15
|
|
3
16
|
- Added "Split Screen" mode (accessible via the switch in the bottom-right corner of the screen), which allows you to work in two windows simultaneously. It is currently experimental (beta). Future updates will include Code Interpreter and Canvas running in tabs.
|
pygpt_net/__init__.py
CHANGED
@@ -6,15 +6,15 @@
|
|
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.12.
|
9
|
+
# Updated Date: 2024.12.13 21:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
__author__ = "Marcin Szczygliński"
|
13
13
|
__copyright__ = "Copyright 2024, Marcin Szczygliński"
|
14
14
|
__credits__ = ["Marcin Szczygliński"]
|
15
15
|
__license__ = "MIT"
|
16
|
-
__version__ = "2.4.
|
17
|
-
__build__ = "2024.12.
|
16
|
+
__version__ = "2.4.40"
|
17
|
+
__build__ = "2024.12.13"
|
18
18
|
__maintainer__ = "Marcin Szczygliński"
|
19
19
|
__github__ = "https://github.com/szczyglis-dev/py-gpt"
|
20
20
|
__website__ = "https://pygpt.net"
|
pygpt_net/controller/__init__.py
CHANGED
@@ -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.12.09
|
9
|
+
# Updated Date: 2024.12.09 23:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
from pygpt_net.controller.access import Access
|
@@ -87,15 +87,16 @@ class Controller:
|
|
87
87
|
self.chat.init()
|
88
88
|
|
89
89
|
# setup layout
|
90
|
-
self.ui.pre_setup()
|
91
90
|
self.layout.setup()
|
92
91
|
self.ui.setup()
|
92
|
+
self.ui.tabs.setup()
|
93
93
|
|
94
94
|
# setup controllers
|
95
95
|
self.lang.setup()
|
96
96
|
self.assistant.setup()
|
97
97
|
self.chat.setup()
|
98
98
|
self.agent.setup()
|
99
|
+
self.tools.setup()
|
99
100
|
self.ctx.setup()
|
100
101
|
self.presets.setup()
|
101
102
|
self.idx.setup()
|
@@ -105,7 +106,8 @@ class Controller:
|
|
105
106
|
self.attachment.setup()
|
106
107
|
self.camera.setup_ui()
|
107
108
|
self.access.setup()
|
108
|
-
|
109
|
+
|
110
|
+
|
109
111
|
|
110
112
|
def post_setup(self):
|
111
113
|
"""Post-setup, after plugins are loaded"""
|
@@ -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.
|
9
|
+
# Updated Date: 2024.12.13 08:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
import os
|
@@ -200,6 +200,14 @@ class Audio:
|
|
200
200
|
}
|
201
201
|
self.window.dispatch(event, all=True)
|
202
202
|
|
203
|
+
def stop_audio(self):
|
204
|
+
"""Stop audio playback"""
|
205
|
+
ctx = CtxItem()
|
206
|
+
event = Event(Event.AUDIO_OUTPUT_STOP)
|
207
|
+
event.ctx = ctx
|
208
|
+
event.data = {}
|
209
|
+
self.window.dispatch(event, all=True)
|
210
|
+
|
203
211
|
def play_sound(self, filename: str):
|
204
212
|
"""
|
205
213
|
Play sound
|
@@ -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.
|
9
|
+
# Updated Date: 2024.12.12 04:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
from pygpt_net.core.bridge import BridgeContext
|
@@ -52,6 +52,7 @@ class Input:
|
|
52
52
|
"""
|
53
53
|
self.window.controller.agent.experts.unlock() # unlock experts
|
54
54
|
self.window.controller.agent.llama.reset_eval_step() # reset evaluation steps
|
55
|
+
self.window.controller.ui.tabs.switch_to_first_chat() # switch to first active chat tab
|
55
56
|
|
56
57
|
# get text from input
|
57
58
|
text = self.window.ui.nodes['input'].toPlainText().strip()
|
@@ -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.12.
|
9
|
+
# Updated Date: 2024.12.12 04:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
from PySide6.QtCore import Slot, QTimer
|
@@ -16,7 +16,7 @@ from pygpt_net.core.render.base import BaseRenderer
|
|
16
16
|
from pygpt_net.core.render.markdown.renderer import Renderer as MarkdownRenderer
|
17
17
|
from pygpt_net.core.render.plain.renderer import Renderer as PlainTextRenderer
|
18
18
|
from pygpt_net.core.render.web.renderer import Renderer as WebRenderer
|
19
|
-
from pygpt_net.core.tabs import Tab
|
19
|
+
from pygpt_net.core.tabs.tab import Tab
|
20
20
|
from pygpt_net.core.text.utils import output_html2text, output_clean_html
|
21
21
|
from pygpt_net.item.ctx import CtxItem, CtxMeta
|
22
22
|
|
@@ -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.12.
|
9
|
+
# Updated Date: 2024.12.12 04:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
from PySide6.QtCore import QModelIndex
|
@@ -19,7 +19,7 @@ from .summarizer import Summarizer
|
|
19
19
|
from .extra import Extra
|
20
20
|
|
21
21
|
from pygpt_net.utils import trans
|
22
|
-
from pygpt_net.core.tabs import Tab
|
22
|
+
from pygpt_net.core.tabs.tab import Tab
|
23
23
|
|
24
24
|
|
25
25
|
class Ctx:
|
@@ -15,6 +15,8 @@ from logging import ERROR, WARNING, INFO, DEBUG
|
|
15
15
|
from PySide6.QtCore import Slot, QObject
|
16
16
|
from PySide6.QtGui import QTextCursor
|
17
17
|
|
18
|
+
from pygpt_net.core.events import RenderEvent
|
19
|
+
|
18
20
|
|
19
21
|
class Debug(QObject):
|
20
22
|
def __init__(self, window=None):
|
@@ -53,8 +55,17 @@ class Debug(QObject):
|
|
53
55
|
|
54
56
|
def toggle_menu(self):
|
55
57
|
"""Toggle debug menu"""
|
56
|
-
|
57
|
-
self.window.ui.menu['menu.debug'].menuAction().setVisible(
|
58
|
+
state = self.window.core.config.get('debug')
|
59
|
+
self.window.ui.menu['menu.debug'].menuAction().setVisible(state)
|
60
|
+
|
61
|
+
def toggle_render(self):
|
62
|
+
"""Toggle render debug"""
|
63
|
+
value = self.window.ui.menu['debug.render'].isChecked()
|
64
|
+
self.window.core.config.set('debug.render', value)
|
65
|
+
self.window.core.config.save()
|
66
|
+
event = RenderEvent(RenderEvent.ON_THEME_CHANGE)
|
67
|
+
self.window.dispatch(event)
|
68
|
+
self.window.controller.ctx.refresh()
|
58
69
|
|
59
70
|
def set_log_level(self, level: str = 'error'):
|
60
71
|
"""
|
@@ -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.
|
9
|
+
# Updated Date: 2024.12.13 08:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
import time
|
@@ -251,6 +251,7 @@ class Kernel(QObject):
|
|
251
251
|
"""
|
252
252
|
self.halt = True
|
253
253
|
self.window.controller.chat.common.stop(exit=exit) # it stops legacy agent also
|
254
|
+
self.window.controller.audio.stop_audio()
|
254
255
|
if not exit:
|
255
256
|
self.window.dispatch(KernelEvent(KernelEvent.STOP))
|
256
257
|
self.set_state(KernelEvent(KernelEvent.STATE_IDLE, {"msg": trans("status.stopped")}))
|
pygpt_net/controller/notepad.py
CHANGED
@@ -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.12.
|
9
|
+
# Updated Date: 2024.12.12 01:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
from PySide6.QtGui import QTextCursor
|
@@ -38,13 +38,14 @@ class Notepad:
|
|
38
38
|
"""
|
39
39
|
if idx is None:
|
40
40
|
idx = self.window.core.tabs.count_by_type(Tab.TAB_NOTEPAD) + 1
|
41
|
-
|
42
|
-
self.window.ui.notepad[
|
43
|
-
self.window.ui.notepad[
|
41
|
+
data_id = idx
|
42
|
+
self.window.ui.notepad[data_id] = NotepadWidget(self.window)
|
43
|
+
self.window.ui.notepad[data_id].id = idx
|
44
|
+
self.window.ui.notepad[data_id].textarea.id = idx
|
44
45
|
title = trans('output.tab.notepad')
|
45
46
|
title += " " + str(idx)
|
46
|
-
children = self.window.core.tabs.from_widget(self.window.ui.notepad[
|
47
|
-
return children, idx
|
47
|
+
children = self.window.core.tabs.from_widget(self.window.ui.notepad[data_id])
|
48
|
+
return children, idx, data_id
|
48
49
|
|
49
50
|
def load(self):
|
50
51
|
"""Load all notepads contents"""
|
@@ -6,9 +6,9 @@
|
|
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.
|
9
|
+
# Updated Date: 2024.12.12 01:00:00 #
|
10
10
|
# ================================================== #
|
11
|
-
|
11
|
+
|
12
12
|
from pygpt_net.core.events import RenderEvent
|
13
13
|
|
14
14
|
|
@@ -93,9 +93,6 @@ class Nodes:
|
|
93
93
|
continue
|
94
94
|
self.apply(key, type)
|
95
95
|
|
96
|
-
# self.window.interpreter.update_stylesheet(self.window.controller.theme.style('font.chat.output'))
|
97
|
-
# self.window.ui.nodes['interpreter.input'].update_stylesheet(self.window.controller.theme.style('font.chat.input'))
|
98
|
-
|
99
96
|
# apply to notepads
|
100
97
|
num_notepads = self.window.controller.notepad.get_num_notepads()
|
101
98
|
if num_notepads > 0:
|
@@ -6,10 +6,15 @@
|
|
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.
|
9
|
+
# Updated Date: 2024.12.12 01:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
|
+
from PySide6.QtGui import QAction, QIcon
|
13
|
+
from PySide6.QtWidgets import QTabWidget, QMenu
|
14
|
+
|
12
15
|
from pygpt_net.core.tabs.tab import Tab
|
16
|
+
from pygpt_net.utils import trans
|
17
|
+
|
13
18
|
|
14
19
|
class Tools:
|
15
20
|
def __init__(self, window=None):
|
@@ -44,6 +49,37 @@ class Tools:
|
|
44
49
|
if idx is not None:
|
45
50
|
self.window.controller.ui.tabs.switch_tab_by_idx(idx)
|
46
51
|
|
52
|
+
def append_tab_menu(
|
53
|
+
self,
|
54
|
+
parent: QTabWidget,
|
55
|
+
menu: QMenu,
|
56
|
+
idx: int,
|
57
|
+
column_idx: int
|
58
|
+
) -> QMenu:
|
59
|
+
"""
|
60
|
+
Append tab menu
|
61
|
+
|
62
|
+
:param parent: parent widget
|
63
|
+
:param menu: menu
|
64
|
+
:param idx: tab index
|
65
|
+
:param column_idx: column index
|
66
|
+
:return: tab add submenu
|
67
|
+
"""
|
68
|
+
submenu = menu.addMenu(QIcon(":/icons/add.svg"), trans("action.tab.add.tool"))
|
69
|
+
tools = self.window.tools.get_all()
|
70
|
+
for id in tools:
|
71
|
+
tool = tools[id]
|
72
|
+
if not tool.has_tab:
|
73
|
+
continue
|
74
|
+
icon = tool.tab_icon
|
75
|
+
title = trans(tool.tab_title)
|
76
|
+
action = QAction(QIcon(icon), title, parent)
|
77
|
+
action.triggered.connect(
|
78
|
+
lambda idx=idx, column_idx=column_idx, id=id: parent.add_tab(idx, column_idx, Tab.TAB_TOOL, id)
|
79
|
+
)
|
80
|
+
submenu.addAction(action)
|
81
|
+
return submenu
|
82
|
+
|
47
83
|
def get_tab_tools(self) -> dict:
|
48
84
|
"""
|
49
85
|
Get tab tools
|
@@ -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.
|
9
|
+
# Updated Date: 2024.12.09 23:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
from PySide6.QtGui import QColor
|
@@ -47,10 +47,6 @@ class UI:
|
|
47
47
|
self.update()
|
48
48
|
self.init_toolbox()
|
49
49
|
|
50
|
-
def pre_setup(self):
|
51
|
-
"""Post setup UI"""
|
52
|
-
self.tabs.setup()
|
53
|
-
|
54
50
|
def update(self):
|
55
51
|
"""Update all elements"""
|
56
52
|
|
pygpt_net/controller/ui/tabs.py
CHANGED
@@ -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.12.
|
9
|
+
# Updated Date: 2024.12.12 01:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
from PySide6.QtCore import QTimer
|
@@ -32,6 +32,7 @@ class Tabs:
|
|
32
32
|
self.column_idx = 0
|
33
33
|
self.tmp_column_idx = 0
|
34
34
|
self.locked = False
|
35
|
+
self.col = {}
|
35
36
|
|
36
37
|
def setup(self):
|
37
38
|
"""Setup tabs"""
|
@@ -53,7 +54,8 @@ class Tabs:
|
|
53
54
|
title: str,
|
54
55
|
icon=None,
|
55
56
|
child=None,
|
56
|
-
data_id=None
|
57
|
+
data_id=None,
|
58
|
+
tool_id=None,
|
57
59
|
):
|
58
60
|
"""
|
59
61
|
Add a new tab
|
@@ -63,37 +65,55 @@ class Tabs:
|
|
63
65
|
:param icon: Tab icon
|
64
66
|
:param child: Tab child (child widget)
|
65
67
|
:param data_id: Tab data ID (child data ID)
|
68
|
+
:param tool_id: Tool ID
|
66
69
|
"""
|
67
70
|
self.window.core.tabs.add(
|
68
71
|
type=type,
|
69
72
|
title=title,
|
70
73
|
icon=icon,
|
71
74
|
child=child,
|
72
|
-
data_id=data_id
|
75
|
+
data_id=data_id,
|
76
|
+
tool_id=tool_id
|
73
77
|
)
|
74
78
|
|
75
79
|
def append(
|
76
80
|
self,
|
77
81
|
type: int,
|
78
|
-
|
82
|
+
tool_id: str = None,
|
83
|
+
idx: int = 0,
|
79
84
|
column_idx: int = 0
|
80
85
|
):
|
81
86
|
"""
|
82
87
|
Append tab at tab index
|
83
88
|
|
84
89
|
:param type: Tab type
|
90
|
+
:param tool_id: Tool ID
|
85
91
|
:param idx: Tab index
|
86
92
|
:param column_idx: Column index
|
87
93
|
"""
|
88
94
|
self.appended = True # lock reload in previous tab
|
89
95
|
self.column_idx = column_idx # switch to column
|
90
|
-
self.window.core.tabs.append(
|
91
|
-
|
96
|
+
tab = self.window.core.tabs.append(
|
97
|
+
type=type,
|
98
|
+
idx=idx,
|
99
|
+
column_idx=column_idx,
|
100
|
+
tool_id=tool_id
|
101
|
+
)
|
102
|
+
self.switch_tab_by_idx(tab.idx, column_idx) # switch to new tab
|
92
103
|
|
93
104
|
def reload_titles(self):
|
94
105
|
"""Reload tab titles"""
|
95
106
|
self.window.core.tabs.reload_titles()
|
96
107
|
|
108
|
+
def update_current(self):
|
109
|
+
"""Update current tab"""
|
110
|
+
curr_tab = self.get_current_tab()
|
111
|
+
curr_column = self.get_current_column_idx()
|
112
|
+
if curr_column not in self.col:
|
113
|
+
self.col[curr_column] = -1
|
114
|
+
if curr_tab is not None:
|
115
|
+
self.col[curr_column] = curr_tab.pid
|
116
|
+
|
97
117
|
def reload(self):
|
98
118
|
"""Reload tabs"""
|
99
119
|
self.window.core.tabs.reload()
|
@@ -131,7 +151,6 @@ class Tabs:
|
|
131
151
|
if meta is not None:
|
132
152
|
self.window.controller.ctx.load(meta.id) # reload
|
133
153
|
|
134
|
-
|
135
154
|
prev_tab = self.current
|
136
155
|
prev_column = self.column_idx
|
137
156
|
self.current = idx
|
@@ -156,6 +175,9 @@ class Tabs:
|
|
156
175
|
if prev_tab != idx or prev_column != column_idx:
|
157
176
|
self.window.dispatch(AppEvent(AppEvent.TAB_SELECTED)) # app event
|
158
177
|
|
178
|
+
self.window.controller.ui.update()
|
179
|
+
self.update_current()
|
180
|
+
|
159
181
|
def get_current_idx(self, column_idx: int = 0) -> int:
|
160
182
|
"""
|
161
183
|
Get current tab index
|
@@ -234,6 +256,8 @@ class Tabs:
|
|
234
256
|
current_ctx = self.window.core.ctx.get_current()
|
235
257
|
if current_ctx is not None and current_ctx != tab.data_id:
|
236
258
|
self.window.controller.ctx.select_on_list_only(tab.data_id)
|
259
|
+
self.window.controller.ui.update()
|
260
|
+
self.update_current()
|
237
261
|
|
238
262
|
def on_tab_clicked(self, idx: int, column_idx: int = 0):
|
239
263
|
"""
|
@@ -245,6 +269,7 @@ class Tabs:
|
|
245
269
|
self.current = idx
|
246
270
|
self.column_idx = column_idx
|
247
271
|
self.on_column_changed()
|
272
|
+
self.update_current()
|
248
273
|
|
249
274
|
def on_column_focus(self, idx: int):
|
250
275
|
"""
|
@@ -254,6 +279,7 @@ class Tabs:
|
|
254
279
|
"""
|
255
280
|
self.column_idx = idx
|
256
281
|
self.on_column_changed()
|
282
|
+
self.update_current()
|
257
283
|
|
258
284
|
def on_tab_dbl_clicked(self, idx: int, column_idx: int = 0):
|
259
285
|
"""
|
@@ -264,6 +290,7 @@ class Tabs:
|
|
264
290
|
"""
|
265
291
|
self.column_idx = column_idx
|
266
292
|
self.on_tab_changed(idx, column_idx)
|
293
|
+
self.update_current()
|
267
294
|
|
268
295
|
def on_tab_closed(self, idx: int, column_idx: int = 0):
|
269
296
|
"""
|
@@ -272,7 +299,10 @@ class Tabs:
|
|
272
299
|
:param idx: tab index
|
273
300
|
:param column_idx: column index
|
274
301
|
"""
|
302
|
+
if self.locked:
|
303
|
+
return
|
275
304
|
self.window.core.tabs.remove_tab_by_idx(idx, column_idx)
|
305
|
+
self.update_current()
|
276
306
|
|
277
307
|
def on_tab_moved(self, idx: int, column_idx: int = 0):
|
278
308
|
"""
|
@@ -281,7 +311,10 @@ class Tabs:
|
|
281
311
|
:param idx: tab index
|
282
312
|
:param column_idx: column index
|
283
313
|
"""
|
314
|
+
if self.locked:
|
315
|
+
return
|
284
316
|
self.window.core.tabs.update()
|
317
|
+
self.update_current()
|
285
318
|
|
286
319
|
def close(self, idx: int, column_idx: int = 0):
|
287
320
|
"""
|
@@ -291,6 +324,7 @@ class Tabs:
|
|
291
324
|
:param column_idx: column index
|
292
325
|
"""
|
293
326
|
self.on_tab_closed(idx, column_idx)
|
327
|
+
self.update_current()
|
294
328
|
|
295
329
|
def close_all(
|
296
330
|
self,
|
@@ -315,6 +349,7 @@ class Tabs:
|
|
315
349
|
return
|
316
350
|
column_idx = self.tmp_column_idx
|
317
351
|
self.window.core.tabs.remove_all_by_type(type, column_idx)
|
352
|
+
self.update_current()
|
318
353
|
|
319
354
|
def next_tab(self):
|
320
355
|
"""Switch to next tab"""
|
@@ -487,7 +522,12 @@ class Tabs:
|
|
487
522
|
:param column_idx: column index
|
488
523
|
"""
|
489
524
|
idx = self.get_current_idx(column_idx)
|
490
|
-
self.append(
|
525
|
+
self.append(
|
526
|
+
type=Tab.TAB_CHAT,
|
527
|
+
tool_id=None,
|
528
|
+
idx=idx,
|
529
|
+
column_idx=column_idx
|
530
|
+
)
|
491
531
|
|
492
532
|
def restore_data(self):
|
493
533
|
"""Restore tab data"""
|
@@ -495,6 +535,9 @@ class Tabs:
|
|
495
535
|
if not data:
|
496
536
|
self.switch_tab_by_idx(0, 0)
|
497
537
|
return
|
538
|
+
|
539
|
+
# reverse order, second column is first
|
540
|
+
data = dict(reversed(list(data.items())))
|
498
541
|
for col_idx in data:
|
499
542
|
tab_idx = data[col_idx]
|
500
543
|
self.switch_tab_by_idx(int(tab_idx), int(col_idx))
|
@@ -515,18 +558,67 @@ class Tabs:
|
|
515
558
|
tab = self.window.core.tabs.get_tab_by_index(idx, column_idx)
|
516
559
|
self.window.core.tabs.move_tab(tab, new_column_idx)
|
517
560
|
self.locked = False
|
561
|
+
# switch to new column
|
562
|
+
self.column_idx = new_column_idx
|
563
|
+
self.on_column_changed()
|
564
|
+
# switch to new tab
|
565
|
+
self.switch_tab_by_idx(tab.idx, new_column_idx)
|
518
566
|
|
519
567
|
def toggle_split_screen(self, state):
|
520
568
|
"""
|
521
|
-
Toggle split screen
|
569
|
+
Toggle split screen mode
|
522
570
|
|
523
|
-
:param state:
|
571
|
+
:param state: True if split screen is enabled
|
524
572
|
"""
|
525
573
|
if state:
|
526
|
-
#self.rightWidget.show()
|
574
|
+
# self.rightWidget.show()
|
527
575
|
self.window.ui.splitters['columns'].setSizes([1, 1])
|
528
576
|
else:
|
529
|
-
#self.rightWidget.hide()
|
577
|
+
# self.rightWidget.hide()
|
530
578
|
self.window.ui.splitters['columns'].setSizes([1, 0])
|
579
|
+
# set to first column
|
580
|
+
self.column_idx = 0
|
581
|
+
self.on_column_changed()
|
531
582
|
self.window.core.config.set("layout.split", state)
|
532
583
|
self.window.core.config.save()
|
584
|
+
|
585
|
+
def is_current_by_type(self, type: int) -> bool:
|
586
|
+
"""
|
587
|
+
Check if one of current tabs is of given type
|
588
|
+
|
589
|
+
:param type: tab type
|
590
|
+
:return: True if one of tab is of given type
|
591
|
+
"""
|
592
|
+
for col in self.col:
|
593
|
+
pid = self.col[col]
|
594
|
+
tab = self.window.core.tabs.get_tab_by_pid(pid)
|
595
|
+
if tab is not None and tab.type == type:
|
596
|
+
return True
|
597
|
+
|
598
|
+
def is_current_tool(self, tool_id: str) -> bool:
|
599
|
+
"""
|
600
|
+
Check if one of current tabs is of given tool ID
|
601
|
+
|
602
|
+
:param tool_id: tool ID
|
603
|
+
:return: True if one of tab is of given tool ID
|
604
|
+
"""
|
605
|
+
for col in self.col:
|
606
|
+
pid = self.col[col]
|
607
|
+
tab = self.window.core.tabs.get_tab_by_pid(pid)
|
608
|
+
if tab is not None and tab.tool_id == tool_id:
|
609
|
+
return True
|
610
|
+
|
611
|
+
def switch_to_first_chat(self):
|
612
|
+
"""Switch to first chat tab"""
|
613
|
+
if self.is_current_by_type(Tab.TAB_CHAT):
|
614
|
+
return
|
615
|
+
# abort if active tab is chat
|
616
|
+
if self.get_current_type() == Tab.TAB_CHAT:
|
617
|
+
return
|
618
|
+
# find first chat tab
|
619
|
+
for col in self.col:
|
620
|
+
pid = self.col[col]
|
621
|
+
tab = self.window.core.tabs.get_tab_by_pid(pid)
|
622
|
+
if tab is not None and tab.type == Tab.TAB_CHAT:
|
623
|
+
self.switch_tab_by_idx(tab.idx, col)
|
624
|
+
return
|