pygpt-net 2.4.38__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 +19 -0
- README.md +25 -2
- pygpt_net/CHANGELOG.txt +19 -0
- pygpt_net/__init__.py +3 -3
- pygpt_net/controller/__init__.py +7 -3
- pygpt_net/controller/audio/__init__.py +9 -1
- pygpt_net/controller/calendar/__init__.py +3 -1
- pygpt_net/controller/chat/input.py +2 -1
- pygpt_net/controller/chat/render.py +8 -5
- pygpt_net/controller/ctx/__init__.py +33 -25
- pygpt_net/controller/ctx/common.py +3 -2
- pygpt_net/controller/debug/__init__.py +13 -2
- pygpt_net/controller/dialogs/confirm.py +2 -2
- pygpt_net/controller/kernel/__init__.py +2 -1
- pygpt_net/controller/lang/custom.py +2 -7
- pygpt_net/controller/lang/mapping.py +2 -2
- pygpt_net/controller/layout.py +2 -2
- pygpt_net/controller/notepad.py +14 -10
- 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 +295 -60
- pygpt_net/core/command.py +3 -1
- pygpt_net/core/ctx/__init__.py +16 -2
- pygpt_net/core/ctx/container.py +18 -11
- pygpt_net/core/ctx/output.py +86 -67
- pygpt_net/core/debug/tabs.py +5 -2
- pygpt_net/core/filesystem/url.py +7 -3
- pygpt_net/core/render/base.py +14 -3
- pygpt_net/core/render/markdown/renderer.py +3 -1
- pygpt_net/core/render/plain/renderer.py +3 -3
- pygpt_net/core/render/web/body.py +10 -4
- pygpt_net/core/render/web/renderer.py +213 -41
- pygpt_net/core/tabs/__init__.py +268 -98
- pygpt_net/core/tabs/tab.py +16 -4
- pygpt_net/core/web.py +127 -1
- pygpt_net/data/config/config.json +12 -5
- 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 +3 -0
- pygpt_net/data/locale/locale.en.ini +6 -1
- pygpt_net/data/locale/locale.es.ini +3 -0
- pygpt_net/data/locale/locale.fr.ini +3 -0
- pygpt_net/data/locale/locale.it.ini +3 -0
- pygpt_net/data/locale/locale.pl.ini +4 -1
- pygpt_net/data/locale/locale.uk.ini +3 -0
- pygpt_net/data/locale/locale.zh.ini +3 -0
- 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_input/simple.py +4 -2
- 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 +29 -1
- pygpt_net/provider/core/ctx/base.py +4 -1
- pygpt_net/provider/core/ctx/db_sqlite/__init__.py +10 -1
- pygpt_net/provider/core/ctx/db_sqlite/storage.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/chat/input.py +10 -18
- pygpt_net/ui/layout/chat/output.py +26 -44
- pygpt_net/ui/layout/ctx/ctx_list.py +13 -4
- pygpt_net/ui/layout/toolbox/footer.py +18 -2
- 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/layout.py +195 -0
- pygpt_net/ui/widget/tabs/output.py +209 -55
- pygpt_net/ui/widget/textarea/html.py +11 -1
- pygpt_net/ui/widget/textarea/output.py +10 -1
- pygpt_net/ui/widget/textarea/web.py +49 -9
- {pygpt_net-2.4.38.dist-info → pygpt_net-2.4.40.dist-info}/METADATA +26 -3
- {pygpt_net-2.4.38.dist-info → pygpt_net-2.4.40.dist-info}/RECORD +105 -103
- {pygpt_net-2.4.38.dist-info → pygpt_net-2.4.40.dist-info}/LICENSE +0 -0
- {pygpt_net-2.4.38.dist-info → pygpt_net-2.4.40.dist-info}/WHEEL +0 -0
- {pygpt_net-2.4.38.dist-info → pygpt_net-2.4.40.dist-info}/entry_points.txt +0 -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.
|
9
|
+
# Updated Date: 2024.12.12 01:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
from PySide6.QtCore import QTimer
|
@@ -29,40 +29,91 @@ class Tabs:
|
|
29
29
|
self.initialized = False
|
30
30
|
self.appended = False
|
31
31
|
self.current = 0
|
32
|
+
self.column_idx = 0
|
33
|
+
self.tmp_column_idx = 0
|
34
|
+
self.locked = False
|
35
|
+
self.col = {}
|
32
36
|
|
33
37
|
def setup(self):
|
34
38
|
"""Setup tabs"""
|
35
39
|
self.window.core.tabs.load()
|
36
40
|
self.window.controller.notepad.load()
|
41
|
+
self.setup_options()
|
37
42
|
self.initialized = True
|
38
43
|
|
39
|
-
def
|
40
|
-
"""
|
41
|
-
|
44
|
+
def setup_options(self):
|
45
|
+
"""Setup options"""
|
46
|
+
state = self.window.core.config.get("layout.split", False)
|
47
|
+
self.window.ui.nodes['layout.split'].setChecked(state)
|
48
|
+
if not state:
|
49
|
+
self.window.ui.splitters['columns'].setSizes([1, 0])
|
50
|
+
|
51
|
+
def add(
|
52
|
+
self,
|
53
|
+
type: int,
|
54
|
+
title: str,
|
55
|
+
icon=None,
|
56
|
+
child=None,
|
57
|
+
data_id=None,
|
58
|
+
tool_id=None,
|
59
|
+
):
|
60
|
+
"""
|
61
|
+
Add a new tab
|
42
62
|
|
43
63
|
:param type: Tab type
|
44
64
|
:param title: Tab title
|
45
65
|
:param icon: Tab icon
|
46
|
-
:param
|
47
|
-
:param data_id: Tab data ID
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
66
|
+
:param child: Tab child (child widget)
|
67
|
+
:param data_id: Tab data ID (child data ID)
|
68
|
+
:param tool_id: Tool ID
|
69
|
+
"""
|
70
|
+
self.window.core.tabs.add(
|
71
|
+
type=type,
|
72
|
+
title=title,
|
73
|
+
icon=icon,
|
74
|
+
child=child,
|
75
|
+
data_id=data_id,
|
76
|
+
tool_id=tool_id
|
77
|
+
)
|
78
|
+
|
79
|
+
def append(
|
80
|
+
self,
|
81
|
+
type: int,
|
82
|
+
tool_id: str = None,
|
83
|
+
idx: int = 0,
|
84
|
+
column_idx: int = 0
|
85
|
+
):
|
86
|
+
"""
|
87
|
+
Append tab at tab index
|
54
88
|
|
55
89
|
:param type: Tab type
|
90
|
+
:param tool_id: Tool ID
|
56
91
|
:param idx: Tab index
|
92
|
+
:param column_idx: Column index
|
57
93
|
"""
|
58
94
|
self.appended = True # lock reload in previous tab
|
59
|
-
self.
|
60
|
-
self.
|
95
|
+
self.column_idx = column_idx # switch to column
|
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
|
61
103
|
|
62
104
|
def reload_titles(self):
|
63
105
|
"""Reload tab titles"""
|
64
106
|
self.window.core.tabs.reload_titles()
|
65
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
|
+
|
66
117
|
def reload(self):
|
67
118
|
"""Reload tabs"""
|
68
119
|
self.window.core.tabs.reload()
|
@@ -78,15 +129,16 @@ class Tabs:
|
|
78
129
|
else:
|
79
130
|
self.window.ui.nodes['output_plain'][pid].setVisible(False)
|
80
131
|
self.window.ui.nodes['output'][pid].setVisible(True)
|
81
|
-
self.switch_tab(Tab.TAB_CHAT)
|
132
|
+
#self.switch_tab(Tab.TAB_CHAT)
|
82
133
|
|
83
|
-
def on_tab_changed(self, idx: int):
|
134
|
+
def on_tab_changed(self, idx: int, column_idx: int = 0):
|
84
135
|
"""
|
85
136
|
Output tab changed
|
86
137
|
|
87
138
|
:param idx: tab index
|
139
|
+
:param column_idx: column index
|
88
140
|
"""
|
89
|
-
tab = self.window.core.tabs.get_tab_by_index(idx)
|
141
|
+
tab = self.window.core.tabs.get_tab_by_index(idx, column_idx)
|
90
142
|
if tab is None:
|
91
143
|
self.appended = False
|
92
144
|
return
|
@@ -99,43 +151,57 @@ class Tabs:
|
|
99
151
|
if meta is not None:
|
100
152
|
self.window.controller.ctx.load(meta.id) # reload
|
101
153
|
|
102
|
-
|
103
154
|
prev_tab = self.current
|
155
|
+
prev_column = self.column_idx
|
104
156
|
self.current = idx
|
157
|
+
self.column_idx = column_idx
|
105
158
|
self.window.controller.ui.mode.update()
|
106
159
|
self.window.controller.ui.vision.update()
|
107
160
|
|
108
161
|
# check type
|
109
162
|
if tab.type == Tab.TAB_NOTEPAD:
|
110
163
|
self.window.controller.notepad.opened_once = True
|
111
|
-
self.window.controller.notepad.on_open(idx)
|
164
|
+
self.window.controller.notepad.on_open(idx, column_idx)
|
112
165
|
elif tab.type == Tab.TAB_CHAT:
|
113
|
-
|
114
|
-
|
166
|
+
# get meta for selected tab, if not loaded yet then append meta here
|
167
|
+
meta_id = self.window.core.ctx.output.prepare_meta(tab)
|
168
|
+
meta = self.window.core.ctx.get_meta_by_id(meta_id)
|
115
169
|
if meta is not None:
|
116
|
-
self.window.controller.ctx.load(
|
170
|
+
self.window.controller.ctx.load(meta.id) # reload renderer
|
117
171
|
elif tab.type == Tab.TAB_TOOL_PAINTER:
|
118
172
|
if self.window.core.config.get('vision.capture.enabled'):
|
119
173
|
self.window.controller.camera.enable_capture()
|
120
174
|
|
121
|
-
if prev_tab != idx:
|
175
|
+
if prev_tab != idx or prev_column != column_idx:
|
122
176
|
self.window.dispatch(AppEvent(AppEvent.TAB_SELECTED)) # app event
|
123
177
|
|
124
|
-
|
178
|
+
self.window.controller.ui.update()
|
179
|
+
self.update_current()
|
180
|
+
|
181
|
+
def get_current_idx(self, column_idx: int = 0) -> int:
|
125
182
|
"""
|
126
183
|
Get current tab index
|
127
184
|
|
185
|
+
:param column_idx: column index
|
128
186
|
:return: tab index
|
129
187
|
"""
|
130
188
|
return self.current
|
131
189
|
|
190
|
+
def get_current_column_idx(self) -> int:
|
191
|
+
"""
|
192
|
+
Get current column index
|
193
|
+
|
194
|
+
:return: column index
|
195
|
+
"""
|
196
|
+
return self.column_idx
|
197
|
+
|
132
198
|
def get_current_tab(self) -> Tab or None:
|
133
199
|
"""
|
134
200
|
Get current tab
|
135
201
|
|
136
202
|
:return: tab
|
137
203
|
"""
|
138
|
-
return self.window.core.tabs.get_tab_by_index(self.
|
204
|
+
return self.window.core.tabs.get_tab_by_index(self.get_current_idx(), self.column_idx)
|
139
205
|
|
140
206
|
def get_current_type(self) -> int or None:
|
141
207
|
"""
|
@@ -143,7 +209,7 @@ class Tabs:
|
|
143
209
|
|
144
210
|
:return: tab type
|
145
211
|
"""
|
146
|
-
tab = self.window.core.tabs.get_tab_by_index(self.
|
212
|
+
tab = self.window.core.tabs.get_tab_by_index(self.get_current_idx(), self.column_idx)
|
147
213
|
if tab is None:
|
148
214
|
return None
|
149
215
|
return tab.type
|
@@ -154,7 +220,7 @@ class Tabs:
|
|
154
220
|
|
155
221
|
:return: tab PID
|
156
222
|
"""
|
157
|
-
tab = self.window.core.tabs.get_tab_by_index(self.
|
223
|
+
tab = self.window.core.tabs.get_tab_by_index(self.get_current_idx(), self.column_idx)
|
158
224
|
if tab is None:
|
159
225
|
return None
|
160
226
|
return tab.pid
|
@@ -166,7 +232,7 @@ class Tabs:
|
|
166
232
|
:param idx: tab index
|
167
233
|
:return: tab type
|
168
234
|
"""
|
169
|
-
tab = self.window.core.tabs.get_tab_by_index(idx)
|
235
|
+
tab = self.window.core.tabs.get_tab_by_index(idx, self.column_idx)
|
170
236
|
if tab is None:
|
171
237
|
return None
|
172
238
|
return tab.type
|
@@ -178,68 +244,118 @@ class Tabs:
|
|
178
244
|
:param type: tab type
|
179
245
|
:return: tab index
|
180
246
|
"""
|
181
|
-
return self.window.core.tabs.get_min_idx_by_type(type)
|
247
|
+
return self.window.core.tabs.get_min_idx_by_type(type, self.column_idx)
|
182
248
|
|
183
|
-
def
|
249
|
+
def on_column_changed(self):
|
250
|
+
"""Column changed event"""
|
251
|
+
if self.locked:
|
252
|
+
return
|
253
|
+
tab = self.window.core.tabs.get_tab_by_index(self.current, self.column_idx)
|
254
|
+
if tab is None:
|
255
|
+
return
|
256
|
+
current_ctx = self.window.core.ctx.get_current()
|
257
|
+
if current_ctx is not None and current_ctx != tab.data_id:
|
258
|
+
self.window.controller.ctx.select_on_list_only(tab.data_id)
|
259
|
+
self.window.controller.ui.update()
|
260
|
+
self.update_current()
|
261
|
+
|
262
|
+
def on_tab_clicked(self, idx: int, column_idx: int = 0):
|
184
263
|
"""
|
185
264
|
Tab click event
|
186
265
|
|
187
266
|
:param idx: tab index
|
267
|
+
:param column_idx: column index
|
268
|
+
"""
|
269
|
+
self.current = idx
|
270
|
+
self.column_idx = column_idx
|
271
|
+
self.on_column_changed()
|
272
|
+
self.update_current()
|
273
|
+
|
274
|
+
def on_column_focus(self, idx: int):
|
275
|
+
"""
|
276
|
+
Column focus event
|
277
|
+
|
278
|
+
:param idx: column index
|
188
279
|
"""
|
189
|
-
|
280
|
+
self.column_idx = idx
|
281
|
+
self.on_column_changed()
|
282
|
+
self.update_current()
|
190
283
|
|
191
|
-
def on_tab_dbl_clicked(self, idx: int):
|
284
|
+
def on_tab_dbl_clicked(self, idx: int, column_idx: int = 0):
|
192
285
|
"""
|
193
286
|
Tab double click event
|
194
287
|
|
195
288
|
:param idx: tab index
|
289
|
+
:param column_idx: column index
|
196
290
|
"""
|
197
|
-
|
291
|
+
self.column_idx = column_idx
|
292
|
+
self.on_tab_changed(idx, column_idx)
|
293
|
+
self.update_current()
|
198
294
|
|
199
|
-
def on_tab_closed(self, idx: int):
|
295
|
+
def on_tab_closed(self, idx: int, column_idx: int = 0):
|
200
296
|
"""
|
201
297
|
Tab close event
|
202
298
|
|
203
299
|
:param idx: tab index
|
300
|
+
:param column_idx: column index
|
204
301
|
"""
|
205
|
-
self.
|
302
|
+
if self.locked:
|
303
|
+
return
|
304
|
+
self.window.core.tabs.remove_tab_by_idx(idx, column_idx)
|
305
|
+
self.update_current()
|
206
306
|
|
207
|
-
def on_tab_moved(self, idx: int):
|
307
|
+
def on_tab_moved(self, idx: int, column_idx: int = 0):
|
208
308
|
"""
|
209
309
|
Tab moved event
|
210
310
|
|
211
311
|
:param idx: tab index
|
312
|
+
:param column_idx: column index
|
212
313
|
"""
|
314
|
+
if self.locked:
|
315
|
+
return
|
213
316
|
self.window.core.tabs.update()
|
317
|
+
self.update_current()
|
214
318
|
|
215
|
-
def close(self, idx: int):
|
319
|
+
def close(self, idx: int, column_idx: int = 0):
|
216
320
|
"""
|
217
321
|
Close tab
|
218
322
|
|
219
323
|
:param idx: tab index
|
324
|
+
:param column_idx: column index
|
220
325
|
"""
|
221
|
-
self.on_tab_closed(idx)
|
326
|
+
self.on_tab_closed(idx, column_idx)
|
327
|
+
self.update_current()
|
222
328
|
|
223
|
-
def close_all(
|
329
|
+
def close_all(
|
330
|
+
self,
|
331
|
+
type: int,
|
332
|
+
column_idx: int = 0,
|
333
|
+
force: bool = False
|
334
|
+
):
|
224
335
|
"""
|
225
336
|
Close all tabs
|
226
337
|
|
227
338
|
:param type: tab type
|
339
|
+
:param column_idx: column index
|
228
340
|
:param force: force close
|
229
341
|
"""
|
230
342
|
if not force:
|
343
|
+
self.tmp_column_idx = column_idx
|
231
344
|
self.window.ui.dialogs.confirm(
|
232
345
|
type='tab.close_all',
|
233
346
|
id=type,
|
234
347
|
msg=trans('tab.close_all.confirm'),
|
235
348
|
)
|
236
349
|
return
|
237
|
-
self.
|
350
|
+
column_idx = self.tmp_column_idx
|
351
|
+
self.window.core.tabs.remove_all_by_type(type, column_idx)
|
352
|
+
self.update_current()
|
238
353
|
|
239
354
|
def next_tab(self):
|
240
355
|
"""Switch to next tab"""
|
241
|
-
|
242
|
-
|
356
|
+
tabs = self.window.ui.layout.get_active_tabs()
|
357
|
+
current = tabs.currentIndex()
|
358
|
+
all = len(tabs.children())
|
243
359
|
next = current + 1
|
244
360
|
if next >= all:
|
245
361
|
next = 0
|
@@ -247,8 +363,9 @@ class Tabs:
|
|
247
363
|
|
248
364
|
def prev_tab(self):
|
249
365
|
"""Switch to previous tab"""
|
250
|
-
|
251
|
-
|
366
|
+
tabs = self.window.ui.layout.get_active_tabs()
|
367
|
+
current = tabs.currentIndex()
|
368
|
+
all = len(tabs.children())
|
252
369
|
prev = current - 1
|
253
370
|
if prev < 0:
|
254
371
|
prev = all - 1
|
@@ -264,14 +381,16 @@ class Tabs:
|
|
264
381
|
if idx is not None:
|
265
382
|
self.switch_tab_by_idx(idx)
|
266
383
|
|
267
|
-
def switch_tab_by_idx(self, idx: int):
|
384
|
+
def switch_tab_by_idx(self, idx: int, column_idx: int = 0):
|
268
385
|
"""
|
269
386
|
Switch tab by index
|
270
387
|
|
271
388
|
:param idx: tab index
|
389
|
+
:param column_idx: column index
|
272
390
|
"""
|
273
|
-
self.window.ui.
|
274
|
-
|
391
|
+
tabs = self.window.ui.layout.get_tabs_by_idx(column_idx)
|
392
|
+
tabs.setCurrentIndex(idx)
|
393
|
+
self.on_tab_changed(idx, column_idx)
|
275
394
|
|
276
395
|
def get_current_tab_name(self) -> str:
|
277
396
|
"""
|
@@ -279,7 +398,8 @@ class Tabs:
|
|
279
398
|
|
280
399
|
:return: tab name
|
281
400
|
"""
|
282
|
-
|
401
|
+
tabs = self.window.ui.layout.get_active_tabs()
|
402
|
+
return tabs.tabText(self.current)
|
283
403
|
|
284
404
|
def get_current_tab_name_for_audio(self) -> str:
|
285
405
|
"""
|
@@ -309,18 +429,20 @@ class Tabs:
|
|
309
429
|
"""
|
310
430
|
Update tab tooltip
|
311
431
|
|
312
|
-
:param tooltip: tooltip
|
432
|
+
:param tooltip: tooltip text
|
313
433
|
"""
|
314
|
-
self.window.ui.
|
434
|
+
tabs = self.window.ui.layout.get_active_tabs()
|
435
|
+
tabs.setTabToolTip(self.current, tooltip)
|
315
436
|
|
316
|
-
def rename(self, idx: int):
|
437
|
+
def rename(self, idx: int, column_idx: int = 0):
|
317
438
|
"""
|
318
|
-
Rename tab
|
439
|
+
Rename tab (show dialog)
|
319
440
|
|
320
441
|
:param idx: tab idx
|
442
|
+
:param column_idx: column idx
|
321
443
|
"""
|
322
444
|
# get tab
|
323
|
-
tab = self.window.core.tabs.get_tab_by_index(idx)
|
445
|
+
tab = self.window.core.tabs.get_tab_by_index(idx, column_idx)
|
324
446
|
if tab is None:
|
325
447
|
return
|
326
448
|
# set dialog and show
|
@@ -329,7 +451,12 @@ class Tabs:
|
|
329
451
|
self.window.ui.dialog['rename'].current = idx
|
330
452
|
self.window.ui.dialog['rename'].show()
|
331
453
|
|
332
|
-
def update_name(
|
454
|
+
def update_name(
|
455
|
+
self,
|
456
|
+
idx: int,
|
457
|
+
name: str,
|
458
|
+
close: bool = True
|
459
|
+
):
|
333
460
|
"""
|
334
461
|
Update tab title
|
335
462
|
|
@@ -349,7 +476,11 @@ class Tabs:
|
|
349
476
|
"""
|
350
477
|
self.update_name(self.current, name)
|
351
478
|
|
352
|
-
def update_title(
|
479
|
+
def update_title(
|
480
|
+
self,
|
481
|
+
idx: int,
|
482
|
+
title: str
|
483
|
+
):
|
353
484
|
"""
|
354
485
|
Update tab title
|
355
486
|
|
@@ -359,8 +490,9 @@ class Tabs:
|
|
359
490
|
# check if current tab is chat
|
360
491
|
if self.get_current_type() != Tab.TAB_CHAT:
|
361
492
|
return
|
493
|
+
tabs = self.window.ui.layout.get_active_tabs()
|
362
494
|
tooltip = title
|
363
|
-
|
495
|
+
tabs.setTabToolTip(idx, tooltip)
|
364
496
|
if len(title) > 8:
|
365
497
|
title = title[:8] + '...' # truncate to max 8 chars
|
366
498
|
self.window.core.tabs.update_title(idx, title, tooltip)
|
@@ -383,7 +515,110 @@ class Tabs:
|
|
383
515
|
if idx is not None:
|
384
516
|
self.switch_tab_by_idx(idx)
|
385
517
|
|
386
|
-
def new_tab(self):
|
387
|
-
"""
|
388
|
-
|
389
|
-
|
518
|
+
def new_tab(self, column_idx: int = 0):
|
519
|
+
"""
|
520
|
+
Handle [+] button
|
521
|
+
|
522
|
+
:param column_idx: column index
|
523
|
+
"""
|
524
|
+
idx = self.get_current_idx(column_idx)
|
525
|
+
self.append(
|
526
|
+
type=Tab.TAB_CHAT,
|
527
|
+
tool_id=None,
|
528
|
+
idx=idx,
|
529
|
+
column_idx=column_idx
|
530
|
+
)
|
531
|
+
|
532
|
+
def restore_data(self):
|
533
|
+
"""Restore tab data"""
|
534
|
+
data = self.window.core.config.get("tabs.opened", [])
|
535
|
+
if not data:
|
536
|
+
self.switch_tab_by_idx(0, 0)
|
537
|
+
return
|
538
|
+
|
539
|
+
# reverse order, second column is first
|
540
|
+
data = dict(reversed(list(data.items())))
|
541
|
+
for col_idx in data:
|
542
|
+
tab_idx = data[col_idx]
|
543
|
+
self.switch_tab_by_idx(int(tab_idx), int(col_idx))
|
544
|
+
|
545
|
+
# set default column to 0
|
546
|
+
self.column_idx = 0
|
547
|
+
self.on_column_changed()
|
548
|
+
|
549
|
+
def move_tab(self, idx: int, column_idx: int, new_column_idx: int):
|
550
|
+
"""
|
551
|
+
Move tab to another column
|
552
|
+
|
553
|
+
:param idx: tab index
|
554
|
+
:param column_idx: column index
|
555
|
+
:param new_column_idx: new column index
|
556
|
+
"""
|
557
|
+
self.locked = True
|
558
|
+
tab = self.window.core.tabs.get_tab_by_index(idx, column_idx)
|
559
|
+
self.window.core.tabs.move_tab(tab, new_column_idx)
|
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)
|
566
|
+
|
567
|
+
def toggle_split_screen(self, state):
|
568
|
+
"""
|
569
|
+
Toggle split screen mode
|
570
|
+
|
571
|
+
:param state: True if split screen is enabled
|
572
|
+
"""
|
573
|
+
if state:
|
574
|
+
# self.rightWidget.show()
|
575
|
+
self.window.ui.splitters['columns'].setSizes([1, 1])
|
576
|
+
else:
|
577
|
+
# self.rightWidget.hide()
|
578
|
+
self.window.ui.splitters['columns'].setSizes([1, 0])
|
579
|
+
# set to first column
|
580
|
+
self.column_idx = 0
|
581
|
+
self.on_column_changed()
|
582
|
+
self.window.core.config.set("layout.split", state)
|
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
|
pygpt_net/core/command.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.
|
9
|
+
# Updated Date: 2024.12.13 08:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
import copy
|
@@ -18,6 +18,7 @@ from pygpt_net.core.types import (
|
|
18
18
|
MODE_COMPLETION,
|
19
19
|
MODE_LANGCHAIN,
|
20
20
|
MODE_LLAMA_INDEX,
|
21
|
+
MODE_AUDIO,
|
21
22
|
)
|
22
23
|
from pygpt_net.core.events import Event
|
23
24
|
from pygpt_net.item.ctx import CtxItem
|
@@ -537,6 +538,7 @@ class Command:
|
|
537
538
|
MODE_LLAMA_INDEX,
|
538
539
|
MODE_LANGCHAIN,
|
539
540
|
MODE_COMPLETION,
|
541
|
+
MODE_AUDIO,
|
540
542
|
]
|
541
543
|
mode = self.window.core.config.get('mode')
|
542
544
|
if mode in disabled_modes:
|