pygpt-net 2.6.21__py3-none-any.whl → 2.6.23__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.
- pygpt_net/CHANGELOG.txt +12 -0
- pygpt_net/__init__.py +3 -3
- pygpt_net/app.py +3 -1
- pygpt_net/controller/__init__.py +4 -8
- pygpt_net/controller/access/voice.py +2 -2
- pygpt_net/controller/agent/llama.py +3 -0
- pygpt_net/controller/assistant/batch.py +2 -3
- pygpt_net/controller/assistant/editor.py +2 -2
- pygpt_net/controller/assistant/files.py +2 -3
- pygpt_net/controller/assistant/store.py +2 -2
- pygpt_net/controller/audio/audio.py +2 -2
- pygpt_net/controller/chat/response.py +4 -0
- pygpt_net/controller/ctx/ctx.py +2 -1
- pygpt_net/controller/files/files.py +24 -55
- pygpt_net/controller/idx/indexer.py +85 -76
- pygpt_net/controller/lang/lang.py +52 -34
- pygpt_net/controller/model/importer.py +2 -2
- pygpt_net/controller/notepad/notepad.py +86 -84
- pygpt_net/controller/plugins/settings.py +3 -4
- pygpt_net/controller/settings/profile.py +105 -124
- pygpt_net/controller/theme/menu.py +154 -57
- pygpt_net/controller/theme/nodes.py +51 -44
- pygpt_net/controller/theme/theme.py +33 -9
- pygpt_net/controller/tools/tools.py +2 -2
- pygpt_net/controller/ui/tabs.py +2 -3
- pygpt_net/core/agents/observer/evaluation.py +2 -2
- pygpt_net/core/agents/runners/loop.py +1 -0
- pygpt_net/core/bridge/bridge.py +2 -0
- pygpt_net/core/ctx/container.py +13 -12
- pygpt_net/core/ctx/output.py +7 -4
- pygpt_net/core/debug/console/console.py +2 -2
- pygpt_net/core/filesystem/actions.py +1 -2
- pygpt_net/core/filesystem/opener.py +261 -0
- pygpt_net/core/filesystem/url.py +13 -10
- pygpt_net/core/platforms/platforms.py +5 -4
- pygpt_net/core/render/plain/helpers.py +2 -5
- pygpt_net/core/render/plain/renderer.py +26 -30
- pygpt_net/core/render/web/body.py +1 -1
- pygpt_net/core/settings/settings.py +43 -13
- pygpt_net/core/tabs/tabs.py +20 -13
- pygpt_net/data/config/config.json +4 -4
- pygpt_net/data/config/models.json +3 -3
- pygpt_net/data/css/web-blocks.dark.css +7 -1
- pygpt_net/data/css/web-blocks.light.css +5 -2
- pygpt_net/data/css/web-chatgpt.dark.css +7 -1
- pygpt_net/data/css/web-chatgpt.light.css +3 -0
- pygpt_net/data/css/web-chatgpt_wide.dark.css +7 -1
- pygpt_net/data/css/web-chatgpt_wide.light.css +3 -0
- pygpt_net/data/locale/locale.de.ini +5 -1
- pygpt_net/data/locale/locale.en.ini +5 -1
- pygpt_net/data/locale/locale.es.ini +5 -1
- pygpt_net/data/locale/locale.fr.ini +5 -1
- pygpt_net/data/locale/locale.it.ini +5 -1
- pygpt_net/data/locale/locale.pl.ini +6 -4
- pygpt_net/data/locale/locale.uk.ini +5 -1
- pygpt_net/data/locale/locale.zh.ini +5 -1
- pygpt_net/plugin/twitter/plugin.py +2 -2
- pygpt_net/provider/core/config/patch.py +12 -1
- pygpt_net/tools/audio_transcriber/ui/dialogs.py +44 -54
- pygpt_net/tools/code_interpreter/body.py +1 -2
- pygpt_net/tools/code_interpreter/tool.py +7 -4
- pygpt_net/tools/code_interpreter/ui/html.py +1 -3
- pygpt_net/tools/code_interpreter/ui/widgets.py +2 -3
- pygpt_net/tools/html_canvas/ui/widgets.py +1 -3
- pygpt_net/tools/image_viewer/ui/dialogs.py +40 -37
- pygpt_net/tools/indexer/ui/widgets.py +2 -4
- pygpt_net/tools/media_player/tool.py +2 -5
- pygpt_net/tools/media_player/ui/widgets.py +60 -36
- pygpt_net/tools/text_editor/ui/widgets.py +18 -19
- pygpt_net/tools/translator/ui/widgets.py +39 -35
- pygpt_net/ui/base/context_menu.py +9 -4
- pygpt_net/ui/dialog/db.py +1 -3
- pygpt_net/ui/dialog/models.py +1 -3
- pygpt_net/ui/dialog/models_importer.py +2 -4
- pygpt_net/ui/dialogs.py +34 -30
- pygpt_net/ui/layout/chat/attachments.py +72 -84
- pygpt_net/ui/layout/chat/attachments_ctx.py +40 -44
- pygpt_net/ui/layout/chat/attachments_uploaded.py +36 -39
- pygpt_net/ui/layout/chat/calendar.py +100 -70
- pygpt_net/ui/layout/chat/chat.py +23 -17
- pygpt_net/ui/layout/chat/input.py +95 -118
- pygpt_net/ui/layout/chat/output.py +100 -162
- pygpt_net/ui/layout/chat/painter.py +89 -61
- pygpt_net/ui/layout/ctx/ctx_list.py +43 -52
- pygpt_net/ui/layout/status.py +23 -14
- pygpt_net/ui/layout/toolbox/agent.py +27 -38
- pygpt_net/ui/layout/toolbox/agent_llama.py +41 -45
- pygpt_net/ui/layout/toolbox/assistants.py +42 -38
- pygpt_net/ui/layout/toolbox/computer_env.py +32 -23
- pygpt_net/ui/layout/toolbox/footer.py +13 -16
- pygpt_net/ui/layout/toolbox/image.py +18 -21
- pygpt_net/ui/layout/toolbox/indexes.py +46 -89
- pygpt_net/ui/layout/toolbox/mode.py +20 -7
- pygpt_net/ui/layout/toolbox/model.py +12 -10
- pygpt_net/ui/layout/toolbox/presets.py +68 -52
- pygpt_net/ui/layout/toolbox/prompt.py +31 -58
- pygpt_net/ui/layout/toolbox/toolbox.py +25 -21
- pygpt_net/ui/layout/toolbox/vision.py +20 -22
- pygpt_net/ui/main.py +2 -4
- pygpt_net/ui/menu/about.py +64 -84
- pygpt_net/ui/menu/audio.py +87 -63
- pygpt_net/ui/menu/config.py +121 -127
- pygpt_net/ui/menu/debug.py +69 -76
- pygpt_net/ui/menu/file.py +32 -35
- pygpt_net/ui/menu/menu.py +2 -3
- pygpt_net/ui/menu/plugins.py +69 -33
- pygpt_net/ui/menu/theme.py +45 -46
- pygpt_net/ui/menu/tools.py +56 -60
- pygpt_net/ui/menu/video.py +20 -25
- pygpt_net/ui/tray.py +1 -2
- pygpt_net/ui/widget/audio/bar.py +1 -3
- pygpt_net/ui/widget/audio/input_button.py +3 -4
- pygpt_net/ui/widget/calendar/select.py +1 -2
- pygpt_net/ui/widget/dialog/base.py +12 -9
- pygpt_net/ui/widget/dialog/editor_file.py +20 -23
- pygpt_net/ui/widget/dialog/find.py +25 -24
- pygpt_net/ui/widget/dialog/profile.py +57 -53
- pygpt_net/ui/widget/draw/painter.py +62 -93
- pygpt_net/ui/widget/element/button.py +42 -30
- pygpt_net/ui/widget/element/checkbox.py +23 -15
- pygpt_net/ui/widget/element/group.py +6 -5
- pygpt_net/ui/widget/element/labels.py +1 -2
- pygpt_net/ui/widget/filesystem/explorer.py +93 -102
- pygpt_net/ui/widget/image/display.py +1 -2
- pygpt_net/ui/widget/lists/assistant.py +1 -2
- pygpt_net/ui/widget/lists/attachment.py +1 -2
- pygpt_net/ui/widget/lists/attachment_ctx.py +1 -2
- pygpt_net/ui/widget/lists/context.py +2 -4
- pygpt_net/ui/widget/lists/index.py +1 -2
- pygpt_net/ui/widget/lists/model.py +1 -2
- pygpt_net/ui/widget/lists/model_editor.py +1 -2
- pygpt_net/ui/widget/lists/model_importer.py +1 -2
- pygpt_net/ui/widget/lists/preset.py +1 -2
- pygpt_net/ui/widget/lists/preset_plugins.py +1 -2
- pygpt_net/ui/widget/lists/profile.py +1 -2
- pygpt_net/ui/widget/lists/uploaded.py +1 -2
- pygpt_net/ui/widget/option/checkbox.py +2 -4
- pygpt_net/ui/widget/option/checkbox_list.py +1 -4
- pygpt_net/ui/widget/option/cmd.py +1 -4
- pygpt_net/ui/widget/option/dictionary.py +25 -28
- pygpt_net/ui/widget/option/input.py +1 -3
- pygpt_net/ui/widget/tabs/Input.py +16 -12
- pygpt_net/ui/widget/tabs/body.py +5 -3
- pygpt_net/ui/widget/tabs/layout.py +41 -28
- pygpt_net/ui/widget/tabs/output.py +442 -85
- pygpt_net/ui/widget/textarea/calendar_note.py +1 -2
- pygpt_net/ui/widget/textarea/editor.py +41 -73
- pygpt_net/ui/widget/textarea/find.py +11 -10
- pygpt_net/ui/widget/textarea/html.py +3 -6
- pygpt_net/ui/widget/textarea/input.py +134 -69
- pygpt_net/ui/widget/textarea/notepad.py +54 -38
- pygpt_net/ui/widget/textarea/output.py +65 -54
- pygpt_net/ui/widget/textarea/search_input.py +5 -4
- pygpt_net/ui/widget/textarea/web.py +2 -4
- pygpt_net/ui/widget/vision/camera.py +2 -31
- {pygpt_net-2.6.21.dist-info → pygpt_net-2.6.23.dist-info}/METADATA +38 -174
- {pygpt_net-2.6.21.dist-info → pygpt_net-2.6.23.dist-info}/RECORD +160 -159
- {pygpt_net-2.6.21.dist-info → pygpt_net-2.6.23.dist-info}/LICENSE +0 -0
- {pygpt_net-2.6.21.dist-info → pygpt_net-2.6.23.dist-info}/WHEEL +0 -0
- {pygpt_net-2.6.21.dist-info → pygpt_net-2.6.23.dist-info}/entry_points.txt +0 -0
|
@@ -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: 2025.08.
|
|
9
|
+
# Updated Date: 2025.08.24 23:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import os
|
|
@@ -140,7 +140,6 @@ class Body:
|
|
|
140
140
|
</style>
|
|
141
141
|
<script type="text/javascript" src="qrc:///qtwebchannel/qwebchannel.js"></script>
|
|
142
142
|
<script type="text/javascript" src="qrc:///js/highlight.min.js"></script>
|
|
143
|
-
<script type="text/javascript" src="qrc:///js/auto-render.min.js"></script>
|
|
144
143
|
<script>
|
|
145
144
|
|
|
146
145
|
let scrollTimeout = null;
|
|
@@ -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: 2025.08.
|
|
9
|
+
# Updated Date: 2025.08.24 23:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import json
|
|
@@ -26,7 +26,7 @@ from pygpt_net.item.ctx import CtxItem
|
|
|
26
26
|
from pygpt_net.utils import trans
|
|
27
27
|
from .ui.html import HtmlOutput, CodeBlock
|
|
28
28
|
|
|
29
|
-
from .ui.widgets import PythonInput,
|
|
29
|
+
from .ui.widgets import PythonInput, ToolWidget, ToolSignals
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
class CodeInterpreter(BaseTool):
|
|
@@ -48,6 +48,7 @@ class CodeInterpreter(BaseTool):
|
|
|
48
48
|
self.ipython = True
|
|
49
49
|
self.auto_opened = False
|
|
50
50
|
self.signals = ToolSignals()
|
|
51
|
+
self.max_history_size = 1000 # max history lines
|
|
51
52
|
|
|
52
53
|
# interpreter data files in /data directory
|
|
53
54
|
self.file_current = ".interpreter.current.py"
|
|
@@ -366,11 +367,13 @@ class CodeInterpreter(BaseTool):
|
|
|
366
367
|
|
|
367
368
|
def save_history(self, input: str):
|
|
368
369
|
"""
|
|
369
|
-
Save input data
|
|
370
|
+
Save input data (history)
|
|
370
371
|
|
|
371
372
|
:param input: Input data
|
|
372
373
|
"""
|
|
373
374
|
path = self.get_path_input()
|
|
375
|
+
if self.max_history_size > 0 and isinstance(input, str):
|
|
376
|
+
input = ''.join(input.splitlines(True)[-self.max_history_size:])
|
|
374
377
|
with open(path , "w", encoding="utf-8") as f:
|
|
375
378
|
f.write(input)
|
|
376
379
|
|
|
@@ -431,7 +434,7 @@ class CodeInterpreter(BaseTool):
|
|
|
431
434
|
self.window.controller.command.dispatch_only(event)
|
|
432
435
|
self.signals.focus_input.emit()
|
|
433
436
|
event = KernelEvent(KernelEvent.STATUS, {
|
|
434
|
-
'status': "[OK] Kernel restarted at
|
|
437
|
+
'status': f"[OK] Kernel restarted at {strftime('%H:%M:%S')}.",
|
|
435
438
|
})
|
|
436
439
|
self.window.dispatch(event)
|
|
437
440
|
|
|
@@ -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: 2025.08.
|
|
9
|
+
# Updated Date: 2025.08.24 23:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import json
|
|
@@ -25,8 +25,6 @@ from pygpt_net.core.text.web_finder import WebFinder
|
|
|
25
25
|
from pygpt_net.tools.code_interpreter.body import Body
|
|
26
26
|
from pygpt_net.utils import trans
|
|
27
27
|
|
|
28
|
-
import pygpt_net.icons_rc
|
|
29
|
-
|
|
30
28
|
class CodeBlock:
|
|
31
29
|
def __init__(
|
|
32
30
|
self,
|
|
@@ -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: 2025.08.
|
|
9
|
+
# Updated Date: 2025.08.24 23:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from PySide6 import QtCore
|
|
@@ -17,10 +17,9 @@ from PySide6.QtWidgets import QTextEdit, QApplication, QVBoxLayout, QLabel, QChe
|
|
|
17
17
|
|
|
18
18
|
from pygpt_net.item.ctx import CtxItem
|
|
19
19
|
from pygpt_net.ui.widget.textarea.editor import BaseCodeEditor
|
|
20
|
+
from pygpt_net.utils import trans
|
|
20
21
|
|
|
21
22
|
from .html import HtmlOutput, CustomWebEnginePage
|
|
22
|
-
from pygpt_net.utils import trans
|
|
23
|
-
import pygpt_net.icons_rc
|
|
24
23
|
|
|
25
24
|
|
|
26
25
|
class ToolWidget:
|
|
@@ -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: 2025.08.
|
|
9
|
+
# Updated Date: 2025.08.24 23:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from PySide6.QtCore import Qt, Slot, QUrl, QObject, Signal
|
|
@@ -15,8 +15,6 @@ from PySide6.QtWidgets import QVBoxLayout, QCheckBox, QHBoxLayout
|
|
|
15
15
|
from pygpt_net.ui.widget.element.labels import HelpLabel
|
|
16
16
|
from pygpt_net.ui.widget.textarea.editor import BaseCodeEditor
|
|
17
17
|
from pygpt_net.ui.widget.textarea.html import HtmlOutput, CustomWebEnginePage
|
|
18
|
-
|
|
19
|
-
import pygpt_net.icons_rc
|
|
20
18
|
from pygpt_net.utils import trans
|
|
21
19
|
|
|
22
20
|
|
|
@@ -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:
|
|
9
|
+
# Updated Date: 2025.08.24 23:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from PySide6.QtCore import Qt
|
|
@@ -17,8 +17,6 @@ from pygpt_net.ui.widget.dialog.base import BaseDialog
|
|
|
17
17
|
from pygpt_net.ui.widget.image.display import ImageLabel
|
|
18
18
|
from pygpt_net.utils import trans
|
|
19
19
|
|
|
20
|
-
import pygpt_net.icons_rc
|
|
21
|
-
|
|
22
20
|
class DialogSpawner:
|
|
23
21
|
def __init__(self, window=None):
|
|
24
22
|
"""
|
|
@@ -37,9 +35,13 @@ class DialogSpawner:
|
|
|
37
35
|
:param id: dialog id
|
|
38
36
|
:return: BaseDialog instance
|
|
39
37
|
"""
|
|
40
|
-
|
|
38
|
+
dialog = ImageViewerDialog(self.window, self.id)
|
|
39
|
+
dialog.disable_geometry_store = True # disable geometry store
|
|
40
|
+
dialog.id = id
|
|
41
|
+
|
|
42
|
+
source = ImageLabel(dialog, self.path)
|
|
41
43
|
source.setVisible(False)
|
|
42
|
-
pixmap = ImageLabel(
|
|
44
|
+
pixmap = ImageLabel(dialog, self.path)
|
|
43
45
|
pixmap.setSizePolicy(QSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored))
|
|
44
46
|
|
|
45
47
|
row = QHBoxLayout()
|
|
@@ -48,11 +50,7 @@ class DialogSpawner:
|
|
|
48
50
|
layout = QVBoxLayout()
|
|
49
51
|
layout.addLayout(row)
|
|
50
52
|
|
|
51
|
-
dialog = ImageViewerDialog(self.window, self.id)
|
|
52
|
-
dialog.disable_geometry_store = True # disable geometry store
|
|
53
|
-
dialog.id = id
|
|
54
53
|
dialog.append_layout(layout)
|
|
55
|
-
dialog.setLayout(layout)
|
|
56
54
|
dialog.source = source
|
|
57
55
|
dialog.pixmap = pixmap
|
|
58
56
|
|
|
@@ -74,9 +72,14 @@ class ImageViewerDialog(BaseDialog):
|
|
|
74
72
|
self.menu_bar = None
|
|
75
73
|
self.file_menu = None
|
|
76
74
|
self.actions = {}
|
|
77
|
-
self.resizeEvent = self.onResizeEvent # resize event to adjust the pixmap
|
|
78
75
|
self.source = None
|
|
79
76
|
self.pixmap = None
|
|
77
|
+
self._last_src_key = 0
|
|
78
|
+
self._last_target_size = None
|
|
79
|
+
self._icon_add = QIcon(":/icons/add.svg")
|
|
80
|
+
self._icon_folder = QIcon(":/icons/folder.svg")
|
|
81
|
+
self._icon_save = QIcon(":/icons/save.svg")
|
|
82
|
+
self._icon_logout = QIcon(":/icons/logout.svg")
|
|
80
83
|
|
|
81
84
|
def append_layout(self, layout):
|
|
82
85
|
"""
|
|
@@ -84,23 +87,29 @@ class ImageViewerDialog(BaseDialog):
|
|
|
84
87
|
|
|
85
88
|
:param layout: layout
|
|
86
89
|
"""
|
|
87
|
-
layout.setMenuBar(self.setup_menu())
|
|
90
|
+
layout.setMenuBar(self.setup_menu())
|
|
88
91
|
self.setLayout(layout)
|
|
89
92
|
|
|
90
|
-
def
|
|
93
|
+
def resizeEvent(self, event):
|
|
91
94
|
"""
|
|
92
95
|
Resize event to adjust the pixmap on window resizing
|
|
93
96
|
|
|
94
97
|
:param event: resize event
|
|
95
98
|
"""
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
99
|
+
src = self.source.pixmap() if self.source is not None else None
|
|
100
|
+
if src and not src.isNull() and self.pixmap is not None:
|
|
101
|
+
target_size = self.pixmap.size()
|
|
102
|
+
key = src.cacheKey()
|
|
103
|
+
if key != self._last_src_key or target_size != self._last_target_size:
|
|
104
|
+
self.pixmap.setPixmap(
|
|
105
|
+
src.scaled(
|
|
106
|
+
target_size,
|
|
107
|
+
Qt.KeepAspectRatio,
|
|
108
|
+
Qt.SmoothTransformation
|
|
109
|
+
)
|
|
102
110
|
)
|
|
103
|
-
|
|
111
|
+
self._last_src_key = key
|
|
112
|
+
self._last_target_size = target_size
|
|
104
113
|
super(ImageViewerDialog, self).resizeEvent(event)
|
|
105
114
|
|
|
106
115
|
def setup_menu(self) -> QMenuBar:
|
|
@@ -109,44 +118,38 @@ class ImageViewerDialog(BaseDialog):
|
|
|
109
118
|
|
|
110
119
|
:return: QMenuBar
|
|
111
120
|
"""
|
|
112
|
-
self.menu_bar = QMenuBar()
|
|
121
|
+
self.menu_bar = QMenuBar(self)
|
|
113
122
|
self.file_menu = self.menu_bar.addMenu(trans("menu.file"))
|
|
114
123
|
|
|
115
|
-
|
|
116
|
-
self.actions["new"] = QAction(QIcon(":/icons/add.svg"), trans("action.new"))
|
|
124
|
+
self.actions["new"] = QAction(self._icon_add, trans("action.new"), self)
|
|
117
125
|
self.actions["new"].triggered.connect(
|
|
118
|
-
lambda: self.window.tools.get("viewer").new()
|
|
126
|
+
lambda checked=False: self.window.tools.get("viewer").new()
|
|
119
127
|
)
|
|
120
128
|
|
|
121
|
-
|
|
122
|
-
self.actions["open"] = QAction(QIcon(":/icons/folder.svg"), trans("action.open"))
|
|
129
|
+
self.actions["open"] = QAction(self._icon_folder, trans("action.open"), self)
|
|
123
130
|
self.actions["open"].triggered.connect(
|
|
124
|
-
lambda: self.window.tools.get("viewer").open_file(self.id, auto_close=True)
|
|
131
|
+
lambda checked=False: self.window.tools.get("viewer").open_file(self.id, auto_close=True)
|
|
125
132
|
)
|
|
126
133
|
|
|
127
|
-
|
|
128
|
-
self.actions["open_new"] = QAction(QIcon(":/icons/folder.svg"), trans("action.open_new_window"))
|
|
134
|
+
self.actions["open_new"] = QAction(self._icon_folder, trans("action.open_new_window"), self)
|
|
129
135
|
self.actions["open_new"].triggered.connect(
|
|
130
|
-
lambda: self.window.tools.get("viewer").open_file(self.id, auto_close=False)
|
|
136
|
+
lambda checked=False: self.window.tools.get("viewer").open_file(self.id, auto_close=False)
|
|
131
137
|
)
|
|
132
138
|
|
|
133
|
-
|
|
134
|
-
self.actions["save_as"] = QAction(QIcon(":/icons/save.svg"), trans("action.save_as"))
|
|
139
|
+
self.actions["save_as"] = QAction(self._icon_save, trans("action.save_as"), self)
|
|
135
140
|
self.actions["save_as"].triggered.connect(
|
|
136
|
-
lambda: self.window.tools.get("viewer").save_by_id(self.id)
|
|
141
|
+
lambda checked=False: self.window.tools.get("viewer").save_by_id(self.id)
|
|
137
142
|
)
|
|
138
143
|
|
|
139
|
-
|
|
140
|
-
self.actions["exit"] = QAction(QIcon(":/icons/logout.svg"), trans("menu.file.exit"))
|
|
144
|
+
self.actions["exit"] = QAction(self._icon_logout, trans("menu.file.exit"), self)
|
|
141
145
|
self.actions["exit"].triggered.connect(
|
|
142
|
-
lambda: self.window.tools.get("viewer").close_preview(self.id)
|
|
146
|
+
lambda checked=False: self.window.tools.get("viewer").close_preview(self.id)
|
|
143
147
|
)
|
|
144
148
|
|
|
145
|
-
# add actions
|
|
146
149
|
self.file_menu.addAction(self.actions["new"])
|
|
147
150
|
self.file_menu.addAction(self.actions["open"])
|
|
148
151
|
self.file_menu.addAction(self.actions["open_new"])
|
|
149
152
|
self.file_menu.addAction(self.actions["save_as"])
|
|
150
153
|
self.file_menu.addAction(self.actions["exit"])
|
|
151
154
|
|
|
152
|
-
return self.menu_bar
|
|
155
|
+
return self.menu_bar
|
|
@@ -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:
|
|
9
|
+
# Updated Date: 2025.08.24 23:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from PySide6.QtCore import Qt
|
|
@@ -33,7 +33,6 @@ class IdxBrowseList(DatabaseList):
|
|
|
33
33
|
|
|
34
34
|
:param parent: Parent
|
|
35
35
|
"""
|
|
36
|
-
|
|
37
36
|
def copy_to_clipboard():
|
|
38
37
|
index = parent.currentIndex()
|
|
39
38
|
if index.isValid():
|
|
@@ -64,9 +63,8 @@ class IdxBrowser(DataBrowser):
|
|
|
64
63
|
:return: Tables dictionary
|
|
65
64
|
"""
|
|
66
65
|
data = self.window.tools.get("indexer").get_tables()
|
|
67
|
-
|
|
66
|
+
return {k: v for k, v in data.items() if k in [
|
|
68
67
|
"idx_ctx", "idx_file", "idx_external"]}
|
|
69
|
-
return tables
|
|
70
68
|
|
|
71
69
|
@override
|
|
72
70
|
def get_filters(self):
|
|
@@ -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: 2025.08.
|
|
9
|
+
# Updated Date: 2025.08.24 23:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import datetime
|
|
@@ -15,15 +15,12 @@ import shutil
|
|
|
15
15
|
from typing import Dict
|
|
16
16
|
|
|
17
17
|
from PySide6.QtGui import QAction, QIcon
|
|
18
|
+
from PySide6.QtWidgets import QMessageBox, QFileDialog
|
|
18
19
|
|
|
19
20
|
from pygpt_net.tools.base import BaseTool
|
|
20
21
|
from pygpt_net.tools.media_player.ui.dialogs import VideoPlayer
|
|
21
|
-
from PySide6.QtWidgets import QMessageBox, QFileDialog
|
|
22
|
-
|
|
23
22
|
from pygpt_net.utils import trans
|
|
24
23
|
|
|
25
|
-
import pygpt_net.icons_rc
|
|
26
|
-
|
|
27
24
|
|
|
28
25
|
class MediaPlayer(BaseTool):
|
|
29
26
|
def __init__(self, *args, **kwargs):
|
|
@@ -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: 2025.08.
|
|
9
|
+
# Updated Date: 2025.08.25 03:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import os
|
|
@@ -19,8 +19,6 @@ from PySide6.QtWidgets import (QWidget, QPushButton, QHBoxLayout, QVBoxLayout,
|
|
|
19
19
|
from pygpt_net.ui.widget.element.labels import HelpLabel
|
|
20
20
|
from pygpt_net.utils import trans
|
|
21
21
|
|
|
22
|
-
import pygpt_net.icons_rc
|
|
23
|
-
|
|
24
22
|
class VideoPlayerWidget(QWidget):
|
|
25
23
|
def __init__(self, window=None):
|
|
26
24
|
super().__init__(window)
|
|
@@ -28,14 +26,18 @@ class VideoPlayerWidget(QWidget):
|
|
|
28
26
|
self.player = None
|
|
29
27
|
self.audio = None
|
|
30
28
|
self.video = None
|
|
31
|
-
self._QMediaPlayer = None
|
|
32
|
-
self._QAudioOutput = None
|
|
33
|
-
self._QVideoWidget = None
|
|
34
29
|
self.loaded = False
|
|
35
30
|
self.path = None
|
|
36
31
|
self.stopped = False
|
|
37
32
|
self.seeking = False
|
|
38
33
|
|
|
34
|
+
self._QMediaPlayer = None
|
|
35
|
+
self._QAudioOutput = None
|
|
36
|
+
self._QVideoWidget = None
|
|
37
|
+
|
|
38
|
+
self._waiting_position_set = False
|
|
39
|
+
self._last_position = -1
|
|
40
|
+
|
|
39
41
|
self.update_timer = QTimer(self)
|
|
40
42
|
self.update_timer.setInterval(200)
|
|
41
43
|
self.update_timer.timeout.connect(self.update_ui)
|
|
@@ -48,11 +50,15 @@ class VideoPlayerWidget(QWidget):
|
|
|
48
50
|
self._video_placeholder.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
|
49
51
|
self._video_placeholder.setMinimumSize(640, 480)
|
|
50
52
|
|
|
53
|
+
self._icon_play = self.style().standardIcon(QStyle.SP_MediaPlay)
|
|
54
|
+
self._icon_pause = self.style().standardIcon(QStyle.SP_MediaPause)
|
|
55
|
+
self._icon_stop = self.style().standardIcon(QStyle.SP_MediaStop)
|
|
56
|
+
|
|
51
57
|
self.btn_play_pause = QPushButton()
|
|
52
58
|
self.btn_play_pause.setEnabled(False)
|
|
53
59
|
|
|
54
60
|
self.btn_stop = QPushButton()
|
|
55
|
-
self.btn_stop.setIcon(self.
|
|
61
|
+
self.btn_stop.setIcon(self._icon_stop)
|
|
56
62
|
self.btn_stop.setEnabled(False)
|
|
57
63
|
|
|
58
64
|
self.btn_mute = QPushButton()
|
|
@@ -149,6 +155,7 @@ class VideoPlayerWidget(QWidget):
|
|
|
149
155
|
self.volume_slider.valueChanged.connect(self.adjust_volume)
|
|
150
156
|
self.slider.sliderPressed.connect(self.on_slider_pressed)
|
|
151
157
|
self.slider.sliderReleased.connect(self.on_slider_released)
|
|
158
|
+
self.slider.valueChanged.connect(self.on_slider_value_changed)
|
|
152
159
|
self._video_placeholder.mousePressEvent = self.video_widget_clicked
|
|
153
160
|
self.seeking = False
|
|
154
161
|
|
|
@@ -210,7 +217,7 @@ class VideoPlayerWidget(QWidget):
|
|
|
210
217
|
self.stopped = True
|
|
211
218
|
self.slider.setValue(0)
|
|
212
219
|
self.label_time.setText(self.format_time(0))
|
|
213
|
-
self.btn_play_pause.setIcon(self.
|
|
220
|
+
self.btn_play_pause.setIcon(self._icon_play)
|
|
214
221
|
self.update_timer.stop()
|
|
215
222
|
|
|
216
223
|
def toggle_play_pause(self):
|
|
@@ -226,11 +233,13 @@ class VideoPlayerWidget(QWidget):
|
|
|
226
233
|
if self.player and self.player.source():
|
|
227
234
|
self.player.stop()
|
|
228
235
|
self.player.setSource(QUrl())
|
|
229
|
-
self.btn_play_pause.setIcon(self.
|
|
236
|
+
self.btn_play_pause.setIcon(self._icon_play)
|
|
230
237
|
self.update_timer.stop()
|
|
231
238
|
self.slider.setValue(0)
|
|
232
239
|
self.seeking = False
|
|
233
240
|
self.loaded = False
|
|
241
|
+
self._waiting_position_set = False
|
|
242
|
+
self._last_position = -1
|
|
234
243
|
|
|
235
244
|
def reset_player(self):
|
|
236
245
|
"""Reset player to default state"""
|
|
@@ -296,6 +305,7 @@ class VideoPlayerWidget(QWidget):
|
|
|
296
305
|
def on_close(self):
|
|
297
306
|
"""Stop video"""
|
|
298
307
|
self.reset()
|
|
308
|
+
self.autoplay_timer.stop()
|
|
299
309
|
|
|
300
310
|
def toggle_fullscreen(self):
|
|
301
311
|
"""Toggle fullscreen"""
|
|
@@ -387,22 +397,28 @@ class VideoPlayerWidget(QWidget):
|
|
|
387
397
|
return
|
|
388
398
|
if self._QMediaPlayer and self.player.playbackState() == self._QMediaPlayer.PlayingState:
|
|
389
399
|
self.player.pause()
|
|
390
|
-
self.
|
|
400
|
+
self._waiting_position_set = True
|
|
391
401
|
self.player.setPosition(position)
|
|
392
402
|
|
|
393
403
|
def on_slider_pressed(self):
|
|
394
404
|
"""Slider pressed"""
|
|
395
405
|
self.seeking = True
|
|
406
|
+
self._waiting_position_set = False
|
|
396
407
|
if self.player:
|
|
397
408
|
self.player.pause()
|
|
398
409
|
|
|
410
|
+
def on_slider_value_changed(self, value):
|
|
411
|
+
"""Slider value changed"""
|
|
412
|
+
if self.seeking:
|
|
413
|
+
self.label_time.setText(self.format_time(value))
|
|
414
|
+
|
|
399
415
|
def on_slider_released(self):
|
|
400
416
|
"""Slider released"""
|
|
401
417
|
if self.seeking:
|
|
402
418
|
if self.player:
|
|
403
419
|
self.player.setPosition(self.slider.value())
|
|
404
420
|
self.update_audio()
|
|
405
|
-
self.player.play
|
|
421
|
+
QTimer.singleShot(0, self.player.play)
|
|
406
422
|
self.seeking = False
|
|
407
423
|
|
|
408
424
|
def position_changed(self, position):
|
|
@@ -411,25 +427,15 @@ class VideoPlayerWidget(QWidget):
|
|
|
411
427
|
|
|
412
428
|
:param position: position
|
|
413
429
|
"""
|
|
430
|
+
if self._waiting_position_set and self.player:
|
|
431
|
+
self._waiting_position_set = False
|
|
432
|
+
if self._QMediaPlayer and self.player.playbackState() == self._QMediaPlayer.PausedState:
|
|
433
|
+
QTimer.singleShot(100, self.player.play)
|
|
414
434
|
if not self.seeking:
|
|
435
|
+
self._last_position = position
|
|
415
436
|
self.slider.setValue(position)
|
|
416
437
|
self.label_time.setText(self.format_time(position))
|
|
417
438
|
|
|
418
|
-
def on_position_set(self, position):
|
|
419
|
-
"""
|
|
420
|
-
On position set
|
|
421
|
-
|
|
422
|
-
:param position: position
|
|
423
|
-
"""
|
|
424
|
-
if self.seeking and self.player:
|
|
425
|
-
try:
|
|
426
|
-
self.player.positionChanged.disconnect(self.on_position_set)
|
|
427
|
-
except Exception:
|
|
428
|
-
pass
|
|
429
|
-
if self._QMediaPlayer and self.player.playbackState() == self._QMediaPlayer.PausedState:
|
|
430
|
-
QTimer.singleShot(100, self.player.play)
|
|
431
|
-
self.seeking = False
|
|
432
|
-
|
|
433
439
|
def update_label_path(self):
|
|
434
440
|
"""Update label path"""
|
|
435
441
|
if self.path:
|
|
@@ -440,32 +446,50 @@ class VideoPlayerWidget(QWidget):
|
|
|
440
446
|
def update_play_pause_icon(self):
|
|
441
447
|
"""Update play/pause icon"""
|
|
442
448
|
if self.player and self._QMediaPlayer and self.player.playbackState() == self._QMediaPlayer.PlayingState:
|
|
443
|
-
self.btn_play_pause.setIcon(self.
|
|
444
|
-
self.update_timer.
|
|
449
|
+
self.btn_play_pause.setIcon(self._icon_pause)
|
|
450
|
+
if not self.update_timer.isActive():
|
|
451
|
+
self.update_timer.start()
|
|
445
452
|
else:
|
|
446
|
-
self.btn_play_pause.setIcon(self.
|
|
447
|
-
self.update_timer.
|
|
453
|
+
self.btn_play_pause.setIcon(self._icon_play)
|
|
454
|
+
if self.update_timer.isActive():
|
|
455
|
+
self.update_timer.stop()
|
|
448
456
|
|
|
449
457
|
def update_audio(self):
|
|
450
458
|
"""Re-assign audio"""
|
|
451
459
|
if self.player and self.audio:
|
|
452
|
-
|
|
453
|
-
|
|
460
|
+
try:
|
|
461
|
+
current = self.player.audioOutput()
|
|
462
|
+
except Exception:
|
|
463
|
+
current = None
|
|
464
|
+
if current is not self.audio:
|
|
465
|
+
self.player.setAudioOutput(self.audio)
|
|
454
466
|
|
|
455
467
|
def update_mute_icon(self):
|
|
456
468
|
"""Update mute icon"""
|
|
457
469
|
if self.audio:
|
|
458
|
-
self.
|
|
470
|
+
muted = self.audio.isMuted()
|
|
471
|
+
if self.btn_mute.isChecked() != muted:
|
|
472
|
+
block = self.btn_mute.blockSignals(True)
|
|
473
|
+
self.btn_mute.setChecked(muted)
|
|
474
|
+
self.btn_mute.blockSignals(block)
|
|
459
475
|
|
|
460
476
|
def update_volume_slider(self):
|
|
461
477
|
"""Update volume slider"""
|
|
462
478
|
if self.audio:
|
|
463
|
-
|
|
479
|
+
v = int(self.audio.volume() * 100)
|
|
480
|
+
if self.volume_slider.value() != v:
|
|
481
|
+
block = self.volume_slider.blockSignals(True)
|
|
482
|
+
self.volume_slider.setValue(v)
|
|
483
|
+
self.volume_slider.blockSignals(block)
|
|
464
484
|
|
|
465
485
|
def update_ui(self):
|
|
466
486
|
"""Update UI"""
|
|
467
|
-
if self.player:
|
|
468
|
-
self.
|
|
487
|
+
if self.player and not self.seeking:
|
|
488
|
+
pos = self.player.position()
|
|
489
|
+
if pos != self._last_position:
|
|
490
|
+
self._last_position = pos
|
|
491
|
+
self.slider.setValue(pos)
|
|
492
|
+
self.label_time.setText(self.format_time(pos))
|
|
469
493
|
|
|
470
494
|
def format_time(self, ms):
|
|
471
495
|
"""
|
|
@@ -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:
|
|
9
|
+
# Updated Date: 2025.08.24 23:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from PySide6.QtGui import QAction, QIcon, QKeySequence
|
|
@@ -14,8 +14,6 @@ from PySide6.QtGui import QAction, QIcon, QKeySequence
|
|
|
14
14
|
from pygpt_net.ui.widget.textarea.editor import BaseCodeEditor
|
|
15
15
|
from pygpt_net.utils import trans
|
|
16
16
|
|
|
17
|
-
import pygpt_net.icons_rc
|
|
18
|
-
|
|
19
17
|
class TextFileEditor(BaseCodeEditor):
|
|
20
18
|
def __init__(self, window=None):
|
|
21
19
|
"""
|
|
@@ -23,7 +21,7 @@ class TextFileEditor(BaseCodeEditor):
|
|
|
23
21
|
|
|
24
22
|
:param window: main window
|
|
25
23
|
"""
|
|
26
|
-
super(
|
|
24
|
+
super().__init__(window)
|
|
27
25
|
self.window = window
|
|
28
26
|
self.setReadOnly(True)
|
|
29
27
|
self.value = 12
|
|
@@ -33,6 +31,10 @@ class TextFileEditor(BaseCodeEditor):
|
|
|
33
31
|
self.default_stylesheet = ""
|
|
34
32
|
self.setStyleSheet(self.default_stylesheet)
|
|
35
33
|
|
|
34
|
+
self._icon_volume = QIcon(":/icons/volume.svg")
|
|
35
|
+
self._icon_save = QIcon(":/icons/save.svg")
|
|
36
|
+
self._icon_search = QIcon(":/icons/search.svg")
|
|
37
|
+
|
|
36
38
|
def contextMenuEvent(self, event):
|
|
37
39
|
"""
|
|
38
40
|
Context menu event
|
|
@@ -40,38 +42,35 @@ class TextFileEditor(BaseCodeEditor):
|
|
|
40
42
|
:param event: Event
|
|
41
43
|
"""
|
|
42
44
|
menu = self.createStandardContextMenu()
|
|
43
|
-
|
|
45
|
+
cursor = self.textCursor()
|
|
44
46
|
|
|
45
|
-
if
|
|
46
|
-
|
|
47
|
-
plain_text =
|
|
47
|
+
if cursor.hasSelection():
|
|
48
|
+
selected_text = cursor.selectedText()
|
|
49
|
+
plain_text = cursor.selection().toPlainText()
|
|
48
50
|
|
|
49
|
-
|
|
50
|
-
action = QAction(QIcon(":/icons/volume.svg"), trans('text.context_menu.audio.read'), self)
|
|
51
|
+
action = QAction(self._icon_volume, trans('text.context_menu.audio.read'), menu)
|
|
51
52
|
action.triggered.connect(self.audio_read_selection)
|
|
52
53
|
menu.addAction(action)
|
|
53
54
|
|
|
54
|
-
|
|
55
|
-
copy_to_menu = self.window.ui.context_menu.get_copy_to_menu(self, selected_text)
|
|
55
|
+
copy_to_menu = self.window.ui.context_menu.get_copy_to_menu(menu, selected_text)
|
|
56
56
|
menu.addMenu(copy_to_menu)
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
action = QAction(QIcon(":/icons/save.svg"), trans('action.save_as'), self)
|
|
58
|
+
action = QAction(self._icon_save, trans('action.save_as'), menu)
|
|
60
59
|
action.triggered.connect(
|
|
61
60
|
lambda: self.window.controller.chat.common.save_text(plain_text)
|
|
62
61
|
)
|
|
63
62
|
menu.addAction(action)
|
|
64
63
|
else:
|
|
65
|
-
|
|
66
|
-
action = QAction(QIcon(":/icons/save.svg"), trans('action.save_as'), self)
|
|
64
|
+
action = QAction(self._icon_save, trans('action.save_as'), menu)
|
|
67
65
|
action.triggered.connect(
|
|
68
66
|
lambda: self.window.controller.chat.common.save_text(self.toPlainText())
|
|
69
67
|
)
|
|
70
68
|
menu.addAction(action)
|
|
71
69
|
|
|
72
|
-
action = QAction(
|
|
70
|
+
action = QAction(self._icon_search, trans('text.context_menu.find'), menu)
|
|
73
71
|
action.triggered.connect(self.find_open)
|
|
74
|
-
action.setShortcut(QKeySequence
|
|
72
|
+
action.setShortcut(QKeySequence.StandardKey.Find)
|
|
75
73
|
menu.addAction(action)
|
|
76
74
|
|
|
77
|
-
menu.exec_(event.globalPos())
|
|
75
|
+
menu.exec_(event.globalPos())
|
|
76
|
+
menu.deleteLater()
|