pygpt-net 2.4.37__py3-none-any.whl → 2.4.41__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 +29 -0
- README.md +44 -115
- pygpt_net/CHANGELOG.txt +29 -0
- pygpt_net/__init__.py +3 -3
- pygpt_net/controller/__init__.py +7 -3
- pygpt_net/controller/access/control.py +1 -1
- pygpt_net/controller/access/voice.py +11 -5
- pygpt_net/controller/agent/experts.py +11 -6
- pygpt_net/controller/agent/legacy.py +8 -6
- pygpt_net/controller/agent/llama.py +4 -2
- pygpt_net/controller/assistant/__init__.py +9 -4
- pygpt_net/controller/assistant/batch.py +38 -21
- pygpt_net/controller/assistant/editor.py +7 -6
- pygpt_net/controller/assistant/files.py +23 -7
- pygpt_net/controller/assistant/store.py +20 -7
- pygpt_net/controller/assistant/threads.py +34 -8
- pygpt_net/controller/attachment.py +29 -10
- pygpt_net/controller/audio/__init__.py +25 -4
- pygpt_net/controller/calendar/__init__.py +23 -4
- pygpt_net/controller/calendar/note.py +57 -11
- pygpt_net/controller/camera.py +3 -2
- pygpt_net/controller/chat/__init__.py +5 -3
- pygpt_net/controller/chat/attachment.py +34 -7
- pygpt_net/controller/chat/command.py +4 -2
- pygpt_net/controller/chat/common.py +11 -4
- pygpt_net/controller/chat/files.py +10 -3
- pygpt_net/controller/chat/image.py +17 -5
- pygpt_net/controller/chat/input.py +10 -7
- pygpt_net/controller/chat/output.py +21 -6
- pygpt_net/controller/chat/render.py +100 -21
- pygpt_net/controller/chat/response.py +34 -7
- pygpt_net/controller/chat/stream.py +4 -2
- pygpt_net/controller/chat/text.py +6 -4
- pygpt_net/controller/command.py +11 -3
- pygpt_net/controller/config/__init__.py +34 -6
- pygpt_net/controller/config/field/checkbox.py +7 -4
- pygpt_net/controller/config/field/cmd.py +7 -5
- pygpt_net/controller/config/field/combo.py +14 -6
- pygpt_net/controller/config/field/dictionary.py +14 -11
- pygpt_net/controller/config/field/input.py +9 -6
- pygpt_net/controller/config/field/slider.py +11 -8
- pygpt_net/controller/config/field/textarea.py +8 -5
- pygpt_net/controller/config/placeholder.py +52 -21
- pygpt_net/controller/ctx/__init__.py +138 -49
- pygpt_net/controller/ctx/common.py +15 -4
- pygpt_net/controller/ctx/extra.py +11 -3
- pygpt_net/controller/ctx/summarizer.py +24 -5
- pygpt_net/controller/debug/__init__.py +27 -6
- pygpt_net/controller/dialogs/confirm.py +34 -7
- pygpt_net/controller/dialogs/debug.py +4 -2
- pygpt_net/controller/dialogs/info.py +7 -2
- pygpt_net/controller/files.py +48 -10
- pygpt_net/controller/finder.py +11 -5
- pygpt_net/controller/idx/__init__.py +10 -3
- pygpt_net/controller/idx/common.py +4 -2
- pygpt_net/controller/idx/indexer.py +25 -17
- pygpt_net/controller/idx/settings.py +9 -3
- pygpt_net/controller/kernel/__init__.py +34 -8
- pygpt_net/controller/kernel/reply.py +12 -3
- pygpt_net/controller/kernel/stack.py +5 -3
- pygpt_net/controller/lang/custom.py +2 -7
- pygpt_net/controller/lang/mapping.py +5 -3
- pygpt_net/controller/layout.py +2 -2
- pygpt_net/controller/mode.py +16 -4
- pygpt_net/controller/model/__init__.py +14 -3
- pygpt_net/controller/model/editor.py +8 -3
- pygpt_net/controller/notepad.py +26 -12
- pygpt_net/controller/painter/capture.py +23 -4
- pygpt_net/controller/painter/common.py +9 -7
- pygpt_net/controller/plugins/__init__.py +19 -5
- pygpt_net/controller/plugins/presets.py +15 -6
- pygpt_net/controller/plugins/settings.py +9 -3
- pygpt_net/controller/presets/__init__.py +55 -16
- pygpt_net/controller/presets/editor.py +26 -10
- pygpt_net/controller/settings/__init__.py +3 -2
- pygpt_net/controller/settings/editor.py +29 -7
- pygpt_net/controller/settings/profile.py +22 -5
- pygpt_net/controller/theme/__init__.py +54 -12
- pygpt_net/controller/theme/common.py +24 -2
- pygpt_net/controller/theme/markdown.py +32 -16
- pygpt_net/controller/theme/menu.py +26 -5
- pygpt_net/controller/theme/nodes.py +2 -5
- pygpt_net/controller/tools/__init__.py +40 -2
- pygpt_net/controller/ui/__init__.py +4 -6
- pygpt_net/controller/ui/tabs.py +363 -65
- pygpt_net/core/access/actions.py +6 -4
- pygpt_net/core/access/shortcuts.py +4 -3
- pygpt_net/core/access/voice.py +6 -5
- pygpt_net/core/agents/legacy.py +4 -2
- pygpt_net/core/agents/memory.py +7 -2
- pygpt_net/core/agents/observer/evaluation.py +15 -7
- pygpt_net/core/agents/provider.py +9 -4
- pygpt_net/core/agents/runner.py +61 -15
- pygpt_net/core/agents/tools.py +23 -5
- pygpt_net/core/assistants/__init__.py +6 -4
- pygpt_net/core/assistants/files.py +35 -12
- pygpt_net/core/assistants/store.py +20 -10
- pygpt_net/core/attachments/__init__.py +54 -15
- pygpt_net/core/attachments/context.py +92 -29
- pygpt_net/core/audio/__init__.py +71 -3
- pygpt_net/core/audio/context.py +7 -2
- pygpt_net/core/bridge/__init__.py +22 -6
- pygpt_net/core/bridge/context.py +5 -3
- pygpt_net/core/calendar/__init__.py +57 -11
- pygpt_net/core/chain/__init__.py +8 -2
- pygpt_net/core/chain/chat.py +10 -8
- pygpt_net/core/chain/completion.py +10 -7
- pygpt_net/core/command.py +62 -17
- pygpt_net/core/ctx/__init__.py +260 -58
- pygpt_net/core/ctx/bag.py +25 -4
- pygpt_net/core/ctx/container.py +28 -17
- pygpt_net/core/ctx/idx.py +45 -8
- pygpt_net/core/ctx/output.py +95 -74
- pygpt_net/core/ctx/reply.py +5 -2
- pygpt_net/core/db/__init__.py +8 -7
- pygpt_net/core/db/viewer.py +17 -11
- pygpt_net/core/debug/__init__.py +10 -9
- pygpt_net/core/debug/tabs.py +5 -2
- pygpt_net/core/docker/__init__.py +11 -5
- pygpt_net/core/docker/builder.py +11 -3
- pygpt_net/core/events/app.py +5 -3
- pygpt_net/core/events/base.py +11 -5
- pygpt_net/core/events/control.py +5 -3
- pygpt_net/core/events/event.py +17 -7
- pygpt_net/core/events/kernel.py +5 -3
- pygpt_net/core/events/render.py +5 -3
- pygpt_net/core/experts/__init__.py +5 -4
- pygpt_net/core/filesystem/__init__.py +52 -34
- pygpt_net/core/filesystem/actions.py +8 -5
- pygpt_net/core/filesystem/editor.py +13 -3
- pygpt_net/core/filesystem/types.py +12 -7
- pygpt_net/core/filesystem/url.py +7 -3
- pygpt_net/core/idx/__init__.py +34 -25
- pygpt_net/core/idx/chat.py +40 -16
- pygpt_net/core/idx/context.py +6 -2
- pygpt_net/core/idx/indexing.py +84 -35
- pygpt_net/core/idx/llm.py +11 -3
- pygpt_net/core/idx/metadata.py +13 -3
- pygpt_net/core/idx/types/ctx.py +32 -6
- pygpt_net/core/idx/types/external.py +41 -7
- pygpt_net/core/idx/types/files.py +31 -6
- pygpt_net/core/image.py +15 -4
- pygpt_net/core/llm/__init__.py +13 -3
- pygpt_net/core/locale.py +34 -8
- pygpt_net/core/models.py +4 -3
- pygpt_net/core/notepad.py +9 -4
- pygpt_net/core/plugins.py +7 -6
- pygpt_net/core/presets.py +19 -10
- pygpt_net/core/profile.py +12 -6
- pygpt_net/core/prompt/__init__.py +10 -3
- pygpt_net/core/prompt/custom.py +7 -6
- pygpt_net/core/prompt/template.py +9 -3
- pygpt_net/core/render/base.py +117 -22
- pygpt_net/core/render/markdown/body.py +27 -7
- pygpt_net/core/render/markdown/renderer.py +119 -22
- pygpt_net/core/render/plain/body.py +22 -5
- pygpt_net/core/render/plain/renderer.py +97 -21
- pygpt_net/core/render/web/body.py +75 -25
- pygpt_net/core/render/web/renderer.py +313 -63
- pygpt_net/core/settings.py +9 -4
- pygpt_net/core/tabs/__init__.py +290 -103
- pygpt_net/core/tabs/tab.py +17 -4
- pygpt_net/core/tokens.py +44 -11
- pygpt_net/core/updater/__init__.py +20 -7
- pygpt_net/core/vision/analyzer.py +29 -6
- pygpt_net/core/web.py +130 -2
- pygpt_net/data/config/config.json +15 -4
- pygpt_net/data/config/models.json +3 -3
- pygpt_net/data/config/modes.json +3 -3
- pygpt_net/data/config/settings.json +55 -10
- pygpt_net/data/config/settings_section.json +3 -0
- pygpt_net/data/css/style.light.css +1 -0
- pygpt_net/data/css/{web.css → web-blocks.css} +162 -133
- pygpt_net/data/css/{web.light.css → web-blocks.light.css} +7 -0
- pygpt_net/data/css/web-chatgpt.css +350 -0
- pygpt_net/data/css/web-chatgpt.dark.css +64 -0
- pygpt_net/data/css/web-chatgpt.light.css +75 -0
- pygpt_net/data/css/web-chatgpt_wide.css +350 -0
- pygpt_net/data/css/web-chatgpt_wide.dark.css +64 -0
- pygpt_net/data/css/web-chatgpt_wide.light.css +75 -0
- pygpt_net/data/icons/split_screen.svg +1 -0
- pygpt_net/data/locale/locale.de.ini +12 -0
- pygpt_net/data/locale/locale.en.ini +17 -2
- pygpt_net/data/locale/locale.es.ini +12 -0
- pygpt_net/data/locale/locale.fr.ini +12 -0
- pygpt_net/data/locale/locale.it.ini +12 -0
- pygpt_net/data/locale/locale.pl.ini +12 -0
- pygpt_net/data/locale/locale.uk.ini +12 -0
- pygpt_net/data/locale/locale.zh.ini +12 -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 +21 -5
- pygpt_net/plugin/audio_output/__init__.py +4 -1
- pygpt_net/plugin/base/config.py +4 -2
- pygpt_net/plugin/base/plugin.py +26 -6
- pygpt_net/plugin/base/worker.py +37 -9
- 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 +43 -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/provider/gpt/assistants.py +10 -9
- pygpt_net/provider/gpt/audio.py +3 -2
- pygpt_net/provider/gpt/chat.py +8 -7
- pygpt_net/provider/gpt/completion.py +6 -4
- pygpt_net/provider/gpt/image.py +9 -2
- pygpt_net/provider/gpt/store.py +14 -13
- pygpt_net/provider/gpt/vision.py +6 -5
- 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/config.py +7 -11
- pygpt_net/ui/menu/debug.py +11 -1
- pygpt_net/ui/menu/theme.py +9 -2
- pygpt_net/ui/widget/filesystem/explorer.py +2 -2
- pygpt_net/ui/widget/lists/context.py +27 -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 +218 -55
- pygpt_net/ui/widget/textarea/html.py +11 -1
- pygpt_net/ui/widget/textarea/output.py +10 -1
- pygpt_net/ui/widget/textarea/search_input.py +4 -1
- pygpt_net/ui/widget/textarea/web.py +49 -9
- {pygpt_net-2.4.37.dist-info → pygpt_net-2.4.41.dist-info}/METADATA +45 -116
- {pygpt_net-2.4.37.dist-info → pygpt_net-2.4.41.dist-info}/RECORD +255 -247
- /pygpt_net/data/css/{web.dark.css → web-blocks.dark.css} +0 -0
- {pygpt_net-2.4.37.dist-info → pygpt_net-2.4.41.dist-info}/LICENSE +0 -0
- {pygpt_net-2.4.37.dist-info → pygpt_net-2.4.41.dist-info}/WHEEL +0 -0
- {pygpt_net-2.4.37.dist-info → pygpt_net-2.4.41.dist-info}/entry_points.txt +0 -0
@@ -6,29 +6,32 @@
|
|
6
6
|
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
7
7
|
# MIT License #
|
8
8
|
# Created By : Marcin Szczygliński #
|
9
|
-
# Updated Date: 2024.
|
9
|
+
# Updated Date: 2024.12.09 23:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
import re
|
13
13
|
|
14
14
|
from PySide6.QtCore import Qt
|
15
15
|
from PySide6.QtGui import QAction, QIcon
|
16
|
-
from PySide6.QtWidgets import
|
16
|
+
from PySide6.QtWidgets import QMenuBar, QVBoxLayout
|
17
17
|
|
18
|
-
from pygpt_net.tools.html_canvas.ui.widgets import CanvasOutput, CanvasEdit
|
19
18
|
from pygpt_net.ui.widget.dialog.base import BaseDialog
|
20
|
-
from pygpt_net.ui.widget.element.labels import HelpLabel
|
21
|
-
from pygpt_net.ui.widget.textarea.html import CustomWebEnginePage
|
22
19
|
from pygpt_net.utils import trans
|
23
20
|
|
24
|
-
|
25
|
-
|
21
|
+
from .widgets import ToolWidget
|
22
|
+
|
23
|
+
class Tool:
|
24
|
+
def __init__(self, window=None, tool=None):
|
26
25
|
"""
|
27
26
|
HTML/JS canvas dialog
|
28
27
|
|
29
28
|
:param window: Window instance
|
29
|
+
:param tool: Tool instance
|
30
30
|
"""
|
31
31
|
self.window = window
|
32
|
+
self.tool = tool # tool instance
|
33
|
+
self.widget = ToolWidget(window, tool)
|
34
|
+
self.layout = None
|
32
35
|
self.menu_bar = None
|
33
36
|
self.menu = {}
|
34
37
|
self.actions = {} # menu actions
|
@@ -45,20 +48,20 @@ class Canvas:
|
|
45
48
|
|
46
49
|
self.actions["file.open"] = QAction(QIcon(":/icons/folder.svg"), trans("tool.html_canvas.menu.file.open"))
|
47
50
|
self.actions["file.open"].triggered.connect(
|
48
|
-
lambda: self.
|
51
|
+
lambda: self.tool.open_file()
|
49
52
|
)
|
50
53
|
self.actions["file.save_as"] = QAction(QIcon(":/icons/save.svg"), trans("tool.html_canvas.menu.file.save_as"))
|
51
54
|
self.actions["file.save_as"].triggered.connect(
|
52
|
-
lambda: self.
|
53
|
-
re.sub(r'\n{2,}', '\n\n', self.
|
55
|
+
lambda: self.widget.output.signals.save_as.emit(
|
56
|
+
re.sub(r'\n{2,}', '\n\n', self.widget.output.html_content), 'html')
|
54
57
|
)
|
55
58
|
self.actions["file.reload"] = QAction(QIcon(":/icons/reload.svg"), trans("tool.html_canvas.menu.file.reload"))
|
56
59
|
self.actions["file.reload"].triggered.connect(
|
57
|
-
lambda: self.
|
60
|
+
lambda: self.tool.reload_output()
|
58
61
|
)
|
59
62
|
self.actions["file.clear"] = QAction(QIcon(":/icons/close.svg"), trans("tool.html_canvas.menu.file.clear"))
|
60
63
|
self.actions["file.clear"].triggered.connect(
|
61
|
-
lambda: self.
|
64
|
+
lambda: self.tool.clear()
|
62
65
|
)
|
63
66
|
|
64
67
|
# add actions
|
@@ -70,61 +73,44 @@ class Canvas:
|
|
70
73
|
|
71
74
|
def setup(self):
|
72
75
|
"""Setup canvas dialog"""
|
73
|
-
self.
|
74
|
-
self.
|
75
|
-
CustomWebEnginePage(self.window, self.window.ui.nodes['html_canvas.output'])
|
76
|
-
)
|
77
|
-
self.window.ui.nodes['html_canvas.edit'] = CanvasEdit(self.window)
|
78
|
-
self.window.ui.nodes['html_canvas.edit'].setVisible(False)
|
79
|
-
self.window.ui.nodes['html_canvas.edit'].textChanged.connect(
|
80
|
-
lambda: self.window.tools.get("html_canvas").save_output()
|
81
|
-
)
|
82
|
-
|
83
|
-
# edit checkbox
|
84
|
-
self.window.ui.nodes['html_canvas.btn.edit'] = QCheckBox(trans("html_canvas.btn.edit"))
|
85
|
-
self.window.ui.nodes['html_canvas.btn.edit'].stateChanged.connect(
|
86
|
-
lambda: self.window.tools.get("html_canvas").toggle_edit()
|
87
|
-
)
|
88
|
-
|
89
|
-
path = self.window.tools.get("html_canvas").get_current_path()
|
90
|
-
path_label = HelpLabel(path)
|
91
|
-
path_label.setMaximumHeight(30)
|
92
|
-
path_label.setAlignment(Qt.AlignRight)
|
76
|
+
self.layout = self.widget.setup()
|
77
|
+
self.layout.setMenuBar(self.setup_menu()) # add menu bar
|
93
78
|
|
94
|
-
|
95
|
-
|
96
|
-
|
79
|
+
id = self.tool.get_dialog_id()
|
80
|
+
dialog = ToolDialog(window=self.window, tool=self.tool)
|
81
|
+
dialog.setLayout(self.layout)
|
82
|
+
dialog.setWindowTitle(trans("dialog.html_canvas.title"))
|
83
|
+
dialog.resize(800, 500)
|
84
|
+
self.window.ui.dialog[id] = dialog
|
97
85
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
output_layout.setContentsMargins(0, 0, 0, 0)
|
86
|
+
def get_widget(self) -> ToolWidget:
|
87
|
+
"""
|
88
|
+
Get widget
|
102
89
|
|
103
|
-
|
104
|
-
|
105
|
-
self.
|
90
|
+
:return: ToolWidget
|
91
|
+
"""
|
92
|
+
return self.widget
|
106
93
|
|
107
|
-
|
108
|
-
|
109
|
-
layout
|
110
|
-
layout.addLayout(bottom_layout)
|
94
|
+
def get_tab(self) -> QVBoxLayout:
|
95
|
+
"""
|
96
|
+
Get layout
|
111
97
|
|
112
|
-
|
113
|
-
|
114
|
-
self.
|
115
|
-
self.window.ui.dialog['html_canvas'].resize(800, 500)
|
98
|
+
:return: QVBoxLayout
|
99
|
+
"""
|
100
|
+
return self.layout
|
116
101
|
|
117
102
|
|
118
|
-
class
|
119
|
-
def __init__(self, window=None, id="html_canvas"):
|
103
|
+
class ToolDialog(BaseDialog):
|
104
|
+
def __init__(self, window=None, id="html_canvas", tool=None):
|
120
105
|
"""
|
121
106
|
HTML canvas dialog
|
122
107
|
|
123
108
|
:param window: main window
|
124
109
|
:param id: logger id
|
125
110
|
"""
|
126
|
-
super(
|
111
|
+
super(ToolDialog, self).__init__(window, id)
|
127
112
|
self.window = window
|
113
|
+
self.tool = tool
|
128
114
|
|
129
115
|
def closeEvent(self, event):
|
130
116
|
"""
|
@@ -133,7 +119,7 @@ class CanvasDialog(BaseDialog):
|
|
133
119
|
:param event: close event
|
134
120
|
"""
|
135
121
|
self.cleanup()
|
136
|
-
super(
|
122
|
+
super(ToolDialog, self).closeEvent(event)
|
137
123
|
|
138
124
|
def keyPressEvent(self, event):
|
139
125
|
"""
|
@@ -145,14 +131,12 @@ class CanvasDialog(BaseDialog):
|
|
145
131
|
self.cleanup()
|
146
132
|
self.close() # close dialog when the Esc key is pressed.
|
147
133
|
else:
|
148
|
-
super(
|
134
|
+
super(ToolDialog, self).keyPressEvent(event)
|
149
135
|
|
150
136
|
def cleanup(self):
|
151
|
-
"""
|
152
|
-
|
153
|
-
"""
|
154
|
-
if self.window is None:
|
137
|
+
"""Cleanup on close"""
|
138
|
+
if self.window is None or self.tool is None:
|
155
139
|
return
|
156
|
-
self.
|
157
|
-
self.
|
158
|
-
self.
|
140
|
+
self.tool.opened = False
|
141
|
+
self.tool.close()
|
142
|
+
self.tool.update()
|
@@ -6,13 +6,101 @@
|
|
6
6
|
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
7
7
|
# MIT License #
|
8
8
|
# Created By : Marcin Szczygliński #
|
9
|
-
# Updated Date: 2024.
|
9
|
+
# Updated Date: 2024.12.09 23:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
|
+
from PySide6.QtCore import Qt, Slot, QUrl, QObject, Signal
|
13
|
+
from PySide6.QtWidgets import QVBoxLayout, QCheckBox, QHBoxLayout
|
14
|
+
|
15
|
+
from pygpt_net.ui.widget.element.labels import HelpLabel
|
12
16
|
from pygpt_net.ui.widget.textarea.editor import BaseCodeEditor
|
13
|
-
from pygpt_net.ui.widget.textarea.html import HtmlOutput
|
17
|
+
from pygpt_net.ui.widget.textarea.html import HtmlOutput, CustomWebEnginePage
|
14
18
|
|
15
19
|
import pygpt_net.icons_rc
|
20
|
+
from pygpt_net.utils import trans
|
21
|
+
|
22
|
+
|
23
|
+
class ToolWidget:
|
24
|
+
def __init__(self, window=None, tool=None):
|
25
|
+
"""
|
26
|
+
HTML/JS canvas widget
|
27
|
+
|
28
|
+
:param window: Window instance
|
29
|
+
:param tool: Tool instance
|
30
|
+
"""
|
31
|
+
self.window = window
|
32
|
+
self.tool = tool # tool instance
|
33
|
+
self.output = None # canvas output
|
34
|
+
self.edit = None # canvas edit
|
35
|
+
self.btn_edit = None # edit checkbox
|
36
|
+
|
37
|
+
def setup(self) -> QVBoxLayout:
|
38
|
+
"""
|
39
|
+
Setup widget body
|
40
|
+
|
41
|
+
:return: QVBoxLayout
|
42
|
+
"""
|
43
|
+
self.output = CanvasOutput(self.window)
|
44
|
+
self.output.setPage(
|
45
|
+
CustomWebEnginePage(self.window, self.output)
|
46
|
+
)
|
47
|
+
self.edit = CanvasEdit(self.window)
|
48
|
+
self.edit.setVisible(False)
|
49
|
+
self.edit.textChanged.connect(
|
50
|
+
lambda: self.tool.save_output()
|
51
|
+
)
|
52
|
+
|
53
|
+
# edit checkbox
|
54
|
+
self.btn_edit = QCheckBox(trans("html_canvas.btn.edit"))
|
55
|
+
self.btn_edit.stateChanged.connect(
|
56
|
+
lambda: self.tool.toggle_edit(self)
|
57
|
+
)
|
58
|
+
|
59
|
+
path = self.tool.get_current_path()
|
60
|
+
path_label = HelpLabel(path)
|
61
|
+
path_label.setMaximumHeight(30)
|
62
|
+
path_label.setAlignment(Qt.AlignRight)
|
63
|
+
|
64
|
+
bottom_layout = QHBoxLayout()
|
65
|
+
bottom_layout.addWidget(self.btn_edit)
|
66
|
+
bottom_layout.addWidget(path_label)
|
67
|
+
|
68
|
+
output_layout = QVBoxLayout()
|
69
|
+
output_layout.addWidget(self.output)
|
70
|
+
output_layout.addWidget(self.edit)
|
71
|
+
output_layout.setContentsMargins(0, 0, 0, 0)
|
72
|
+
|
73
|
+
# connect signals
|
74
|
+
self.output.signals.save_as.connect(
|
75
|
+
self.tool.handle_save_as)
|
76
|
+
self.output.signals.audio_read.connect(
|
77
|
+
self.window.controller.chat.render.handle_audio_read)
|
78
|
+
|
79
|
+
self.tool.signals.update.connect(self.set_output)
|
80
|
+
self.tool.signals.reload.connect(self.load_output)
|
81
|
+
|
82
|
+
layout = QVBoxLayout()
|
83
|
+
layout.addLayout(output_layout)
|
84
|
+
layout.addLayout(bottom_layout)
|
85
|
+
return layout
|
86
|
+
|
87
|
+
@Slot(str)
|
88
|
+
def set_output(self, content: str):
|
89
|
+
"""
|
90
|
+
Set output content
|
91
|
+
|
92
|
+
:param content: Content
|
93
|
+
"""
|
94
|
+
self.edit.setPlainText(content)
|
95
|
+
|
96
|
+
@Slot(str)
|
97
|
+
def load_output(self, path: str):
|
98
|
+
"""
|
99
|
+
Load output content
|
100
|
+
|
101
|
+
:param path: Content
|
102
|
+
"""
|
103
|
+
self.output.setUrl(QUrl().fromLocalFile(path))
|
16
104
|
|
17
105
|
class CanvasOutput(HtmlOutput):
|
18
106
|
def __init__(self, window=None):
|
@@ -39,4 +127,9 @@ class CanvasEdit(BaseCodeEditor):
|
|
39
127
|
self.min_font_size = 8
|
40
128
|
self.setProperty('class', 'interpreter-output')
|
41
129
|
self.default_stylesheet = ""
|
42
|
-
self.setStyleSheet(self.default_stylesheet)
|
130
|
+
self.setStyleSheet(self.default_stylesheet)
|
131
|
+
|
132
|
+
|
133
|
+
class ToolSignals(QObject):
|
134
|
+
update = Signal(str) # data
|
135
|
+
reload = Signal(str) # path
|
@@ -6,13 +6,13 @@
|
|
6
6
|
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
7
7
|
# MIT License #
|
8
8
|
# Created By : Marcin Szczygliński #
|
9
|
-
# Updated Date: 2024.
|
9
|
+
# Updated Date: 2024.12.12 04:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
from PySide6.QtWidgets import QMenu
|
13
13
|
from PySide6.QtGui import QAction, QIcon
|
14
14
|
|
15
|
-
from pygpt_net.core.tabs import Tab
|
15
|
+
from pygpt_net.core.tabs.tab import Tab
|
16
16
|
from pygpt_net.utils import trans
|
17
17
|
import pygpt_net.icons_rc
|
18
18
|
|
@@ -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 03:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
from PySide6.QtCore import Qt
|
@@ -153,14 +153,6 @@ class Input:
|
|
153
153
|
"""
|
154
154
|
# header (input label + input counter)
|
155
155
|
self.window.ui.nodes['input.label'] = HelpLabel(trans("input.label"))
|
156
|
-
self.window.ui.nodes['input.counter'] = QLabel("")
|
157
|
-
self.window.ui.nodes['input.counter'].setToolTip(trans('tip.tokens.input'))
|
158
|
-
|
159
|
-
# inline vision
|
160
|
-
self.window.ui.nodes['inline.vision'] = HelpLabel(trans('inline.vision'))
|
161
|
-
self.window.ui.nodes['inline.vision'].setVisible(False)
|
162
|
-
self.window.ui.nodes['inline.vision'].setContentsMargins(0, 0, 0, 0)
|
163
|
-
self.window.ui.nodes['inline.vision'].setToolTip(trans('vision.checkbox.tooltip'))
|
164
156
|
|
165
157
|
# plugin audio input addon
|
166
158
|
self.window.ui.plugin_addon['audio.input'] = AudioInput(self.window)
|
@@ -168,10 +160,10 @@ class Input:
|
|
168
160
|
|
169
161
|
grid = QGridLayout()
|
170
162
|
|
171
|
-
left_layout = QHBoxLayout()
|
172
|
-
left_layout.addWidget(self.window.ui.nodes['input.label'])
|
173
|
-
left_layout.addWidget(self.window.ui.nodes['inline.vision'])
|
174
|
-
left_layout.addStretch(1)
|
163
|
+
#left_layout = QHBoxLayout()
|
164
|
+
#left_layout.addWidget(self.window.ui.nodes['input.label'])
|
165
|
+
#left_layout.addWidget(self.window.ui.nodes['inline.vision'])
|
166
|
+
#left_layout.addStretch(1)
|
175
167
|
|
176
168
|
center_layout = QHBoxLayout()
|
177
169
|
center_layout.addStretch()
|
@@ -179,13 +171,13 @@ class Input:
|
|
179
171
|
center_layout.addWidget(self.window.ui.plugin_addon['audio.input.btn'])
|
180
172
|
center_layout.addStretch()
|
181
173
|
|
182
|
-
right_layout = QHBoxLayout()
|
183
|
-
right_layout.addStretch(1)
|
184
|
-
right_layout.addWidget(self.window.ui.nodes['input.counter'])
|
174
|
+
#right_layout = QHBoxLayout()
|
175
|
+
#right_layout.addStretch(1)
|
176
|
+
#right_layout.addWidget(self.window.ui.nodes['input.counter'])
|
185
177
|
|
186
|
-
grid.addLayout(left_layout, 0, 0)
|
178
|
+
#grid.addLayout(left_layout, 0, 0)
|
187
179
|
grid.addLayout(center_layout, 0, 1, alignment=Qt.AlignCenter)
|
188
|
-
grid.addLayout(right_layout, 0, 2, alignment=Qt.AlignRight)
|
180
|
+
#grid.addLayout(right_layout, 0, 2, alignment=Qt.AlignRight)
|
189
181
|
|
190
182
|
grid.setContentsMargins(0, 0, 0, 0)
|
191
183
|
return grid
|
@@ -6,18 +6,17 @@
|
|
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 03:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
from PySide6.QtCore import Qt
|
13
|
-
from PySide6.QtGui import QIcon
|
14
13
|
from PySide6.QtWidgets import QVBoxLayout, QLabel, QHBoxLayout, QCheckBox, QWidget, QSizePolicy, QPushButton, \
|
15
|
-
QGridLayout,
|
14
|
+
QGridLayout, QWidgetItem, QLayout
|
16
15
|
|
17
16
|
from pygpt_net.ui.widget.audio.output import AudioOutput
|
18
17
|
from pygpt_net.ui.widget.element.labels import ChatStatusLabel, IconLabel, HelpLabel
|
19
|
-
from pygpt_net.ui.widget.
|
20
|
-
from pygpt_net.ui.widget.
|
18
|
+
from pygpt_net.ui.widget.anims.loader import Loading
|
19
|
+
from pygpt_net.ui.widget.tabs.layout import OutputLayout
|
21
20
|
|
22
21
|
from .explorer import Explorer
|
23
22
|
from .input import Input
|
@@ -28,6 +27,7 @@ from pygpt_net.utils import trans
|
|
28
27
|
import pygpt_net.icons_rc
|
29
28
|
|
30
29
|
|
30
|
+
|
31
31
|
class Output:
|
32
32
|
def __init__(self, window=None):
|
33
33
|
"""
|
@@ -47,46 +47,15 @@ class Output:
|
|
47
47
|
|
48
48
|
:return: QWidget
|
49
49
|
"""
|
50
|
-
#
|
51
|
-
self.window.ui.
|
52
|
-
|
53
|
-
#
|
54
|
-
plus_button = QPushButton(QIcon(":/icons/add.svg"), "")
|
55
|
-
plus_button.setFixedSize(30, 25)
|
56
|
-
plus_button.setFlat(True)
|
57
|
-
plus_button.clicked.connect(self.window.controller.ui.tabs.new_tab)
|
58
|
-
plus_button.setObjectName('tab-add')
|
59
|
-
plus_button.setProperty('tabAdd', True)
|
60
|
-
plus_button.setToolTip(trans('action.tab.add.chat'))
|
61
|
-
|
62
|
-
# Add the button to the top right corner of the tab bar
|
63
|
-
self.window.ui.tabs['output'].setCornerWidget(plus_button, corner=Qt.TopRightCorner)
|
64
|
-
|
65
|
-
# create empty tabs
|
50
|
+
# prepare columns
|
51
|
+
self.window.ui.layout = OutputLayout(self.window)
|
52
|
+
|
53
|
+
# create empty containers for chat output
|
66
54
|
self.window.ui.nodes['output'] = {}
|
67
55
|
self.window.ui.nodes['output_plain'] = {}
|
68
56
|
|
69
|
-
# connect signals
|
70
|
-
self.window.ui.tabs['output'].currentChanged.connect(
|
71
|
-
self.window.controller.ui.tabs.on_tab_changed
|
72
|
-
)
|
73
|
-
self.window.ui.tabs['output'].tabBarClicked.connect(
|
74
|
-
self.window.controller.ui.tabs.on_tab_clicked
|
75
|
-
)
|
76
|
-
self.window.ui.tabs['output'].tabBarDoubleClicked.connect(
|
77
|
-
self.window.controller.ui.tabs.on_tab_dbl_clicked
|
78
|
-
)
|
79
|
-
self.window.ui.tabs['output'].tabCloseRequested.connect(
|
80
|
-
self.window.controller.ui.tabs.on_tab_closed
|
81
|
-
)
|
82
|
-
|
83
|
-
# tab bar signals
|
84
|
-
self.window.ui.tabs['output'].tabBar().tabMoved.connect(
|
85
|
-
self.window.controller.ui.tabs.on_tab_moved
|
86
|
-
)
|
87
|
-
|
88
57
|
layout = QVBoxLayout()
|
89
|
-
layout.addWidget(self.window.ui.
|
58
|
+
layout.addWidget(self.window.ui.layout)
|
90
59
|
layout.addLayout(self.setup_bottom())
|
91
60
|
layout.setContentsMargins(0, 5, 0, 0)
|
92
61
|
|
@@ -177,18 +146,29 @@ class Output:
|
|
177
146
|
self.window.ui.nodes['prompt.context'].setToolTip(trans('tip.tokens.ctx'))
|
178
147
|
self.window.ui.nodes['prompt.context'].setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
|
179
148
|
|
149
|
+
self.window.ui.nodes['input.counter'] = ChatStatusLabel("")
|
150
|
+
self.window.ui.nodes['input.counter'].setToolTip(trans('tip.tokens.input'))
|
151
|
+
self.window.ui.nodes['input.counter'].setWordWrap(False)
|
152
|
+
|
180
153
|
# plugin audio output addon
|
181
154
|
self.window.ui.plugin_addon['audio.output'] = AudioOutput(self.window)
|
182
155
|
|
183
156
|
# schedule
|
184
157
|
self.window.ui.plugin_addon['schedule'] = ChatStatusLabel("")
|
185
158
|
|
159
|
+
# inline vision
|
160
|
+
self.window.ui.nodes['inline.vision'] = HelpLabel(trans('inline.vision'))
|
161
|
+
self.window.ui.nodes['inline.vision'].setVisible(False)
|
162
|
+
self.window.ui.nodes['inline.vision'].setContentsMargins(0, 0, 0, 0)
|
163
|
+
self.window.ui.nodes['inline.vision'].setToolTip(trans('vision.checkbox.tooltip'))
|
164
|
+
|
186
165
|
opts_layout = QHBoxLayout()
|
187
166
|
# opts_layout.setSpacing(2) #
|
188
167
|
opts_layout.setContentsMargins(0, 0, 0, 0)
|
189
168
|
opts_layout.addWidget(self.window.ui.nodes['output.timestamp'])
|
190
169
|
# opts_layout.addWidget(self.window.ui.nodes['output.edit'])
|
191
170
|
opts_layout.addWidget(self.window.ui.nodes['output.raw'])
|
171
|
+
opts_layout.addWidget(self.window.ui.nodes['inline.vision'])
|
192
172
|
opts_layout.setAlignment(Qt.AlignLeft)
|
193
173
|
|
194
174
|
left_layout = QHBoxLayout()
|
@@ -210,6 +190,8 @@ class Output:
|
|
210
190
|
right_layout.addWidget(self.window.ui.nodes['chat.model'])
|
211
191
|
right_layout.addWidget(QLabel(" "))
|
212
192
|
right_layout.addWidget(self.window.ui.nodes['prompt.context'])
|
193
|
+
right_layout.addWidget(QLabel(" "))
|
194
|
+
right_layout.addWidget(self.window.ui.nodes['input.counter'])
|
213
195
|
right_layout.setContentsMargins(0, 0, 0, 0)
|
214
196
|
|
215
197
|
left_widget = QWidget()
|
@@ -224,14 +206,14 @@ class Output:
|
|
224
206
|
|
225
207
|
left_layout = QHBoxLayout()
|
226
208
|
left_layout.addWidget(left_widget)
|
227
|
-
left_layout.addStretch(1)
|
209
|
+
#left_layout.addStretch(1)
|
228
210
|
left_layout.setContentsMargins(0, 0, 0, 0)
|
229
211
|
|
230
212
|
center_layout = QHBoxLayout()
|
231
|
-
center_layout.addStretch()
|
213
|
+
#center_layout.addStretch()
|
232
214
|
center_layout.addWidget(self.window.ui.nodes['anim.loading'])
|
233
215
|
center_layout.addStretch()
|
234
|
-
center_layout.setContentsMargins(
|
216
|
+
center_layout.setContentsMargins(20, 0, 0, 0)
|
235
217
|
|
236
218
|
right_layout = QHBoxLayout()
|
237
219
|
right_layout.addStretch(1)
|
@@ -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 PySide6 import QtCore
|
@@ -211,10 +211,19 @@ class CtxList:
|
|
211
211
|
item.dt = dt
|
212
212
|
item.isPinned = data.important
|
213
213
|
item.setData(tooltip_text, QtCore.Qt.ToolTipRole)
|
214
|
+
is_important = False
|
215
|
+
is_attachment = False
|
216
|
+
label = data.label
|
214
217
|
if data.important:
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
+
is_important = True
|
219
|
+
if data.additional_ctx and len(data.additional_ctx) > 0:
|
220
|
+
is_attachment = True
|
221
|
+
custom_data = {
|
222
|
+
"label": label,
|
223
|
+
"is_important": is_important,
|
224
|
+
"is_attachment": is_attachment,
|
225
|
+
}
|
226
|
+
item.setData(custom_data, QtCore.Qt.ItemDataRole.UserRole)
|
218
227
|
item.setData(name)
|
219
228
|
return item
|
220
229
|
|
@@ -6,14 +6,14 @@
|
|
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 03:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
import os
|
13
13
|
|
14
14
|
from PySide6.QtCore import QSize
|
15
15
|
from PySide6.QtGui import QIcon
|
16
|
-
from PySide6.QtWidgets import QVBoxLayout, QLabel, QPushButton, QWidget, QSizePolicy
|
16
|
+
from PySide6.QtWidgets import QVBoxLayout, QLabel, QPushButton, QWidget, QSizePolicy, QHBoxLayout
|
17
17
|
|
18
18
|
from pygpt_net.ui.widget.textarea.name import NameInput
|
19
19
|
from pygpt_net.ui.widget.option.slider import OptionSlider
|
@@ -25,6 +25,7 @@ from .agent_llama import AgentLlama
|
|
25
25
|
from .image import Image
|
26
26
|
from .indexes import Indexes
|
27
27
|
from .vision import Vision
|
28
|
+
from ...widget.option.toggle_label import ToggleLabel
|
28
29
|
|
29
30
|
|
30
31
|
class Footer:
|
@@ -75,6 +76,21 @@ class Footer:
|
|
75
76
|
rows.addWidget(self.window.ui.nodes['voice.control.btn'])
|
76
77
|
rows.setContentsMargins(2, 0, 0, 0)
|
77
78
|
|
79
|
+
self.window.ui.nodes['layout.split'] = ToggleLabel(trans('layout.split'), label_position="left",
|
80
|
+
icon=":/icons/split_screen.svg")
|
81
|
+
self.window.ui.nodes['layout.split'].box.stateChanged.connect(
|
82
|
+
lambda: self.window.controller.ui.tabs.toggle_split_screen(self.window.ui.nodes['layout.split'].box.isChecked())
|
83
|
+
)
|
84
|
+
split_layout = QHBoxLayout()
|
85
|
+
|
86
|
+
split_layout.addWidget(QLabel(""))
|
87
|
+
split_layout.addStretch(1)
|
88
|
+
split_layout.addWidget(self.window.ui.nodes['layout.split'])
|
89
|
+
split_layout.setContentsMargins(5, 0, 15, 0)
|
90
|
+
split_widget = QWidget()
|
91
|
+
split_widget.setLayout(split_layout)
|
92
|
+
rows.addWidget(split_widget)
|
93
|
+
|
78
94
|
# logo
|
79
95
|
logo_button = self.setup_logo()
|
80
96
|
|
pygpt_net/ui/main.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.09 23:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
import os
|
@@ -192,8 +192,8 @@ class MainWindow(QMainWindow, QtStyleTools):
|
|
192
192
|
|
193
193
|
def setup(self):
|
194
194
|
"""Setup app"""
|
195
|
-
self.controller.setup()
|
196
195
|
self.tools.setup()
|
196
|
+
self.controller.setup()
|
197
197
|
self.controller.plugins.setup()
|
198
198
|
self.controller.post_setup()
|
199
199
|
|
pygpt_net/ui/menu/config.py
CHANGED
@@ -6,9 +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.
|
9
|
+
# Updated Date: 2024.12.07 21:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
|
+
import os
|
13
|
+
|
12
14
|
from PySide6.QtGui import QAction, QIcon
|
13
15
|
from PySide6.QtWidgets import QMenu
|
14
16
|
|
@@ -42,16 +44,10 @@ class Config:
|
|
42
44
|
self.window.ui.menu['config.access'] = QAction(QIcon(":/icons/accessibility.svg"),
|
43
45
|
trans("menu.config.access"), self.window)
|
44
46
|
|
45
|
-
|
46
|
-
css_files.
|
47
|
-
css_files.
|
48
|
-
css_files
|
49
|
-
css_files.append("markdown.css")
|
50
|
-
css_files.append("markdown.dark.css")
|
51
|
-
css_files.append("markdown.light.css")
|
52
|
-
css_files.append("web.css")
|
53
|
-
css_files.append("web.dark.css")
|
54
|
-
css_files.append("web.light.css")
|
47
|
+
css_dir = os.path.join(self.window.core.config.path, 'css')
|
48
|
+
css_files = os.listdir(css_dir)
|
49
|
+
css_files = [f for f in css_files if not f.endswith('.backup')] # remove .backup files
|
50
|
+
css_files = sorted(css_files) # sort by name
|
55
51
|
|
56
52
|
json_files = []
|
57
53
|
json_files.append("attachments.json")
|