pygpt-net 2.7.8__py3-none-any.whl → 2.7.10__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 +14 -0
- pygpt_net/LICENSE +1 -1
- pygpt_net/__init__.py +3 -3
- pygpt_net/config.py +15 -1
- pygpt_net/controller/chat/common.py +5 -4
- pygpt_net/controller/chat/image.py +3 -3
- pygpt_net/controller/chat/stream.py +76 -41
- pygpt_net/controller/chat/stream_worker.py +3 -3
- pygpt_net/controller/ctx/extra.py +3 -1
- pygpt_net/controller/dialogs/debug.py +37 -8
- pygpt_net/controller/kernel/kernel.py +3 -7
- pygpt_net/controller/lang/custom.py +25 -12
- pygpt_net/controller/lang/lang.py +45 -3
- pygpt_net/controller/lang/mapping.py +15 -2
- pygpt_net/controller/notepad/notepad.py +68 -25
- pygpt_net/controller/presets/editor.py +5 -1
- pygpt_net/controller/presets/presets.py +17 -5
- pygpt_net/controller/realtime/realtime.py +13 -1
- pygpt_net/controller/theme/theme.py +11 -2
- pygpt_net/controller/ui/tabs.py +1 -1
- pygpt_net/core/ctx/output.py +38 -12
- pygpt_net/core/db/database.py +4 -2
- pygpt_net/core/debug/console/console.py +30 -2
- pygpt_net/core/debug/context.py +2 -1
- pygpt_net/core/debug/ui.py +26 -4
- pygpt_net/core/filesystem/filesystem.py +6 -2
- pygpt_net/core/notepad/notepad.py +2 -2
- pygpt_net/core/tabs/tabs.py +79 -19
- pygpt_net/data/config/config.json +4 -3
- pygpt_net/data/config/models.json +37 -22
- pygpt_net/data/config/settings.json +12 -0
- pygpt_net/data/locale/locale.ar.ini +1833 -0
- pygpt_net/data/locale/locale.bg.ini +1833 -0
- pygpt_net/data/locale/locale.cs.ini +1833 -0
- pygpt_net/data/locale/locale.da.ini +1833 -0
- pygpt_net/data/locale/locale.de.ini +4 -1
- pygpt_net/data/locale/locale.en.ini +70 -67
- pygpt_net/data/locale/locale.es.ini +4 -1
- pygpt_net/data/locale/locale.fi.ini +1833 -0
- pygpt_net/data/locale/locale.fr.ini +4 -1
- pygpt_net/data/locale/locale.he.ini +1833 -0
- pygpt_net/data/locale/locale.hi.ini +1833 -0
- pygpt_net/data/locale/locale.hu.ini +1833 -0
- pygpt_net/data/locale/locale.it.ini +4 -1
- pygpt_net/data/locale/locale.ja.ini +1833 -0
- pygpt_net/data/locale/locale.ko.ini +1833 -0
- pygpt_net/data/locale/locale.nl.ini +1833 -0
- pygpt_net/data/locale/locale.no.ini +1833 -0
- pygpt_net/data/locale/locale.pl.ini +5 -2
- pygpt_net/data/locale/locale.pt.ini +1833 -0
- pygpt_net/data/locale/locale.ro.ini +1833 -0
- pygpt_net/data/locale/locale.ru.ini +1833 -0
- pygpt_net/data/locale/locale.sk.ini +1833 -0
- pygpt_net/data/locale/locale.sv.ini +1833 -0
- pygpt_net/data/locale/locale.tr.ini +1833 -0
- pygpt_net/data/locale/locale.uk.ini +4 -1
- pygpt_net/data/locale/locale.zh.ini +4 -1
- pygpt_net/item/notepad.py +8 -2
- pygpt_net/migrations/Version20260121190000.py +25 -0
- pygpt_net/migrations/Version20260122140000.py +25 -0
- pygpt_net/migrations/__init__.py +5 -1
- pygpt_net/preload.py +246 -3
- pygpt_net/provider/api/__init__.py +16 -2
- pygpt_net/provider/api/anthropic/__init__.py +21 -7
- pygpt_net/provider/api/google/__init__.py +21 -7
- pygpt_net/provider/api/google/image.py +89 -2
- pygpt_net/provider/api/google/realtime/client.py +70 -24
- pygpt_net/provider/api/google/realtime/realtime.py +48 -12
- pygpt_net/provider/api/google/video.py +2 -2
- pygpt_net/provider/api/openai/__init__.py +26 -11
- pygpt_net/provider/api/openai/image.py +79 -3
- pygpt_net/provider/api/openai/realtime/realtime.py +26 -6
- pygpt_net/provider/api/openai/responses.py +11 -31
- pygpt_net/provider/api/openai/video.py +2 -2
- pygpt_net/provider/api/x_ai/__init__.py +21 -10
- pygpt_net/provider/api/x_ai/realtime/client.py +185 -146
- pygpt_net/provider/api/x_ai/realtime/realtime.py +30 -15
- pygpt_net/provider/api/x_ai/remote_tools.py +83 -0
- pygpt_net/provider/api/x_ai/tools.py +51 -0
- pygpt_net/provider/core/config/patch.py +12 -1
- pygpt_net/provider/core/model/patch.py +36 -1
- pygpt_net/provider/core/notepad/db_sqlite/storage.py +53 -10
- pygpt_net/tools/agent_builder/ui/dialogs.py +2 -1
- pygpt_net/tools/audio_transcriber/ui/dialogs.py +2 -1
- pygpt_net/tools/code_interpreter/ui/dialogs.py +2 -1
- pygpt_net/tools/html_canvas/ui/dialogs.py +2 -1
- pygpt_net/tools/image_viewer/ui/dialogs.py +3 -5
- pygpt_net/tools/indexer/ui/dialogs.py +2 -1
- pygpt_net/tools/media_player/ui/dialogs.py +2 -1
- pygpt_net/tools/translator/ui/dialogs.py +2 -1
- pygpt_net/tools/translator/ui/widgets.py +6 -2
- pygpt_net/ui/dialog/about.py +2 -2
- pygpt_net/ui/dialog/db.py +2 -1
- pygpt_net/ui/dialog/debug.py +169 -6
- pygpt_net/ui/dialog/logger.py +6 -2
- pygpt_net/ui/dialog/models.py +36 -3
- pygpt_net/ui/dialog/preset.py +5 -1
- pygpt_net/ui/dialog/remote_store.py +2 -1
- pygpt_net/ui/main.py +3 -2
- pygpt_net/ui/widget/dialog/editor_file.py +2 -1
- pygpt_net/ui/widget/lists/debug.py +12 -7
- pygpt_net/ui/widget/option/checkbox.py +2 -8
- pygpt_net/ui/widget/option/combo.py +10 -2
- pygpt_net/ui/widget/textarea/console.py +156 -7
- pygpt_net/ui/widget/textarea/highlight.py +66 -0
- pygpt_net/ui/widget/textarea/input.py +624 -57
- pygpt_net/ui/widget/textarea/notepad.py +294 -27
- {pygpt_net-2.7.8.dist-info → pygpt_net-2.7.10.dist-info}/LICENSE +1 -1
- {pygpt_net-2.7.8.dist-info → pygpt_net-2.7.10.dist-info}/METADATA +16 -64
- {pygpt_net-2.7.8.dist-info → pygpt_net-2.7.10.dist-info}/RECORD +112 -91
- {pygpt_net-2.7.8.dist-info → pygpt_net-2.7.10.dist-info}/WHEEL +0 -0
- {pygpt_net-2.7.8.dist-info → pygpt_net-2.7.10.dist-info}/entry_points.txt +0 -0
pygpt_net/ui/dialog/db.py
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
|
7
7
|
# MIT License #
|
|
8
8
|
# Created By : Marcin Szczygliński #
|
|
9
|
-
# Updated Date:
|
|
9
|
+
# Updated Date: 2026.01.22 17:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from PySide6.QtCore import Qt, QTimer, QSignalBlocker, QObject, QEvent
|
|
@@ -178,6 +178,7 @@ class Database:
|
|
|
178
178
|
splitter.splitterMoved.connect(self._on_splitter_moved)
|
|
179
179
|
|
|
180
180
|
self.menu_bar = QMenuBar()
|
|
181
|
+
self.menu_bar.setNativeMenuBar(False)
|
|
181
182
|
self.batch_actions_menu = self.menu_bar.addMenu("Actions")
|
|
182
183
|
self.delete_all_action = QAction(QIcon(":/icons/delete.svg"), "Delete all records")
|
|
183
184
|
self.delete_all_action.triggered.connect(self.viewer.delete_all)
|
pygpt_net/ui/dialog/debug.py
CHANGED
|
@@ -6,17 +6,137 @@
|
|
|
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: 2026.01.21 01:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
|
-
from PySide6.QtCore import Qt
|
|
13
|
-
from PySide6.QtWidgets import
|
|
12
|
+
from PySide6.QtCore import Qt, QEvent, QTimer, QObject
|
|
13
|
+
from PySide6.QtWidgets import QScrollArea, QSplitter, QSplitterHandle, QPushButton, \
|
|
14
|
+
QCheckBox, QHBoxLayout, QAbstractItemView, QLabel, QVBoxLayout
|
|
14
15
|
|
|
15
16
|
from pygpt_net.ui.widget.dialog.debug import DebugDialog
|
|
16
17
|
from pygpt_net.ui.widget.lists.debug import DebugList
|
|
17
18
|
from pygpt_net.ui.widget.textarea.editor import CodeEditor
|
|
18
19
|
|
|
19
20
|
|
|
21
|
+
class SmoothSplitterHandle(QSplitterHandle):
|
|
22
|
+
"""
|
|
23
|
+
Splitter handle that notifies the parent splitter about drag begin/end.
|
|
24
|
+
This allows the splitter to temporarily freeze heavy widgets during drag.
|
|
25
|
+
"""
|
|
26
|
+
def __init__(self, orientation, parent):
|
|
27
|
+
super().__init__(orientation, parent)
|
|
28
|
+
self._drag_active = False
|
|
29
|
+
|
|
30
|
+
def mousePressEvent(self, event):
|
|
31
|
+
if event.button() == Qt.LeftButton:
|
|
32
|
+
self._drag_active = True
|
|
33
|
+
sp = self.splitter()
|
|
34
|
+
if hasattr(sp, "_on_drag_begin"):
|
|
35
|
+
sp._on_drag_begin()
|
|
36
|
+
super().mousePressEvent(event)
|
|
37
|
+
|
|
38
|
+
def mouseReleaseEvent(self, event):
|
|
39
|
+
super().mouseReleaseEvent(event)
|
|
40
|
+
if self._drag_active:
|
|
41
|
+
sp = self.splitter()
|
|
42
|
+
if hasattr(sp, "_on_drag_end"):
|
|
43
|
+
sp._on_drag_end()
|
|
44
|
+
self._drag_active = False
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class SmoothSplitter(QSplitter):
|
|
48
|
+
"""
|
|
49
|
+
Splitter optimized for heavy child widgets:
|
|
50
|
+
- Uses non-opaque resize to avoid continuous relayout during drag.
|
|
51
|
+
- Freezes updates on registered heavy widgets while dragging.
|
|
52
|
+
"""
|
|
53
|
+
def __init__(self, orientation, parent=None):
|
|
54
|
+
super().__init__(orientation, parent)
|
|
55
|
+
self._heavy_widgets = []
|
|
56
|
+
self.setOpaqueResize(False) # rubber-band; resize applied on release
|
|
57
|
+
self.setChildrenCollapsible(False) # keep both panes visible
|
|
58
|
+
|
|
59
|
+
def createHandle(self):
|
|
60
|
+
return SmoothSplitterHandle(self.orientation(), self)
|
|
61
|
+
|
|
62
|
+
def add_heavy_widget(self, w):
|
|
63
|
+
if w and w not in self._heavy_widgets:
|
|
64
|
+
self._heavy_widgets.append(w)
|
|
65
|
+
|
|
66
|
+
def _on_drag_begin(self):
|
|
67
|
+
for w in self._heavy_widgets:
|
|
68
|
+
try:
|
|
69
|
+
w.setUpdatesEnabled(False)
|
|
70
|
+
except Exception:
|
|
71
|
+
pass
|
|
72
|
+
|
|
73
|
+
def _on_drag_end(self):
|
|
74
|
+
for w in self._heavy_widgets:
|
|
75
|
+
try:
|
|
76
|
+
w.setUpdatesEnabled(True)
|
|
77
|
+
w.update()
|
|
78
|
+
except Exception:
|
|
79
|
+
pass
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class ResizeFreezeFilter(QObject):
|
|
83
|
+
"""
|
|
84
|
+
Event filter that throttles expensive repaints during parent widget resize.
|
|
85
|
+
Freezes updates for registered heavy widgets while the resize is in progress,
|
|
86
|
+
and restores them shortly after the last resize event.
|
|
87
|
+
"""
|
|
88
|
+
def __init__(self, heavy_widgets, parent=None, defer_ms=120):
|
|
89
|
+
super().__init__(parent)
|
|
90
|
+
self._heavy_widgets = [w for w in heavy_widgets if w is not None]
|
|
91
|
+
self._defer_ms = defer_ms
|
|
92
|
+
self._timer = QTimer(self)
|
|
93
|
+
self._timer.setSingleShot(True)
|
|
94
|
+
self._timer.timeout.connect(self._unfreeze)
|
|
95
|
+
self._frozen = False
|
|
96
|
+
self._saved_view_update_modes = {}
|
|
97
|
+
|
|
98
|
+
def eventFilter(self, obj, event):
|
|
99
|
+
if event.type() == QEvent.Resize:
|
|
100
|
+
self._freeze()
|
|
101
|
+
self._timer.start(self._defer_ms)
|
|
102
|
+
return False
|
|
103
|
+
|
|
104
|
+
def _freeze(self):
|
|
105
|
+
if self._frozen:
|
|
106
|
+
return
|
|
107
|
+
self._frozen = True
|
|
108
|
+
for w in self._heavy_widgets:
|
|
109
|
+
try:
|
|
110
|
+
if isinstance(w, QAbstractItemView):
|
|
111
|
+
self._saved_view_update_modes[w] = w.viewportUpdateMode()
|
|
112
|
+
w.setViewportUpdateMode(QAbstractItemView.NoViewportUpdate)
|
|
113
|
+
except Exception:
|
|
114
|
+
pass
|
|
115
|
+
try:
|
|
116
|
+
w.setUpdatesEnabled(False)
|
|
117
|
+
except Exception:
|
|
118
|
+
pass
|
|
119
|
+
|
|
120
|
+
def _unfreeze(self):
|
|
121
|
+
if not self._frozen:
|
|
122
|
+
return
|
|
123
|
+
self._frozen = False
|
|
124
|
+
for w in self._heavy_widgets:
|
|
125
|
+
try:
|
|
126
|
+
w.setUpdatesEnabled(True)
|
|
127
|
+
except Exception:
|
|
128
|
+
pass
|
|
129
|
+
try:
|
|
130
|
+
if isinstance(w, QAbstractItemView) and w in self._saved_view_update_modes:
|
|
131
|
+
w.setViewportUpdateMode(self._saved_view_update_modes.pop(w))
|
|
132
|
+
except Exception:
|
|
133
|
+
pass
|
|
134
|
+
try:
|
|
135
|
+
w.update()
|
|
136
|
+
except Exception:
|
|
137
|
+
pass
|
|
138
|
+
|
|
139
|
+
|
|
20
140
|
class Debug:
|
|
21
141
|
def __init__(self, window=None):
|
|
22
142
|
"""
|
|
@@ -43,15 +163,58 @@ class Debug:
|
|
|
43
163
|
viewer.setReadOnly(True)
|
|
44
164
|
self.window.ui.debug[id].viewer = viewer
|
|
45
165
|
|
|
46
|
-
splitter
|
|
166
|
+
# optimized splitter for heavy widgets
|
|
167
|
+
splitter = SmoothSplitter(Qt.Horizontal)
|
|
47
168
|
splitter.addWidget(scroll)
|
|
48
169
|
splitter.addWidget(viewer)
|
|
49
170
|
splitter.setStretchFactor(0, 3)
|
|
50
171
|
splitter.setStretchFactor(1, 1)
|
|
51
172
|
|
|
52
|
-
|
|
53
|
-
|
|
173
|
+
# register heavy widgets to freeze during drag
|
|
174
|
+
splitter.add_heavy_widget(self.window.ui.debug[id])
|
|
175
|
+
splitter.add_heavy_widget(self.window.ui.debug[id].viewport())
|
|
176
|
+
splitter.add_heavy_widget(viewer)
|
|
177
|
+
|
|
178
|
+
realtime_btn = QCheckBox("Realtime")
|
|
179
|
+
realtime_btn.setChecked(False)
|
|
180
|
+
realtime_btn.toggled.connect(
|
|
181
|
+
lambda checked: self.window.controller.dialogs.debug.set_realtime(id, checked)
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
refresh_btn = QPushButton("Refresh")
|
|
185
|
+
refresh_btn.clicked.connect(
|
|
186
|
+
lambda: self.window.controller.dialogs.debug.refresh(id)
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
last_update_label = QLabel("Last update: N/A")
|
|
190
|
+
self.window.ui.debug[id].last_update_label = last_update_label
|
|
191
|
+
|
|
192
|
+
opts_layout = QHBoxLayout()
|
|
193
|
+
opts_layout.addWidget(realtime_btn)
|
|
194
|
+
opts_layout.addStretch(1)
|
|
195
|
+
opts_layout.addWidget(refresh_btn)
|
|
196
|
+
opts_layout.addStretch(1)
|
|
197
|
+
opts_layout.addWidget(last_update_label)
|
|
198
|
+
|
|
199
|
+
layout = QVBoxLayout()
|
|
200
|
+
layout.addWidget(splitter, 1)
|
|
201
|
+
layout.addLayout(opts_layout, 0)
|
|
202
|
+
layout.setContentsMargins(5, 5, 5, 5)
|
|
54
203
|
|
|
55
204
|
self.window.ui.dialog['debug.' + id] = DebugDialog(self.window, id)
|
|
56
205
|
self.window.ui.dialog['debug.' + id].setLayout(layout)
|
|
57
206
|
self.window.ui.dialog['debug.' + id].setWindowTitle("Debug" + ": " + id)
|
|
207
|
+
|
|
208
|
+
# throttle heavy repaints during dialog resize
|
|
209
|
+
heavy_widgets = [
|
|
210
|
+
self.window.ui.debug[id],
|
|
211
|
+
getattr(self.window.ui.debug[id], "viewport", lambda: None)(),
|
|
212
|
+
viewer,
|
|
213
|
+
scroll,
|
|
214
|
+
getattr(scroll, "viewport", lambda: None)(),
|
|
215
|
+
]
|
|
216
|
+
resize_filter = ResizeFreezeFilter(heavy_widgets, parent=self.window.ui.dialog['debug.' + id], defer_ms=120)
|
|
217
|
+
self.window.ui.dialog['debug.' + id].installEventFilter(resize_filter)
|
|
218
|
+
splitter.installEventFilter(resize_filter)
|
|
219
|
+
# keep a strong reference to avoid garbage collection
|
|
220
|
+
self.window.ui.dialog['debug.' + id]._resize_freeze_filter = resize_filter
|
pygpt_net/ui/dialog/logger.py
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
|
7
7
|
# MIT License #
|
|
8
8
|
# Created By : Marcin Szczygliński #
|
|
9
|
-
# Updated Date:
|
|
9
|
+
# Updated Date: 2026.01.20 21:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from PySide6.QtWidgets import QPushButton, QHBoxLayout, QVBoxLayout
|
|
@@ -34,6 +34,10 @@ class Logger:
|
|
|
34
34
|
|
|
35
35
|
self.window.console = ConsoleInput(self.window)
|
|
36
36
|
|
|
37
|
+
# TAB completion commands
|
|
38
|
+
if hasattr(self.window.core.debug, "console") and hasattr(self.window.core.debug.console, "get_supported_commands"):
|
|
39
|
+
self.window.console.set_commands(self.window.core.debug.console.get_supported_commands())
|
|
40
|
+
|
|
37
41
|
send_btn = QPushButton("Send")
|
|
38
42
|
send_btn.clicked.connect(self.window.core.debug.console.on_send)
|
|
39
43
|
|
|
@@ -58,4 +62,4 @@ class Logger:
|
|
|
58
62
|
self.window.ui.dialog['logger'] = LoggerDialog(self.window)
|
|
59
63
|
self.window.ui.dialog['logger'].setLayout(layout)
|
|
60
64
|
self.window.ui.dialog['logger'].setWindowTitle(trans('dialog.logger.title'))
|
|
61
|
-
self.window.ui.dialog['logger'].resize(800, 500)
|
|
65
|
+
self.window.ui.dialog['logger'].resize(800, 500)
|
pygpt_net/ui/dialog/models.py
CHANGED
|
@@ -6,16 +6,16 @@
|
|
|
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: 2026.01.22 17:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import copy
|
|
13
13
|
from typing import Dict, List, Optional
|
|
14
14
|
|
|
15
15
|
from PySide6.QtCore import Qt
|
|
16
|
-
from PySide6.QtGui import QStandardItemModel, QIcon
|
|
16
|
+
from PySide6.QtGui import QStandardItemModel, QIcon, QAction
|
|
17
17
|
from PySide6.QtWidgets import QPushButton, QHBoxLayout, QLabel, QVBoxLayout, QScrollArea, QWidget, QTabWidget, QFrame, \
|
|
18
|
-
QSplitter, QSizePolicy
|
|
18
|
+
QSplitter, QSizePolicy, QMenuBar
|
|
19
19
|
|
|
20
20
|
from pygpt_net.ui.widget.dialog.model import ModelDialog
|
|
21
21
|
from pygpt_net.ui.widget.element.group import CollapsedGroup
|
|
@@ -41,6 +41,11 @@ class Models:
|
|
|
41
41
|
"""
|
|
42
42
|
self.window = window
|
|
43
43
|
self.dialog_id = "models.editor"
|
|
44
|
+
self.menu_bar = None
|
|
45
|
+
|
|
46
|
+
# Keep menu objects alive and correctly parented
|
|
47
|
+
self._file_menu = None
|
|
48
|
+
self._menu_actions: Dict[str, QAction] = {}
|
|
44
49
|
|
|
45
50
|
# Internal state for filtering/mapping
|
|
46
51
|
self._filter_text: str = ""
|
|
@@ -204,6 +209,34 @@ class Models:
|
|
|
204
209
|
|
|
205
210
|
self.window.ui.dialog[self.dialog_id] = ModelDialog(self.window, self.dialog_id)
|
|
206
211
|
self.window.ui.dialog[self.dialog_id].setLayout(layout)
|
|
212
|
+
|
|
213
|
+
self.menu_bar = QMenuBar(self.window.ui.dialog[self.dialog_id])
|
|
214
|
+
self.menu_bar.setNativeMenuBar(False)
|
|
215
|
+
self._file_menu = self.menu_bar.addMenu(trans("menu.file"))
|
|
216
|
+
|
|
217
|
+
# open importer
|
|
218
|
+
self._menu_actions["import"] = QAction(
|
|
219
|
+
QIcon(":/icons/download.svg"),
|
|
220
|
+
trans("action.import"),
|
|
221
|
+
self.window.ui.dialog[self.dialog_id],
|
|
222
|
+
)
|
|
223
|
+
self._menu_actions["import"].triggered.connect(
|
|
224
|
+
lambda checked=False: self.window.controller.model.importer.open()
|
|
225
|
+
)
|
|
226
|
+
self._menu_actions["close"] = QAction(
|
|
227
|
+
QIcon(":/icons/logout.svg"),
|
|
228
|
+
trans("menu.file.exit"),
|
|
229
|
+
self.window.ui.dialog[self.dialog_id],
|
|
230
|
+
)
|
|
231
|
+
self._menu_actions["close"].triggered.connect(
|
|
232
|
+
lambda checked=False: self.window.ui.dialog[self.dialog_id].close()
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
# add actions
|
|
236
|
+
self._file_menu.addAction(self._menu_actions["import"])
|
|
237
|
+
self._file_menu.addAction(self._menu_actions["close"])
|
|
238
|
+
layout.setMenuBar(self.menu_bar)
|
|
239
|
+
|
|
207
240
|
self.window.ui.dialog[self.dialog_id].setWindowTitle(trans('dialog.models.editor'))
|
|
208
241
|
|
|
209
242
|
# restore current opened tab if idx is set
|
pygpt_net/ui/dialog/preset.py
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
|
7
7
|
# MIT License #
|
|
8
8
|
# Created By : Marcin Szczygliński #
|
|
9
|
-
# Updated Date:
|
|
9
|
+
# Updated Date: 2026.01.21 01:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from PySide6.QtCore import Qt
|
|
@@ -252,6 +252,7 @@ class Preset(BaseConfigDialog):
|
|
|
252
252
|
|
|
253
253
|
# warning label
|
|
254
254
|
warn_label = HelpLabel(trans("preset.personalize.warning"))
|
|
255
|
+
self.window.ui.nodes['preset.editor.warn_label'] = warn_label
|
|
255
256
|
|
|
256
257
|
# avatar
|
|
257
258
|
self.window.ui.nodes['preset.editor.avatar'] = AvatarWidget(self.window)
|
|
@@ -442,6 +443,9 @@ class AvatarWidget(QWidget):
|
|
|
442
443
|
main_layout.setContentsMargins(0, 10, 0, 0)
|
|
443
444
|
main_layout.addStretch()
|
|
444
445
|
|
|
446
|
+
self.window.ui.nodes['preset.editor.personalize.avatar.choose'] = self.choose_button
|
|
447
|
+
self.window.ui.nodes['preset.editor.personalize.avatar.remove'] = self.remove_button
|
|
448
|
+
|
|
445
449
|
def open_file_dialog(self):
|
|
446
450
|
"""Open a file dialog to select an avatar image file."""
|
|
447
451
|
file_name, _ = QFileDialog.getOpenFileName(
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
|
8
8
|
# MIT License #
|
|
9
9
|
# Created By : Marcin Szczygliński #
|
|
10
|
-
# Updated Date: 2026.01.
|
|
10
|
+
# Updated Date: 2026.01.22 17:00:00 #
|
|
11
11
|
# ================================================== #
|
|
12
12
|
|
|
13
13
|
import copy
|
|
@@ -238,6 +238,7 @@ class RemoteStore:
|
|
|
238
238
|
controller = self.window.controller
|
|
239
239
|
self.actions = {}
|
|
240
240
|
self.menu_bar = QMenuBar()
|
|
241
|
+
self.menu_bar.setNativeMenuBar(False)
|
|
241
242
|
|
|
242
243
|
self.menu = {}
|
|
243
244
|
self.menu["current"] = self.menu_bar.addMenu(trans("dialog.remote_store.menu.current"))
|
pygpt_net/ui/main.py
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
|
7
7
|
# MIT License #
|
|
8
8
|
# Created By : Marcin Szczygliński #
|
|
9
|
-
# Updated Date:
|
|
9
|
+
# Updated Date: 2026.01.20 20:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import os
|
|
@@ -376,7 +376,8 @@ class MainWindow(QMainWindow, QtStyleTools):
|
|
|
376
376
|
self.core.presets.save_all()
|
|
377
377
|
print("Exiting...")
|
|
378
378
|
print("")
|
|
379
|
-
print(f"{trans('exit.msg')} https://pygpt.net/#donate")
|
|
379
|
+
print(f"⭐☕ {trans('exit.msg')} https://pygpt.net/#donate ☕⭐")
|
|
380
|
+
print("")
|
|
380
381
|
|
|
381
382
|
def changeEvent(self, event):
|
|
382
383
|
"""
|
|
@@ -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: 2026.01.22 17:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import datetime
|
|
@@ -72,6 +72,7 @@ class EditorFileDialog(BaseDialog):
|
|
|
72
72
|
:return: menu bar
|
|
73
73
|
"""
|
|
74
74
|
self.menu_bar = QMenuBar(self)
|
|
75
|
+
self.menu_bar.setNativeMenuBar(False)
|
|
75
76
|
self.file_menu = self.menu_bar.addMenu(trans("menu.file"))
|
|
76
77
|
self.actions = {}
|
|
77
78
|
|
|
@@ -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: 2026.01.21 01:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import json
|
|
@@ -48,17 +48,22 @@ class DebugList(QTableView):
|
|
|
48
48
|
On data update begin
|
|
49
49
|
"""
|
|
50
50
|
self.adjustColumns()
|
|
51
|
+
self.setUpdatesEnabled(False)
|
|
51
52
|
|
|
52
53
|
def on_data_end(self):
|
|
53
54
|
"""
|
|
54
55
|
On data update end
|
|
55
56
|
"""
|
|
56
57
|
# update data viewer
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
self.
|
|
61
|
-
|
|
58
|
+
try:
|
|
59
|
+
if self.viewer_index:
|
|
60
|
+
new = self.model().data(self.viewer_index)
|
|
61
|
+
if self.viewer_current != new:
|
|
62
|
+
self.viewer.setPlainText(self.parse_view(new))
|
|
63
|
+
self.viewer_current = new
|
|
64
|
+
self.setUpdatesEnabled(True)
|
|
65
|
+
except Exception:
|
|
66
|
+
pass
|
|
62
67
|
|
|
63
68
|
def parse_view(self, data):
|
|
64
69
|
"""
|
|
@@ -116,4 +121,4 @@ class DebugList(QTableView):
|
|
|
116
121
|
data = self.model().data(index)
|
|
117
122
|
self.viewer.setPlainText(str(self.parse_view(data)))
|
|
118
123
|
self.viewer_index = index
|
|
119
|
-
self.viewer_current = data
|
|
124
|
+
self.viewer_current = data
|
|
@@ -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: 2026.01.21 01:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from PySide6.QtGui import QIcon
|
|
@@ -54,7 +54,6 @@ class OptionCheckbox(QWidget):
|
|
|
54
54
|
if "real_time" in self.option:
|
|
55
55
|
self.real_time = self.option["real_time"]
|
|
56
56
|
|
|
57
|
-
# self.box = QCheckBox(self.title, self.window)
|
|
58
57
|
self.box = AnimToggle('', self.window)
|
|
59
58
|
if self.value is not None:
|
|
60
59
|
self.box.setChecked(self.value)
|
|
@@ -77,17 +76,11 @@ class OptionCheckbox(QWidget):
|
|
|
77
76
|
ico.setPixmap(pixmap)
|
|
78
77
|
self.layout.addWidget(ico)
|
|
79
78
|
|
|
80
|
-
|
|
81
79
|
self.layout.addWidget(self.label)
|
|
82
80
|
self.layout.addStretch()
|
|
83
81
|
self.layout.setContentsMargins(0, 0, 0, 0)
|
|
84
82
|
self.setLayout(self.layout)
|
|
85
83
|
|
|
86
|
-
# self.layout = QHBoxLayout()
|
|
87
|
-
#self.layout.addWidget(self.box)
|
|
88
|
-
|
|
89
|
-
#self.setLayout(self.layout)
|
|
90
|
-
|
|
91
84
|
def trans_or_not(self, label: str):
|
|
92
85
|
"""
|
|
93
86
|
Translate label or return it as is if translation is not available
|
|
@@ -116,6 +109,7 @@ class OptionCheckbox(QWidget):
|
|
|
116
109
|
|
|
117
110
|
:param text: text
|
|
118
111
|
"""
|
|
112
|
+
self.title = text
|
|
119
113
|
self.label.setText(text)
|
|
120
114
|
|
|
121
115
|
def setChecked(self, state: bool):
|
|
@@ -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: 2026.01.01
|
|
9
|
+
# Updated Date: 2026.01.21 01:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
import sys
|
|
12
12
|
|
|
@@ -1649,4 +1649,12 @@ class OptionCombo(QWidget):
|
|
|
1649
1649
|
|
|
1650
1650
|
def fit_to_content(self):
|
|
1651
1651
|
"""Fit to content"""
|
|
1652
|
-
self.combo.setSizeAdjustPolicy(QComboBox.AdjustToContents)
|
|
1652
|
+
self.combo.setSizeAdjustPolicy(QComboBox.AdjustToContents)
|
|
1653
|
+
|
|
1654
|
+
def setText(self, title: str):
|
|
1655
|
+
"""
|
|
1656
|
+
Set label text
|
|
1657
|
+
|
|
1658
|
+
:param text: text
|
|
1659
|
+
"""
|
|
1660
|
+
self.title = title
|