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,10 +6,10 @@
|
|
6
6
|
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
7
7
|
# MIT License #
|
8
8
|
# Created By : Marcin Szczygliński #
|
9
|
-
# Updated Date: 2024.
|
9
|
+
# Updated Date: 2024.12.14 07:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
|
-
from PySide6.QtWidgets import QTabWidget, QMenu
|
12
|
+
from PySide6.QtWidgets import QTabWidget, QMenu, QPushButton
|
13
13
|
from PySide6.QtCore import Qt, Slot
|
14
14
|
from PySide6.QtGui import QAction, QIcon
|
15
15
|
|
@@ -18,17 +18,128 @@ from pygpt_net.utils import trans
|
|
18
18
|
import pygpt_net.icons_rc
|
19
19
|
|
20
20
|
|
21
|
+
class AddButton(QPushButton):
|
22
|
+
def __init__(self, window=None, column=None, tabs=None):
|
23
|
+
super(AddButton, self).__init__(QIcon(":/icons/add.svg"), "", window)
|
24
|
+
self.window = window
|
25
|
+
self.column = column
|
26
|
+
self.tabs = tabs
|
27
|
+
self.setFixedSize(30, 25)
|
28
|
+
self.setFlat(True)
|
29
|
+
self.clicked.connect(
|
30
|
+
lambda: self.window.controller.ui.tabs.new_tab(self.column.get_idx())
|
31
|
+
)
|
32
|
+
self.setObjectName('tab-add')
|
33
|
+
self.setProperty('tabAdd', True)
|
34
|
+
self.setToolTip(trans('action.tab.add.chat'))
|
35
|
+
|
36
|
+
def mousePressEvent(self, event):
|
37
|
+
"""
|
38
|
+
Mouse press event
|
39
|
+
|
40
|
+
:param event: event
|
41
|
+
"""
|
42
|
+
if event.button() == Qt.RightButton:
|
43
|
+
idx = 0
|
44
|
+
column_idx = self.column.get_idx()
|
45
|
+
self.show_menu(idx, column_idx, event.globalPos())
|
46
|
+
super(AddButton, self).mousePressEvent(event)
|
47
|
+
|
48
|
+
def show_menu(self, index: int, column_idx: int, global_pos):
|
49
|
+
"""
|
50
|
+
Show context menu
|
51
|
+
|
52
|
+
:param index: index
|
53
|
+
:param column_idx: column index
|
54
|
+
:param global_pos: global position
|
55
|
+
"""
|
56
|
+
context_menu = self.prepare_menu(index, column_idx)
|
57
|
+
context_menu.exec(global_pos)
|
58
|
+
|
59
|
+
def prepare_menu(self, index: int, column_idx: int) -> QMenu:
|
60
|
+
"""
|
61
|
+
Prepare and return context menu
|
62
|
+
|
63
|
+
:param index: index
|
64
|
+
:param column_idx: column index
|
65
|
+
:return: menu
|
66
|
+
"""
|
67
|
+
menu = QMenu(self)
|
68
|
+
|
69
|
+
actions = {}
|
70
|
+
actions['add_chat'] = QAction(QIcon(":/icons/add.svg"), trans('action.tab.add.chat'), self)
|
71
|
+
actions['add_chat'].triggered.connect(
|
72
|
+
lambda: self.tabs.add_tab(index, column_idx, Tab.TAB_CHAT)
|
73
|
+
)
|
74
|
+
actions['add_notepad'] = QAction(QIcon(":/icons/add.svg"), trans('action.tab.add.notepad'), self)
|
75
|
+
actions['add_notepad'].triggered.connect(
|
76
|
+
lambda: self.tabs.add_tab(index, column_idx, Tab.TAB_NOTEPAD)
|
77
|
+
)
|
78
|
+
|
79
|
+
# add chat, add notepad
|
80
|
+
menu.addAction(actions['add_chat'])
|
81
|
+
menu.addAction(actions['add_notepad'])
|
82
|
+
|
83
|
+
# add tools submenu
|
84
|
+
self.window.controller.tools.append_tab_menu(self, menu, index, column_idx)
|
85
|
+
|
86
|
+
return menu
|
87
|
+
|
21
88
|
class OutputTabs(QTabWidget):
|
22
|
-
def __init__(self, window=None):
|
89
|
+
def __init__(self, window=None, column=None):
|
23
90
|
super(OutputTabs, self).__init__(window)
|
24
91
|
self.window = window
|
92
|
+
self.active = True
|
93
|
+
self.column = column
|
25
94
|
self.setMinimumHeight(1)
|
26
95
|
self.owner = None
|
27
96
|
self.setMovable(True)
|
97
|
+
self.init()
|
98
|
+
|
99
|
+
def set_active(self, active: bool):
|
100
|
+
"""Set the active state of the tab bar."""
|
101
|
+
self.active = active
|
102
|
+
if self.active:
|
103
|
+
self.setStyleSheet("QTabBar::tab { border-bottom-width: 2px; }")
|
104
|
+
else:
|
105
|
+
self.setStyleSheet("QTabBar::tab { border-bottom-width: 0px; }")
|
106
|
+
|
107
|
+
def init(self):
|
108
|
+
"""Initialize"""
|
109
|
+
# create the [+] button
|
110
|
+
add_button = AddButton(self.window, self.column, self)
|
111
|
+
|
112
|
+
# add the button to the top right corner of the tab bar
|
113
|
+
self.setCornerWidget(add_button, corner=Qt.TopRightCorner)
|
114
|
+
|
115
|
+
# connect signals
|
116
|
+
self.currentChanged.connect(
|
117
|
+
lambda: self.window.controller.ui.tabs.on_tab_changed(self.currentIndex(), self.column.get_idx())
|
118
|
+
)
|
119
|
+
self.tabBarClicked.connect(
|
120
|
+
lambda: self.window.controller.ui.tabs.on_tab_clicked(self.currentIndex(), self.column.get_idx())
|
121
|
+
)
|
122
|
+
self.tabBarDoubleClicked.connect(
|
123
|
+
lambda: self.window.controller.ui.tabs.on_tab_dbl_clicked(self.currentIndex(), self.column.get_idx())
|
124
|
+
)
|
125
|
+
self.tabCloseRequested.connect(
|
126
|
+
lambda: self.window.controller.ui.tabs.on_tab_closed(self.currentIndex(), self.column.get_idx())
|
127
|
+
)
|
128
|
+
self.tabBar().tabMoved.connect(
|
129
|
+
lambda: self.window.controller.ui.tabs.on_tab_moved(self.currentIndex(), self.column.get_idx())
|
130
|
+
)
|
131
|
+
|
132
|
+
def get_column(self):
|
133
|
+
"""
|
134
|
+
Get column
|
135
|
+
|
136
|
+
:return: OutputColumn
|
137
|
+
"""
|
138
|
+
return self.column
|
28
139
|
|
29
140
|
def setOwner(self, owner: Tab):
|
30
141
|
"""
|
31
|
-
Set
|
142
|
+
Set internal tab instance
|
32
143
|
|
33
144
|
:param owner: parent tab instance
|
34
145
|
"""
|
@@ -42,158 +153,210 @@ class OutputTabs(QTabWidget):
|
|
42
153
|
"""
|
43
154
|
if event.button() == Qt.RightButton:
|
44
155
|
idx = self.tabBar().tabAt(event.pos())
|
45
|
-
|
156
|
+
column_idx = self.column.get_idx()
|
157
|
+
tab = self.window.core.tabs.get_tab_by_index(idx, column_idx)
|
46
158
|
if tab is not None:
|
47
159
|
if tab.type == Tab.TAB_NOTEPAD:
|
48
|
-
self.show_notepad_menu(idx, event.globalPos()) # notepad
|
160
|
+
self.show_notepad_menu(idx, column_idx, event.globalPos()) # notepad
|
49
161
|
elif tab.type == Tab.TAB_CHAT:
|
50
|
-
self.show_chat_menu(idx, event.globalPos()) # chat
|
162
|
+
self.show_chat_menu(idx, column_idx, event.globalPos()) # chat
|
51
163
|
elif tab.type == Tab.TAB_FILES:
|
52
|
-
self.show_files_menu(idx, event.globalPos()) # files
|
164
|
+
self.show_files_menu(idx, column_idx, event.globalPos()) # files
|
165
|
+
elif tab.type == Tab.TAB_TOOL:
|
166
|
+
self.show_tool_menu(idx, column_idx, event.globalPos()) # tool
|
53
167
|
else:
|
54
|
-
self.show_default_menu(idx, event.globalPos()) # default
|
168
|
+
self.show_default_menu(idx, column_idx, event.globalPos()) # default
|
55
169
|
super(OutputTabs, self).mousePressEvent(event)
|
56
170
|
|
57
|
-
def
|
171
|
+
def prepare_menu(self, index: int, column_idx: int) -> QMenu:
|
58
172
|
"""
|
59
|
-
|
173
|
+
Prepare and return context menu
|
60
174
|
|
61
175
|
:param index: index
|
62
|
-
:
|
176
|
+
:param column_idx: column index
|
177
|
+
:return: menu
|
63
178
|
"""
|
179
|
+
menu = QMenu(self)
|
180
|
+
|
64
181
|
actions = {}
|
65
182
|
actions['add_chat'] = QAction(QIcon(":/icons/add.svg"), trans('action.tab.add.chat'), self)
|
66
183
|
actions['add_chat'].triggered.connect(
|
67
|
-
lambda: self.add_tab(index, Tab.TAB_CHAT)
|
184
|
+
lambda: self.add_tab(index, column_idx, Tab.TAB_CHAT)
|
68
185
|
)
|
69
186
|
actions['add_notepad'] = QAction(QIcon(":/icons/add.svg"), trans('action.tab.add.notepad'), self)
|
70
187
|
actions['add_notepad'].triggered.connect(
|
71
|
-
lambda: self.add_tab(index, Tab.TAB_NOTEPAD)
|
188
|
+
lambda: self.add_tab(index, column_idx, Tab.TAB_NOTEPAD)
|
72
189
|
)
|
73
190
|
actions['edit'] = QAction(QIcon(":/icons/edit.svg"), trans('action.rename'), self)
|
74
191
|
actions['edit'].triggered.connect(
|
75
|
-
lambda: self.rename_tab(index)
|
192
|
+
lambda: self.rename_tab(index, column_idx)
|
193
|
+
)
|
194
|
+
actions['move_right'] = QAction(QIcon(":/icons/forward"), trans('action.tab.move.right'), self)
|
195
|
+
actions['move_right'].triggered.connect(
|
196
|
+
lambda: self.window.controller.ui.tabs.move_tab(index, column_idx, 1)
|
76
197
|
)
|
77
|
-
|
198
|
+
actions['move_left'] = QAction(QIcon(":/icons/back"), trans('action.tab.move.left'), self)
|
199
|
+
actions['move_left'].triggered.connect(
|
200
|
+
lambda: self.window.controller.ui.tabs.move_tab(index, column_idx, 0)
|
201
|
+
)
|
202
|
+
|
203
|
+
# add chat, add notepad
|
204
|
+
menu.addAction(actions['add_chat'])
|
205
|
+
menu.addAction(actions['add_notepad'])
|
206
|
+
|
207
|
+
# add tools submenu
|
208
|
+
self.window.controller.tools.append_tab_menu(self, menu, index, column_idx)
|
209
|
+
|
210
|
+
# rename tab
|
211
|
+
menu.addAction(actions['edit'])
|
212
|
+
|
213
|
+
# move tab left, move tab right
|
214
|
+
if column_idx != 0:
|
215
|
+
menu.addAction(actions['move_left'])
|
216
|
+
if column_idx != 1:
|
217
|
+
menu.addAction(actions['move_right'])
|
78
218
|
|
79
|
-
|
219
|
+
return menu
|
220
|
+
|
221
|
+
def show_notepad_menu(self, index: int, column_idx: int, global_pos):
|
80
222
|
"""
|
81
223
|
Show notepad menu
|
82
224
|
|
83
225
|
:param index: index
|
226
|
+
:param column_idx: column index
|
84
227
|
:param global_pos: global position
|
85
228
|
"""
|
86
|
-
context_menu =
|
87
|
-
actions =
|
229
|
+
context_menu = self.prepare_menu(index, column_idx)
|
230
|
+
actions = {}
|
88
231
|
actions['close'] = QAction(QIcon(":/icons/close.svg"), trans('action.tab.close'), self)
|
89
232
|
actions['close'].triggered.connect(
|
90
|
-
lambda: self.close_tab(index)
|
233
|
+
lambda: self.close_tab(index, column_idx)
|
91
234
|
)
|
92
235
|
actions['close_all'] = QAction(QIcon(":/icons/close.svg"), trans('action.tab.close_all.notepad'), self)
|
93
236
|
actions['close_all'].triggered.connect(
|
94
|
-
lambda: self.close_all(Tab.TAB_NOTEPAD)
|
237
|
+
lambda: self.close_all(Tab.TAB_NOTEPAD, column_idx)
|
95
238
|
)
|
96
|
-
context_menu.addAction(actions['add_chat'])
|
97
|
-
context_menu.addAction(actions['add_notepad'])
|
98
|
-
context_menu.addAction(actions['edit'])
|
99
239
|
context_menu.addAction(actions['close'])
|
100
240
|
|
101
241
|
if self.window.core.tabs.count_by_type(Tab.TAB_NOTEPAD) > 1:
|
102
242
|
context_menu.addAction(actions['close_all'])
|
243
|
+
|
103
244
|
context_menu.exec(global_pos)
|
104
245
|
|
105
|
-
def show_chat_menu(self, index, global_pos):
|
246
|
+
def show_chat_menu(self, index: int, column_idx: int, global_pos):
|
106
247
|
"""
|
107
248
|
Show chat menu
|
108
249
|
|
109
250
|
:param index: index
|
251
|
+
:param column_idx: column index
|
110
252
|
:param global_pos: global position
|
111
253
|
"""
|
112
|
-
context_menu =
|
113
|
-
actions =
|
254
|
+
context_menu = self.prepare_menu(index, column_idx)
|
255
|
+
actions = {}
|
114
256
|
actions['close'] = QAction(QIcon(":/icons/close.svg"), trans('action.tab.close'), self)
|
115
257
|
actions['close'].triggered.connect(
|
116
|
-
lambda: self.close_tab(index)
|
258
|
+
lambda: self.close_tab(index, column_idx)
|
117
259
|
)
|
118
260
|
actions['close_all'] = QAction(QIcon(":/icons/close.svg"), trans('action.tab.close_all.chat'), self)
|
119
261
|
actions['close_all'].triggered.connect(
|
120
|
-
lambda: self.close_all(Tab.TAB_CHAT)
|
262
|
+
lambda: self.close_all(Tab.TAB_CHAT, column_idx)
|
121
263
|
)
|
122
|
-
context_menu.addAction(actions['add_chat'])
|
123
|
-
context_menu.addAction(actions['add_notepad'])
|
124
|
-
context_menu.addAction(actions['edit'])
|
125
264
|
|
126
265
|
# at least one chat tab must be open
|
127
266
|
if self.window.core.tabs.count_by_type(Tab.TAB_CHAT) > 1:
|
128
267
|
context_menu.addAction(actions['close'])
|
129
|
-
|
130
|
-
if self.window.core.tabs.count_by_type(Tab.TAB_CHAT) > 1:
|
131
268
|
context_menu.addAction(actions['close_all'])
|
132
269
|
|
133
270
|
context_menu.exec(global_pos)
|
134
271
|
|
135
|
-
def show_files_menu(self, index, global_pos):
|
272
|
+
def show_files_menu(self, index: int, column_idx: int, global_pos):
|
136
273
|
"""
|
137
274
|
Show files menu
|
138
275
|
|
139
276
|
:param index: index
|
277
|
+
:param column_idx: column index
|
140
278
|
:param global_pos: global position
|
141
279
|
"""
|
142
|
-
context_menu =
|
143
|
-
actions =
|
280
|
+
context_menu = self.prepare_menu(index, column_idx)
|
281
|
+
actions = {}
|
144
282
|
actions['refresh'] = QAction(QIcon(":/icons/reload.svg"), trans('action.refresh'), self)
|
145
283
|
actions['refresh'].triggered.connect(
|
146
284
|
lambda: self.window.controller.files.update_explorer()
|
147
285
|
)
|
148
|
-
context_menu.addAction(actions['add_chat'])
|
149
|
-
context_menu.addAction(actions['add_notepad'])
|
150
286
|
context_menu.addAction(actions['refresh'])
|
151
|
-
context_menu.addAction(actions['edit'])
|
152
287
|
context_menu.exec(global_pos)
|
153
288
|
|
154
|
-
def
|
289
|
+
def show_tool_menu(self, index: int, column_idx: int, global_pos):
|
290
|
+
"""
|
291
|
+
Show tool menu
|
292
|
+
|
293
|
+
:param index: index
|
294
|
+
:param column_idx: column index
|
295
|
+
:param global_pos: global position
|
296
|
+
"""
|
297
|
+
context_menu = self.prepare_menu(index, column_idx)
|
298
|
+
actions = {}
|
299
|
+
actions['close'] = QAction(QIcon(":/icons/close.svg"), trans('action.tab.close'), self)
|
300
|
+
actions['close'].triggered.connect(
|
301
|
+
lambda: self.close_tab(index, column_idx)
|
302
|
+
)
|
303
|
+
context_menu.addAction(actions['close'])
|
304
|
+
context_menu.exec(global_pos)
|
305
|
+
|
306
|
+
def show_default_menu(self, index: int, column_idx: int, global_pos):
|
155
307
|
"""
|
156
308
|
Show default menu
|
157
309
|
|
158
310
|
:param index: index
|
311
|
+
:param column_idx: column index
|
159
312
|
:param global_pos: global position
|
160
313
|
"""
|
161
|
-
context_menu =
|
162
|
-
actions = self.get_common_actions(index)
|
163
|
-
context_menu.addAction(actions['add_chat'])
|
164
|
-
context_menu.addAction(actions['add_notepad'])
|
165
|
-
context_menu.addAction(actions['edit'])
|
314
|
+
context_menu = self.prepare_menu(index, column_idx)
|
166
315
|
context_menu.exec(global_pos)
|
167
316
|
|
168
317
|
@Slot()
|
169
|
-
def rename_tab(self, index):
|
318
|
+
def rename_tab(self, index: int, column_idx: int):
|
170
319
|
"""
|
171
320
|
Rename tab
|
321
|
+
|
172
322
|
:param index: index
|
323
|
+
:param column_idx: column index
|
173
324
|
"""
|
174
|
-
self.window.controller.ui.tabs.rename(index)
|
325
|
+
self.window.controller.ui.tabs.rename(index, column_idx)
|
175
326
|
|
176
327
|
@Slot()
|
177
|
-
def close_tab(self, index):
|
328
|
+
def close_tab(self, index: int, column_idx: int):
|
178
329
|
"""
|
179
330
|
Close tab
|
331
|
+
|
180
332
|
:param index: index
|
333
|
+
:param column_idx: column index
|
181
334
|
"""
|
182
|
-
self.window.controller.ui.tabs.close(index)
|
335
|
+
self.window.controller.ui.tabs.close(index, column_idx)
|
183
336
|
|
184
337
|
@Slot()
|
185
|
-
def close_all(self, type):
|
338
|
+
def close_all(self, type, column_idx: int):
|
186
339
|
"""
|
187
340
|
Close all tabs
|
341
|
+
|
188
342
|
:param type: type
|
343
|
+
:param column_idx: column index
|
189
344
|
"""
|
190
|
-
self.window.controller.ui.tabs.close_all(type)
|
345
|
+
self.window.controller.ui.tabs.close_all(type, column_idx)
|
191
346
|
|
192
347
|
@Slot()
|
193
|
-
def add_tab(self, index, type):
|
348
|
+
def add_tab(self, index: int, column_idx: int, type: int, tool_id: str = None):
|
194
349
|
"""
|
195
|
-
Add tab
|
350
|
+
Add a new tab
|
351
|
+
|
196
352
|
:param index: index
|
353
|
+
:param column_idx: column index
|
197
354
|
:param type: type
|
355
|
+
:param tool_id: tool id
|
198
356
|
"""
|
199
|
-
self.window.controller.ui.tabs.append(
|
357
|
+
self.window.controller.ui.tabs.append(
|
358
|
+
type=type,
|
359
|
+
tool_id=tool_id,
|
360
|
+
idx=index,
|
361
|
+
column_idx=column_idx,
|
362
|
+
)
|
@@ -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 00:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
import re
|
@@ -42,6 +42,15 @@ class HtmlOutput(QWebEngineView):
|
|
42
42
|
self.plain = ""
|
43
43
|
self.html_content = ""
|
44
44
|
self.meta = None
|
45
|
+
self.tab = None
|
46
|
+
|
47
|
+
def set_tab(self, tab):
|
48
|
+
"""
|
49
|
+
Set tab
|
50
|
+
|
51
|
+
:param tab: Tab
|
52
|
+
"""
|
53
|
+
self.tab = tab
|
45
54
|
|
46
55
|
def set_meta(self, meta: CtxMeta):
|
47
56
|
"""
|
@@ -163,6 +172,7 @@ class HtmlOutput(QWebEngineView):
|
|
163
172
|
if success:
|
164
173
|
event = RenderEvent(RenderEvent.ON_PAGE_LOAD, {
|
165
174
|
"meta": self.meta,
|
175
|
+
"tab": self.tab,
|
166
176
|
})
|
167
177
|
self.window.dispatch(event)
|
168
178
|
|
@@ -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 00:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
from PySide6.QtCore import Qt
|
@@ -38,6 +38,15 @@ class ChatOutput(QTextBrowser):
|
|
38
38
|
self.setOpenLinks(False)
|
39
39
|
self.anchorClicked.connect(self.open_external_link)
|
40
40
|
self.setWordWrapMode(QTextOption.WordWrap)
|
41
|
+
self.tab = None
|
42
|
+
|
43
|
+
def set_tab(self, tab):
|
44
|
+
"""
|
45
|
+
Set tab
|
46
|
+
|
47
|
+
:param tab: Tab
|
48
|
+
"""
|
49
|
+
self.tab = tab
|
41
50
|
|
42
51
|
def open_external_link(self, url):
|
43
52
|
"""
|
@@ -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.07 21:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
from PySide6.QtGui import QAction, QIcon
|
@@ -32,6 +32,9 @@ class CtxSearchInput(QLineEdit):
|
|
32
32
|
self.clear_action.triggered.connect(self.clear_search_string)
|
33
33
|
self.addAction(self.clear_action, QLineEdit.TrailingPosition)
|
34
34
|
self.clear_action.setVisible(False)
|
35
|
+
action = QAction(self)
|
36
|
+
action.setIcon(QIcon(":/icons/search.svg"))
|
37
|
+
self.addAction(action, QLineEdit.LeadingPosition)
|
35
38
|
|
36
39
|
self.textChanged.connect(self.on_text_changed)
|
37
40
|
|
@@ -6,21 +6,24 @@
|
|
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 00:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
import re
|
13
13
|
|
14
|
-
from PySide6.QtCore import Qt, QObject, Signal, Slot
|
14
|
+
from PySide6.QtCore import Qt, QObject, Signal, Slot, QEvent
|
15
15
|
from PySide6.QtWebChannel import QWebChannel
|
16
16
|
from PySide6.QtWebEngineCore import QWebEngineSettings, QWebEnginePage
|
17
17
|
from PySide6.QtWebEngineWidgets import QWebEngineView
|
18
18
|
from PySide6.QtGui import QAction, QIcon, QKeySequence
|
19
|
+
from PySide6.QtWidgets import QMenu
|
19
20
|
|
20
21
|
from pygpt_net.core.events import RenderEvent
|
21
22
|
from pygpt_net.item.ctx import CtxMeta
|
22
23
|
from pygpt_net.core.text.web_finder import WebFinder
|
24
|
+
from pygpt_net.ui.widget.tabs.layout import FocusEventFilter
|
23
25
|
from pygpt_net.utils import trans
|
26
|
+
|
24
27
|
import pygpt_net.icons_rc
|
25
28
|
|
26
29
|
|
@@ -38,9 +41,46 @@ class ChatWebOutput(QWebEngineView):
|
|
38
41
|
self.customContextMenuRequested.connect(self.on_context_menu)
|
39
42
|
self.signals = WebEngineSignals()
|
40
43
|
self.setContextMenuPolicy(Qt.CustomContextMenu)
|
44
|
+
self.filter = FocusEventFilter(self, self.on_focus)
|
45
|
+
self.installEventFilter(self)
|
41
46
|
self.plain = ""
|
42
47
|
self.html_content = ""
|
43
48
|
self.meta = None
|
49
|
+
self.tab = None
|
50
|
+
|
51
|
+
def eventFilter(self, source, event):
|
52
|
+
"""
|
53
|
+
Focus event filter
|
54
|
+
|
55
|
+
:param source: source
|
56
|
+
:param event: event
|
57
|
+
"""
|
58
|
+
if (event.type() == QEvent.ChildAdded and
|
59
|
+
source is self and
|
60
|
+
event.child().isWidgetType()):
|
61
|
+
self._glwidget = event.child()
|
62
|
+
self._glwidget.installEventFilter(self)
|
63
|
+
elif (event.type() == event.Type.MouseButtonPress):
|
64
|
+
col_idx = self.tab.column_idx
|
65
|
+
self.window.controller.ui.tabs.on_column_focus(col_idx)
|
66
|
+
return super().eventFilter(source, event)
|
67
|
+
|
68
|
+
def on_focus(self, widget):
|
69
|
+
"""
|
70
|
+
On widget clicked
|
71
|
+
|
72
|
+
:param widget: widget
|
73
|
+
"""
|
74
|
+
self.window.controller.ui.tabs.on_column_focus(self.tab.column_idx)
|
75
|
+
self.setFocus()
|
76
|
+
|
77
|
+
def set_tab(self, tab):
|
78
|
+
"""
|
79
|
+
Set tab
|
80
|
+
|
81
|
+
:param tab: Tab
|
82
|
+
"""
|
83
|
+
self.tab = tab
|
44
84
|
|
45
85
|
def set_meta(self, meta: CtxMeta):
|
46
86
|
"""
|
@@ -72,12 +112,7 @@ class ChatWebOutput(QWebEngineView):
|
|
72
112
|
|
73
113
|
:param position: position
|
74
114
|
"""
|
75
|
-
menu = self
|
76
|
-
|
77
|
-
# remove defaults
|
78
|
-
for action in menu.actions()[::-1]:
|
79
|
-
menu.removeAction(action)
|
80
|
-
|
115
|
+
menu = QMenu(self)
|
81
116
|
selected_text = ""
|
82
117
|
is_selection = self.page().hasSelection()
|
83
118
|
if is_selection:
|
@@ -138,6 +173,10 @@ class ChatWebOutput(QWebEngineView):
|
|
138
173
|
if self.window.core.config.has("zoom"):
|
139
174
|
self.page().setZoomFactor(self.window.core.config.get("zoom"))
|
140
175
|
|
176
|
+
def on_focus_js(self):
|
177
|
+
"""Focus JavaScript"""
|
178
|
+
self.window.controller.ui.tabs.on_column_focus(self.tab.column_idx)
|
179
|
+
|
141
180
|
def get_zoom_value(self) -> float:
|
142
181
|
"""
|
143
182
|
Get zoom value
|
@@ -165,6 +204,7 @@ class ChatWebOutput(QWebEngineView):
|
|
165
204
|
if success:
|
166
205
|
event = RenderEvent(RenderEvent.ON_PAGE_LOAD, {
|
167
206
|
"meta": self.meta,
|
207
|
+
"tab": self.tab,
|
168
208
|
})
|
169
209
|
self.window.dispatch(event)
|
170
210
|
|
@@ -318,4 +358,4 @@ class WebEngineSignals(QObject):
|
|
318
358
|
|
319
359
|
|
320
360
|
class WebEnginePageSignals(QObject):
|
321
|
-
js_message = Signal(int, str, str) # on Javascript message
|
361
|
+
js_message = Signal(int, str, str) # on Javascript message
|