pygpt-net 2.6.21__py3-none-any.whl → 2.6.22__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.
Files changed (144) hide show
  1. pygpt_net/CHANGELOG.txt +4 -0
  2. pygpt_net/__init__.py +3 -3
  3. pygpt_net/app.py +3 -1
  4. pygpt_net/controller/__init__.py +4 -8
  5. pygpt_net/controller/access/voice.py +2 -2
  6. pygpt_net/controller/assistant/batch.py +2 -3
  7. pygpt_net/controller/assistant/editor.py +2 -2
  8. pygpt_net/controller/assistant/files.py +2 -3
  9. pygpt_net/controller/assistant/store.py +2 -2
  10. pygpt_net/controller/audio/audio.py +2 -2
  11. pygpt_net/controller/ctx/ctx.py +2 -1
  12. pygpt_net/controller/idx/indexer.py +85 -76
  13. pygpt_net/controller/lang/lang.py +52 -34
  14. pygpt_net/controller/model/importer.py +2 -2
  15. pygpt_net/controller/notepad/notepad.py +86 -84
  16. pygpt_net/controller/plugins/settings.py +3 -4
  17. pygpt_net/controller/settings/profile.py +105 -124
  18. pygpt_net/controller/theme/menu.py +154 -57
  19. pygpt_net/controller/theme/nodes.py +51 -44
  20. pygpt_net/controller/theme/theme.py +33 -9
  21. pygpt_net/controller/tools/tools.py +2 -2
  22. pygpt_net/controller/ui/tabs.py +2 -3
  23. pygpt_net/core/ctx/container.py +13 -12
  24. pygpt_net/core/ctx/output.py +7 -4
  25. pygpt_net/core/debug/console/console.py +2 -2
  26. pygpt_net/core/filesystem/actions.py +1 -2
  27. pygpt_net/core/render/plain/helpers.py +2 -5
  28. pygpt_net/core/render/plain/renderer.py +26 -30
  29. pygpt_net/core/render/web/body.py +1 -1
  30. pygpt_net/core/settings/settings.py +43 -13
  31. pygpt_net/core/tabs/tabs.py +20 -13
  32. pygpt_net/data/config/config.json +4 -4
  33. pygpt_net/data/config/models.json +3 -3
  34. pygpt_net/data/locale/locale.de.ini +4 -1
  35. pygpt_net/data/locale/locale.en.ini +4 -1
  36. pygpt_net/data/locale/locale.es.ini +4 -1
  37. pygpt_net/data/locale/locale.fr.ini +4 -1
  38. pygpt_net/data/locale/locale.it.ini +4 -1
  39. pygpt_net/data/locale/locale.pl.ini +5 -4
  40. pygpt_net/data/locale/locale.uk.ini +4 -1
  41. pygpt_net/data/locale/locale.zh.ini +4 -1
  42. pygpt_net/plugin/twitter/plugin.py +2 -2
  43. pygpt_net/tools/audio_transcriber/ui/dialogs.py +44 -54
  44. pygpt_net/tools/code_interpreter/body.py +1 -2
  45. pygpt_net/tools/code_interpreter/tool.py +7 -4
  46. pygpt_net/tools/code_interpreter/ui/html.py +1 -3
  47. pygpt_net/tools/code_interpreter/ui/widgets.py +2 -3
  48. pygpt_net/tools/html_canvas/ui/widgets.py +1 -3
  49. pygpt_net/tools/image_viewer/ui/dialogs.py +40 -37
  50. pygpt_net/tools/indexer/ui/widgets.py +2 -4
  51. pygpt_net/tools/media_player/tool.py +2 -5
  52. pygpt_net/tools/media_player/ui/widgets.py +60 -36
  53. pygpt_net/tools/text_editor/ui/widgets.py +18 -19
  54. pygpt_net/tools/translator/ui/widgets.py +39 -35
  55. pygpt_net/ui/base/context_menu.py +9 -4
  56. pygpt_net/ui/dialog/db.py +1 -3
  57. pygpt_net/ui/dialog/models.py +1 -3
  58. pygpt_net/ui/dialog/models_importer.py +2 -4
  59. pygpt_net/ui/dialogs.py +34 -30
  60. pygpt_net/ui/layout/chat/attachments.py +72 -84
  61. pygpt_net/ui/layout/chat/attachments_ctx.py +40 -44
  62. pygpt_net/ui/layout/chat/attachments_uploaded.py +36 -39
  63. pygpt_net/ui/layout/chat/calendar.py +100 -70
  64. pygpt_net/ui/layout/chat/chat.py +23 -17
  65. pygpt_net/ui/layout/chat/input.py +95 -118
  66. pygpt_net/ui/layout/chat/output.py +100 -162
  67. pygpt_net/ui/layout/chat/painter.py +89 -61
  68. pygpt_net/ui/layout/ctx/ctx_list.py +43 -52
  69. pygpt_net/ui/layout/status.py +23 -14
  70. pygpt_net/ui/layout/toolbox/agent.py +27 -38
  71. pygpt_net/ui/layout/toolbox/agent_llama.py +42 -45
  72. pygpt_net/ui/layout/toolbox/assistants.py +42 -38
  73. pygpt_net/ui/layout/toolbox/computer_env.py +32 -23
  74. pygpt_net/ui/layout/toolbox/footer.py +13 -16
  75. pygpt_net/ui/layout/toolbox/image.py +18 -21
  76. pygpt_net/ui/layout/toolbox/indexes.py +46 -89
  77. pygpt_net/ui/layout/toolbox/mode.py +20 -7
  78. pygpt_net/ui/layout/toolbox/model.py +12 -10
  79. pygpt_net/ui/layout/toolbox/presets.py +68 -52
  80. pygpt_net/ui/layout/toolbox/prompt.py +31 -58
  81. pygpt_net/ui/layout/toolbox/toolbox.py +25 -21
  82. pygpt_net/ui/layout/toolbox/vision.py +20 -22
  83. pygpt_net/ui/main.py +2 -4
  84. pygpt_net/ui/menu/about.py +64 -84
  85. pygpt_net/ui/menu/audio.py +87 -63
  86. pygpt_net/ui/menu/config.py +121 -127
  87. pygpt_net/ui/menu/debug.py +69 -76
  88. pygpt_net/ui/menu/file.py +32 -35
  89. pygpt_net/ui/menu/menu.py +2 -3
  90. pygpt_net/ui/menu/plugins.py +69 -33
  91. pygpt_net/ui/menu/theme.py +45 -46
  92. pygpt_net/ui/menu/tools.py +56 -60
  93. pygpt_net/ui/menu/video.py +20 -25
  94. pygpt_net/ui/tray.py +1 -2
  95. pygpt_net/ui/widget/audio/bar.py +1 -3
  96. pygpt_net/ui/widget/audio/input_button.py +3 -4
  97. pygpt_net/ui/widget/calendar/select.py +1 -2
  98. pygpt_net/ui/widget/dialog/base.py +12 -9
  99. pygpt_net/ui/widget/dialog/editor_file.py +20 -23
  100. pygpt_net/ui/widget/dialog/find.py +25 -24
  101. pygpt_net/ui/widget/dialog/profile.py +57 -53
  102. pygpt_net/ui/widget/draw/painter.py +62 -93
  103. pygpt_net/ui/widget/element/button.py +42 -30
  104. pygpt_net/ui/widget/element/checkbox.py +23 -15
  105. pygpt_net/ui/widget/element/group.py +6 -5
  106. pygpt_net/ui/widget/element/labels.py +1 -2
  107. pygpt_net/ui/widget/filesystem/explorer.py +93 -102
  108. pygpt_net/ui/widget/image/display.py +1 -2
  109. pygpt_net/ui/widget/lists/assistant.py +1 -2
  110. pygpt_net/ui/widget/lists/attachment.py +1 -2
  111. pygpt_net/ui/widget/lists/attachment_ctx.py +1 -2
  112. pygpt_net/ui/widget/lists/context.py +2 -4
  113. pygpt_net/ui/widget/lists/index.py +1 -2
  114. pygpt_net/ui/widget/lists/model.py +1 -2
  115. pygpt_net/ui/widget/lists/model_editor.py +1 -2
  116. pygpt_net/ui/widget/lists/model_importer.py +1 -2
  117. pygpt_net/ui/widget/lists/preset.py +1 -2
  118. pygpt_net/ui/widget/lists/preset_plugins.py +1 -2
  119. pygpt_net/ui/widget/lists/profile.py +1 -2
  120. pygpt_net/ui/widget/lists/uploaded.py +1 -2
  121. pygpt_net/ui/widget/option/checkbox.py +2 -4
  122. pygpt_net/ui/widget/option/checkbox_list.py +1 -4
  123. pygpt_net/ui/widget/option/cmd.py +1 -4
  124. pygpt_net/ui/widget/option/dictionary.py +25 -28
  125. pygpt_net/ui/widget/option/input.py +1 -3
  126. pygpt_net/ui/widget/tabs/Input.py +16 -12
  127. pygpt_net/ui/widget/tabs/body.py +5 -3
  128. pygpt_net/ui/widget/tabs/layout.py +36 -25
  129. pygpt_net/ui/widget/tabs/output.py +96 -74
  130. pygpt_net/ui/widget/textarea/calendar_note.py +1 -2
  131. pygpt_net/ui/widget/textarea/editor.py +41 -73
  132. pygpt_net/ui/widget/textarea/find.py +11 -10
  133. pygpt_net/ui/widget/textarea/html.py +3 -6
  134. pygpt_net/ui/widget/textarea/input.py +63 -64
  135. pygpt_net/ui/widget/textarea/notepad.py +54 -38
  136. pygpt_net/ui/widget/textarea/output.py +65 -54
  137. pygpt_net/ui/widget/textarea/search_input.py +5 -4
  138. pygpt_net/ui/widget/textarea/web.py +2 -4
  139. pygpt_net/ui/widget/vision/camera.py +2 -31
  140. {pygpt_net-2.6.21.dist-info → pygpt_net-2.6.22.dist-info}/METADATA +15 -151
  141. {pygpt_net-2.6.21.dist-info → pygpt_net-2.6.22.dist-info}/RECORD +144 -144
  142. {pygpt_net-2.6.21.dist-info → pygpt_net-2.6.22.dist-info}/LICENSE +0 -0
  143. {pygpt_net-2.6.21.dist-info → pygpt_net-2.6.22.dist-info}/WHEEL +0 -0
  144. {pygpt_net-2.6.21.dist-info → pygpt_net-2.6.22.dist-info}/entry_points.txt +0 -0
@@ -6,12 +6,14 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2025.01.18 03:00:00 #
9
+ # Updated Date: 2025.08.24 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
+ from functools import partial
13
+
12
14
  from PySide6.QtCore import Qt
13
15
  from PySide6.QtGui import QIcon
14
- from PySide6.QtWidgets import QVBoxLayout, QLabel, QHBoxLayout, QPushButton, QRadioButton, QCheckBox, QWidget, \
16
+ from PySide6.QtWidgets import QVBoxLayout, QHBoxLayout, QPushButton, QRadioButton, QCheckBox, QWidget, \
15
17
  QGridLayout
16
18
 
17
19
  from pygpt_net.ui.layout.chat.attachments import Attachments
@@ -25,7 +27,6 @@ from pygpt_net.ui.widget.element.labels import HelpLabel
25
27
  from pygpt_net.ui.widget.tabs.Input import InputTabs
26
28
  from pygpt_net.ui.widget.textarea.input import ChatInput
27
29
  from pygpt_net.utils import trans
28
- import pygpt_net.icons_rc
29
30
 
30
31
 
31
32
  class Input:
@@ -58,30 +59,27 @@ class Input:
58
59
  files_uploaded = self.setup_attachments_uploaded()
59
60
  files_ctx = self.setup_attachments_ctx()
60
61
 
61
- # tabs
62
62
  self.window.ui.tabs['input'] = InputTabs(self.window)
63
- self.window.ui.tabs['input'].setMinimumHeight(self.min_height_input_tab)
64
- self.window.ui.tabs['input'].addTab(input, trans('input.tab'))
65
- self.window.ui.tabs['input'].addTab(files, trans('attachments.tab'))
66
- self.window.ui.tabs['input'].addTab(files_uploaded, trans('attachments_uploaded.tab'))
67
- self.window.ui.tabs['input'].addTab(files_ctx, trans('attachments_uploaded.tab'))
68
- self.window.ui.tabs['input'].currentChanged.connect(self.update_min_height) # update min height on tab change
69
-
70
- self.window.ui.tabs['input'].setTabIcon(0, QIcon(":/icons/input.svg"))
71
- self.window.ui.tabs['input'].setTabIcon(1, QIcon(":/icons/attachment.svg"))
72
- self.window.ui.tabs['input'].setTabIcon(2, QIcon(":/icons/upload.svg"))
73
- self.window.ui.tabs['input'].setTabIcon(3, QIcon(":/icons/upload.svg"))
74
-
75
- # layout
76
- layout = QVBoxLayout()
63
+ tabs = self.window.ui.tabs['input']
64
+ tabs.setMinimumHeight(self.min_height_input_tab)
65
+ tabs.addTab(input, trans('input.tab'))
66
+ tabs.addTab(files, trans('attachments.tab'))
67
+ tabs.addTab(files_uploaded, trans('attachments_uploaded.tab'))
68
+ tabs.addTab(files_ctx, trans('attachments_uploaded.tab'))
69
+ tabs.currentChanged.connect(self.update_min_height)
70
+
71
+ tabs.setTabIcon(0, QIcon(":/icons/input.svg"))
72
+ upload_icon = QIcon(":/icons/upload.svg")
73
+ tabs.setTabIcon(1, QIcon(":/icons/attachment.svg"))
74
+ tabs.setTabIcon(2, upload_icon)
75
+ tabs.setTabIcon(3, upload_icon)
76
+
77
+ widget = QWidget()
78
+ layout = QVBoxLayout(widget)
77
79
  layout.addLayout(self.setup_header())
78
- layout.addWidget(self.window.ui.tabs['input'])
80
+ layout.addWidget(tabs)
79
81
  layout.addLayout(self.setup_bottom())
80
82
  layout.setContentsMargins(0, 0, 0, 5)
81
-
82
- widget = QWidget()
83
- widget.setLayout(layout)
84
-
85
83
  return widget
86
84
 
87
85
  def setup_input(self) -> QWidget:
@@ -90,16 +88,13 @@ class Input:
90
88
 
91
89
  :return: QWidget
92
90
  """
93
- # input textarea
94
91
  self.window.ui.nodes['input'] = ChatInput(self.window)
95
92
  self.window.ui.nodes['input'].setMinimumHeight(self.min_height_input)
96
93
 
97
- layout = QVBoxLayout()
94
+ widget = QWidget()
95
+ layout = QVBoxLayout(widget)
98
96
  layout.addWidget(self.window.ui.nodes['input'])
99
97
  layout.setContentsMargins(0, 0, 0, 0)
100
-
101
- widget = QWidget()
102
- widget.setLayout(layout)
103
98
  return widget
104
99
 
105
100
  def setup_attachments(self) -> QWidget:
@@ -108,12 +103,10 @@ class Input:
108
103
 
109
104
  :return: QWidget
110
105
  """
111
- layout = QVBoxLayout()
106
+ widget = QWidget()
107
+ layout = QVBoxLayout(widget)
112
108
  layout.addLayout(self.attachments.setup())
113
109
  layout.setContentsMargins(0, 0, 0, 0)
114
-
115
- widget = QWidget()
116
- widget.setLayout(layout)
117
110
  widget.setMinimumHeight(self.min_height_files_tab)
118
111
  return widget
119
112
 
@@ -123,12 +116,10 @@ class Input:
123
116
 
124
117
  :return: QWidget
125
118
  """
126
- layout = QVBoxLayout()
119
+ widget = QWidget()
120
+ layout = QVBoxLayout(widget)
127
121
  layout.addLayout(self.attachments_uploaded.setup())
128
122
  layout.setContentsMargins(0, 0, 0, 0)
129
-
130
- widget = QWidget()
131
- widget.setLayout(layout)
132
123
  widget.setMinimumHeight(self.min_height_files_tab)
133
124
  return widget
134
125
 
@@ -138,12 +129,10 @@ class Input:
138
129
 
139
130
  :return: QWidget
140
131
  """
141
- layout = QVBoxLayout()
132
+ widget = QWidget()
133
+ layout = QVBoxLayout(widget)
142
134
  layout.addLayout(self.attachments_ctx.setup())
143
135
  layout.setContentsMargins(0, 0, 0, 0)
144
-
145
- widget = QWidget()
146
- widget.setLayout(layout)
147
136
  widget.setMinimumHeight(self.min_height_files_tab)
148
137
  return widget
149
138
 
@@ -184,7 +173,6 @@ class Input:
184
173
  layout.addWidget(self.window.ui.plugin_addon['audio.output.bar'], alignment=Qt.AlignCenter)
185
174
  layout.addLayout(self.setup_buttons())
186
175
  layout.setContentsMargins(2, 0, 2, 0)
187
-
188
176
  return layout
189
177
 
190
178
  def setup_buttons(self) -> QHBoxLayout:
@@ -193,87 +181,76 @@ class Input:
193
181
 
194
182
  :return: QHBoxLayout
195
183
  """
196
- # send with: enter
197
- self.window.ui.nodes['input.send_enter'] = QRadioButton(trans("input.radio.enter"))
198
- self.window.ui.nodes['input.send_enter'].clicked.connect(
199
- lambda: self.window.controller.chat.common.toggle_send_shift(
200
- 1))
201
-
202
- # send with: shift + enter
203
- self.window.ui.nodes['input.send_shift_enter'] = QRadioButton(trans("input.radio.enter_shift"))
204
- self.window.ui.nodes['input.send_shift_enter'].clicked.connect(
205
- lambda: self.window.controller.chat.common.toggle_send_shift(
206
- 2))
207
-
208
- # send with: none
209
- self.window.ui.nodes['input.send_none'] = QRadioButton(trans("input.radio.none"))
210
- self.window.ui.nodes['input.send_none'].clicked.connect(
211
- lambda: self.window.controller.chat.common.toggle_send_shift(
212
- 0))
213
-
214
- # send clear
215
- self.window.ui.nodes['input.send_clear'] = QCheckBox(trans('input.send_clear'))
216
- self.window.ui.nodes['input.send_clear'].stateChanged.connect(
217
- lambda: self.window.controller.chat.common.toggle_send_clear(
218
- self.window.ui.nodes['input.send_clear'].isChecked()))
219
-
220
- # stream
221
- self.window.ui.nodes['input.stream'] = QCheckBox(trans('input.stream'))
222
- self.window.ui.nodes['input.stream'].stateChanged.connect(
223
- lambda: self.window.controller.chat.common.toggle_stream(self.window.ui.nodes['input.stream'].isChecked()))
224
-
225
- # send button
226
- self.window.ui.nodes['input.send_btn'] = QPushButton(trans("input.btn.send"))
227
- self.window.ui.nodes['input.send_btn'].clicked.connect(
228
- lambda: self.window.controller.chat.input.send_input())
229
-
230
- # stop button
231
- self.window.ui.nodes['input.stop_btn'] = QPushButton(trans("input.btn.stop"))
232
- self.window.ui.nodes['input.stop_btn'].setVisible(False)
233
- self.window.ui.nodes['input.stop_btn'].clicked.connect(
234
- lambda: self.window.controller.kernel.stop())
235
-
236
- # update button
237
- self.window.ui.nodes['input.update_btn'] = QPushButton(trans("input.btn.update"))
238
- self.window.ui.nodes['input.update_btn'].setVisible(False)
239
- self.window.ui.nodes['input.update_btn'].clicked.connect(
240
- lambda: self.window.controller.ctx.extra.edit_submit())
241
-
242
- # cancel button
243
- self.window.ui.nodes['input.cancel_btn'] = QPushButton(trans("input.btn.cancel"))
244
- self.window.ui.nodes['input.cancel_btn'].setVisible(False)
245
- self.window.ui.nodes['input.cancel_btn'].clicked.connect(
246
- lambda: self.window.controller.ctx.extra.edit_cancel())
247
-
248
- # layout
249
- self.window.ui.nodes['ui.input.buttons'] = QHBoxLayout()
250
- self.window.ui.nodes['ui.input.buttons'].addWidget(self.window.ui.nodes['input.stream'])
251
- self.window.ui.nodes['ui.input.buttons'].addWidget(self.window.ui.nodes['input.send_clear'])
252
- self.window.ui.nodes['ui.input.buttons'].addWidget(self.window.ui.nodes['input.send_enter'])
253
- self.window.ui.nodes['ui.input.buttons'].addWidget(self.window.ui.nodes['input.send_shift_enter'])
254
- self.window.ui.nodes['ui.input.buttons'].addWidget(self.window.ui.nodes['input.send_none'])
255
- self.window.ui.nodes['ui.input.buttons'].addWidget(self.window.ui.nodes['input.send_btn'])
256
- self.window.ui.nodes['ui.input.buttons'].addWidget(self.window.ui.nodes['input.stop_btn'])
257
- self.window.ui.nodes['ui.input.buttons'].addWidget(self.window.ui.nodes['input.cancel_btn'])
258
- self.window.ui.nodes['ui.input.buttons'].addWidget(self.window.ui.nodes['input.update_btn'])
259
- self.window.ui.nodes['ui.input.buttons'].setAlignment(Qt.AlignRight)
260
-
261
- return self.window.ui.nodes['ui.input.buttons']
184
+ nodes = self.window.ui.nodes
185
+ controller = self.window.controller
186
+
187
+ nodes['input.send_enter'] = QRadioButton(trans("input.radio.enter"))
188
+ nodes['input.send_enter'].toggled.connect(partial(self._on_send_mode_toggled, 1))
189
+
190
+ nodes['input.send_shift_enter'] = QRadioButton(trans("input.radio.enter_shift"))
191
+ nodes['input.send_shift_enter'].toggled.connect(partial(self._on_send_mode_toggled, 2))
192
+
193
+ nodes['input.send_none'] = QRadioButton(trans("input.radio.none"))
194
+ nodes['input.send_none'].toggled.connect(partial(self._on_send_mode_toggled, 0))
195
+
196
+ nodes['input.send_clear'] = QCheckBox(trans('input.send_clear'))
197
+ nodes['input.send_clear'].toggled.connect(controller.chat.common.toggle_send_clear)
198
+
199
+ nodes['input.stream'] = QCheckBox(trans('input.stream'))
200
+ nodes['input.stream'].toggled.connect(controller.chat.common.toggle_stream)
201
+
202
+ nodes['input.send_btn'] = QPushButton(trans("input.btn.send"))
203
+ nodes['input.send_btn'].clicked.connect(controller.chat.input.send_input)
204
+
205
+ nodes['input.stop_btn'] = QPushButton(trans("input.btn.stop"))
206
+ nodes['input.stop_btn'].setVisible(False)
207
+ nodes['input.stop_btn'].clicked.connect(controller.kernel.stop)
208
+
209
+ nodes['input.update_btn'] = QPushButton(trans("input.btn.update"))
210
+ nodes['input.update_btn'].setVisible(False)
211
+ nodes['input.update_btn'].clicked.connect(controller.ctx.extra.edit_submit)
212
+
213
+ nodes['input.cancel_btn'] = QPushButton(trans("input.btn.cancel"))
214
+ nodes['input.cancel_btn'].setVisible(False)
215
+ nodes['input.cancel_btn'].clicked.connect(controller.ctx.extra.edit_cancel)
216
+
217
+ nodes['ui.input.buttons'] = QHBoxLayout()
218
+ nodes['ui.input.buttons'].addWidget(nodes['input.stream'])
219
+ nodes['ui.input.buttons'].addWidget(nodes['input.send_clear'])
220
+ nodes['ui.input.buttons'].addWidget(nodes['input.send_enter'])
221
+ nodes['ui.input.buttons'].addWidget(nodes['input.send_shift_enter'])
222
+ nodes['ui.input.buttons'].addWidget(nodes['input.send_none'])
223
+ nodes['ui.input.buttons'].addWidget(nodes['input.send_btn'])
224
+ nodes['ui.input.buttons'].addWidget(nodes['input.stop_btn'])
225
+ nodes['ui.input.buttons'].addWidget(nodes['input.cancel_btn'])
226
+ nodes['ui.input.buttons'].addWidget(nodes['input.update_btn'])
227
+ nodes['ui.input.buttons'].setAlignment(Qt.AlignRight)
228
+
229
+ return nodes['ui.input.buttons']
230
+
231
+ def _on_send_mode_toggled(self, mode: int, checked: bool):
232
+ if checked:
233
+ self.window.controller.chat.common.toggle_send_shift(mode)
262
234
 
263
235
  def update_min_height(self):
264
236
  """
265
237
  Update the minimum height of the input tab
266
238
  """
267
- idx = self.window.ui.tabs['input'].currentIndex()
239
+ tabs = self.window.ui.tabs['input']
240
+ nodes = self.window.ui.nodes
241
+ splitters = self.window.ui.splitters
242
+ controller_ui = self.window.controller.ui
243
+
244
+ idx = tabs.currentIndex()
268
245
  if idx == 0:
269
- self.window.ui.nodes['input'].setMinimumHeight(self.min_height_input)
270
- self.window.ui.tabs['input'].setMinimumHeight(self.min_height_input_tab)
271
- if (self.window.controller.ui.splitter_output_size_input
272
- and self.window.controller.ui.splitter_output_size_input != [0,0]):
273
- self.window.ui.splitters['main.output'].setSizes(self.window.controller.ui.splitter_output_size_input)
246
+ nodes['input'].setMinimumHeight(self.min_height_input)
247
+ tabs.setMinimumHeight(self.min_height_input_tab)
248
+ sizes = controller_ui.splitter_output_size_input
249
+ if sizes and sizes != [0, 0]:
250
+ splitters['main.output'].setSizes(sizes)
274
251
  else:
275
- if (self.window.controller.ui.splitter_output_size_files
276
- and self.window.controller.ui.splitter_output_size_input != [0,0]):
277
- self.window.ui.splitters['main.output'].setSizes(self.window.controller.ui.splitter_output_size_files)
278
- self.window.ui.nodes['input'].setMinimumHeight(self.min_height_files_tab)
279
- self.window.ui.tabs['input'].setMinimumHeight(self.min_height_files_tab + 90)
252
+ sizes = controller_ui.splitter_output_size_files
253
+ if sizes and controller_ui.splitter_output_size_input != [0, 0]:
254
+ splitters['main.output'].setSizes(sizes)
255
+ nodes['input'].setMinimumHeight(self.min_height_files_tab)
256
+ tabs.setMinimumHeight(self.min_height_files_tab + 90)
@@ -6,28 +6,23 @@
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.07 19:00:00 #
9
+ # Updated Date: 2025.08.24 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtCore import Qt
13
- from PySide6.QtWidgets import QVBoxLayout, QLabel, QHBoxLayout, QCheckBox, QWidget, QSizePolicy, QPushButton, \
14
- QGridLayout, QWidgetItem, QLayout
13
+ from PySide6.QtWidgets import QVBoxLayout, QHBoxLayout, QCheckBox, QWidget, QSizePolicy, \
14
+ QGridLayout
15
15
 
16
16
  from pygpt_net.ui.widget.audio.output import AudioOutput
17
17
  from pygpt_net.ui.widget.element.labels import ChatStatusLabel, IconLabel, HelpLabel
18
- from pygpt_net.ui.widget.anims.loader import Loading
19
18
  from pygpt_net.ui.widget.tabs.layout import OutputLayout
19
+ from pygpt_net.utils import trans
20
20
 
21
21
  from .explorer import Explorer
22
22
  from .input import Input
23
23
  from .calendar import Calendar
24
24
  from .painter import Painter
25
25
 
26
- from pygpt_net.utils import trans
27
- import pygpt_net.icons_rc
28
-
29
-
30
-
31
26
  class Output:
32
27
  def __init__(self, window=None):
33
28
  """
@@ -47,10 +42,7 @@ class Output:
47
42
 
48
43
  :return: QWidget
49
44
  """
50
- # prepare columns
51
45
  self.window.ui.layout = OutputLayout(self.window)
52
-
53
- # create empty containers for chat output
54
46
  self.window.ui.nodes['output'] = {}
55
47
  self.window.ui.nodes['output_plain'] = {}
56
48
 
@@ -69,176 +61,122 @@ class Output:
69
61
 
70
62
  :return: QHBoxLayout
71
63
  """
72
- # video capture icon
73
- self.window.ui.nodes['icon.video.capture'] = IconLabel(":/icons/webcam.svg", window=self.window)
74
- self.window.ui.nodes['icon.video.capture'].setToolTip(trans("icon.video.capture"))
75
- self.window.ui.nodes['icon.video.capture'].clicked.connect(
76
- lambda:self.window.controller.camera.toggle_capture()
77
- )
78
-
79
- # audio output icon
80
- self.window.ui.nodes['icon.audio.output'] = IconLabel(":/icons/volume.svg", window=self.window)
81
- self.window.ui.nodes['icon.audio.output'].setToolTip(trans("icon.audio.output"))
82
- self.window.ui.nodes['icon.audio.output'].clicked.connect(
83
- lambda: self.window.controller.plugins.toggle('audio_output')
84
- )
85
-
86
- # audio input icon
87
- self.window.ui.nodes['icon.audio.input'] = IconLabel(":/icons/mic.svg", window=self.window)
88
- self.window.ui.nodes['icon.audio.input'].setToolTip(trans("icon.audio.input"))
89
- self.window.ui.nodes['icon.audio.input'].clicked.connect(
90
- lambda: self.window.controller.plugins.toggle('audio_input')
91
- )
92
-
93
- # interpreter icon
94
- self.window.ui.nodes['icon.interpreter'] = IconLabel(":/icons/code.svg", window=self.window)
95
- self.window.ui.nodes['icon.interpreter'].setToolTip("Python Code Interpreter")
96
- self.window.ui.nodes['icon.interpreter'].clicked.connect(
97
- lambda: self.window.tools.get("interpreter").toggle()
98
- )
99
-
100
- # indexer icon
101
- self.window.ui.nodes['icon.indexer'] = IconLabel(":/icons/db.svg", window=self.window)
102
- self.window.ui.nodes['icon.indexer'].setToolTip("Indexer")
103
- self.window.ui.nodes['icon.indexer'].clicked.connect(
104
- lambda: self.window.tools.get("indexer").toggle()
105
- )
106
-
107
- # mode
108
- self.window.ui.nodes['chat.label'] = ChatStatusLabel("")
109
- self.window.ui.nodes['chat.label'].setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
110
- self.window.ui.nodes['chat.label'].setWordWrap(False)
111
-
112
- # model
113
- self.window.ui.nodes['chat.model'] = ChatStatusLabel("")
114
- self.window.ui.nodes['chat.model'].setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
115
- self.window.ui.nodes['chat.model'].setWordWrap(False)
116
-
117
- # plugins
118
- self.window.ui.nodes['chat.plugins'] = ChatStatusLabel("")
119
- self.window.ui.nodes['chat.plugins'].setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
120
-
121
- # timestamp
122
- self.window.ui.nodes['output.timestamp'] = QCheckBox(trans('output.timestamp'))
123
- self.window.ui.nodes['output.timestamp'].stateChanged.connect(
124
- lambda: self.window.controller.chat.common.toggle_timestamp(
125
- self.window.ui.nodes['output.timestamp'].isChecked())
126
- )
127
-
128
- # plain text
129
- self.window.ui.nodes['output.raw'] = QCheckBox(trans('output.raw'))
130
- self.window.ui.nodes['output.raw'].clicked.connect(
131
- lambda: self.window.controller.chat.common.toggle_raw(
132
- self.window.ui.nodes['output.raw'].isChecked())
133
- )
64
+ nodes = self.window.ui.nodes
65
+ plugin_addon = self.window.ui.plugin_addon
66
+ ctrl = self.window.controller
67
+ tools = self.window.tools
134
68
 
135
- """
136
- # edit icons
137
- self.window.ui.nodes['output.edit'] = QCheckBox(trans('output.edit'))
138
- self.window.ui.nodes['output.edit'].clicked.connect(
139
- lambda: self.window.controller.chat.common.toggle_edit_icons(
140
- self.window.ui.nodes['output.edit'].isChecked())
141
- )
142
- """
69
+ nodes['icon.video.capture'] = IconLabel(":/icons/webcam.svg", window=self.window)
70
+ nodes['icon.video.capture'].setToolTip(trans("icon.video.capture"))
71
+ nodes['icon.video.capture'].clicked.connect(lambda: ctrl.camera.toggle_capture())
72
+
73
+ nodes['icon.audio.output'] = IconLabel(":/icons/volume.svg", window=self.window)
74
+ nodes['icon.audio.output'].setToolTip(trans("icon.audio.output"))
75
+ nodes['icon.audio.output'].clicked.connect(lambda: ctrl.plugins.toggle('audio_output'))
143
76
 
144
- # tokens
145
- self.window.ui.nodes['prompt.context'] = ChatStatusLabel("")
146
- self.window.ui.nodes['prompt.context'].setToolTip(trans('tip.tokens.ctx'))
147
- self.window.ui.nodes['prompt.context'].setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
77
+ nodes['icon.audio.input'] = IconLabel(":/icons/mic.svg", window=self.window)
78
+ nodes['icon.audio.input'].setToolTip(trans("icon.audio.input"))
79
+ nodes['icon.audio.input'].clicked.connect(lambda: ctrl.plugins.toggle('audio_input'))
148
80
 
149
- self.window.ui.nodes['input.counter'] = ChatStatusLabel("")
150
- self.window.ui.nodes['input.counter'].setToolTip(trans('tip.tokens.input'))
151
- self.window.ui.nodes['input.counter'].setWordWrap(False)
81
+ nodes['icon.interpreter'] = IconLabel(":/icons/code.svg", window=self.window)
82
+ nodes['icon.interpreter'].setToolTip("Python Code Interpreter")
83
+ nodes['icon.interpreter'].clicked.connect(lambda: tools.get("interpreter").toggle())
152
84
 
153
- # plugin audio output addon
154
- self.window.ui.plugin_addon['audio.output'] = AudioOutput(self.window)
85
+ nodes['icon.indexer'] = IconLabel(":/icons/db.svg", window=self.window)
86
+ nodes['icon.indexer'].setToolTip("Indexer")
87
+ nodes['icon.indexer'].clicked.connect(lambda: tools.get("indexer").toggle())
155
88
 
156
- # schedule
157
- self.window.ui.plugin_addon['schedule'] = ChatStatusLabel("")
89
+ min_policy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
158
90
 
159
- # inline vision
160
- self.window.ui.nodes['inline.vision'] = HelpLabel(trans('inline.vision'))
161
- self.window.ui.nodes['inline.vision'].setVisible(False)
162
- self.window.ui.nodes['inline.vision'].setContentsMargins(0, 0, 0, 0)
91
+ nodes['chat.label'] = ChatStatusLabel("")
92
+ nodes['chat.label'].setSizePolicy(min_policy)
93
+ nodes['chat.label'].setWordWrap(False)
94
+
95
+ nodes['chat.model'] = ChatStatusLabel("")
96
+ nodes['chat.model'].setSizePolicy(min_policy)
97
+ nodes['chat.model'].setWordWrap(False)
98
+
99
+ nodes['chat.plugins'] = ChatStatusLabel("")
100
+ nodes['chat.plugins'].setSizePolicy(min_policy)
101
+
102
+ nodes['output.timestamp'] = QCheckBox(trans('output.timestamp'))
103
+ nodes['output.timestamp'].toggled.connect(ctrl.chat.common.toggle_timestamp)
104
+
105
+ nodes['output.raw'] = QCheckBox(trans('output.raw'))
106
+ nodes['output.raw'].toggled.connect(ctrl.chat.common.toggle_raw)
107
+
108
+ nodes['prompt.context'] = ChatStatusLabel("")
109
+ nodes['prompt.context'].setToolTip(trans('tip.tokens.ctx'))
110
+ nodes['prompt.context'].setSizePolicy(min_policy)
111
+
112
+ nodes['input.counter'] = ChatStatusLabel("")
113
+ nodes['input.counter'].setToolTip(trans('tip.tokens.input'))
114
+ nodes['input.counter'].setWordWrap(False)
115
+
116
+ plugin_addon['audio.output'] = AudioOutput(self.window)
117
+ plugin_addon['schedule'] = ChatStatusLabel("")
118
+
119
+ nodes['inline.vision'] = HelpLabel(trans('inline.vision'))
120
+ nodes['inline.vision'].setVisible(False)
121
+ nodes['inline.vision'].setContentsMargins(0, 0, 0, 0)
163
122
 
164
123
  opts_layout = QHBoxLayout()
165
- # opts_layout.setSpacing(2) #
166
124
  opts_layout.setContentsMargins(0, 0, 0, 0)
167
- opts_layout.addWidget(self.window.ui.nodes['output.raw'])
168
- opts_layout.addWidget(self.window.ui.nodes['output.timestamp'])
169
- # opts_layout.addWidget(self.window.ui.nodes['output.edit'])
170
-
171
- opts_layout.addWidget(self.window.ui.nodes['inline.vision'])
125
+ opts_layout.addWidget(nodes['output.raw'])
126
+ opts_layout.addWidget(nodes['output.timestamp'])
127
+ opts_layout.addWidget(nodes['inline.vision'])
172
128
  opts_layout.setAlignment(Qt.AlignLeft)
173
129
 
174
- left_layout = QHBoxLayout()
175
- left_layout.addLayout(opts_layout)
176
- left_layout.setContentsMargins(0, 0, 0, 0)
177
-
178
- right_layout = QHBoxLayout()
179
- right_layout.addWidget(self.window.ui.nodes['icon.video.capture'])
180
- right_layout.addWidget(self.window.ui.nodes['icon.audio.input'])
181
- right_layout.addWidget(self.window.ui.nodes['icon.audio.output'])
182
- right_layout.addWidget(self.window.ui.nodes['icon.interpreter'])
183
- right_layout.addWidget(self.window.ui.nodes['icon.indexer'])
184
- right_layout.addWidget(self.window.ui.plugin_addon['schedule'])
185
- right_layout.addWidget(QLabel(" "))
186
- right_layout.addWidget(self.window.ui.nodes['chat.plugins'])
187
- right_layout.addWidget(QLabel(" "))
188
- right_layout.addWidget(self.window.ui.nodes['chat.label'])
189
- right_layout.addWidget(QLabel(" "))
190
- right_layout.addWidget(self.window.ui.nodes['chat.model'])
191
- right_layout.addWidget(QLabel(" "))
192
- right_layout.addWidget(self.window.ui.nodes['prompt.context'])
193
- right_layout.addWidget(QLabel(" "))
194
- right_layout.addWidget(self.window.ui.nodes['input.counter'])
195
- right_layout.setContentsMargins(0, 8, 20, 0)
196
-
197
- left_widget = QWidget()
198
- left_widget.setLayout(left_layout)
199
- right_widget = QWidget()
200
- right_widget.setLayout(right_layout)
201
-
202
- self.window.ui.nodes['anim.loading'] = QWidget()
203
- self.window.ui.nodes['anim.loading'].hide()
130
+ left_bar_layout = QHBoxLayout()
131
+ left_bar_layout.addLayout(opts_layout)
132
+ left_bar_layout.setContentsMargins(0, 0, 0, 0)
133
+
134
+ nodes['anim.loading'] = QWidget()
135
+ nodes['anim.loading'].hide()
136
+
137
+ right_bar_layout = QHBoxLayout()
138
+ right_bar_layout.addWidget(nodes['icon.video.capture'])
139
+ right_bar_layout.addWidget(nodes['icon.audio.input'])
140
+ right_bar_layout.addWidget(nodes['icon.audio.output'])
141
+ right_bar_layout.addWidget(nodes['icon.interpreter'])
142
+ right_bar_layout.addWidget(nodes['icon.indexer'])
143
+ right_bar_layout.addWidget(plugin_addon['schedule'])
144
+ right_bar_layout.addSpacing(6)
145
+ right_bar_layout.addWidget(nodes['chat.plugins'])
146
+ right_bar_layout.addSpacing(6)
147
+ right_bar_layout.addWidget(nodes['chat.label'])
148
+ right_bar_layout.addSpacing(12)
149
+ right_bar_layout.addWidget(nodes['chat.model'])
150
+ right_bar_layout.addSpacing(12)
151
+ right_bar_layout.addWidget(nodes['prompt.context'])
152
+ right_bar_layout.addSpacing(12)
153
+ right_bar_layout.addWidget(nodes['input.counter'])
154
+ right_bar_layout.setContentsMargins(0, 8, 20, 0)
204
155
 
205
156
  grid = QGridLayout()
206
-
207
- left_layout = QHBoxLayout()
208
- left_layout.addWidget(left_widget)
209
- #left_layout.addStretch(1)
210
- left_layout.setContentsMargins(0, 0, 0, 0)
211
-
212
- center_layout = QHBoxLayout()
213
- #center_layout.addStretch()
214
- center_layout.addWidget(self.window.ui.nodes['anim.loading'])
215
- center_layout.addStretch()
216
- center_layout.setContentsMargins(20, 0, 0, 0)
217
-
218
- right_layout = QHBoxLayout()
219
- right_layout.addStretch(1)
220
- right_layout.addWidget(right_widget)
221
- right_layout.setContentsMargins(0, 0, 0, 0)
222
-
223
- grid.addLayout(left_layout, 0, 0)
224
- grid.addLayout(center_layout, 0, 1, alignment=Qt.AlignCenter)
225
- grid.addLayout(right_layout, 0, 2, alignment=Qt.AlignRight)
157
+ grid.addLayout(left_bar_layout, 0, 0)
158
+ grid.addWidget(nodes['anim.loading'], 0, 1, alignment=Qt.AlignCenter)
159
+ grid.addLayout(right_bar_layout, 0, 2, alignment=Qt.AlignRight)
160
+ grid.setColumnStretch(0, 0)
161
+ grid.setColumnStretch(1, 1)
162
+ grid.setColumnStretch(2, 0)
226
163
  grid.setContentsMargins(0, 0, 0, 0)
227
164
 
228
- self.window.ui.nodes['chat.footer'] = QWidget()
229
- self.window.ui.nodes['chat.footer'].setLayout(grid)
165
+ nodes['chat.footer'] = QWidget()
166
+ nodes['chat.footer'].setLayout(grid)
230
167
 
231
168
  bottom_layout = QVBoxLayout()
232
- bottom_layout.addWidget(self.window.ui.nodes['chat.footer'])
169
+ bottom_layout.addWidget(nodes['chat.footer'])
233
170
  bottom_layout.setContentsMargins(2, 0, 2, 0)
234
171
  return bottom_layout
235
172
 
236
173
  def set_fixed_size_policy(self, layout):
237
174
  for i in range(layout.count()):
238
175
  item = layout.itemAt(i)
239
- if isinstance(item, QWidgetItem):
240
- widget = item.widget()
241
- if widget:
242
- widget.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
243
- elif isinstance(item, QLayout):
244
- self.set_fixed_size_policy(item)
176
+ w = item.widget()
177
+ if w is not None:
178
+ w.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
179
+ else:
180
+ l = item.layout()
181
+ if l is not None:
182
+ self.set_fixed_size_policy(l)