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.
Files changed (160) hide show
  1. pygpt_net/CHANGELOG.txt +12 -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/agent/llama.py +3 -0
  7. pygpt_net/controller/assistant/batch.py +2 -3
  8. pygpt_net/controller/assistant/editor.py +2 -2
  9. pygpt_net/controller/assistant/files.py +2 -3
  10. pygpt_net/controller/assistant/store.py +2 -2
  11. pygpt_net/controller/audio/audio.py +2 -2
  12. pygpt_net/controller/chat/response.py +4 -0
  13. pygpt_net/controller/ctx/ctx.py +2 -1
  14. pygpt_net/controller/files/files.py +24 -55
  15. pygpt_net/controller/idx/indexer.py +85 -76
  16. pygpt_net/controller/lang/lang.py +52 -34
  17. pygpt_net/controller/model/importer.py +2 -2
  18. pygpt_net/controller/notepad/notepad.py +86 -84
  19. pygpt_net/controller/plugins/settings.py +3 -4
  20. pygpt_net/controller/settings/profile.py +105 -124
  21. pygpt_net/controller/theme/menu.py +154 -57
  22. pygpt_net/controller/theme/nodes.py +51 -44
  23. pygpt_net/controller/theme/theme.py +33 -9
  24. pygpt_net/controller/tools/tools.py +2 -2
  25. pygpt_net/controller/ui/tabs.py +2 -3
  26. pygpt_net/core/agents/observer/evaluation.py +2 -2
  27. pygpt_net/core/agents/runners/loop.py +1 -0
  28. pygpt_net/core/bridge/bridge.py +2 -0
  29. pygpt_net/core/ctx/container.py +13 -12
  30. pygpt_net/core/ctx/output.py +7 -4
  31. pygpt_net/core/debug/console/console.py +2 -2
  32. pygpt_net/core/filesystem/actions.py +1 -2
  33. pygpt_net/core/filesystem/opener.py +261 -0
  34. pygpt_net/core/filesystem/url.py +13 -10
  35. pygpt_net/core/platforms/platforms.py +5 -4
  36. pygpt_net/core/render/plain/helpers.py +2 -5
  37. pygpt_net/core/render/plain/renderer.py +26 -30
  38. pygpt_net/core/render/web/body.py +1 -1
  39. pygpt_net/core/settings/settings.py +43 -13
  40. pygpt_net/core/tabs/tabs.py +20 -13
  41. pygpt_net/data/config/config.json +4 -4
  42. pygpt_net/data/config/models.json +3 -3
  43. pygpt_net/data/css/web-blocks.dark.css +7 -1
  44. pygpt_net/data/css/web-blocks.light.css +5 -2
  45. pygpt_net/data/css/web-chatgpt.dark.css +7 -1
  46. pygpt_net/data/css/web-chatgpt.light.css +3 -0
  47. pygpt_net/data/css/web-chatgpt_wide.dark.css +7 -1
  48. pygpt_net/data/css/web-chatgpt_wide.light.css +3 -0
  49. pygpt_net/data/locale/locale.de.ini +5 -1
  50. pygpt_net/data/locale/locale.en.ini +5 -1
  51. pygpt_net/data/locale/locale.es.ini +5 -1
  52. pygpt_net/data/locale/locale.fr.ini +5 -1
  53. pygpt_net/data/locale/locale.it.ini +5 -1
  54. pygpt_net/data/locale/locale.pl.ini +6 -4
  55. pygpt_net/data/locale/locale.uk.ini +5 -1
  56. pygpt_net/data/locale/locale.zh.ini +5 -1
  57. pygpt_net/plugin/twitter/plugin.py +2 -2
  58. pygpt_net/provider/core/config/patch.py +12 -1
  59. pygpt_net/tools/audio_transcriber/ui/dialogs.py +44 -54
  60. pygpt_net/tools/code_interpreter/body.py +1 -2
  61. pygpt_net/tools/code_interpreter/tool.py +7 -4
  62. pygpt_net/tools/code_interpreter/ui/html.py +1 -3
  63. pygpt_net/tools/code_interpreter/ui/widgets.py +2 -3
  64. pygpt_net/tools/html_canvas/ui/widgets.py +1 -3
  65. pygpt_net/tools/image_viewer/ui/dialogs.py +40 -37
  66. pygpt_net/tools/indexer/ui/widgets.py +2 -4
  67. pygpt_net/tools/media_player/tool.py +2 -5
  68. pygpt_net/tools/media_player/ui/widgets.py +60 -36
  69. pygpt_net/tools/text_editor/ui/widgets.py +18 -19
  70. pygpt_net/tools/translator/ui/widgets.py +39 -35
  71. pygpt_net/ui/base/context_menu.py +9 -4
  72. pygpt_net/ui/dialog/db.py +1 -3
  73. pygpt_net/ui/dialog/models.py +1 -3
  74. pygpt_net/ui/dialog/models_importer.py +2 -4
  75. pygpt_net/ui/dialogs.py +34 -30
  76. pygpt_net/ui/layout/chat/attachments.py +72 -84
  77. pygpt_net/ui/layout/chat/attachments_ctx.py +40 -44
  78. pygpt_net/ui/layout/chat/attachments_uploaded.py +36 -39
  79. pygpt_net/ui/layout/chat/calendar.py +100 -70
  80. pygpt_net/ui/layout/chat/chat.py +23 -17
  81. pygpt_net/ui/layout/chat/input.py +95 -118
  82. pygpt_net/ui/layout/chat/output.py +100 -162
  83. pygpt_net/ui/layout/chat/painter.py +89 -61
  84. pygpt_net/ui/layout/ctx/ctx_list.py +43 -52
  85. pygpt_net/ui/layout/status.py +23 -14
  86. pygpt_net/ui/layout/toolbox/agent.py +27 -38
  87. pygpt_net/ui/layout/toolbox/agent_llama.py +41 -45
  88. pygpt_net/ui/layout/toolbox/assistants.py +42 -38
  89. pygpt_net/ui/layout/toolbox/computer_env.py +32 -23
  90. pygpt_net/ui/layout/toolbox/footer.py +13 -16
  91. pygpt_net/ui/layout/toolbox/image.py +18 -21
  92. pygpt_net/ui/layout/toolbox/indexes.py +46 -89
  93. pygpt_net/ui/layout/toolbox/mode.py +20 -7
  94. pygpt_net/ui/layout/toolbox/model.py +12 -10
  95. pygpt_net/ui/layout/toolbox/presets.py +68 -52
  96. pygpt_net/ui/layout/toolbox/prompt.py +31 -58
  97. pygpt_net/ui/layout/toolbox/toolbox.py +25 -21
  98. pygpt_net/ui/layout/toolbox/vision.py +20 -22
  99. pygpt_net/ui/main.py +2 -4
  100. pygpt_net/ui/menu/about.py +64 -84
  101. pygpt_net/ui/menu/audio.py +87 -63
  102. pygpt_net/ui/menu/config.py +121 -127
  103. pygpt_net/ui/menu/debug.py +69 -76
  104. pygpt_net/ui/menu/file.py +32 -35
  105. pygpt_net/ui/menu/menu.py +2 -3
  106. pygpt_net/ui/menu/plugins.py +69 -33
  107. pygpt_net/ui/menu/theme.py +45 -46
  108. pygpt_net/ui/menu/tools.py +56 -60
  109. pygpt_net/ui/menu/video.py +20 -25
  110. pygpt_net/ui/tray.py +1 -2
  111. pygpt_net/ui/widget/audio/bar.py +1 -3
  112. pygpt_net/ui/widget/audio/input_button.py +3 -4
  113. pygpt_net/ui/widget/calendar/select.py +1 -2
  114. pygpt_net/ui/widget/dialog/base.py +12 -9
  115. pygpt_net/ui/widget/dialog/editor_file.py +20 -23
  116. pygpt_net/ui/widget/dialog/find.py +25 -24
  117. pygpt_net/ui/widget/dialog/profile.py +57 -53
  118. pygpt_net/ui/widget/draw/painter.py +62 -93
  119. pygpt_net/ui/widget/element/button.py +42 -30
  120. pygpt_net/ui/widget/element/checkbox.py +23 -15
  121. pygpt_net/ui/widget/element/group.py +6 -5
  122. pygpt_net/ui/widget/element/labels.py +1 -2
  123. pygpt_net/ui/widget/filesystem/explorer.py +93 -102
  124. pygpt_net/ui/widget/image/display.py +1 -2
  125. pygpt_net/ui/widget/lists/assistant.py +1 -2
  126. pygpt_net/ui/widget/lists/attachment.py +1 -2
  127. pygpt_net/ui/widget/lists/attachment_ctx.py +1 -2
  128. pygpt_net/ui/widget/lists/context.py +2 -4
  129. pygpt_net/ui/widget/lists/index.py +1 -2
  130. pygpt_net/ui/widget/lists/model.py +1 -2
  131. pygpt_net/ui/widget/lists/model_editor.py +1 -2
  132. pygpt_net/ui/widget/lists/model_importer.py +1 -2
  133. pygpt_net/ui/widget/lists/preset.py +1 -2
  134. pygpt_net/ui/widget/lists/preset_plugins.py +1 -2
  135. pygpt_net/ui/widget/lists/profile.py +1 -2
  136. pygpt_net/ui/widget/lists/uploaded.py +1 -2
  137. pygpt_net/ui/widget/option/checkbox.py +2 -4
  138. pygpt_net/ui/widget/option/checkbox_list.py +1 -4
  139. pygpt_net/ui/widget/option/cmd.py +1 -4
  140. pygpt_net/ui/widget/option/dictionary.py +25 -28
  141. pygpt_net/ui/widget/option/input.py +1 -3
  142. pygpt_net/ui/widget/tabs/Input.py +16 -12
  143. pygpt_net/ui/widget/tabs/body.py +5 -3
  144. pygpt_net/ui/widget/tabs/layout.py +41 -28
  145. pygpt_net/ui/widget/tabs/output.py +442 -85
  146. pygpt_net/ui/widget/textarea/calendar_note.py +1 -2
  147. pygpt_net/ui/widget/textarea/editor.py +41 -73
  148. pygpt_net/ui/widget/textarea/find.py +11 -10
  149. pygpt_net/ui/widget/textarea/html.py +3 -6
  150. pygpt_net/ui/widget/textarea/input.py +134 -69
  151. pygpt_net/ui/widget/textarea/notepad.py +54 -38
  152. pygpt_net/ui/widget/textarea/output.py +65 -54
  153. pygpt_net/ui/widget/textarea/search_input.py +5 -4
  154. pygpt_net/ui/widget/textarea/web.py +2 -4
  155. pygpt_net/ui/widget/vision/camera.py +2 -31
  156. {pygpt_net-2.6.21.dist-info → pygpt_net-2.6.23.dist-info}/METADATA +38 -174
  157. {pygpt_net-2.6.21.dist-info → pygpt_net-2.6.23.dist-info}/RECORD +160 -159
  158. {pygpt_net-2.6.21.dist-info → pygpt_net-2.6.23.dist-info}/LICENSE +0 -0
  159. {pygpt_net-2.6.21.dist-info → pygpt_net-2.6.23.dist-info}/WHEEL +0 -0
  160. {pygpt_net-2.6.21.dist-info → pygpt_net-2.6.23.dist-info}/entry_points.txt +0 -0
@@ -6,11 +6,12 @@
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.19 02:00:00 #
9
+ # Updated Date: 2025.08.24 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtGui import QPixmap, QIcon
13
13
  from PySide6.QtWidgets import QVBoxLayout, QHBoxLayout, QWidget, QRadioButton, QPushButton, QComboBox, QScrollArea
14
+ from PySide6.QtCore import QSize
14
15
 
15
16
  from pygpt_net.ui.widget.draw.painter import PainterWidget
16
17
  from pygpt_net.ui.widget.element.labels import HelpLabel
@@ -26,6 +27,7 @@ class Painter:
26
27
  :param window: Window instance
27
28
  """
28
29
  self.window = window
30
+ self._initialized = False
29
31
 
30
32
  def init(self):
31
33
  """
@@ -33,47 +35,62 @@ class Painter:
33
35
 
34
36
  :return: QWidget
35
37
  """
36
- self.window.ui.painter = PainterWidget(self.window)
38
+ ui = self.window.ui
39
+ nodes = ui.nodes
40
+ common = self.window.controller.painter.common
41
+
42
+ if getattr(ui, 'painter', None) is None:
43
+ ui.painter = PainterWidget(self.window)
37
44
 
38
45
  key = 'painter.btn.brush'
39
- self.window.ui.nodes[key] = QRadioButton(trans('painter.mode.paint'))
40
- self.window.ui.nodes[key].setChecked(True)
41
- self.window.ui.nodes[key].toggled.connect(self.window.controller.painter.common.set_brush_mode)
46
+ if nodes.get(key) is None:
47
+ rb = QRadioButton(trans('painter.mode.paint'))
48
+ rb.setChecked(True)
49
+ rb.toggled.connect(self.window.controller.painter.common.set_brush_mode)
50
+ nodes[key] = rb
42
51
 
43
52
  key = 'painter.btn.erase'
44
- self.window.ui.nodes[key] = QRadioButton(trans('painter.mode.erase'))
45
- self.window.ui.nodes[key].toggled.connect(self.window.controller.painter.common.set_erase_mode)
53
+ if nodes.get(key) is None:
54
+ rb = QRadioButton(trans('painter.mode.erase'))
55
+ rb.toggled.connect(self.window.controller.painter.common.set_erase_mode)
56
+ nodes[key] = rb
46
57
 
47
58
  key = 'painter.select.brush.size'
48
- sizes = self.window.controller.painter.common.get_sizes()
49
- self.window.ui.nodes[key] = QComboBox()
50
- self.window.ui.nodes[key].addItems(sizes)
51
- self.window.ui.nodes[key].currentTextChanged.connect(
52
- self.window.controller.painter.common.change_brush_size)
53
- self.window.ui.nodes[key].setMinimumContentsLength(10)
54
- self.window.ui.nodes[key].setSizeAdjustPolicy(QComboBox.AdjustToContents)
59
+ if nodes.get(key) is None:
60
+ sizes = common.get_sizes()
61
+ cb = QComboBox()
62
+ cb.addItems(sizes)
63
+ cb.currentTextChanged.connect(common.change_brush_size)
64
+ cb.setMinimumContentsLength(10)
65
+ cb.setSizeAdjustPolicy(QComboBox.AdjustToContents)
66
+ nodes[key] = cb
55
67
 
56
68
  key = 'painter.select.canvas.size'
57
- canvas_sizes = self.window.controller.painter.common.get_canvas_sizes()
58
- self.window.ui.nodes[key] = QComboBox()
59
- self.window.ui.nodes[key].addItems(canvas_sizes)
60
- self.window.ui.nodes[key].setMinimumContentsLength(20)
61
- self.window.ui.nodes[key].setSizeAdjustPolicy(QComboBox.AdjustToContents)
62
- self.window.ui.nodes[key].currentTextChanged.connect(
63
- self.window.controller.painter.common.change_canvas_size)
69
+ if nodes.get(key) is None:
70
+ canvas_sizes = common.get_canvas_sizes()
71
+ cb = QComboBox()
72
+ cb.addItems(canvas_sizes)
73
+ cb.setMinimumContentsLength(20)
74
+ cb.setSizeAdjustPolicy(QComboBox.AdjustToContents)
75
+ cb.currentTextChanged.connect(common.change_canvas_size)
76
+ nodes[key] = cb
64
77
 
65
78
  key = 'painter.select.brush.color'
66
- self.window.ui.nodes[key] = QComboBox()
67
- colors = self.window.controller.painter.common.get_colors()
68
- for color_name, color_value in colors.items():
69
- pixmap = QPixmap(100, 100)
70
- pixmap.fill(color_value)
71
- icon = QIcon(pixmap)
72
- self.window.ui.nodes[key].addItem(icon, color_name, color_value)
73
- self.window.ui.nodes[key].currentTextChanged.connect(
74
- self.window.controller.painter.common.change_brush_color)
75
- self.window.ui.nodes[key].setMinimumContentsLength(10)
76
- self.window.ui.nodes[key].setSizeAdjustPolicy(QComboBox.AdjustToContents)
79
+ if nodes.get(key) is None:
80
+ cb = QComboBox()
81
+ cb.setIconSize(QSize(16, 16))
82
+ colors = common.get_colors()
83
+ for color_name, color_value in colors.items():
84
+ pixmap = QPixmap(16, 16)
85
+ pixmap.fill(color_value)
86
+ icon = QIcon(pixmap)
87
+ cb.addItem(icon, color_name, color_value)
88
+ cb.currentTextChanged.connect(common.change_brush_color)
89
+ cb.setMinimumContentsLength(10)
90
+ cb.setSizeAdjustPolicy(QComboBox.AdjustToContents)
91
+ nodes[key] = cb
92
+
93
+ self._initialized = True
77
94
 
78
95
  def setup(self) -> QWidget:
79
96
  """
@@ -81,7 +98,6 @@ class Painter:
81
98
 
82
99
  :return: QWidget
83
100
  """
84
- # build tab body
85
101
  self.init()
86
102
  body = self.window.core.tabs.from_layout(self.setup_painter())
87
103
  body.append(self.window.ui.painter)
@@ -93,39 +109,51 @@ class Painter:
93
109
 
94
110
  :return: QVBoxLayout
95
111
  """
112
+ ui = self.window.ui
113
+ nodes = ui.nodes
114
+
96
115
  top = QHBoxLayout()
97
- top.addWidget(self.window.ui.nodes['painter.btn.brush'])
98
- top.addWidget(self.window.ui.nodes['painter.btn.erase'])
99
- top.addWidget(self.window.ui.nodes['painter.select.brush.size'])
100
- top.addWidget(self.window.ui.nodes['painter.select.brush.color'])
101
- top.addWidget(self.window.ui.nodes['painter.select.canvas.size'])
116
+ top.addWidget(nodes['painter.btn.brush'])
117
+ top.addWidget(nodes['painter.btn.erase'])
118
+ top.addWidget(nodes['painter.select.brush.size'])
119
+ top.addWidget(nodes['painter.select.brush.color'])
120
+ top.addWidget(nodes['painter.select.canvas.size'])
102
121
  top.addStretch(1)
103
122
 
104
- self.window.ui.nodes['painter.btn.capture'] = QPushButton(trans('painter.btn.capture'))
105
- self.window.ui.nodes['painter.btn.capture'].clicked.connect(self.window.controller.painter.capture.use)
106
- top.addWidget(self.window.ui.nodes['painter.btn.capture'])
107
-
108
- self.window.ui.nodes['painter.btn.camera.capture'] = QPushButton(trans('painter.btn.camera.capture'))
109
- self.window.ui.nodes['painter.btn.camera.capture'].clicked.connect(self.window.controller.painter.capture.camera)
110
- top.addWidget(self.window.ui.nodes['painter.btn.camera.capture'])
111
-
112
- self.window.ui.nodes['painter.btn.clear'] = QPushButton(trans('painter.btn.clear'))
113
- self.window.ui.nodes['painter.btn.clear'].clicked.connect(self.window.ui.painter.clear_image)
114
- top.addWidget(self.window.ui.nodes['painter.btn.clear'])
115
-
116
- self.window.ui.painter_scroll = QScrollArea()
117
- self.window.ui.painter_scroll.setWidget(self.window.ui.painter)
118
- self.window.ui.painter_scroll.setWidgetResizable(True)
119
-
120
- self.window.ui.nodes['tip.output.tab.draw'] = HelpLabel(trans('tip.output.tab.draw'), self.window)
123
+ if nodes.get('painter.btn.capture') is None:
124
+ btn = QPushButton(trans('painter.btn.capture'))
125
+ btn.clicked.connect(self.window.controller.painter.capture.use)
126
+ nodes['painter.btn.capture'] = btn
127
+ top.addWidget(nodes['painter.btn.capture'])
128
+
129
+ if nodes.get('painter.btn.camera.capture') is None:
130
+ btn = QPushButton(trans('painter.btn.camera.capture'))
131
+ btn.clicked.connect(self.window.controller.painter.capture.camera)
132
+ nodes['painter.btn.camera.capture'] = btn
133
+ top.addWidget(nodes['painter.btn.camera.capture'])
134
+
135
+ if nodes.get('painter.btn.clear') is None:
136
+ btn = QPushButton(trans('painter.btn.clear'))
137
+ btn.clicked.connect(ui.painter.clear_image)
138
+ nodes['painter.btn.clear'] = btn
139
+ top.addWidget(nodes['painter.btn.clear'])
140
+
141
+ if getattr(ui, 'painter_scroll', None) is None:
142
+ ui.painter_scroll = QScrollArea()
143
+ ui.painter_scroll.setWidget(ui.painter)
144
+ ui.painter_scroll.setWidgetResizable(True)
145
+ else:
146
+ if ui.painter_scroll.widget() is not ui.painter:
147
+ ui.painter_scroll.setWidget(ui.painter)
148
+ ui.painter_scroll.setWidgetResizable(True)
149
+
150
+ if nodes.get('tip.output.tab.draw') is None:
151
+ nodes['tip.output.tab.draw'] = HelpLabel(trans('tip.output.tab.draw'), self.window)
121
152
 
122
153
  layout = QVBoxLayout()
123
154
  layout.addLayout(top)
124
- layout.addWidget( self.window.ui.painter_scroll)
125
- layout.addWidget(self.window.ui.nodes['tip.output.tab.draw'])
155
+ layout.addWidget(ui.painter_scroll)
156
+ layout.addWidget(nodes['tip.output.tab.draw'])
126
157
  layout.setContentsMargins(0, 0, 0, 0)
127
158
 
128
- return layout
129
-
130
-
131
-
159
+ return layout
@@ -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.16 00:00:00 #
9
+ # Updated Date: 2025.08.24 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6 import QtCore
@@ -20,7 +20,6 @@ from pygpt_net.ui.widget.element.button import NewCtxButton
20
20
  from pygpt_net.ui.widget.element.labels import TitleLabel
21
21
  from pygpt_net.ui.widget.lists.context import ContextList, Item, GroupItem, SectionItem
22
22
  from pygpt_net.utils import trans
23
- import pygpt_net.icons_rc
24
23
 
25
24
 
26
25
  class CtxList:
@@ -32,6 +31,8 @@ class CtxList:
32
31
  """
33
32
  self.window = window
34
33
  self.search_input = SearchInput(window)
34
+ self._group_separators = False
35
+ self._pinned_separators = False
35
36
 
36
37
  def setup(self) -> QWidget:
37
38
  """
@@ -39,28 +40,40 @@ class CtxList:
39
40
 
40
41
  :return: QWidget
41
42
  """
42
- id = 'ctx.list'
43
- self.window.ui.nodes['ctx.new'] = NewCtxButton(trans('ctx.new'), self.window)
44
- self.window.ui.nodes[id] = ContextList(self.window, id)
45
- self.window.ui.nodes[id].selection_locked = self.window.controller.ctx.context_change_locked
46
- self.window.ui.nodes['ctx.label'] = TitleLabel(trans("ctx.list.label"))
47
- self.window.ui.nodes['ctx.new'].setContentsMargins(0,0,0,0)
43
+ ctx_id = 'ctx.list'
44
+ ui = self.window.ui
45
+ nodes = ui.nodes
46
+ models = ui.models
47
+
48
+ widget = QWidget()
49
+ widget.setContentsMargins(0, 0, 0, 0)
50
+
51
+ new_btn = NewCtxButton(trans('ctx.new'), self.window)
52
+ new_btn.setContentsMargins(0, 0, 0, 0)
53
+ nodes['ctx.new'] = new_btn
54
+
55
+ ctx_list = ContextList(self.window, ctx_id)
56
+ ctx_list.selection_locked = self.window.controller.ctx.context_change_locked
57
+ nodes[ctx_id] = ctx_list
58
+
59
+ nodes['ctx.label'] = TitleLabel(trans("ctx.list.label"))
48
60
  search_input = self.search_input.setup()
49
61
 
50
- layout = QVBoxLayout()
51
- layout.addWidget(self.window.ui.nodes['ctx.new'])
52
- layout.addWidget(search_input)
53
- layout.addWidget(self.window.ui.nodes[id])
62
+ layout = QVBoxLayout(widget)
54
63
  layout.setContentsMargins(0, 0, 0, 0)
64
+ layout.addWidget(new_btn)
65
+ layout.addWidget(search_input)
66
+ layout.addWidget(ctx_list)
55
67
 
56
- self.window.ui.models[id] = self.create_model(self.window)
57
- self.window.ui.nodes[id].setModel(self.window.ui.models[id])
58
- self.window.ui.nodes[id].selectionModel().selectionChanged.connect(
59
- lambda: self.window.controller.ctx.selection_change()
60
- )
61
- widget = QWidget()
62
- widget.setLayout(layout)
63
- widget.setContentsMargins(0, 0, 0, 0)
68
+ model = self.create_model(self.window)
69
+ models[ctx_id] = model
70
+ ctx_list.setModel(model)
71
+
72
+ ctx = self.window.controller.ctx
73
+ ctx_list.selectionModel().selectionChanged.connect(lambda *_: ctx.selection_change())
74
+
75
+ self._group_separators = self.window.core.config.get("ctx.records.groups.separators")
76
+ self._pinned_separators = self.window.core.config.get("ctx.records.pinned.separators")
64
77
 
65
78
  return widget
66
79
 
@@ -84,6 +97,9 @@ class CtxList:
84
97
  node = self.window.ui.nodes[id]
85
98
  node.backup_selection()
86
99
 
100
+ self._group_separators = self.window.core.config.get("ctx.records.groups.separators")
101
+ self._pinned_separators = self.window.core.config.get("ctx.records.pinned.separators")
102
+
87
103
  model = self.window.ui.models.get(id)
88
104
  if model is not None:
89
105
  node.setUpdatesEnabled(False)
@@ -109,16 +125,12 @@ class CtxList:
109
125
  """
110
126
  i = 0
111
127
  last_dt_str = None
112
- config = self.window.core.config
113
- separators = config.get("ctx.records.separators")
114
- pinned_separators = config.get("ctx.records.pinned.separators")
115
128
  model = self.window.ui.models[id]
116
-
117
129
  for meta_id, meta in data.items():
118
130
  gid = meta.group_id
119
131
  if (gid is None or gid == 0) and not meta.important:
120
132
  item = self.build_item(meta_id, meta, is_group=False)
121
- if separators and (not item.isPinned or pinned_separators):
133
+ if self._group_separators and (not item.isPinned or self._pinned_separators):
122
134
  if i == 0 or last_dt_str != item.dt:
123
135
  section = self.build_date_section(item.dt, group=False)
124
136
  if section:
@@ -137,15 +149,12 @@ class CtxList:
137
149
  i = 0
138
150
  last_dt_str = None
139
151
  model = self.window.ui.models[id]
140
- config = self.window.core.config
141
- separators = config.get("ctx.records.separators")
142
- pinned_separators = config.get("ctx.records.pinned.separators")
143
152
 
144
153
  for meta_id, meta in data.items():
145
154
  gid = meta.group_id
146
155
  if (gid is None or gid == 0) and meta.important:
147
156
  item = self.build_item(meta_id, meta, is_group=False)
148
- if separators and pinned_separators:
157
+ if self._group_separators and self._pinned_separators:
149
158
  if i == 0 or last_dt_str != item.dt:
150
159
  section = self.build_date_section(item.dt, group=False)
151
160
  if section:
@@ -165,10 +174,6 @@ class CtxList:
165
174
  model = self.window.ui.models[id]
166
175
  groups = self.window.core.ctx.get_groups()
167
176
  search_string = self.window.core.ctx.get_search_string()
168
- config = self.window.core.config
169
- is_group_separators = config.get("ctx.records.groups.separators")
170
- is_pinned_separators = config.get("ctx.records.pinned.separators")
171
-
172
177
  grouped = {}
173
178
  for meta_id, meta in data.items():
174
179
  gid = meta.group_id
@@ -213,7 +218,7 @@ class CtxList:
213
218
  i = 0
214
219
  for meta_id, meta in items_in_group:
215
220
  item = self.build_item(meta_id, meta, is_group=True)
216
- if is_group_separators and (not item.isPinned or is_pinned_separators):
221
+ if self._group_separators and (not item.isPinned or self._pinned_separators):
217
222
  if i == 0 or last_dt_str != item.dt:
218
223
  section = self.build_date_section(item.dt, group=True)
219
224
  if section:
@@ -259,13 +264,7 @@ class CtxList:
259
264
  is_important = data.important
260
265
  is_attachment = data.has_additional_ctx()
261
266
  in_group = bool(data.group)
262
-
263
- if is_group:
264
- if self.window.core.config.get("ctx.records.groups.separators"):
265
- append_dt = False
266
- else:
267
- if self.window.core.config.get("ctx.records.separators"):
268
- append_dt = False
267
+ append_dt = False if (is_group and self._pinned_separators) or ((not is_group) and self._group_separators) else append_dt
269
268
 
270
269
  dt = self.convert_date(data.updated)
271
270
  date_time_str = datetime.fromtimestamp(data.updated).strftime("%Y-%m-%d %H:%M")
@@ -274,15 +273,8 @@ class CtxList:
274
273
  title = title[:80] + '...'
275
274
  clean_title = title.replace("\n", "")
276
275
 
277
- if append_dt:
278
- name = f"{clean_title} ({dt})"
279
- else:
280
- name = clean_title
281
-
282
- mode_str = ''
283
- if data.last_mode is not None:
284
- mode_str = f" ({trans('mode.' + data.last_mode)})"
285
-
276
+ name = f"{clean_title} ({dt})" if append_dt else clean_title
277
+ mode_str = f" ({trans('mode.' + data.last_mode)})" if data.last_mode is not None else ""
286
278
  tooltip_text = f"{date_time_str}: {data.name}{mode_str} #{id}"
287
279
 
288
280
  if is_attachment:
@@ -317,8 +309,7 @@ class CtxList:
317
309
  :param group: is group
318
310
  :return: SectionItem
319
311
  """
320
- item = SectionItem(dt, group=group)
321
- return item
312
+ return SectionItem(dt, group=group)
322
313
 
323
314
  def convert_date(self, timestamp: int) -> str:
324
315
  """
@@ -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: 2023.12.25 21:00:00 #
9
+ # Updated Date: 2025.08.24 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtCore import Qt
@@ -32,20 +32,29 @@ class Status:
32
32
 
33
33
  :return: QHBoxLayout
34
34
  """
35
- self.window.ui.nodes['status'] = QLabel(trans('status.started'))
36
- self.window.ui.nodes['status.agent'] = HelpLabel("")
37
- self.window.ui.nodes['status.agent'].setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
38
- self.window.ui.nodes['global.stop'] = QPushButton("STOP")
39
- self.window.ui.nodes['global.stop'].setVisible(False)
40
- self.window.ui.nodes['global.stop'].clicked.connect(self.window.controller.ui.on_global_stop)
41
- self.window.ui.nodes['anim.loading.status'] = Loader()
42
- self.window.ui.nodes['anim.loading.status'].hide()
35
+ nodes = self.window.ui.nodes
36
+
37
+ nodes['status'] = QLabel(trans('status.started'))
38
+ nodes['status'].setParent(self.window)
39
+
40
+ nodes['status.agent'] = HelpLabel("")
41
+ nodes['status.agent'].setParent(self.window)
42
+ nodes['status.agent'].setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
43
+
44
+ nodes['global.stop'] = QPushButton("STOP")
45
+ nodes['global.stop'].setParent(self.window)
46
+ nodes['global.stop'].hide()
47
+ nodes['global.stop'].clicked.connect(self.window.controller.ui.on_global_stop)
48
+
49
+ nodes['anim.loading.status'] = Loader()
50
+ nodes['anim.loading.status'].setParent(self.window)
51
+ nodes['anim.loading.status'].hide()
43
52
 
44
53
  layout = QHBoxLayout()
45
- layout.addWidget(self.window.ui.nodes['anim.loading.status'])
46
- layout.addWidget(self.window.ui.nodes['status.agent'])
47
- layout.addWidget(self.window.ui.nodes['status'])
48
- layout.addWidget(self.window.ui.nodes['global.stop'])
54
+ layout.addWidget(nodes['anim.loading.status'])
55
+ layout.addWidget(nodes['status.agent'])
56
+ layout.addWidget(nodes['status'])
57
+ layout.addWidget(nodes['global.stop'])
49
58
  layout.setAlignment(Qt.AlignLeft)
50
59
 
51
- return layout
60
+ return layout
@@ -6,7 +6,7 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2024.11.24 22:00:00 #
9
+ # Updated Date: 2025.08.24 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtWidgets import QVBoxLayout, QLabel, QHBoxLayout, QWidget, QCheckBox
@@ -31,49 +31,38 @@ class Agent:
31
31
 
32
32
  :return: QWidget
33
33
  """
34
- # iterations
35
- option = self.window.controller.agent.legacy.options["agent.iterations"]
36
- self.window.ui.nodes['agent.iterations.label'] = QLabel(trans("toolbox.agent.iterations.label"))
37
- self.window.ui.nodes['agent.iterations'] = \
38
- OptionSlider(
39
- self.window,
40
- 'global',
41
- 'agent.iterations',
42
- option,
43
- )
44
- self.window.ui.config['global']['agent.iterations'] = self.window.ui.nodes['agent.iterations']
34
+ window = self.window
35
+ ui = window.ui
36
+ nodes = ui.nodes
37
+ cfg = ui.config['global']
38
+ common = window.controller.agent.common
45
39
 
46
- # auto stop
47
- self.window.ui.nodes['agent.auto_stop'] = ToggleLabel(trans("toolbox.agent.auto_stop.label"), parent=self.window)
48
- self.window.ui.nodes['agent.auto_stop'].box.stateChanged.connect(
49
- lambda:
50
- self.window.controller.agent.common.toggle_auto_stop(
51
- self.window.ui.config['global']['agent.auto_stop'].box.isChecked())
52
- )
53
- self.window.ui.config['global']['agent.auto_stop'] = self.window.ui.nodes['agent.auto_stop']
40
+ container = QWidget(window)
54
41
 
55
- # continue more
56
- self.window.ui.nodes['agent.continue'] = ToggleLabel(trans("toolbox.agent.continue.label"), parent=self.window)
57
- self.window.ui.nodes['agent.continue'].box.stateChanged.connect(
58
- lambda:
59
- self.window.controller.agent.common.toggle_continue(
60
- self.window.ui.config['global']['agent.continue'].box.isChecked())
61
- )
62
- self.window.ui.config['global']['agent.continue'] = self.window.ui.nodes['agent.continue']
42
+ option = window.controller.agent.legacy.options["agent.iterations"]
43
+ nodes['agent.iterations.label'] = QLabel(trans("toolbox.agent.iterations.label"), parent=container)
44
+ nodes['agent.iterations'] = OptionSlider(window, 'global', 'agent.iterations', option)
45
+ cfg['agent.iterations'] = nodes['agent.iterations']
46
+
47
+ nodes['agent.auto_stop'] = ToggleLabel(trans("toolbox.agent.auto_stop.label"), parent=window)
48
+ nodes['agent.auto_stop'].box.toggled.connect(common.toggle_auto_stop)
49
+ cfg['agent.auto_stop'] = nodes['agent.auto_stop']
50
+
51
+ nodes['agent.continue'] = ToggleLabel(trans("toolbox.agent.continue.label"), parent=window)
52
+ nodes['agent.continue'].box.toggled.connect(common.toggle_continue)
53
+ cfg['agent.continue'] = nodes['agent.continue']
63
54
 
64
- # options
65
55
  cols = QHBoxLayout()
66
- cols.addWidget(self.window.ui.config['global']['agent.auto_stop'])
67
- cols.addWidget(self.window.ui.config['global']['agent.continue'])
56
+ cols.addWidget(cfg['agent.auto_stop'])
57
+ cols.addWidget(cfg['agent.continue'])
68
58
 
69
- # rows
70
59
  rows = QVBoxLayout()
71
- rows.addWidget(self.window.ui.nodes['agent.iterations.label'])
72
- rows.addWidget(self.window.ui.config['global']['agent.iterations'])
60
+ rows.addWidget(nodes['agent.iterations.label'])
61
+ rows.addWidget(cfg['agent.iterations'])
73
62
  rows.addLayout(cols)
74
63
 
75
- self.window.ui.nodes['agent.options'] = QWidget()
76
- self.window.ui.nodes['agent.options'].setLayout(rows)
77
- self.window.ui.nodes['agent.options'].setContentsMargins(0, 0, 0, 0)
64
+ nodes['agent.options'] = container
65
+ nodes['agent.options'].setLayout(rows)
66
+ nodes['agent.options'].setContentsMargins(0, 0, 0, 0)
78
67
 
79
- return self.window.ui.nodes['agent.options']
68
+ return nodes['agent.options']
@@ -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.07.22 15:00:00 #
9
+ # Updated Date: 2025.08.24 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtWidgets import QVBoxLayout, QLabel, QHBoxLayout, QWidget, QCheckBox
@@ -32,56 +32,52 @@ class AgentLlama:
32
32
 
33
33
  :return: QWidget
34
34
  """
35
- # loop score
36
- option = self.window.controller.agent.llama.options["agent.llama.loop.score"]
37
- self.window.ui.nodes['agent.llama.loop.score.label'] = QLabel(trans("toolbox.agent.llama.loop.score.label"))
38
- self.window.ui.nodes['agent.llama.loop.score'] = \
39
- OptionSlider(
40
- self.window,
41
- 'global',
42
- 'agent.llama.loop.score',
43
- option,
44
- )
45
- self.window.ui.nodes['agent.llama.loop.score'].setToolTip(trans("toolbox.agent.llama.loop.score.tooltip"))
46
- self.window.ui.config['global']['agent.llama.loop.score'] = self.window.ui.nodes['agent.llama.loop.score']
47
-
48
- option_mode = self.window.controller.agent.llama.options["agent.llama.loop.mode"]
49
- self.window.ui.nodes['agent.llama.loop.mode.label'] = QLabel(trans("toolbox.agent.llama.loop.mode.label"))
50
- self.window.ui.nodes['agent.llama.loop.mode'] = \
51
- OptionCombo(
52
- self.window,
53
- 'global',
54
- 'agent.llama.loop.mode',
55
- option_mode,
56
- )
57
- self.window.ui.nodes['agent.llama.loop.mode'].setToolTip(trans("toolbox.agent.llama.loop.mode.tooltip"))
58
- self.window.ui.config['global']['agent.llama.loop.mode'] = self.window.ui.nodes['agent.llama.loop.mode']
59
-
60
- # loop enabled
61
- self.window.ui.nodes['agent.llama.loop.enabled'] = ToggleLabel(trans("toolbox.agent.llama.loop.enabled.label"), parent=self.window)
62
- self.window.ui.nodes['agent.llama.loop.enabled'].box.stateChanged.connect(
63
- lambda:
64
- self.window.controller.agent.common.toggle_loop(
65
- self.window.ui.config['global']['agent.llama.loop.enabled'].box.isChecked())
35
+ win = self.window
36
+ ui = win.ui
37
+ nodes = ui.nodes
38
+ config_global = ui.config.setdefault('global', {})
39
+ llama_opts = win.controller.agent.llama.options
40
+
41
+ container = QWidget(win)
42
+
43
+ nodes['agent.llama.loop.score'] = OptionSlider(
44
+ win,
45
+ 'global',
46
+ 'agent.llama.loop.score',
47
+ llama_opts["agent.llama.loop.score"],
48
+ )
49
+ nodes['agent.llama.loop.score'].setToolTip(trans("toolbox.agent.llama.loop.score.tooltip"))
50
+ config_global['agent.llama.loop.score'] = nodes['agent.llama.loop.score']
51
+
52
+ nodes['agent.llama.loop.mode.label'] = QLabel(trans("toolbox.agent.llama.loop.mode.label"), parent=win)
53
+ nodes['agent.llama.loop.mode'] = OptionCombo(
54
+ win,
55
+ 'global',
56
+ 'agent.llama.loop.mode',
57
+ llama_opts["agent.llama.loop.mode"],
58
+ )
59
+ nodes['agent.llama.loop.mode'].setToolTip(trans("toolbox.agent.llama.loop.mode.tooltip"))
60
+ config_global['agent.llama.loop.mode'] = nodes['agent.llama.loop.mode']
61
+
62
+ nodes['agent.llama.loop.enabled'] = ToggleLabel(trans("toolbox.agent.llama.loop.enabled.label"), parent=win)
63
+ nodes['agent.llama.loop.enabled'].box.toggled.connect(
64
+ win.controller.agent.common.toggle_loop
66
65
  )
67
- self.window.ui.config['global']['agent.llama.loop.enabled'] = self.window.ui.nodes['agent.llama.loop.enabled']
66
+ config_global['agent.llama.loop.enabled'] = nodes['agent.llama.loop.enabled']
68
67
 
69
- # label
70
- self.window.ui.nodes['agent.llama.loop.label'] = QLabel(trans("toolbox.agent.llama.loop.label"))
68
+ nodes['agent.llama.loop.label'] = QLabel(trans("toolbox.agent.llama.loop.label"), parent=win)
71
69
 
72
- # options
73
70
  cols = QHBoxLayout()
74
- cols.addWidget(self.window.ui.config['global']['agent.llama.loop.enabled'])
75
- cols.addWidget(self.window.ui.config['global']['agent.llama.loop.score'])
71
+ cols.addWidget(config_global['agent.llama.loop.enabled'])
72
+ cols.addWidget(config_global['agent.llama.loop.score'])
76
73
 
77
- # rows
78
74
  rows = QVBoxLayout()
79
- rows.addWidget(self.window.ui.nodes['agent.llama.loop.label'])
75
+ rows.addWidget(nodes['agent.llama.loop.label'])
80
76
  rows.addLayout(cols)
81
- rows.addWidget(self.window.ui.nodes['agent.llama.loop.mode'])
77
+ rows.addWidget(nodes['agent.llama.loop.mode'])
82
78
 
83
- self.window.ui.nodes['agent_llama.options'] = QWidget()
84
- self.window.ui.nodes['agent_llama.options'].setLayout(rows)
85
- self.window.ui.nodes['agent_llama.options'].setContentsMargins(0, 0, 0, 0)
79
+ container.setLayout(rows)
80
+ container.setContentsMargins(0, 0, 0, 0)
86
81
 
87
- return self.window.ui.nodes['agent_llama.options']
82
+ nodes['agent_llama.options'] = container
83
+ return nodes['agent_llama.options']