pygpt-net 2.4.28__py3-none-any.whl → 2.4.34__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- CHANGELOG.md +40 -0
- README.md +62 -5
- pygpt_net/CHANGELOG.txt +40 -0
- pygpt_net/__init__.py +3 -3
- pygpt_net/controller/access/__init__.py +5 -5
- pygpt_net/controller/access/control.py +3 -2
- pygpt_net/controller/attachment.py +67 -1
- pygpt_net/controller/audio/__init__.py +34 -6
- pygpt_net/controller/chat/__init__.py +3 -1
- pygpt_net/controller/chat/attachment.py +239 -37
- pygpt_net/controller/chat/audio.py +99 -0
- pygpt_net/controller/chat/input.py +10 -3
- pygpt_net/controller/chat/output.py +4 -1
- pygpt_net/controller/chat/text.py +10 -5
- pygpt_net/controller/dialogs/confirm.py +17 -1
- pygpt_net/controller/kernel/reply.py +5 -8
- pygpt_net/controller/lang/custom.py +3 -1
- pygpt_net/controller/mode.py +2 -1
- pygpt_net/controller/presets/editor.py +11 -2
- pygpt_net/core/access/voice.py +2 -2
- pygpt_net/core/agents/legacy.py +3 -1
- pygpt_net/core/attachments/__init__.py +11 -7
- pygpt_net/core/attachments/context.py +226 -44
- pygpt_net/core/{audio.py → audio/__init__.py} +1 -1
- pygpt_net/core/audio/context.py +34 -0
- pygpt_net/core/bridge/context.py +29 -1
- pygpt_net/core/bridge/worker.py +16 -1
- pygpt_net/core/ctx/__init__.py +4 -1
- pygpt_net/core/db/__init__.py +4 -2
- pygpt_net/core/debug/attachments.py +3 -1
- pygpt_net/core/debug/context.py +5 -1
- pygpt_net/core/debug/presets.py +3 -1
- pygpt_net/core/docker/__init__.py +170 -16
- pygpt_net/core/docker/builder.py +6 -2
- pygpt_net/core/events/event.py +3 -1
- pygpt_net/core/experts/__init__.py +24 -6
- pygpt_net/core/idx/chat.py +55 -4
- pygpt_net/core/idx/indexing.py +123 -15
- pygpt_net/core/modes.py +3 -1
- pygpt_net/core/presets.py +13 -2
- pygpt_net/core/render/markdown/pid.py +2 -1
- pygpt_net/core/render/plain/pid.py +2 -1
- pygpt_net/core/render/web/body.py +34 -12
- pygpt_net/core/render/web/pid.py +2 -1
- pygpt_net/core/render/web/renderer.py +12 -3
- pygpt_net/core/tokens.py +4 -2
- pygpt_net/core/types/mode.py +2 -1
- pygpt_net/data/config/config.json +7 -4
- pygpt_net/data/config/models.json +191 -6
- pygpt_net/data/config/modes.json +11 -5
- pygpt_net/data/config/presets/current.audio.json +34 -0
- pygpt_net/data/config/settings.json +15 -1
- pygpt_net/data/css/web.css +70 -0
- pygpt_net/data/css/web.dark.css +4 -1
- pygpt_net/data/css/web.light.css +1 -1
- pygpt_net/data/locale/locale.de.ini +33 -20
- pygpt_net/data/locale/locale.en.ini +73 -58
- pygpt_net/data/locale/locale.es.ini +33 -20
- pygpt_net/data/locale/locale.fr.ini +35 -22
- pygpt_net/data/locale/locale.it.ini +33 -20
- pygpt_net/data/locale/locale.pl.ini +36 -23
- pygpt_net/data/locale/locale.uk.ini +33 -20
- pygpt_net/data/locale/locale.zh.ini +40 -27
- pygpt_net/data/locale/plugin.cmd_code_interpreter.de.ini +6 -0
- pygpt_net/data/locale/plugin.cmd_code_interpreter.en.ini +15 -7
- pygpt_net/data/locale/plugin.cmd_code_interpreter.es.ini +6 -0
- pygpt_net/data/locale/plugin.cmd_code_interpreter.fr.ini +6 -0
- pygpt_net/data/locale/plugin.cmd_code_interpreter.it.ini +6 -0
- pygpt_net/data/locale/plugin.cmd_code_interpreter.pl.ini +6 -0
- pygpt_net/data/locale/plugin.cmd_code_interpreter.uk.ini +6 -0
- pygpt_net/data/locale/plugin.cmd_code_interpreter.zh.ini +6 -0
- pygpt_net/data/locale/plugin.cmd_files.de.ini +4 -4
- pygpt_net/data/locale/plugin.cmd_files.en.ini +4 -4
- pygpt_net/data/locale/plugin.cmd_files.es.ini +4 -4
- pygpt_net/data/locale/plugin.cmd_files.fr.ini +4 -4
- pygpt_net/data/locale/plugin.cmd_files.it.ini +4 -4
- pygpt_net/data/locale/plugin.cmd_files.pl.ini +4 -4
- pygpt_net/data/locale/plugin.cmd_files.uk.ini +4 -4
- pygpt_net/data/locale/plugin.cmd_files.zh.ini +4 -4
- pygpt_net/data/locale/plugin.cmd_system.de.ini +6 -6
- pygpt_net/data/locale/plugin.cmd_system.en.ini +12 -6
- pygpt_net/data/locale/plugin.cmd_system.es.ini +6 -6
- pygpt_net/data/locale/plugin.cmd_system.fr.ini +6 -6
- pygpt_net/data/locale/plugin.cmd_system.it.ini +6 -6
- pygpt_net/data/locale/plugin.cmd_system.pl.ini +6 -6
- pygpt_net/data/locale/plugin.cmd_system.uk.ini +6 -6
- pygpt_net/data/locale/plugin.cmd_system.zh.ini +6 -6
- pygpt_net/data/locale/plugin.cmd_web.de.ini +5 -5
- pygpt_net/data/locale/plugin.cmd_web.en.ini +5 -5
- pygpt_net/data/locale/plugin.cmd_web.es.ini +5 -5
- pygpt_net/data/locale/plugin.cmd_web.fr.ini +5 -5
- pygpt_net/data/locale/plugin.cmd_web.it.ini +5 -5
- pygpt_net/data/locale/plugin.cmd_web.pl.ini +5 -5
- pygpt_net/data/locale/plugin.cmd_web.uk.ini +5 -5
- pygpt_net/data/locale/plugin.cmd_web.zh.ini +5 -5
- pygpt_net/data/locale/plugin.idx_llama_index.de.ini +12 -12
- pygpt_net/data/locale/plugin.idx_llama_index.en.ini +12 -12
- pygpt_net/data/locale/plugin.idx_llama_index.es.ini +12 -12
- pygpt_net/data/locale/plugin.idx_llama_index.fr.ini +12 -12
- pygpt_net/data/locale/plugin.idx_llama_index.it.ini +12 -12
- pygpt_net/data/locale/plugin.idx_llama_index.pl.ini +12 -12
- pygpt_net/data/locale/plugin.idx_llama_index.uk.ini +12 -12
- pygpt_net/data/locale/plugin.idx_llama_index.zh.ini +12 -12
- pygpt_net/item/attachment.py +9 -1
- pygpt_net/item/ctx.py +9 -1
- pygpt_net/item/preset.py +5 -1
- pygpt_net/launcher.py +3 -1
- pygpt_net/migrations/Version20241126170000.py +28 -0
- pygpt_net/migrations/__init__.py +3 -1
- pygpt_net/plugin/audio_input/__init__.py +11 -1
- pygpt_net/plugin/audio_input/worker.py +9 -1
- pygpt_net/plugin/audio_output/__init__.py +37 -7
- pygpt_net/plugin/audio_output/worker.py +38 -41
- pygpt_net/plugin/cmd_code_interpreter/__init__.py +51 -35
- pygpt_net/plugin/cmd_code_interpreter/builder.py +16 -4
- pygpt_net/plugin/cmd_code_interpreter/config.py +98 -39
- pygpt_net/plugin/cmd_code_interpreter/docker.py +4 -0
- pygpt_net/plugin/cmd_code_interpreter/ipython/__init__.py +13 -0
- pygpt_net/plugin/cmd_code_interpreter/{ipython.py → ipython/docker_kernel.py} +10 -3
- pygpt_net/plugin/cmd_code_interpreter/ipython/local_kernel.py +220 -0
- pygpt_net/plugin/cmd_code_interpreter/runner.py +5 -5
- pygpt_net/plugin/cmd_mouse_control/__init__.py +4 -2
- pygpt_net/plugin/cmd_system/config.py +50 -0
- pygpt_net/plugin/cmd_system/docker.py +4 -0
- pygpt_net/plugin/idx_llama_index/__init__.py +23 -1
- pygpt_net/plugin/idx_llama_index/worker.py +10 -0
- pygpt_net/plugin/openai_dalle/__init__.py +3 -1
- pygpt_net/plugin/openai_vision/__init__.py +3 -1
- pygpt_net/provider/core/attachment/json_file.py +4 -1
- pygpt_net/provider/core/config/patch.py +25 -0
- pygpt_net/provider/core/ctx/db_sqlite/storage.py +14 -4
- pygpt_net/provider/core/ctx/db_sqlite/utils.py +19 -2
- pygpt_net/provider/core/model/patch.py +7 -1
- pygpt_net/provider/core/preset/json_file.py +5 -1
- pygpt_net/provider/gpt/__init__.py +14 -2
- pygpt_net/provider/gpt/audio.py +63 -0
- pygpt_net/provider/gpt/chat.py +76 -44
- pygpt_net/provider/gpt/utils.py +27 -0
- pygpt_net/provider/gpt/vision.py +37 -15
- pygpt_net/provider/loaders/base.py +10 -1
- pygpt_net/provider/loaders/web_yt.py +19 -1
- pygpt_net/tools/code_interpreter/__init__.py +1 -0
- pygpt_net/tools/image_viewer/ui/dialogs.py +3 -1
- pygpt_net/ui/dialog/preset.py +3 -1
- pygpt_net/ui/dialog/url.py +29 -0
- pygpt_net/ui/dialogs.py +5 -1
- pygpt_net/ui/layout/chat/attachments.py +42 -6
- pygpt_net/ui/layout/chat/attachments_ctx.py +14 -4
- pygpt_net/ui/layout/chat/attachments_uploaded.py +8 -4
- pygpt_net/ui/layout/toolbox/agent.py +8 -7
- pygpt_net/ui/layout/toolbox/agent_llama.py +5 -4
- pygpt_net/ui/layout/toolbox/prompt.py +8 -6
- pygpt_net/ui/menu/tools.py +17 -11
- pygpt_net/ui/widget/anims/toggles.py +167 -0
- pygpt_net/ui/widget/dialog/url.py +59 -0
- pygpt_net/ui/widget/element/group.py +2 -1
- pygpt_net/ui/widget/lists/attachment.py +22 -17
- pygpt_net/ui/widget/lists/attachment_ctx.py +65 -3
- pygpt_net/ui/widget/option/checkbox.py +69 -5
- pygpt_net/ui/widget/option/cmd.py +4 -5
- pygpt_net/ui/widget/option/toggle.py +62 -0
- pygpt_net/ui/widget/option/toggle_label.py +79 -0
- pygpt_net/ui/widget/textarea/url.py +43 -0
- {pygpt_net-2.4.28.dist-info → pygpt_net-2.4.34.dist-info}/METADATA +65 -7
- {pygpt_net-2.4.28.dist-info → pygpt_net-2.4.34.dist-info}/RECORD +168 -154
- {pygpt_net-2.4.28.dist-info → pygpt_net-2.4.34.dist-info}/LICENSE +0 -0
- {pygpt_net-2.4.28.dist-info → pygpt_net-2.4.34.dist-info}/WHEEL +0 -0
- {pygpt_net-2.4.28.dist-info → pygpt_net-2.4.34.dist-info}/entry_points.txt +0 -0
@@ -6,18 +6,20 @@
|
|
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.
|
9
|
+
# Updated Date: 2024.11.26 02:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
import os
|
13
13
|
|
14
|
-
from PySide6.QtGui import QStandardItemModel, Qt
|
14
|
+
from PySide6.QtGui import QStandardItemModel, Qt, QIcon
|
15
15
|
from PySide6.QtWidgets import QVBoxLayout, QPushButton, QHBoxLayout, QCheckBox, QWidget
|
16
16
|
|
17
|
+
from pygpt_net.item.attachment import AttachmentItem
|
17
18
|
from pygpt_net.ui.widget.element.labels import HelpLabel
|
18
19
|
from pygpt_net.ui.widget.lists.attachment import AttachmentList
|
19
20
|
from pygpt_net.utils import trans
|
20
21
|
|
22
|
+
import pygpt_net.icons_rc
|
21
23
|
|
22
24
|
class Attachments:
|
23
25
|
def __init__(self, window=None):
|
@@ -38,12 +40,21 @@ class Attachments:
|
|
38
40
|
self.setup_attachments()
|
39
41
|
self.setup_buttons()
|
40
42
|
|
43
|
+
empty_widget = QWidget()
|
44
|
+
self.window.ui.nodes['input.attachments.options.label'] = HelpLabel(trans("attachments.options.label"))
|
45
|
+
|
41
46
|
# buttons layout
|
42
47
|
buttons = QHBoxLayout()
|
43
48
|
buttons.addWidget(self.window.ui.nodes['attachments.btn.add'])
|
49
|
+
buttons.addWidget(self.window.ui.nodes['attachments.btn.add_url'])
|
44
50
|
buttons.addWidget(self.window.ui.nodes['attachments.btn.clear'])
|
51
|
+
buttons.addWidget(empty_widget)
|
52
|
+
buttons.addWidget(self.window.ui.nodes['input.attachments.options.label'])
|
53
|
+
|
54
|
+
buttons.addWidget(self.setup_auto_index())
|
45
55
|
buttons.addWidget(self.setup_send_clear())
|
46
56
|
buttons.addWidget(self.setup_capture_clear())
|
57
|
+
buttons.addStretch()
|
47
58
|
|
48
59
|
self.window.ui.nodes['tip.input.attachments'] = HelpLabel(trans('tip.input.attachments'), self.window)
|
49
60
|
|
@@ -88,15 +99,34 @@ class Attachments:
|
|
88
99
|
|
89
100
|
return widget
|
90
101
|
|
102
|
+
def setup_auto_index(self) -> QWidget:
|
103
|
+
"""
|
104
|
+
Setup auto index checkbox
|
105
|
+
|
106
|
+
:return: QWidget
|
107
|
+
"""
|
108
|
+
layout = QHBoxLayout()
|
109
|
+
layout.setContentsMargins(0, 0, 0, 0)
|
110
|
+
layout.setAlignment(Qt.AlignCenter)
|
111
|
+
layout.addWidget(self.window.ui.nodes['attachments.auto_index'])
|
112
|
+
|
113
|
+
widget = QWidget()
|
114
|
+
widget.setLayout(layout)
|
115
|
+
|
116
|
+
return widget
|
117
|
+
|
91
118
|
def setup_buttons(self):
|
92
119
|
"""
|
93
120
|
Setup buttons
|
94
121
|
"""
|
95
|
-
self.window.ui.nodes['attachments.btn.add'] = QPushButton(trans('attachments.btn.add'))
|
96
|
-
self.window.ui.nodes['attachments.btn.
|
122
|
+
self.window.ui.nodes['attachments.btn.add'] = QPushButton(QIcon(":/icons/add.svg"), trans('attachments.btn.add'))
|
123
|
+
self.window.ui.nodes['attachments.btn.add_url'] = QPushButton(QIcon(":/icons/add.svg"), trans('attachments.btn.add_url'))
|
124
|
+
self.window.ui.nodes['attachments.btn.clear'] = QPushButton(QIcon(":/icons/close.svg"), trans('attachments.btn.clear'))
|
97
125
|
|
98
126
|
self.window.ui.nodes['attachments.btn.add'].clicked.connect(
|
99
127
|
lambda: self.window.controller.attachment.open_add())
|
128
|
+
self.window.ui.nodes['attachments.btn.add_url'].clicked.connect(
|
129
|
+
lambda: self.window.controller.attachment.open_add_url())
|
100
130
|
self.window.ui.nodes['attachments.btn.clear'].clicked.connect(
|
101
131
|
lambda: self.window.controller.attachment.clear(remove_local=True))
|
102
132
|
|
@@ -110,6 +140,11 @@ class Attachments:
|
|
110
140
|
lambda: self.window.controller.attachment.toggle_capture_clear(
|
111
141
|
self.window.ui.nodes['attachments.capture_clear'].isChecked()))
|
112
142
|
|
143
|
+
self.window.ui.nodes['attachments.auto_index'] = QCheckBox(trans('attachments.auto_index'))
|
144
|
+
self.window.ui.nodes['attachments.auto_index'].stateChanged.connect(
|
145
|
+
lambda: self.window.controller.attachment.toggle_auto_index(
|
146
|
+
self.window.ui.nodes['attachments.auto_index'].isChecked()))
|
147
|
+
|
113
148
|
def setup_attachments(self):
|
114
149
|
"""
|
115
150
|
Setup attachments list
|
@@ -144,8 +179,9 @@ class Attachments:
|
|
144
179
|
for id in data:
|
145
180
|
path = data[id].path
|
146
181
|
size = ""
|
147
|
-
if
|
148
|
-
|
182
|
+
if data[id].type == AttachmentItem.TYPE_FILE:
|
183
|
+
if path and os.path.exists(path):
|
184
|
+
size = self.window.core.filesystem.sizeof_fmt(os.path.getsize(path))
|
149
185
|
ctx_str = ""
|
150
186
|
if data[id].ctx:
|
151
187
|
ctx_str = "YES"
|
@@ -6,19 +6,20 @@
|
|
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.
|
9
|
+
# Updated Date: 2024.11.26 02:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
import os
|
13
13
|
|
14
14
|
from PySide6 import QtCore
|
15
|
-
from PySide6.QtGui import QStandardItemModel, Qt
|
15
|
+
from PySide6.QtGui import QStandardItemModel, Qt, QIcon
|
16
16
|
from PySide6.QtWidgets import QVBoxLayout, QPushButton, QHBoxLayout, QWidget, QRadioButton
|
17
17
|
|
18
18
|
from pygpt_net.ui.widget.element.labels import HelpLabel
|
19
19
|
from pygpt_net.ui.widget.lists.attachment_ctx import AttachmentCtxList
|
20
20
|
from pygpt_net.utils import trans
|
21
21
|
|
22
|
+
import pygpt_net.icons_rc
|
22
23
|
|
23
24
|
class AttachmentsCtx:
|
24
25
|
def __init__(self, window=None):
|
@@ -90,7 +91,7 @@ class AttachmentsCtx:
|
|
90
91
|
self.window.ui.nodes[self.id] = AttachmentCtxList(self.window)
|
91
92
|
|
92
93
|
# buttons
|
93
|
-
self.window.ui.nodes['attachments_ctx.btn.clear'] = QPushButton(trans('attachments_uploaded.btn.clear'))
|
94
|
+
self.window.ui.nodes['attachments_ctx.btn.clear'] = QPushButton(QIcon(":/icons/close.svg"), trans('attachments_uploaded.btn.clear'))
|
94
95
|
self.window.ui.nodes['attachments_ctx.btn.clear'].clicked.connect(
|
95
96
|
lambda: self.window.controller.chat.attachment.clear()
|
96
97
|
)
|
@@ -105,11 +106,12 @@ class AttachmentsCtx:
|
|
105
106
|
:param parent: parent widget
|
106
107
|
:return: QStandardItemModel
|
107
108
|
"""
|
108
|
-
model = QStandardItemModel(0,
|
109
|
+
model = QStandardItemModel(0, 5, parent)
|
109
110
|
model.setHeaderData(0, Qt.Horizontal, trans('attachments.header.name'))
|
110
111
|
model.setHeaderData(1, Qt.Horizontal, trans('attachments.header.path'))
|
111
112
|
model.setHeaderData(2, Qt.Horizontal, trans('attachments.header.size'))
|
112
113
|
model.setHeaderData(3, Qt.Horizontal, trans('attachments.header.length'))
|
114
|
+
model.setHeaderData(4, Qt.Horizontal, trans('attachments.header.idx'))
|
113
115
|
return model
|
114
116
|
|
115
117
|
def update(self, data):
|
@@ -121,6 +123,7 @@ class AttachmentsCtx:
|
|
121
123
|
self.window.ui.models[self.id].removeRows(0, self.window.ui.models[self.id].rowCount())
|
122
124
|
i = 0
|
123
125
|
for item in data:
|
126
|
+
indexed = False
|
124
127
|
name = "No name"
|
125
128
|
if 'name' in item:
|
126
129
|
name = item['name']
|
@@ -136,6 +139,12 @@ class AttachmentsCtx:
|
|
136
139
|
length = str(item['length'])
|
137
140
|
if 'tokens' in item:
|
138
141
|
length += ' / ~' + str(item['tokens'])
|
142
|
+
if 'indexed' in item and item['indexed']:
|
143
|
+
indexed = True
|
144
|
+
|
145
|
+
idx_str = ""
|
146
|
+
if indexed:
|
147
|
+
idx_str = trans("attachments.ctx.indexed")
|
139
148
|
|
140
149
|
if os.path.exists(path):
|
141
150
|
size = self.window.core.filesystem.sizeof_fmt(os.path.getsize(path))
|
@@ -149,4 +158,5 @@ class AttachmentsCtx:
|
|
149
158
|
self.window.ui.models[self.id].setData(self.window.ui.models[self.id].index(i, 1), path)
|
150
159
|
self.window.ui.models[self.id].setData(self.window.ui.models[self.id].index(i, 2), size)
|
151
160
|
self.window.ui.models[self.id].setData(self.window.ui.models[self.id].index(i, 3), length)
|
161
|
+
self.window.ui.models[self.id].setData(self.window.ui.models[self.id].index(i, 4), idx_str)
|
152
162
|
i += 1
|
@@ -12,7 +12,7 @@
|
|
12
12
|
import os
|
13
13
|
|
14
14
|
from PySide6 import QtCore
|
15
|
-
from PySide6.QtGui import QStandardItemModel, Qt
|
15
|
+
from PySide6.QtGui import QStandardItemModel, Qt, QIcon
|
16
16
|
from PySide6.QtWidgets import QVBoxLayout, QPushButton, QHBoxLayout, QCheckBox, QLabel, QWidget
|
17
17
|
|
18
18
|
from pygpt_net.ui.widget.element.button import SyncButton
|
@@ -20,6 +20,7 @@ from pygpt_net.ui.widget.element.labels import HelpLabel
|
|
20
20
|
from pygpt_net.ui.widget.lists.uploaded import UploadedFileList
|
21
21
|
from pygpt_net.utils import trans
|
22
22
|
|
23
|
+
import pygpt_net.icons_rc
|
23
24
|
|
24
25
|
class AttachmentsUploaded:
|
25
26
|
def __init__(self, window=None):
|
@@ -38,10 +39,11 @@ class AttachmentsUploaded:
|
|
38
39
|
:return: QVBoxLayout
|
39
40
|
"""
|
40
41
|
self.setup_attachments()
|
42
|
+
empty_widget = QWidget()
|
41
43
|
|
42
|
-
self.window.ui.nodes['attachments_uploaded.sync.tip'] =
|
44
|
+
self.window.ui.nodes['attachments_uploaded.sync.tip'] = HelpLabel(trans('attachments_uploaded.sync.tip'))
|
45
|
+
self.window.ui.nodes['attachments_uploaded.sync.tip'].setWordWrap(False)
|
43
46
|
self.window.ui.nodes['attachments_uploaded.sync.tip'].setAlignment(Qt.AlignCenter)
|
44
|
-
empty_widget = QWidget()
|
45
47
|
|
46
48
|
self.window.ui.nodes['tip.input.attachments.uploaded'] = HelpLabel(trans('tip.input.attachments.uploaded'),
|
47
49
|
self.window)
|
@@ -52,6 +54,8 @@ class AttachmentsUploaded:
|
|
52
54
|
buttons_layout.addWidget(self.window.ui.nodes['attachments_uploaded.btn.clear'])
|
53
55
|
buttons_layout.addWidget(empty_widget)
|
54
56
|
buttons_layout.addWidget(self.window.ui.nodes['attachments_uploaded.sync.tip'])
|
57
|
+
buttons_layout.addStretch()
|
58
|
+
|
55
59
|
|
56
60
|
# layout
|
57
61
|
layout = QVBoxLayout()
|
@@ -70,7 +74,7 @@ class AttachmentsUploaded:
|
|
70
74
|
|
71
75
|
# buttons
|
72
76
|
self.window.ui.nodes['attachments_uploaded.btn.sync'] = SyncButton(trans('attachments_uploaded.btn.sync'), self.window)
|
73
|
-
self.window.ui.nodes['attachments_uploaded.btn.clear'] = QPushButton(trans('attachments_uploaded.btn.clear'))
|
77
|
+
self.window.ui.nodes['attachments_uploaded.btn.clear'] = QPushButton(QIcon(":/icons/close.svg"), trans('attachments_uploaded.btn.clear'))
|
74
78
|
self.window.ui.nodes['attachments_uploaded.btn.clear'].clicked.connect(
|
75
79
|
lambda: self.window.controller.assistant.files.clear()
|
76
80
|
)
|
@@ -6,12 +6,13 @@
|
|
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.
|
9
|
+
# Updated Date: 2024.11.24 22:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
from PySide6.QtWidgets import QVBoxLayout, QLabel, QHBoxLayout, QWidget, QCheckBox
|
13
13
|
|
14
14
|
from pygpt_net.ui.widget.option.slider import OptionSlider
|
15
|
+
from pygpt_net.ui.widget.option.toggle_label import ToggleLabel
|
15
16
|
from pygpt_net.utils import trans
|
16
17
|
|
17
18
|
|
@@ -43,20 +44,20 @@ class Agent:
|
|
43
44
|
self.window.ui.config['global']['agent.iterations'] = self.window.ui.nodes['agent.iterations']
|
44
45
|
|
45
46
|
# auto stop
|
46
|
-
self.window.ui.nodes['agent.auto_stop'] =
|
47
|
-
self.window.ui.nodes['agent.auto_stop'].stateChanged.connect(
|
47
|
+
self.window.ui.nodes['agent.auto_stop'] = ToggleLabel(trans("toolbox.agent.auto_stop.label"))
|
48
|
+
self.window.ui.nodes['agent.auto_stop'].box.stateChanged.connect(
|
48
49
|
lambda:
|
49
50
|
self.window.controller.agent.common.toggle_auto_stop(
|
50
|
-
self.window.ui.config['global']['agent.auto_stop'].isChecked())
|
51
|
+
self.window.ui.config['global']['agent.auto_stop'].box.isChecked())
|
51
52
|
)
|
52
53
|
self.window.ui.config['global']['agent.auto_stop'] = self.window.ui.nodes['agent.auto_stop']
|
53
54
|
|
54
55
|
# continue more
|
55
|
-
self.window.ui.nodes['agent.continue'] =
|
56
|
-
self.window.ui.nodes['agent.continue'].stateChanged.connect(
|
56
|
+
self.window.ui.nodes['agent.continue'] = ToggleLabel(trans("toolbox.agent.continue.label"))
|
57
|
+
self.window.ui.nodes['agent.continue'].box.stateChanged.connect(
|
57
58
|
lambda:
|
58
59
|
self.window.controller.agent.common.toggle_continue(
|
59
|
-
self.window.ui.config['global']['agent.continue'].isChecked())
|
60
|
+
self.window.ui.config['global']['agent.continue'].box.isChecked())
|
60
61
|
)
|
61
62
|
self.window.ui.config['global']['agent.continue'] = self.window.ui.nodes['agent.continue']
|
62
63
|
|
@@ -6,12 +6,13 @@
|
|
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.
|
9
|
+
# Updated Date: 2024.11.24 22:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
from PySide6.QtWidgets import QVBoxLayout, QLabel, QHBoxLayout, QWidget, QCheckBox
|
13
13
|
|
14
14
|
from pygpt_net.ui.widget.option.slider import OptionSlider
|
15
|
+
from pygpt_net.ui.widget.option.toggle_label import ToggleLabel
|
15
16
|
from pygpt_net.utils import trans
|
16
17
|
|
17
18
|
|
@@ -45,11 +46,11 @@ class AgentLlama:
|
|
45
46
|
self.window.ui.config['global']['agent.llama.loop.score'] = self.window.ui.nodes['agent.llama.loop.score']
|
46
47
|
|
47
48
|
# loop enabled
|
48
|
-
self.window.ui.nodes['agent.llama.loop.enabled'] =
|
49
|
-
self.window.ui.nodes['agent.llama.loop.enabled'].stateChanged.connect(
|
49
|
+
self.window.ui.nodes['agent.llama.loop.enabled'] = ToggleLabel(trans("toolbox.agent.llama.loop.enabled.label"))
|
50
|
+
self.window.ui.nodes['agent.llama.loop.enabled'].box.stateChanged.connect(
|
50
51
|
lambda:
|
51
52
|
self.window.controller.agent.common.toggle_loop(
|
52
|
-
self.window.ui.config['global']['agent.llama.loop.enabled'].isChecked())
|
53
|
+
self.window.ui.config['global']['agent.llama.loop.enabled'].box.isChecked())
|
53
54
|
)
|
54
55
|
self.window.ui.config['global']['agent.llama.loop.enabled'] = self.window.ui.nodes['agent.llama.loop.enabled']
|
55
56
|
|
@@ -6,14 +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: 2024.11.
|
9
|
+
# Updated Date: 2024.11.24 22:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
from PySide6.QtGui import Qt, QIcon
|
13
13
|
from PySide6.QtWidgets import QVBoxLayout, QHBoxLayout, QPushButton, QWidget, QCheckBox, QSizePolicy
|
14
14
|
|
15
|
+
from pygpt_net.ui.widget.anims.toggles import AnimToggle
|
15
16
|
from pygpt_net.ui.widget.element.labels import HelpLabel, TitleLabel
|
16
17
|
from pygpt_net.ui.widget.option.prompt import PromptTextarea
|
18
|
+
from pygpt_net.ui.widget.option.toggle_label import ToggleLabel
|
17
19
|
from pygpt_net.utils import trans
|
18
20
|
import pygpt_net.icons_rc
|
19
21
|
|
@@ -33,12 +35,12 @@ class Prompt:
|
|
33
35
|
:return: QWidget
|
34
36
|
"""
|
35
37
|
# cmd enable/disable
|
36
|
-
self.window.ui.nodes['cmd.enabled'] =
|
37
|
-
self.window.ui.nodes['cmd.enabled'].stateChanged.connect(
|
38
|
-
lambda: self.window.controller.chat.common.toggle_cmd(self.window.ui.nodes['cmd.enabled'].isChecked())
|
38
|
+
self.window.ui.nodes['cmd.enabled'] = ToggleLabel(trans('cmd.enabled'), label_position="left",icon = ":/icons/build.svg")
|
39
|
+
self.window.ui.nodes['cmd.enabled'].box.stateChanged.connect(
|
40
|
+
lambda: self.window.controller.chat.common.toggle_cmd(self.window.ui.nodes['cmd.enabled'].box.isChecked())
|
39
41
|
)
|
40
|
-
self.window.ui.nodes['cmd.enabled'].setToolTip(trans('cmd.tip'))
|
41
|
-
self.window.ui.nodes['cmd.enabled'].setIcon(QIcon(":/icons/add.svg"))
|
42
|
+
self.window.ui.nodes['cmd.enabled'].box.setToolTip(trans('cmd.tip'))
|
43
|
+
self.window.ui.nodes['cmd.enabled'].box.setIcon(QIcon(":/icons/add.svg"))
|
42
44
|
|
43
45
|
# label
|
44
46
|
self.window.ui.nodes['toolbox.prompt.label'] = TitleLabel(trans("toolbox.prompt"))
|
pygpt_net/ui/menu/tools.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: 2024.11.
|
9
|
+
# Updated Date: 2024.11.24 22:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
from PySide6.QtGui import QAction, QIcon
|
@@ -55,23 +55,29 @@ class Tools:
|
|
55
55
|
self.window.ui.menu[key] = actions[key]
|
56
56
|
self.window.ui.menu['menu.tools'].addAction(self.window.ui.menu[key])
|
57
57
|
|
58
|
-
#
|
59
|
-
|
58
|
+
# ------------------------------------------------- #
|
59
|
+
|
60
|
+
# Docker images rebuild:
|
61
|
+
|
62
|
+
# IPython container
|
60
63
|
self.window.ui.menu['menu.tools'].addSeparator()
|
61
|
-
self.window.ui.menu['menu.tools.ipython.rebuild'] = QAction(QIcon(":/icons/reload.svg"),
|
64
|
+
self.window.ui.menu['menu.tools.ipython.rebuild'] = QAction(QIcon(":/icons/reload.svg"),
|
65
|
+
"Rebuild IPython Docker Image", self.window)
|
62
66
|
self.window.ui.menu['menu.tools'].addAction(self.window.ui.menu['menu.tools.ipython.rebuild'])
|
63
67
|
self.window.ui.menu['menu.tools.ipython.rebuild'].triggered.connect(
|
64
|
-
lambda: self.window.core.plugins.get("cmd_code_interpreter").builder.
|
68
|
+
lambda: self.window.core.plugins.get("cmd_code_interpreter").builder.build_and_restart()
|
65
69
|
)
|
66
|
-
#
|
67
|
-
self.window.ui.menu['menu.tools.python_legacy.rebuild'] = QAction(QIcon(":/icons/reload.svg"),
|
70
|
+
# Python Legacy container
|
71
|
+
self.window.ui.menu['menu.tools.python_legacy.rebuild'] = QAction(QIcon(":/icons/reload.svg"),
|
72
|
+
"Rebuild Python (Legacy) Docker Image", self.window)
|
68
73
|
self.window.ui.menu['menu.tools'].addAction(self.window.ui.menu['menu.tools.python_legacy.rebuild'])
|
69
74
|
self.window.ui.menu['menu.tools.python_legacy.rebuild'].triggered.connect(
|
70
|
-
lambda: self.window.core.plugins.get("cmd_code_interpreter").docker.
|
75
|
+
lambda: self.window.core.plugins.get("cmd_code_interpreter").docker.build_and_restart()
|
71
76
|
)
|
72
|
-
#
|
73
|
-
self.window.ui.menu['menu.tools.system.rebuild'] = QAction(QIcon(":/icons/reload.svg"),
|
77
|
+
# System container
|
78
|
+
self.window.ui.menu['menu.tools.system.rebuild'] = QAction(QIcon(":/icons/reload.svg"),
|
79
|
+
"Rebuild System Sandbox Docker Image", self.window)
|
74
80
|
self.window.ui.menu['menu.tools'].addAction(self.window.ui.menu['menu.tools.system.rebuild'])
|
75
81
|
self.window.ui.menu['menu.tools.system.rebuild'].triggered.connect(
|
76
|
-
lambda: self.window.core.plugins.get("cmd_system").docker.
|
82
|
+
lambda: self.window.core.plugins.get("cmd_system").docker.build_and_restart()
|
77
83
|
)
|
@@ -0,0 +1,167 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
# ================================================== #
|
4
|
+
# This file is a part of PYGPT package #
|
5
|
+
# Website: https://pygpt.net #
|
6
|
+
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
7
|
+
# MIT License #
|
8
|
+
# Created By : Marcin Szczygliński #
|
9
|
+
# Updated Date: 2024.11.24 22:00:00 #
|
10
|
+
# ================================================== #
|
11
|
+
|
12
|
+
from PySide6.QtCore import (
|
13
|
+
Qt, QSize, QPoint, QPointF, QRectF,
|
14
|
+
QEasingCurve, QPropertyAnimation, QSequentialAnimationGroup,
|
15
|
+
Slot, Property, QEvent)
|
16
|
+
|
17
|
+
from PySide6.QtWidgets import QCheckBox
|
18
|
+
from PySide6.QtGui import QColor, QBrush, QPaintEvent, QPen, QPainter, QPalette
|
19
|
+
|
20
|
+
|
21
|
+
class AnimToggle(QCheckBox):
|
22
|
+
|
23
|
+
# Based on widget from: https://www.pythonguis.com/tutorials/pyside6-animated-widgets/
|
24
|
+
|
25
|
+
_transparent_pen = QPen(Qt.transparent)
|
26
|
+
_light_grey_pen = QPen(Qt.lightGray)
|
27
|
+
|
28
|
+
def __init__(self, title="", parent=None):
|
29
|
+
super().__init__(parent)
|
30
|
+
self.setText(title)
|
31
|
+
|
32
|
+
# Initialize the colors based on the current palette
|
33
|
+
self.updateColors()
|
34
|
+
|
35
|
+
# Setup the rest of the widget.
|
36
|
+
self.setContentsMargins(8, 0, 8, 0)
|
37
|
+
self.setMaximumWidth(58)
|
38
|
+
self._handle_position = 0
|
39
|
+
self._pulse_radius = 0
|
40
|
+
|
41
|
+
# Setup animations
|
42
|
+
self.animation = QPropertyAnimation(self, b"handle_position", self)
|
43
|
+
self.animation.setEasingCurve(QEasingCurve.InOutCubic)
|
44
|
+
self.animation.setDuration(200) # time in ms
|
45
|
+
|
46
|
+
self.pulse_anim = QPropertyAnimation(self, b"pulse_radius", self)
|
47
|
+
self.pulse_anim.setDuration(350) # time in ms
|
48
|
+
self.pulse_anim.setStartValue(10)
|
49
|
+
self.pulse_anim.setEndValue(20)
|
50
|
+
|
51
|
+
self.animations_group = QSequentialAnimationGroup()
|
52
|
+
self.animations_group.addAnimation(self.animation)
|
53
|
+
self.animations_group.addAnimation(self.pulse_anim)
|
54
|
+
|
55
|
+
self.stateChanged.connect(self.setup_animation)
|
56
|
+
|
57
|
+
def updateColors(self):
|
58
|
+
# Get colors from the palette.
|
59
|
+
palette = self.palette()
|
60
|
+
#bar_color = QPen(Qt.lightGray).color()
|
61
|
+
bar_color = QColor("#969696")
|
62
|
+
#bar_checked_color = palette.color(QPalette.Dark)
|
63
|
+
bar_checked_color = QColor("#969696")
|
64
|
+
bar_color.setAlpha(0x80)
|
65
|
+
handle_color = palette.color(QPalette.Shadow)
|
66
|
+
handle_checked_color = palette.color(QPalette.ButtonText)
|
67
|
+
|
68
|
+
# Create semi-transparent colors for the pulse effect
|
69
|
+
pulse_unchecked_color = bar_color.darker(110)
|
70
|
+
pulse_checked_color = bar_checked_color.lighter(130)
|
71
|
+
pulse_unchecked_color.setAlpha(0x44)
|
72
|
+
pulse_checked_color.setAlpha(0x44)
|
73
|
+
|
74
|
+
# Now set the brushes
|
75
|
+
self._bar_brush = QBrush(bar_color)
|
76
|
+
self._bar_checked_brush = QBrush(bar_checked_color)
|
77
|
+
self._handle_brush = QBrush(handle_color)
|
78
|
+
self._handle_checked_brush = QBrush(handle_checked_color)
|
79
|
+
self._pulse_unchecked_animation = QBrush(pulse_unchecked_color)
|
80
|
+
self._pulse_checked_animation = QBrush(pulse_checked_color)
|
81
|
+
|
82
|
+
# Update the widget to redraw with new colors
|
83
|
+
self.update()
|
84
|
+
|
85
|
+
def event(self, e):
|
86
|
+
if e.type() == QEvent.PaletteChange:
|
87
|
+
self.updateColors()
|
88
|
+
return super().event(e)
|
89
|
+
|
90
|
+
def sizeHint(self):
|
91
|
+
return QSize(58, 45)
|
92
|
+
|
93
|
+
def hitButton(self, pos: QPoint):
|
94
|
+
return self.contentsRect().contains(pos)
|
95
|
+
|
96
|
+
@Slot(int)
|
97
|
+
def setup_animation(self, value):
|
98
|
+
self.animations_group.stop()
|
99
|
+
if value:
|
100
|
+
self.animation.setEndValue(1)
|
101
|
+
else:
|
102
|
+
self.animation.setEndValue(0)
|
103
|
+
self.animations_group.start()
|
104
|
+
|
105
|
+
def paintEvent(self, e: QPaintEvent):
|
106
|
+
|
107
|
+
contRect = self.contentsRect()
|
108
|
+
handleRadius = round(0.24 * contRect.height())
|
109
|
+
|
110
|
+
p = QPainter(self)
|
111
|
+
p.setRenderHint(QPainter.Antialiasing)
|
112
|
+
p.setPen(self._transparent_pen)
|
113
|
+
|
114
|
+
barRect = QRectF(
|
115
|
+
0, 0,
|
116
|
+
contRect.width() - handleRadius, 0.40 * contRect.height()
|
117
|
+
)
|
118
|
+
barRect.moveCenter(contRect.center())
|
119
|
+
rounding = barRect.height() / 2
|
120
|
+
|
121
|
+
# The handle will move along this line
|
122
|
+
trailLength = contRect.width() - 2 * handleRadius
|
123
|
+
|
124
|
+
xPos = contRect.x() + handleRadius + trailLength * self._handle_position
|
125
|
+
|
126
|
+
if self.pulse_anim.state() == QPropertyAnimation.Running:
|
127
|
+
p.setBrush(
|
128
|
+
self._pulse_checked_animation if
|
129
|
+
self.isChecked() else self._pulse_unchecked_animation)
|
130
|
+
p.drawEllipse(QPointF(xPos, barRect.center().y()),
|
131
|
+
self._pulse_radius, self._pulse_radius)
|
132
|
+
|
133
|
+
if self.isChecked():
|
134
|
+
p.setBrush(self._bar_checked_brush)
|
135
|
+
p.drawRoundedRect(barRect, rounding, rounding)
|
136
|
+
p.setBrush(self._handle_checked_brush)
|
137
|
+
else:
|
138
|
+
p.setBrush(self._bar_brush)
|
139
|
+
p.drawRoundedRect(barRect, rounding, rounding)
|
140
|
+
p.setPen(self._light_grey_pen)
|
141
|
+
p.setBrush(self._handle_brush)
|
142
|
+
|
143
|
+
p.drawEllipse(
|
144
|
+
QPointF(xPos, barRect.center().y()),
|
145
|
+
handleRadius, handleRadius)
|
146
|
+
|
147
|
+
p.end()
|
148
|
+
|
149
|
+
@Property(float)
|
150
|
+
def handle_position(self):
|
151
|
+
return self._handle_position
|
152
|
+
|
153
|
+
@handle_position.setter
|
154
|
+
def handle_position(self, pos):
|
155
|
+
# Update the position and redraw
|
156
|
+
self._handle_position = pos
|
157
|
+
self.update()
|
158
|
+
|
159
|
+
@Property(float)
|
160
|
+
def pulse_radius(self):
|
161
|
+
return self._pulse_radius
|
162
|
+
|
163
|
+
@pulse_radius.setter
|
164
|
+
def pulse_radius(self, pos):
|
165
|
+
# Update the pulse radius and redraw
|
166
|
+
self._pulse_radius = pos
|
167
|
+
self.update()
|
@@ -0,0 +1,59 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
# ================================================== #
|
4
|
+
# This file is a part of PYGPT package #
|
5
|
+
# Website: https://pygpt.net #
|
6
|
+
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
7
|
+
# MIT License #
|
8
|
+
# Created By : Marcin Szczygliński #
|
9
|
+
# Updated Date: 2024.11.26 02:00:00 #
|
10
|
+
# ================================================== #
|
11
|
+
|
12
|
+
from PySide6.QtWidgets import QDialog, QLabel, QHBoxLayout, QVBoxLayout, QPushButton
|
13
|
+
|
14
|
+
from pygpt_net.ui.widget.element.labels import HelpLabel
|
15
|
+
from pygpt_net.utils import trans
|
16
|
+
from pygpt_net.ui.widget.textarea.url import UrlInput
|
17
|
+
|
18
|
+
|
19
|
+
class UrlDialog(QDialog):
|
20
|
+
def __init__(self, window=None, id=None):
|
21
|
+
"""
|
22
|
+
Url dialog
|
23
|
+
|
24
|
+
:param window: main window
|
25
|
+
:param id: info window id
|
26
|
+
"""
|
27
|
+
super(UrlDialog, self).__init__(window)
|
28
|
+
self.window = window
|
29
|
+
self.id = id
|
30
|
+
self.current = None
|
31
|
+
self.input = UrlInput(window, id)
|
32
|
+
self.input.setMinimumWidth(400)
|
33
|
+
|
34
|
+
self.window.ui.nodes['dialog.url.btn.update'] = QPushButton(trans('dialog.url.update'))
|
35
|
+
self.window.ui.nodes['dialog.url.btn.update'].clicked.connect(
|
36
|
+
lambda: self.window.controller.dialogs.confirm.accept_url(
|
37
|
+
self.id,
|
38
|
+
self.window.ui.dialog['url'].current,
|
39
|
+
self.input.text()),
|
40
|
+
)
|
41
|
+
|
42
|
+
self.window.ui.nodes['dialog.url.btn.dismiss'] = QPushButton(trans('dialog.url.dismiss'))
|
43
|
+
self.window.ui.nodes['dialog.url.btn.dismiss'].clicked.connect(
|
44
|
+
lambda: self.window.controller.dialogs.confirm.dismiss_url())
|
45
|
+
|
46
|
+
bottom = QHBoxLayout()
|
47
|
+
bottom.addWidget(self.window.ui.nodes['dialog.url.btn.dismiss'])
|
48
|
+
bottom.addWidget(self.window.ui.nodes['dialog.url.btn.update'])
|
49
|
+
|
50
|
+
self.window.ui.nodes['dialog.url.label'] = QLabel(trans("dialog.url.title"))
|
51
|
+
self.window.ui.nodes['dialog.url.tip'] = HelpLabel(trans("dialog.url.tip"))
|
52
|
+
|
53
|
+
layout = QVBoxLayout()
|
54
|
+
layout.addWidget(self.window.ui.nodes['dialog.url.label'])
|
55
|
+
layout.addWidget(self.input)
|
56
|
+
layout.addWidget(self.window.ui.nodes['dialog.url.tip'])
|
57
|
+
layout.addLayout(bottom)
|
58
|
+
|
59
|
+
self.setLayout(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.
|
9
|
+
# Updated Date: 2024.11.24 22:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
from PySide6.QtCore import Qt
|
12
12
|
from PySide6.QtGui import QIcon
|
@@ -53,6 +53,7 @@ class CollapsedGroup(QWidget):
|
|
53
53
|
height: 0px;
|
54
54
|
}
|
55
55
|
""")
|
56
|
+
self.update_icon(self.box.checkState())
|
56
57
|
|
57
58
|
# options layout
|
58
59
|
self.options = QVBoxLayout()
|