pygpt-net 2.7.2__py3-none-any.whl → 2.7.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pygpt_net/CHANGELOG.txt +12 -0
- pygpt_net/__init__.py +3 -3
- pygpt_net/app.py +382 -350
- pygpt_net/controller/chat/attachment.py +5 -1
- pygpt_net/controller/chat/image.py +40 -5
- pygpt_net/controller/files/files.py +3 -1
- pygpt_net/controller/layout/layout.py +2 -2
- pygpt_net/controller/media/media.py +70 -1
- pygpt_net/controller/theme/nodes.py +2 -1
- pygpt_net/controller/ui/mode.py +5 -1
- pygpt_net/controller/ui/ui.py +17 -2
- pygpt_net/core/filesystem/url.py +4 -1
- pygpt_net/core/render/web/helpers.py +5 -0
- pygpt_net/data/config/config.json +5 -4
- pygpt_net/data/config/models.json +3 -3
- pygpt_net/data/config/settings.json +0 -14
- pygpt_net/data/css/web-blocks.css +3 -0
- pygpt_net/data/css/web-chatgpt.css +3 -0
- pygpt_net/data/locale/locale.de.ini +6 -0
- pygpt_net/data/locale/locale.en.ini +7 -1
- pygpt_net/data/locale/locale.es.ini +6 -0
- pygpt_net/data/locale/locale.fr.ini +6 -0
- pygpt_net/data/locale/locale.it.ini +6 -0
- pygpt_net/data/locale/locale.pl.ini +7 -1
- pygpt_net/data/locale/locale.uk.ini +6 -0
- pygpt_net/data/locale/locale.zh.ini +6 -0
- pygpt_net/launcher.py +115 -55
- pygpt_net/preload.py +243 -0
- pygpt_net/provider/api/google/image.py +317 -10
- pygpt_net/provider/api/google/video.py +160 -4
- pygpt_net/provider/api/openai/image.py +201 -93
- pygpt_net/provider/api/openai/video.py +99 -24
- pygpt_net/provider/api/x_ai/image.py +25 -2
- pygpt_net/provider/core/config/patch.py +17 -1
- pygpt_net/ui/layout/chat/input.py +20 -2
- pygpt_net/ui/layout/chat/painter.py +6 -4
- pygpt_net/ui/layout/toolbox/image.py +21 -11
- pygpt_net/ui/layout/toolbox/raw.py +2 -2
- pygpt_net/ui/layout/toolbox/video.py +22 -9
- pygpt_net/ui/main.py +84 -3
- pygpt_net/ui/widget/dialog/base.py +3 -10
- pygpt_net/ui/widget/option/combo.py +119 -1
- pygpt_net/ui/widget/textarea/input_extra.py +664 -0
- {pygpt_net-2.7.2.dist-info → pygpt_net-2.7.4.dist-info}/METADATA +27 -20
- {pygpt_net-2.7.2.dist-info → pygpt_net-2.7.4.dist-info}/RECORD +48 -46
- {pygpt_net-2.7.2.dist-info → pygpt_net-2.7.4.dist-info}/LICENSE +0 -0
- {pygpt_net-2.7.2.dist-info → pygpt_net-2.7.4.dist-info}/WHEEL +0 -0
- {pygpt_net-2.7.2.dist-info → pygpt_net-2.7.4.dist-info}/entry_points.txt +0 -0
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
|
7
7
|
# MIT License #
|
|
8
8
|
# Created By : Marcin Szczygliński #
|
|
9
|
-
# Updated Date: 2025.12.
|
|
9
|
+
# Updated Date: 2025.12.31 16:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import os
|
|
@@ -376,10 +376,14 @@ class Attachment(QObject):
|
|
|
376
376
|
|
|
377
377
|
def show_uploaded(self):
|
|
378
378
|
"""Show uploaded attachments"""
|
|
379
|
+
if self.window.ui.tabs['input'].isTabVisible(self.uploaded_tab_idx):
|
|
380
|
+
return
|
|
379
381
|
self.window.ui.tabs['input'].setTabVisible(self.uploaded_tab_idx, True)
|
|
380
382
|
|
|
381
383
|
def hide_uploaded(self):
|
|
382
384
|
"""Hide uploaded attachments"""
|
|
385
|
+
if not self.window.ui.tabs['input'].isTabVisible(self.uploaded_tab_idx):
|
|
386
|
+
return
|
|
383
387
|
self.window.ui.tabs['input'].setTabVisible(self.uploaded_tab_idx, False)
|
|
384
388
|
|
|
385
389
|
def delete_by_idx(
|
|
@@ -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.
|
|
9
|
+
# Updated Date: 2025.12.31 16:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import os
|
|
@@ -47,7 +47,7 @@ class Image:
|
|
|
47
47
|
update_status = self.window.update_status
|
|
48
48
|
dispatch = self.window.dispatch
|
|
49
49
|
|
|
50
|
-
num = int(self.window.ui.config['global']['img_variants'].
|
|
50
|
+
num = int(self.window.ui.config['global']['img_variants'].text() or 1)
|
|
51
51
|
if num < 1:
|
|
52
52
|
num = 1
|
|
53
53
|
elif num > 4:
|
|
@@ -57,7 +57,9 @@ class Image:
|
|
|
57
57
|
mode = core.config.get('mode')
|
|
58
58
|
model = core.config.get('model')
|
|
59
59
|
model_data = core.models.get(model)
|
|
60
|
-
|
|
60
|
+
extra_prompt = self.window.ui.nodes['input_extra'].toPlainText().strip()
|
|
61
|
+
if (model_data and model_data.id
|
|
62
|
+
and (model_data.id == 'dall-e-3' or model_data.id.startswith('gpt-image-1'))):
|
|
61
63
|
num = 1
|
|
62
64
|
|
|
63
65
|
update_status(trans('status.sending'))
|
|
@@ -70,6 +72,26 @@ class Image:
|
|
|
70
72
|
ctx.prev_ctx = prev_ctx # store previous context item
|
|
71
73
|
ctx.live = True
|
|
72
74
|
|
|
75
|
+
# prepare previous image_id and video_id from last context (for variations)
|
|
76
|
+
image_id = None
|
|
77
|
+
video_id = None
|
|
78
|
+
|
|
79
|
+
if core.config.get("video.remix") or core.config.get("img.remix"):
|
|
80
|
+
items = core.ctx.get_items()
|
|
81
|
+
reversed_items = reversed(items)
|
|
82
|
+
for item in reversed_items:
|
|
83
|
+
if isinstance(item.extra, dict):
|
|
84
|
+
if core.config.get("video.remix"):
|
|
85
|
+
tmp_video_id = item.extra.get('video_id')
|
|
86
|
+
if video_id is None and tmp_video_id:
|
|
87
|
+
video_id = tmp_video_id
|
|
88
|
+
if core.config.get("img.remix"):
|
|
89
|
+
tmp_image_id = item.extra.get('image_id')
|
|
90
|
+
if image_id is None and tmp_image_id:
|
|
91
|
+
image_id = tmp_image_id
|
|
92
|
+
if image_id and video_id:
|
|
93
|
+
break
|
|
94
|
+
|
|
73
95
|
# event: context before
|
|
74
96
|
event = Event(Event.CTX_BEFORE)
|
|
75
97
|
event.ctx = ctx
|
|
@@ -117,6 +139,9 @@ class Image:
|
|
|
117
139
|
'context': context,
|
|
118
140
|
'extra': {
|
|
119
141
|
"num": num,
|
|
142
|
+
"image_id": image_id, # pass previous image_id for variations
|
|
143
|
+
"video_id": video_id, # pass previous video_id for variations
|
|
144
|
+
"extra_prompt": extra_prompt,
|
|
120
145
|
},
|
|
121
146
|
}))
|
|
122
147
|
except Exception as e:
|
|
@@ -150,10 +175,20 @@ class Image:
|
|
|
150
175
|
}))
|
|
151
176
|
string = ""
|
|
152
177
|
i = 1
|
|
178
|
+
urls = []
|
|
179
|
+
ico_dir = os.path.join("%appdir%", "data", "icons")
|
|
180
|
+
ico_download = os.path.join(ico_dir, "download.svg")
|
|
181
|
+
ico_preview = os.path.join(ico_dir, "view.svg")
|
|
153
182
|
for path in paths:
|
|
154
|
-
|
|
155
|
-
|
|
183
|
+
safe_path = self.window.core.filesystem.make_local(path)
|
|
184
|
+
"""
|
|
185
|
+
urls.append(f" [**{trans('action.preview')}**]({safe_path}) "
|
|
186
|
+
f"[**{trans('action.download')}**](bridge://download/{safe_path})")
|
|
187
|
+
"""
|
|
188
|
+
urls.append(f"[**{trans('action.open')}**]({safe_path}) | "
|
|
189
|
+
f"[**{trans('action.download')}**](bridge://download/{safe_path})")
|
|
156
190
|
i += 1
|
|
191
|
+
string += "\n".join(urls)
|
|
157
192
|
|
|
158
193
|
if not core.config.get('img_raw'):
|
|
159
194
|
string += f"\nPrompt: {prompt}"
|
|
@@ -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.12.
|
|
9
|
+
# Updated Date: 2025.12.31 17:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
import datetime
|
|
@@ -14,6 +14,7 @@ import os
|
|
|
14
14
|
import shutil
|
|
15
15
|
from typing import Optional, Union
|
|
16
16
|
from shutil import copy2
|
|
17
|
+
from urllib.parse import unquote
|
|
17
18
|
|
|
18
19
|
from PySide6.QtWidgets import QFileDialog, QApplication
|
|
19
20
|
|
|
@@ -210,6 +211,7 @@ class Files:
|
|
|
210
211
|
for p in path:
|
|
211
212
|
self.download_local(p)
|
|
212
213
|
return
|
|
214
|
+
path = self.window.core.filesystem.to_workdir(unquote(path))
|
|
213
215
|
last_dir = self.window.core.config.get_last_used_dir()
|
|
214
216
|
dialog = QFileDialog(self.window)
|
|
215
217
|
dialog.setDirectory(last_dir)
|
|
@@ -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.
|
|
9
|
+
# Updated Date: 2025.12.31 16:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from PySide6.QtWidgets import QApplication
|
|
@@ -34,7 +34,7 @@ class Layout:
|
|
|
34
34
|
"interpreter.columns",
|
|
35
35
|
"columns",
|
|
36
36
|
]
|
|
37
|
-
self.text_nodes = ["input"]
|
|
37
|
+
self.text_nodes = ["input", "input_extra"]
|
|
38
38
|
|
|
39
39
|
def setup(self):
|
|
40
40
|
"""Setup 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.12.
|
|
9
|
+
# Updated Date: 2025.12.30 22:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from typing import Any
|
|
@@ -30,6 +30,34 @@ class Media:
|
|
|
30
30
|
else:
|
|
31
31
|
self.window.ui.config['global']['img_raw'].setChecked(False)
|
|
32
32
|
|
|
33
|
+
# remix for images
|
|
34
|
+
if self.window.core.config.get('img.remix'):
|
|
35
|
+
self.window.ui.config['global']['img.remix'].setChecked(True)
|
|
36
|
+
else:
|
|
37
|
+
self.window.ui.config['global']['img.remix'].setChecked(False)
|
|
38
|
+
|
|
39
|
+
# remix for video
|
|
40
|
+
if self.window.core.config.get('video.remix'):
|
|
41
|
+
self.window.ui.config['global']['video.remix'].setChecked(True)
|
|
42
|
+
else:
|
|
43
|
+
self.window.ui.config['global']['video.remix'].setChecked(False)
|
|
44
|
+
|
|
45
|
+
# img variants
|
|
46
|
+
opt_variants = {
|
|
47
|
+
"type": "int",
|
|
48
|
+
"label": "img_variants",
|
|
49
|
+
"min": 1,
|
|
50
|
+
"max": 4,
|
|
51
|
+
"value": 1,
|
|
52
|
+
}
|
|
53
|
+
variants = self.window.core.config.get('img_variants', 1)
|
|
54
|
+
self.window.controller.config.apply_value(
|
|
55
|
+
parent_id="global",
|
|
56
|
+
key="img_variants",
|
|
57
|
+
option=opt_variants,
|
|
58
|
+
value=variants,
|
|
59
|
+
)
|
|
60
|
+
|
|
33
61
|
# mode (image|video|music)
|
|
34
62
|
mode = self.window.core.config.get('img_mode', 'image')
|
|
35
63
|
self.window.controller.config.apply_value(
|
|
@@ -79,6 +107,7 @@ class Media:
|
|
|
79
107
|
if not self.initialized:
|
|
80
108
|
self.window.ui.add_hook("update.global.img_resolution", self.hook_update)
|
|
81
109
|
self.window.ui.add_hook("update.global.img_mode", self.hook_update)
|
|
110
|
+
self.window.ui.add_hook("update.global.img_variants", self.hook_update)
|
|
82
111
|
self.window.ui.add_hook("update.global.video.aspect_ratio", self.hook_update)
|
|
83
112
|
self.window.ui.add_hook("update.global.video.resolution", self.hook_update)
|
|
84
113
|
self.window.ui.add_hook("update.global.video.duration", self.hook_update)
|
|
@@ -99,6 +128,10 @@ class Media:
|
|
|
99
128
|
if not value:
|
|
100
129
|
return
|
|
101
130
|
self.window.core.config.set('img_resolution', value)
|
|
131
|
+
elif key == "img_variants":
|
|
132
|
+
if not value:
|
|
133
|
+
return
|
|
134
|
+
self.window.core.config.set('img_variants', int(value))
|
|
102
135
|
elif key == "img_mode":
|
|
103
136
|
if not value:
|
|
104
137
|
return
|
|
@@ -135,6 +168,42 @@ class Media:
|
|
|
135
168
|
else:
|
|
136
169
|
self.enable_raw()
|
|
137
170
|
|
|
171
|
+
def enable_remix_image(self):
|
|
172
|
+
"""Enable remix for image"""
|
|
173
|
+
self.window.core.config.set('img.remix', True)
|
|
174
|
+
self.window.core.config.save()
|
|
175
|
+
|
|
176
|
+
def disable_remix_image(self):
|
|
177
|
+
"""Disable remix for image"""
|
|
178
|
+
self.window.core.config.set('img.remix', False)
|
|
179
|
+
self.window.core.config.save()
|
|
180
|
+
|
|
181
|
+
def toggle_remix_image(self):
|
|
182
|
+
"""Save remix enabled option for image"""
|
|
183
|
+
state = self.window.ui.config['global']['img.remix'].isChecked()
|
|
184
|
+
if not state:
|
|
185
|
+
self.disable_remix_image()
|
|
186
|
+
else:
|
|
187
|
+
self.enable_remix_image()
|
|
188
|
+
|
|
189
|
+
def enable_remix_video(self):
|
|
190
|
+
"""Enable remix for video"""
|
|
191
|
+
self.window.core.config.set('video.remix', True)
|
|
192
|
+
self.window.core.config.save()
|
|
193
|
+
|
|
194
|
+
def disable_remix_video(self):
|
|
195
|
+
"""Disable remix for video"""
|
|
196
|
+
self.window.core.config.set('video.remix', False)
|
|
197
|
+
self.window.core.config.save()
|
|
198
|
+
|
|
199
|
+
def toggle_remix_video(self):
|
|
200
|
+
"""Save remix enabled option for video"""
|
|
201
|
+
state = self.window.ui.config['global']['video.remix'].isChecked()
|
|
202
|
+
if not state:
|
|
203
|
+
self.disable_remix_video()
|
|
204
|
+
else:
|
|
205
|
+
self.enable_remix_video()
|
|
206
|
+
|
|
138
207
|
def get_mode(self) -> str:
|
|
139
208
|
"""Get media generation mode (image/video/music)"""
|
|
140
209
|
return self.window.core.config.get("img_mode", "image")
|
|
@@ -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.
|
|
9
|
+
# Updated Date: 2025.12.31 16:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from pygpt_net.core.events import RenderEvent
|
|
@@ -58,6 +58,7 @@ class Nodes:
|
|
|
58
58
|
nodes = {
|
|
59
59
|
'font.chat.input': [
|
|
60
60
|
'input',
|
|
61
|
+
'input_extra',
|
|
61
62
|
],
|
|
62
63
|
'font.chat.output': [
|
|
63
64
|
'output',
|
pygpt_net/controller/ui/mode.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: 2025.12.
|
|
9
|
+
# Updated Date: 2025.12.31 16:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from pygpt_net.core.types import (
|
|
@@ -59,6 +59,8 @@ class Mode:
|
|
|
59
59
|
is_completion = mode == MODE_COMPLETION
|
|
60
60
|
is_audio = mode == MODE_AUDIO
|
|
61
61
|
|
|
62
|
+
ctrl.ui.hide_input_extra()
|
|
63
|
+
|
|
62
64
|
# enable/disable system prompt edit - disable in agents (prompts are defined per agent in presets)
|
|
63
65
|
if not is_agent_openai and not is_agent_llama:
|
|
64
66
|
presets_editor.toggle_tab("personalize", True)
|
|
@@ -178,6 +180,8 @@ class Mode:
|
|
|
178
180
|
ui_nodes['media.raw'].setVisible(False)
|
|
179
181
|
ui_nodes['dalle.options'].setVisible(False)
|
|
180
182
|
ui_nodes['video.options'].setVisible(False)
|
|
183
|
+
|
|
184
|
+
ctrl.ui.show_input_extra()
|
|
181
185
|
else:
|
|
182
186
|
ui_nodes['media.raw'].setVisible(False)
|
|
183
187
|
ui_nodes['dalle.options'].setVisible(False)
|
pygpt_net/controller/ui/ui.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: 2025.12.
|
|
9
|
+
# Updated Date: 2025.12.31 16:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from typing import Optional
|
|
@@ -53,6 +53,7 @@ class UI:
|
|
|
53
53
|
|
|
54
54
|
# Cache for Input tab tooltip to avoid redundant updates
|
|
55
55
|
self._last_input_tab_tooltip = None
|
|
56
|
+
self._input_extra_tab_idx = 4
|
|
56
57
|
|
|
57
58
|
def setup(self):
|
|
58
59
|
"""Setup UI"""
|
|
@@ -275,4 +276,18 @@ class UI:
|
|
|
275
276
|
key="img_mode",
|
|
276
277
|
option=self.window.core.image.get_mode_option(),
|
|
277
278
|
value=current,
|
|
278
|
-
)
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
def show_input_extra(self):
|
|
282
|
+
"""Show extra input area"""
|
|
283
|
+
if self.window.ui.tabs['input'].isTabVisible(self._input_extra_tab_idx):
|
|
284
|
+
return
|
|
285
|
+
self.window.ui.tabs['input'].setTabText(self._input_extra_tab_idx, trans('input.tab.extra.negative_prompt'))
|
|
286
|
+
self.window.ui.tabs['input'].setTabVisible(self._input_extra_tab_idx, True)
|
|
287
|
+
|
|
288
|
+
def hide_input_extra(self):
|
|
289
|
+
"""Hide extra input area"""
|
|
290
|
+
if not self.window.ui.tabs['input'].isTabVisible(self._input_extra_tab_idx):
|
|
291
|
+
return
|
|
292
|
+
self.window.ui.tabs['input'].setTabVisible(self._input_extra_tab_idx, False)
|
|
293
|
+
self.window.ui.tabs['input'].setCurrentIndex(0)
|
pygpt_net/core/filesystem/url.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: 2025.
|
|
9
|
+
# Updated Date: 2025.12.31 16:00:00 #
|
|
10
10
|
# ================================================== #
|
|
11
11
|
|
|
12
12
|
from PySide6.QtCore import QUrl
|
|
@@ -47,6 +47,9 @@ class Url:
|
|
|
47
47
|
elif url.toString().startswith('bridge://play_video/'):
|
|
48
48
|
self.window.controller.media.play_video(url.toString().replace("bridge://play_video/", ""))
|
|
49
49
|
return
|
|
50
|
+
elif url.toString().startswith('bridge://download/'):
|
|
51
|
+
self.window.controller.files.download_local(url.toString().replace("bridge://download/", ""))
|
|
52
|
+
return
|
|
50
53
|
|
|
51
54
|
# -------------
|
|
52
55
|
extra_schemes = (
|
|
@@ -17,6 +17,7 @@ class Helpers:
|
|
|
17
17
|
|
|
18
18
|
_RE_HTML_ANGLE_OR_MATH = re.compile(r'(\\\[.*?\\\])|(<)|(>)', flags=re.DOTALL)
|
|
19
19
|
_RE_WORKDIR_TOKEN = re.compile(r'\(%workdir%([^)]+)\)')
|
|
20
|
+
_RE_APPDIR_TOKEN = re.compile(r'\(%appdir%([^)]+)\)')
|
|
20
21
|
|
|
21
22
|
_PLACEHOLDER_THINK_OPEN = "{{{{think}}}}"
|
|
22
23
|
_PLACEHOLDER_THINK_CLOSE = "{{{{/think}}}}"
|
|
@@ -183,6 +184,10 @@ class Helpers:
|
|
|
183
184
|
prefix = self.window.core.filesystem.get_workdir_prefix()
|
|
184
185
|
s = self._RE_WORKDIR_TOKEN.sub(lambda m, p=prefix: f'({p}{m.group(1)})', s)
|
|
185
186
|
|
|
187
|
+
if "%appdir%" in s:
|
|
188
|
+
prefix = self.window.core.config.get_app_path()
|
|
189
|
+
s = self._RE_APPDIR_TOKEN.sub(lambda m, p=prefix: f'({p}{m.group(1)})', s)
|
|
190
|
+
|
|
186
191
|
return s
|
|
187
192
|
|
|
188
193
|
def post_format_text(self, text: str) -> str:
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"__meta__": {
|
|
3
|
-
"version": "2.7.
|
|
4
|
-
"app.version": "2.7.
|
|
5
|
-
"updated_at": "2025-12-
|
|
3
|
+
"version": "2.7.4",
|
|
4
|
+
"app.version": "2.7.4",
|
|
5
|
+
"updated_at": "2025-12-31T00:00:00"
|
|
6
6
|
},
|
|
7
7
|
"access.audio.event.speech": false,
|
|
8
8
|
"access.audio.event.speech.disabled": [],
|
|
@@ -213,6 +213,7 @@
|
|
|
213
213
|
"img_resolution": "1024x1024",
|
|
214
214
|
"img_quality": "standard",
|
|
215
215
|
"img_variants": 1,
|
|
216
|
+
"img.remix": false,
|
|
216
217
|
"interpreter.auto_clear": false,
|
|
217
218
|
"interpreter.execute_all": false,
|
|
218
219
|
"interpreter.edit": false,
|
|
@@ -537,11 +538,11 @@
|
|
|
537
538
|
"video.duration": 8,
|
|
538
539
|
"video.fps": 24,
|
|
539
540
|
"video.generate_audio": false,
|
|
540
|
-
"video.negative_prompt": "",
|
|
541
541
|
"video.player.path": "",
|
|
542
542
|
"video.player.volume": 100,
|
|
543
543
|
"video.player.volume.mute": false,
|
|
544
544
|
"video.prompt_model": "gemini-2.5-flash",
|
|
545
|
+
"video.remix": false,
|
|
545
546
|
"video.resolution": "720p",
|
|
546
547
|
"video.seed": "",
|
|
547
548
|
"vision.capture.auto": false,
|
|
@@ -1608,20 +1608,6 @@
|
|
|
1608
1608
|
"advanced": false,
|
|
1609
1609
|
"tab": "video"
|
|
1610
1610
|
},
|
|
1611
|
-
"video.negative_prompt": {
|
|
1612
|
-
"section": "images",
|
|
1613
|
-
"type": "textarea",
|
|
1614
|
-
"slider": false,
|
|
1615
|
-
"label": "settings.video.negative_prompt",
|
|
1616
|
-
"description": "settings.video.negative_prompt.desc",
|
|
1617
|
-
"value": "",
|
|
1618
|
-
"min": null,
|
|
1619
|
-
"max": null,
|
|
1620
|
-
"multiplier": null,
|
|
1621
|
-
"step": null,
|
|
1622
|
-
"advanced": false,
|
|
1623
|
-
"tab": "video"
|
|
1624
|
-
},
|
|
1625
1611
|
"video.prompt_model": {
|
|
1626
1612
|
"section": "images",
|
|
1627
1613
|
"type": "combo",
|
|
@@ -748,6 +748,8 @@ idx.token.warn = Dies wird zusätzliche Token für das Einbetten der Daten verbr
|
|
|
748
748
|
img.action.open = In voller Größe öffnen
|
|
749
749
|
img.action.save = Speichern unter...
|
|
750
750
|
img.raw = Raw-Modus
|
|
751
|
+
img.remix = Remixen/Erweitern
|
|
752
|
+
img.remix.tooltip = Remixen/Erweitern vom vorherigen Bild im Kontext aktivieren.\nFalls aktiviert, wird das vorherige Bild als Referenz verwendet, anstatt ein neues von Grund auf zu erstellen.
|
|
751
753
|
img.save.title = Bild speichern
|
|
752
754
|
img.status.downloading = Herunterladen...
|
|
753
755
|
img.status.error = Fehler bei der Bildgenerierung
|
|
@@ -771,6 +773,8 @@ input.search.placeholder = Suchen...
|
|
|
771
773
|
input.send_clear = Nach dem Senden löschen
|
|
772
774
|
input.stream = Streamen
|
|
773
775
|
input.tab = Eingabe
|
|
776
|
+
input.tab.extra = Zusätzlicher Prompt
|
|
777
|
+
input.tab.extra.negative_prompt = Negative prompt
|
|
774
778
|
input.tab.tooltip = {chars} Zeichen (~{tokens} Token)
|
|
775
779
|
interpreter.all = Verlauf ausführen (alle)
|
|
776
780
|
interpreter.auto_clear = Bei Senden löschen
|
|
@@ -1677,6 +1681,8 @@ updater.check.launch = Beim Start prüfen
|
|
|
1677
1681
|
update.released = Build
|
|
1678
1682
|
update.snap = Zum Snap Store gehen
|
|
1679
1683
|
update.title = Nach Updates suchen
|
|
1684
|
+
video.remix = Remixen/Erweitern
|
|
1685
|
+
video.remix.tooltip = Remixen/Erweitern vom vorherigen Video im Kontext aktivieren (Sora2, Veo3.1).\nFalls aktiviert, wird das vorherige Video als Referenz verwendet, anstatt ein neues von Grund auf zu erstellen.
|
|
1680
1686
|
vid.status.downloading = Video wird heruntergeladen... bitte warten...
|
|
1681
1687
|
vid.status.generating = Video wird generiert von
|
|
1682
1688
|
vid.status.prompt.error = Fehler bei der Verbesserungsaufforderung
|
|
@@ -761,7 +761,9 @@ idx.status.truncating = Removing index... please wait...
|
|
|
761
761
|
idx.token.warn = This will consume additional tokens to embed the data.
|
|
762
762
|
img.action.open = Open full size
|
|
763
763
|
img.action.save = Save As...
|
|
764
|
-
img.raw = Raw
|
|
764
|
+
img.raw = Raw
|
|
765
|
+
img.remix = Remix/Extend
|
|
766
|
+
img.remix.tooltip = Enable remix/extend from the previous image in context.\nIf enabled, the previous image will be used as a reference instead of creating a new one from scratch.
|
|
765
767
|
img.save.title = Save image
|
|
766
768
|
img.status.downloading = Downloading...
|
|
767
769
|
img.status.error = Image generation error
|
|
@@ -785,6 +787,8 @@ input.search.placeholder = Search...
|
|
|
785
787
|
input.send_clear = Clear on send
|
|
786
788
|
input.stream = Stream
|
|
787
789
|
input.tab = Input
|
|
790
|
+
input.tab.extra = Extra Input
|
|
791
|
+
input.tab.extra.negative_prompt = Negative prompt
|
|
788
792
|
input.tab.tooltip = {chars} chars (~{tokens} tokens)
|
|
789
793
|
interpreter.all = Execute history (all)
|
|
790
794
|
interpreter.auto_clear = Clear output on send
|
|
@@ -1758,6 +1762,8 @@ updater.check.launch = Check on launch
|
|
|
1758
1762
|
update.released = build
|
|
1759
1763
|
update.snap = Go to Snap Store
|
|
1760
1764
|
update.title = Check for updates
|
|
1765
|
+
video.remix = Remix/Extend
|
|
1766
|
+
video.remix.tooltip = Enable remix/extend from the previous video in context (Sora2, Veo3.1).\nIf enabled, the previous video will be used as a reference instead of creating a new one from scratch.
|
|
1761
1767
|
vid.status.downloading = Downloading video... please wait...
|
|
1762
1768
|
vid.status.generating = Generating video from
|
|
1763
1769
|
vid.status.prompt.error = Enhancement prompt error occured
|
|
@@ -749,6 +749,8 @@ idx.token.warn = Esto consumirá tokens adicionales para incrustar los datos.
|
|
|
749
749
|
img.action.open = Abrir tamaño completo
|
|
750
750
|
img.action.save = Guardar como...
|
|
751
751
|
img.raw = Modo raw
|
|
752
|
+
img.remix = Remix/Extender
|
|
753
|
+
img.remix.tooltip = Habilitar remix/extensión de la imagen anterior en el contexto.\nSi está habilitado, la imagen anterior se usará como referencia en lugar de crear una nueva desde cero.
|
|
752
754
|
img.save.title = Guardar imagen
|
|
753
755
|
img.status.downloading = Descargando...
|
|
754
756
|
img.status.error = Error al generar la imagen
|
|
@@ -772,6 +774,8 @@ input.search.placeholder = Buscar...
|
|
|
772
774
|
input.send_clear = Limpiar al enviar
|
|
773
775
|
input.stream = Transmisión
|
|
774
776
|
input.tab = Entrada
|
|
777
|
+
input.tab.extra = Prompt adicional
|
|
778
|
+
input.tab.extra.negative_prompt = Negative prompt
|
|
775
779
|
input.tab.tooltip = {chars} caracteres (~{tokens} fichas)
|
|
776
780
|
interpreter.all = Ejecutar historial (todo)
|
|
777
781
|
interpreter.auto_clear = Limpiar al enviar
|
|
@@ -1678,6 +1682,8 @@ updater.check.launch = Comprobar al iniciar
|
|
|
1678
1682
|
update.released = Versión
|
|
1679
1683
|
update.snap = Ir a Snap Store
|
|
1680
1684
|
update.title = Buscando actualizaciones
|
|
1685
|
+
video.remix = Remix/Extender
|
|
1686
|
+
video.remix.tooltip = Habilitar remix/extensión del video anterior en el contexto (Sora2, Veo3.1).\nSi está habilitado, el video anterior se usará como referencia en lugar de crear uno nuevo desde cero.
|
|
1681
1687
|
vid.status.downloading = Descargando video... por favor espere...
|
|
1682
1688
|
vid.status.generating = Generando video desde
|
|
1683
1689
|
vid.status.prompt.error = Ocurrió un error en la indicación de mejora
|
|
@@ -748,6 +748,8 @@ idx.token.warn = Cela consommera des jetons supplémentaires pour l'encastrement
|
|
|
748
748
|
img.action.open = Ouvrir en taille réelle
|
|
749
749
|
img.action.save = Enregistrer sous...
|
|
750
750
|
img.raw = Mode brut
|
|
751
|
+
img.remix = Remixer/Étendre
|
|
752
|
+
img.remix.tooltip = Activer le remixage/étendre à partir de l'image précédente dans le contexte.\nSi activé, l'image précédente sera utilisée comme référence au lieu de créer une nouvelle à partir de zéro.
|
|
751
753
|
img.save.title = Enregistrer l'image
|
|
752
754
|
img.status.downloading = Téléchargement en cours...
|
|
753
755
|
img.status.error = Erreur de génération d'image
|
|
@@ -771,6 +773,8 @@ input.search.placeholder = Rechercher...
|
|
|
771
773
|
input.send_clear = Effacer après envoi
|
|
772
774
|
input.stream = Flux
|
|
773
775
|
input.tab = Entrée
|
|
776
|
+
input.tab.extra = Prompt supplémentaire
|
|
777
|
+
input.tab.extra.negative_prompt = Negative prompt
|
|
774
778
|
input.tab.tooltip = {chars} caractères (~{tokens} jetons)
|
|
775
779
|
interpreter.all = Exécuter l'historique (tous)
|
|
776
780
|
interpreter.auto_clear = Effacer à l'envoi
|
|
@@ -1677,6 +1681,8 @@ updater.check.launch = Vérifier au démarrage
|
|
|
1677
1681
|
update.released = build
|
|
1678
1682
|
update.snap = Aller au Snap Store
|
|
1679
1683
|
update.title = Vérification des mises à jour
|
|
1684
|
+
video.remix = Remixer/Étendre
|
|
1685
|
+
video.remix.tooltip = Activer le remixage/étendre à partir de la vidéo précédente dans le contexte (Sora2, Veo3.1).\nSi activé, la vidéo précédente sera utilisée comme référence au lieu de créer une nouvelle à partir de zéro.
|
|
1680
1686
|
vid.status.downloading = Téléchargement de la vidéo... veuillez patienter...
|
|
1681
1687
|
vid.status.generating = Génération de la vidéo à partir de
|
|
1682
1688
|
vid.status.prompt.error = Erreur d'amélioration de l'invite survenue
|
|
@@ -748,6 +748,8 @@ idx.token.warn = Questo consumerà token aggiuntivi per incorporare i dati.
|
|
|
748
748
|
img.action.open = Apri a piena dimensione
|
|
749
749
|
img.action.save = Salva come...
|
|
750
750
|
img.raw = Modalità grezza
|
|
751
|
+
img.remix = Remix/Estendi
|
|
752
|
+
img.remix.tooltip = Abilita remix/estensione dall'immagine precedente nel contesto.\nSe abilitato, l'immagine precedente sarà utilizzata come riferimento invece di crearne una nuova da zero.
|
|
751
753
|
img.save.title = Salva immagine
|
|
752
754
|
img.status.downloading = Scaricamento in corso...
|
|
753
755
|
img.status.error = Errore nella generazione dell'immagine
|
|
@@ -771,6 +773,8 @@ input.search.placeholder = Cerca...
|
|
|
771
773
|
input.send_clear = Pulisci dopo l'invio
|
|
772
774
|
input.stream = Flusso
|
|
773
775
|
input.tab = Input
|
|
776
|
+
input.tab.extra = Prompt extra
|
|
777
|
+
input.tab.extra.negative_prompt = Negative prompt
|
|
774
778
|
input.tab.tooltip = {chars} caratteri (~{tokens} token)
|
|
775
779
|
interpreter.all = Esegui cronologia (tutto)
|
|
776
780
|
interpreter.auto_clear = Cancella all'invio
|
|
@@ -1677,6 +1681,8 @@ updater.check.launch = Controlla all'avvio
|
|
|
1677
1681
|
update.released = build
|
|
1678
1682
|
update.snap = Vai allo Snap Store
|
|
1679
1683
|
update.title = Controllo degli aggiornamenti
|
|
1684
|
+
video.remix = Remix/Estendi
|
|
1685
|
+
video.remix.tooltip = Abilita remix/estensione dal video precedente nel contesto (Sora2, Veo3.1).\nSe abilitato, il video precedente sarà utilizzato come riferimento invece di crearne uno nuovo da zero.
|
|
1680
1686
|
vid.status.downloading = Download del video... si prega di attendere...
|
|
1681
1687
|
vid.status.generating = Generazione video da
|
|
1682
1688
|
vid.status.prompt.error = Si è verificato un errore nel prompt di miglioramento
|
|
@@ -38,7 +38,7 @@ action.open_dir_src = Otwórz katalog źródłowy
|
|
|
38
38
|
action.open_dir_storage = Otwórz katalog magazynowy
|
|
39
39
|
action.open_new_tab = Otwórz w nowej karcie
|
|
40
40
|
action.open_new_window = Otwórz (w nowym oknie)
|
|
41
|
-
action.pack = Spakuj
|
|
41
|
+
action.pack = Spakuj
|
|
42
42
|
action.paste = Wklej
|
|
43
43
|
action.pin = Przypnij na górze
|
|
44
44
|
action.preview = Podgląd
|
|
@@ -749,6 +749,8 @@ idx.token.warn = Spowoduje to użycie dodatkowych tokenów w celu osadzenia dany
|
|
|
749
749
|
img.action.open = Otwórz pełny rozmiar
|
|
750
750
|
img.action.save = Zapisz jako...
|
|
751
751
|
img.raw = Tryb raw
|
|
752
|
+
img.remix = Remiks/Rozszerz
|
|
753
|
+
img.remix.tooltip = Umożliwiaj remiks/rozszerzenie z poprzedniego obrazu w kontekście.\nJeśli włączone, poprzedni obraz będzie używany jako odniesienie zamiast tworzenia nowego od zera.
|
|
752
754
|
img.save.title = Zapisz obraz
|
|
753
755
|
img.status.downloading = Pobieranie obrazu...
|
|
754
756
|
img.status.error = Błąd generowania obrazu
|
|
@@ -772,6 +774,8 @@ input.search.placeholder = Szukaj...
|
|
|
772
774
|
input.send_clear = Wyczyść po wysłaniu
|
|
773
775
|
input.stream = Stream
|
|
774
776
|
input.tab = Input
|
|
777
|
+
input.tab.extra = Dodatkowy prompt
|
|
778
|
+
input.tab.extra.negative_prompt = Negative prompt
|
|
775
779
|
input.tab.tooltip = {chars} znaków (~{tokens} tokenów)
|
|
776
780
|
interpreter.all = Wykonaj historię (wszystko)
|
|
777
781
|
interpreter.auto_clear = Wyczyść wyjście przy wysyłaniu
|
|
@@ -1678,6 +1682,8 @@ updater.check.launch = Sprawdzaj przy uruchamianiu
|
|
|
1678
1682
|
update.released = wydanie
|
|
1679
1683
|
update.snap = Pobierz ze Snap Store
|
|
1680
1684
|
update.title = Sprawdzanie dostępności aktualizacji
|
|
1685
|
+
video.remix = Remiks/Rozszerz
|
|
1686
|
+
video.remix.tooltip = Umożliwiaj remiks/rozszerzenie z poprzedniego wideo w kontekście (Sora2, Veo3.1).\nJeśli włączone, poprzednie wideo będzie używane jako odniesienie zamiast tworzenia nowego od zera.
|
|
1681
1687
|
vid.status.downloading = Downloading video... please wait...
|
|
1682
1688
|
vid.status.generating = Generating video from
|
|
1683
1689
|
vid.status.prompt.error = Enhancement prompt error occured
|