pygpt-net 2.4.36.post1__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 +38 -1
- README.md +71 -114
- pygpt_net/CHANGELOG.txt +38 -1
- 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 +39 -44
- 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 +217 -64
- 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/bridge/worker.py +16 -2
- 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 +18 -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 +60 -38
- 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 +19 -6
- pygpt_net/data/config/models.json +3 -3
- pygpt_net/data/config/modes.json +3 -3
- pygpt_net/data/config/settings.json +81 -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 +19 -3
- pygpt_net/data/locale/locale.en.ini +30 -11
- pygpt_net/data/locale/locale.es.ini +19 -3
- pygpt_net/data/locale/locale.fr.ini +19 -3
- pygpt_net/data/locale/locale.it.ini +19 -3
- pygpt_net/data/locale/locale.pl.ini +20 -4
- pygpt_net/data/locale/locale.uk.ini +19 -3
- pygpt_net/data/locale/locale.zh.ini +20 -4
- 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/plugin/idx_llama_index/__init__.py +2 -2
- pygpt_net/plugin/real_time/__init__.py +2 -2
- pygpt_net/provider/core/config/patch.py +54 -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.36.post1.dist-info → pygpt_net-2.4.41.dist-info}/METADATA +72 -115
- {pygpt_net-2.4.36.post1.dist-info → pygpt_net-2.4.41.dist-info}/RECORD +258 -250
- /pygpt_net/data/css/{web.dark.css → web-blocks.dark.css} +0 -0
- {pygpt_net-2.4.36.post1.dist-info → pygpt_net-2.4.41.dist-info}/LICENSE +0 -0
- {pygpt_net-2.4.36.post1.dist-info → pygpt_net-2.4.41.dist-info}/WHEEL +0 -0
- {pygpt_net-2.4.36.post1.dist-info → pygpt_net-2.4.41.dist-info}/entry_points.txt +0 -0
@@ -6,20 +6,277 @@
|
|
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 import QtCore
|
13
|
-
from PySide6.QtCore import Qt
|
14
|
-
from PySide6.
|
13
|
+
from PySide6.QtCore import Qt, QObject, Signal, Slot
|
14
|
+
from PySide6.QtGui import QTextCursor
|
15
|
+
from PySide6.QtWidgets import QTextEdit, QApplication, QVBoxLayout, QLabel, QCheckBox, QPushButton, QWidget, QSplitter, \
|
16
|
+
QHBoxLayout
|
15
17
|
|
16
18
|
from pygpt_net.ui.widget.textarea.editor import BaseCodeEditor
|
17
19
|
|
20
|
+
from pygpt_net.utils import trans
|
18
21
|
import pygpt_net.icons_rc
|
19
22
|
|
20
23
|
|
24
|
+
class ToolWidget:
|
25
|
+
def __init__(self, window=None, tool=None):
|
26
|
+
"""
|
27
|
+
Python Code Interpreter
|
28
|
+
|
29
|
+
:param window: Window instance
|
30
|
+
:param tool: Tool instance
|
31
|
+
"""
|
32
|
+
self.window = window # window instance
|
33
|
+
self.tool = tool # tool instance
|
34
|
+
self.history = None # history
|
35
|
+
self.input = None # input
|
36
|
+
self.output = None # output
|
37
|
+
self.checkbox_all = None # all checkbox
|
38
|
+
self.checkbox_auto_clear = None # auto clear checkbox
|
39
|
+
self.checkbox_ipython = None # IPython checkbox
|
40
|
+
self.btn_send = None # send button
|
41
|
+
self.btn_clear = None # clear button
|
42
|
+
self.label_output = None # output label
|
43
|
+
self.label_history = None # history label
|
44
|
+
|
45
|
+
def setup(self, all: bool = True) -> QVBoxLayout:
|
46
|
+
"""
|
47
|
+
Setup widget body
|
48
|
+
|
49
|
+
:param all: with all widgets
|
50
|
+
:return: QVBoxLayout
|
51
|
+
"""
|
52
|
+
self.output = PythonOutput(self.window, self.tool)
|
53
|
+
self.output.setReadOnly(True)
|
54
|
+
|
55
|
+
if all:
|
56
|
+
self.history = PythonOutput(self.window, self.tool)
|
57
|
+
self.history.textChanged.connect(
|
58
|
+
lambda: self.tool.store_history(self)
|
59
|
+
)
|
60
|
+
self.history.setReadOnly(False)
|
61
|
+
self.history.excluded_copy_to = ["interpreter_edit"]
|
62
|
+
|
63
|
+
self.label_output = QLabel(trans("interpreter.edit_label.output"))
|
64
|
+
self.label_history = QLabel(trans("interpreter.edit_label.edit"))
|
65
|
+
|
66
|
+
if all:
|
67
|
+
self.checkbox_all = QCheckBox(trans("interpreter.all"))
|
68
|
+
self.checkbox_all.setChecked(True)
|
69
|
+
self.checkbox_all.clicked.connect(
|
70
|
+
lambda: self.tool.toggle_all(self)
|
71
|
+
)
|
72
|
+
|
73
|
+
self.checkbox_auto_clear = QCheckBox(trans("interpreter.auto_clear"))
|
74
|
+
self.checkbox_auto_clear.setChecked(False)
|
75
|
+
self.checkbox_auto_clear.clicked.connect(
|
76
|
+
lambda: self.tool.toggle_auto_clear(self)
|
77
|
+
)
|
78
|
+
|
79
|
+
self.checkbox_ipython = QCheckBox("IPython")
|
80
|
+
self.checkbox_ipython.setChecked(True)
|
81
|
+
self.checkbox_ipython.clicked.connect(
|
82
|
+
lambda: self.tool.toggle_ipython(self)
|
83
|
+
)
|
84
|
+
|
85
|
+
self.btn_clear = QPushButton(trans("interpreter.btn.clear"))
|
86
|
+
self.btn_clear.clicked.connect(
|
87
|
+
lambda: self.tool.clear(self)
|
88
|
+
)
|
89
|
+
|
90
|
+
self.btn_send = QPushButton(trans("interpreter.btn.send"))
|
91
|
+
self.btn_send.clicked.connect(
|
92
|
+
lambda: self.tool.send_input(self)
|
93
|
+
)
|
94
|
+
|
95
|
+
self.input = PythonInput(self.window, self.tool, self)
|
96
|
+
self.input.setPlaceholderText(trans("interpreter.input.placeholder"))
|
97
|
+
self.input.excluded_copy_to = ["interpreter_input"]
|
98
|
+
|
99
|
+
left_layout = QVBoxLayout()
|
100
|
+
left_layout.addWidget(self.label_output)
|
101
|
+
left_layout.addWidget(self.output)
|
102
|
+
left_layout.setContentsMargins(0, 0, 0, 0)
|
103
|
+
left_widget = QWidget()
|
104
|
+
left_widget.setLayout(left_layout)
|
105
|
+
|
106
|
+
self.window.ui.splitters['interpreter.columns'] = QSplitter(Qt.Horizontal)
|
107
|
+
self.window.ui.splitters['interpreter.columns'].addWidget(left_widget)
|
108
|
+
|
109
|
+
if all:
|
110
|
+
right_layout = QVBoxLayout()
|
111
|
+
right_layout.addWidget(self.label_history)
|
112
|
+
right_layout.addWidget(self.history)
|
113
|
+
right_layout.setContentsMargins(0, 0, 0, 0)
|
114
|
+
right_widget = QWidget()
|
115
|
+
right_widget.setLayout(right_layout)
|
116
|
+
right_widget.setMinimumWidth(300)
|
117
|
+
self.window.ui.splitters['interpreter.columns'].addWidget(right_widget)
|
118
|
+
|
119
|
+
bottom_layout = QHBoxLayout()
|
120
|
+
bottom_layout.addWidget(self.btn_clear)
|
121
|
+
bottom_layout.addWidget(self.checkbox_ipython)
|
122
|
+
bottom_layout.addWidget(self.checkbox_auto_clear)
|
123
|
+
bottom_layout.addStretch()
|
124
|
+
if all:
|
125
|
+
bottom_layout.addWidget(self.checkbox_all)
|
126
|
+
bottom_layout.addWidget(self.btn_send)
|
127
|
+
|
128
|
+
edit_layout = QVBoxLayout()
|
129
|
+
edit_layout.addWidget(self.window.ui.splitters['interpreter.columns'])
|
130
|
+
edit_layout.setContentsMargins(0, 0, 0, 0)
|
131
|
+
edit_widget = QWidget()
|
132
|
+
edit_widget.setLayout(edit_layout)
|
133
|
+
|
134
|
+
self.window.ui.splitters['interpreter'] = QSplitter(Qt.Vertical)
|
135
|
+
self.window.ui.splitters['interpreter'].addWidget(edit_widget)
|
136
|
+
self.window.ui.splitters['interpreter'].addWidget(self.input)
|
137
|
+
self.window.ui.splitters['interpreter'].setStretchFactor(0, 4)
|
138
|
+
self.window.ui.splitters['interpreter'].setStretchFactor(1, 1)
|
139
|
+
|
140
|
+
# connect signals
|
141
|
+
self.tool.signals.update.connect(self.set_output)
|
142
|
+
self.tool.signals.update_history.connect(self.set_history)
|
143
|
+
self.tool.signals.clear_history.connect(self.clear_history)
|
144
|
+
self.tool.signals.clear_output.connect(self.clear_output)
|
145
|
+
self.tool.signals.focus_input.connect(self.set_focus)
|
146
|
+
self.tool.signals.append_input.connect(self.append_to_input)
|
147
|
+
self.tool.signals.update_input.connect(self.set_input)
|
148
|
+
self.tool.signals.set_checkbox_all.connect(self.set_checkbox_all)
|
149
|
+
self.tool.signals.set_checkbox_auto_clear.connect(self.set_checkbox_auto_clear)
|
150
|
+
self.tool.signals.set_checkbox_ipython.connect(self.set_checkbox_ipython)
|
151
|
+
self.tool.signals.toggle_all_visible.connect(self.toggle_all_visible)
|
152
|
+
|
153
|
+
layout = QVBoxLayout()
|
154
|
+
layout.addWidget(self.window.ui.splitters['interpreter'])
|
155
|
+
layout.addLayout(bottom_layout)
|
156
|
+
return layout
|
157
|
+
|
158
|
+
@Slot(str, str)
|
159
|
+
def set_output(self, output: str, type="stdout"):
|
160
|
+
"""
|
161
|
+
Set output content
|
162
|
+
|
163
|
+
:param output: Content
|
164
|
+
:param type: Output type
|
165
|
+
"""
|
166
|
+
area = self.output
|
167
|
+
if type == "stdin":
|
168
|
+
data = ">> " + str(output)
|
169
|
+
else:
|
170
|
+
data = str(output)
|
171
|
+
cur = area.textCursor()
|
172
|
+
cur.movePosition(QTextCursor.End)
|
173
|
+
s = data + "\n"
|
174
|
+
while s:
|
175
|
+
head, sep, s = s.partition("\n")
|
176
|
+
cur.insertText(head)
|
177
|
+
if sep: # New line if LF
|
178
|
+
cur.insertText("\n")
|
179
|
+
area.setTextCursor(cur)
|
180
|
+
|
181
|
+
@Slot()
|
182
|
+
def set_history(self, data: str):
|
183
|
+
"""
|
184
|
+
Set history
|
185
|
+
|
186
|
+
:param data: history data
|
187
|
+
"""
|
188
|
+
if not self.history:
|
189
|
+
return
|
190
|
+
self.history.setPlainText(data)
|
191
|
+
cur = self.history.textCursor()
|
192
|
+
cur.movePosition(QTextCursor.End)
|
193
|
+
self.history.setTextCursor(cur)
|
194
|
+
|
195
|
+
@Slot()
|
196
|
+
def append_to_input(self, data: str):
|
197
|
+
"""
|
198
|
+
Append data to input
|
199
|
+
|
200
|
+
:param data: Data
|
201
|
+
"""
|
202
|
+
current = self.input.toPlainText()
|
203
|
+
if current:
|
204
|
+
current += "\n"
|
205
|
+
current += data
|
206
|
+
self.input.setPlainText(current)
|
207
|
+
|
208
|
+
@Slot(str)
|
209
|
+
def set_input(self, data: str):
|
210
|
+
"""
|
211
|
+
Set input
|
212
|
+
|
213
|
+
:param data: Data
|
214
|
+
"""
|
215
|
+
self.input.setPlainText(data)
|
216
|
+
|
217
|
+
@Slot()
|
218
|
+
def clear_history(self):
|
219
|
+
"""Clear input"""
|
220
|
+
if not self.history:
|
221
|
+
return
|
222
|
+
self.history.clear()
|
223
|
+
|
224
|
+
@Slot()
|
225
|
+
def clear_output(self):
|
226
|
+
"""Clear output"""
|
227
|
+
self.output.clear()
|
228
|
+
|
229
|
+
@Slot()
|
230
|
+
def set_focus(self):
|
231
|
+
"""Set focus to input"""
|
232
|
+
self.input.setFocus()
|
233
|
+
|
234
|
+
@Slot(bool)
|
235
|
+
def set_checkbox_all(self, value: bool):
|
236
|
+
"""
|
237
|
+
Set checkbox all
|
238
|
+
|
239
|
+
:param value: Value
|
240
|
+
"""
|
241
|
+
if not self.checkbox_all:
|
242
|
+
return
|
243
|
+
self.checkbox_all.setChecked(value)
|
244
|
+
|
245
|
+
@Slot(bool)
|
246
|
+
def set_checkbox_auto_clear(self, value: bool):
|
247
|
+
"""
|
248
|
+
Set checkbox auto clear
|
249
|
+
|
250
|
+
:param value: Value
|
251
|
+
"""
|
252
|
+
self.checkbox_auto_clear.setChecked(value)
|
253
|
+
|
254
|
+
@Slot(bool)
|
255
|
+
def set_checkbox_ipython(self, value: bool):
|
256
|
+
"""
|
257
|
+
Set checkbox IPython
|
258
|
+
|
259
|
+
:param value: Value
|
260
|
+
"""
|
261
|
+
self.checkbox_ipython.setChecked(value)
|
262
|
+
|
263
|
+
@Slot(bool)
|
264
|
+
def toggle_all_visible(self, value: bool):
|
265
|
+
"""
|
266
|
+
Toggle all visible
|
267
|
+
|
268
|
+
:param value: Value
|
269
|
+
"""
|
270
|
+
if not self.checkbox_all:
|
271
|
+
return
|
272
|
+
if value:
|
273
|
+
self.checkbox_all.setVisible(True)
|
274
|
+
else:
|
275
|
+
self.checkbox_all.setVisible(False)
|
276
|
+
|
277
|
+
|
21
278
|
class PythonInput(QTextEdit):
|
22
|
-
def __init__(self, window=None):
|
279
|
+
def __init__(self, window=None, tool=None, widget=None):
|
23
280
|
"""
|
24
281
|
Python interpreter input
|
25
282
|
|
@@ -27,6 +284,8 @@ class PythonInput(QTextEdit):
|
|
27
284
|
"""
|
28
285
|
super(PythonInput, self).__init__(window)
|
29
286
|
self.window = window
|
287
|
+
self.tool = tool
|
288
|
+
self.widget = widget
|
30
289
|
self.setAcceptRichText(False)
|
31
290
|
self.value = 12
|
32
291
|
self.max_font_size = 42
|
@@ -35,7 +294,7 @@ class PythonInput(QTextEdit):
|
|
35
294
|
self.default_stylesheet = ""
|
36
295
|
self.setStyleSheet(self.default_stylesheet)
|
37
296
|
self.textChanged.connect(
|
38
|
-
lambda: self.
|
297
|
+
lambda: self.tool.update_input()
|
39
298
|
)
|
40
299
|
self.setFocus()
|
41
300
|
|
@@ -60,11 +319,11 @@ class PythonInput(QTextEdit):
|
|
60
319
|
if mode == 2: # Shift + Enter
|
61
320
|
modifiers = QApplication.keyboardModifiers()
|
62
321
|
if modifiers == QtCore.Qt.ShiftModifier:
|
63
|
-
self.
|
322
|
+
self.tool.send_input(self.widget)
|
64
323
|
else: # Enter
|
65
324
|
modifiers = QApplication.keyboardModifiers()
|
66
325
|
if modifiers != QtCore.Qt.ShiftModifier:
|
67
|
-
self.
|
326
|
+
self.tool.send_input(self.widget)
|
68
327
|
self.setFocus()
|
69
328
|
|
70
329
|
def wheelEvent(self, event):
|
@@ -89,7 +348,7 @@ class PythonInput(QTextEdit):
|
|
89
348
|
|
90
349
|
|
91
350
|
class PythonOutput(BaseCodeEditor):
|
92
|
-
def __init__(self, window=None):
|
351
|
+
def __init__(self, window=None, tool=None):
|
93
352
|
"""
|
94
353
|
Python interpreter output
|
95
354
|
|
@@ -97,6 +356,7 @@ class PythonOutput(BaseCodeEditor):
|
|
97
356
|
"""
|
98
357
|
super(PythonOutput, self).__init__(window)
|
99
358
|
self.window = window
|
359
|
+
self.tool = tool
|
100
360
|
self.setReadOnly(True)
|
101
361
|
self.value = 12
|
102
362
|
self.max_font_size = 42
|
@@ -108,4 +368,19 @@ class PythonOutput(BaseCodeEditor):
|
|
108
368
|
def clear_content(self):
|
109
369
|
"""Clear content"""
|
110
370
|
super(PythonOutput, self).clear_content()
|
111
|
-
self.
|
371
|
+
self.tool.save_output()
|
372
|
+
|
373
|
+
|
374
|
+
class ToolSignals(QObject):
|
375
|
+
update = Signal(str, str) # content, type
|
376
|
+
update_history = Signal(str) # content
|
377
|
+
update_input = Signal(str) # content
|
378
|
+
append_input = Signal(str) # content
|
379
|
+
reload = Signal(str) # path
|
380
|
+
clear_history = Signal()
|
381
|
+
clear_output = Signal()
|
382
|
+
focus_input = Signal()
|
383
|
+
set_checkbox_all = Signal(bool)
|
384
|
+
set_checkbox_auto_clear = Signal(bool)
|
385
|
+
set_checkbox_ipython = Signal(bool)
|
386
|
+
toggle_all_visible = Signal(bool)
|
@@ -6,36 +6,45 @@
|
|
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
|
import os
|
13
13
|
|
14
|
-
from PySide6.QtCore import QTimer, Slot
|
14
|
+
from PySide6.QtCore import QTimer, Slot
|
15
15
|
from PySide6.QtGui import QAction, QIcon
|
16
|
-
from PySide6.QtWidgets import QFileDialog
|
16
|
+
from PySide6.QtWidgets import QFileDialog, QWidget
|
17
17
|
|
18
|
+
from pygpt_net.core.tabs.tab import Tab
|
18
19
|
from pygpt_net.core.text.utils import output_clean_html, output_html2text
|
19
20
|
from pygpt_net.tools.base import BaseTool
|
20
|
-
from pygpt_net.tools.html_canvas.ui.dialogs import Canvas
|
21
21
|
from pygpt_net.utils import trans
|
22
22
|
|
23
|
+
from .ui.dialogs import Tool
|
24
|
+
from .ui.widgets import ToolWidget, ToolSignals
|
25
|
+
|
23
26
|
|
24
27
|
class HtmlCanvas(BaseTool):
|
25
28
|
def __init__(self, *args, **kwargs):
|
26
29
|
"""
|
27
|
-
HTML/JS
|
30
|
+
HTML/JS Canvas
|
28
31
|
|
29
32
|
:param window: Window instance
|
30
33
|
"""
|
31
34
|
super(HtmlCanvas, self).__init__(*args, **kwargs)
|
32
35
|
self.id = "html_canvas"
|
36
|
+
self.dialog_id = "html_canvas"
|
37
|
+
self.has_tab = True
|
38
|
+
self.tab_title = "menu.tools.html_canvas"
|
39
|
+
self.tab_icon = ":/icons/code.svg"
|
33
40
|
self.opened = False
|
34
41
|
self.is_edit = False
|
35
42
|
self.auto_clear = True
|
36
43
|
self.dialog = None
|
37
44
|
self.is_edit = False
|
45
|
+
self.auto_opened = False
|
38
46
|
self.file_output = ".canvas.html"
|
47
|
+
self.signals = ToolSignals()
|
39
48
|
|
40
49
|
def setup(self):
|
41
50
|
"""Setup"""
|
@@ -50,16 +59,19 @@ class HtmlCanvas(BaseTool):
|
|
50
59
|
"""Update menu"""
|
51
60
|
self.update_menu()
|
52
61
|
|
53
|
-
def toggle_edit(self):
|
54
|
-
"""
|
62
|
+
def toggle_edit(self, widget: ToolWidget):
|
63
|
+
"""
|
64
|
+
Toggle edit mode
|
65
|
+
|
66
|
+
:param widget: Canvas widget
|
67
|
+
"""
|
55
68
|
current = self.is_edit
|
56
69
|
self.is_edit = not self.is_edit
|
57
|
-
|
58
|
-
|
70
|
+
widget.edit.setVisible(self.is_edit)
|
71
|
+
widget.output.setVisible(not self.is_edit)
|
59
72
|
if current:
|
60
|
-
self.set_output(
|
73
|
+
self.set_output(widget.edit.toPlainText())
|
61
74
|
self.save_output()
|
62
|
-
self.window.ui.nodes['html_canvas.btn.edit'].setChecked(self.is_edit)
|
63
75
|
|
64
76
|
def update_menu(self):
|
65
77
|
"""Update menu"""
|
@@ -78,18 +90,26 @@ class HtmlCanvas(BaseTool):
|
|
78
90
|
"""
|
79
91
|
return os.path.join(self.window.core.config.get_user_dir("data"), self.file_output)
|
80
92
|
|
93
|
+
def get_dialog_id(self) -> str:
|
94
|
+
"""
|
95
|
+
Get dialog ID
|
96
|
+
|
97
|
+
:return: Dialog ID
|
98
|
+
"""
|
99
|
+
return self.dialog_id
|
100
|
+
|
81
101
|
def set_output(self, output: str):
|
82
102
|
"""
|
83
103
|
Set output HTML
|
84
104
|
|
85
105
|
:param output: Output HTML code
|
86
106
|
"""
|
87
|
-
path =
|
107
|
+
path = self.get_current_path()
|
88
108
|
with open(path, "w", encoding="utf-8") as f:
|
89
109
|
f.write(output)
|
90
110
|
if os.path.exists(path):
|
91
|
-
self.
|
92
|
-
self.
|
111
|
+
self.signals.reload.emit(path)
|
112
|
+
self.signals.update.emit(output)
|
93
113
|
|
94
114
|
def reload_output(self):
|
95
115
|
"""Reload output data"""
|
@@ -102,11 +122,16 @@ class HtmlCanvas(BaseTool):
|
|
102
122
|
|
103
123
|
:return: Output data
|
104
124
|
"""
|
105
|
-
|
125
|
+
path = self.get_current_path()
|
126
|
+
data = ""
|
127
|
+
if os.path.exists(path):
|
128
|
+
with open(path, "r", encoding="utf-8") as f:
|
129
|
+
data = f.read()
|
130
|
+
return data
|
106
131
|
|
107
132
|
def load_output(self):
|
108
133
|
"""Load output data from file"""
|
109
|
-
path =
|
134
|
+
path = self.get_current_path()
|
110
135
|
data = ""
|
111
136
|
if os.path.exists(path):
|
112
137
|
with open(path, "r", encoding="utf-8") as f:
|
@@ -115,14 +140,14 @@ class HtmlCanvas(BaseTool):
|
|
115
140
|
|
116
141
|
def save_output(self):
|
117
142
|
"""Save output data to file"""
|
118
|
-
path =
|
143
|
+
path = self.get_current_path()
|
119
144
|
data = self.get_output()
|
120
145
|
with open(path, "w", encoding="utf-8") as f:
|
121
146
|
f.write(data)
|
122
147
|
|
123
148
|
def clear_output(self):
|
124
149
|
"""Clear output"""
|
125
|
-
path =
|
150
|
+
path = self.get_current_path()
|
126
151
|
if os.path.exists(path):
|
127
152
|
os.remove(path)
|
128
153
|
self.set_output("")
|
@@ -151,9 +176,17 @@ class HtmlCanvas(BaseTool):
|
|
151
176
|
if not self.opened:
|
152
177
|
self.opened = True
|
153
178
|
self.load_output()
|
154
|
-
self.window.ui.dialogs.open(
|
179
|
+
self.window.ui.dialogs.open(self.dialog_id, width=800, height=600)
|
155
180
|
self.update()
|
156
181
|
|
182
|
+
def auto_open(self):
|
183
|
+
"""Auto open canvas dialog"""
|
184
|
+
if self.window.controller.ui.tabs.is_current_tool(self.id):
|
185
|
+
return # do not open if already opened in tab
|
186
|
+
if not self.auto_opened:
|
187
|
+
self.auto_opened = True
|
188
|
+
self.open()
|
189
|
+
|
157
190
|
def open_file(self):
|
158
191
|
"""Open file dialog"""
|
159
192
|
last_dir = self.window.core.config.get_last_used_dir()
|
@@ -172,7 +205,7 @@ class HtmlCanvas(BaseTool):
|
|
172
205
|
def close(self):
|
173
206
|
"""Close HTML canvas dialog"""
|
174
207
|
self.opened = False
|
175
|
-
self.window.ui.dialogs.close(
|
208
|
+
self.window.ui.dialogs.close(self.dialog_id)
|
176
209
|
self.update()
|
177
210
|
|
178
211
|
def toggle(self):
|
@@ -193,13 +226,21 @@ class HtmlCanvas(BaseTool):
|
|
193
226
|
else:
|
194
227
|
self.close()
|
195
228
|
|
229
|
+
def get_toolbar_icon(self) -> QWidget:
|
230
|
+
"""
|
231
|
+
Get toolbar icon
|
232
|
+
|
233
|
+
:return: QWidget
|
234
|
+
"""
|
235
|
+
return self.window.ui.nodes['icon.html_canvas']
|
236
|
+
|
196
237
|
def toggle_icon(self, state: bool):
|
197
238
|
"""
|
198
239
|
Toggle canvas icon
|
199
240
|
|
200
241
|
:param state: State
|
201
242
|
"""
|
202
|
-
self.
|
243
|
+
self.get_toolbar_icon().setVisible(state)
|
203
244
|
|
204
245
|
def get_current_output(self) -> str:
|
205
246
|
"""
|
@@ -207,7 +248,7 @@ class HtmlCanvas(BaseTool):
|
|
207
248
|
|
208
249
|
:return: Output data
|
209
250
|
"""
|
210
|
-
return self.
|
251
|
+
return self.get_output()
|
211
252
|
|
212
253
|
@Slot(str, str)
|
213
254
|
def handle_save_as(self, text: str, type: str = 'txt'):
|
@@ -242,9 +283,23 @@ class HtmlCanvas(BaseTool):
|
|
242
283
|
)
|
243
284
|
return actions
|
244
285
|
|
286
|
+
def as_tab(self, tab: Tab) -> QWidget:
|
287
|
+
"""
|
288
|
+
Spawn and return tab instance
|
289
|
+
|
290
|
+
:param tab: Parent Tab instance
|
291
|
+
:return: Tab widget instance
|
292
|
+
"""
|
293
|
+
canvas = Tool(window=self.window, tool=self)
|
294
|
+
layout = canvas.widget.setup()
|
295
|
+
widget = QWidget()
|
296
|
+
widget.setLayout(layout)
|
297
|
+
self.load_output()
|
298
|
+
return widget
|
299
|
+
|
245
300
|
def setup_dialogs(self):
|
246
301
|
"""Setup dialogs (static)"""
|
247
|
-
self.dialog =
|
302
|
+
self.dialog = Tool(window=self.window, tool=self)
|
248
303
|
self.dialog.setup()
|
249
304
|
|
250
305
|
def setup_theme(self):
|