pygpt-net 2.6.30__py3-none-any.whl → 2.6.32__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 (122) hide show
  1. pygpt_net/CHANGELOG.txt +15 -0
  2. pygpt_net/__init__.py +3 -3
  3. pygpt_net/app.py +7 -1
  4. pygpt_net/app_core.py +3 -1
  5. pygpt_net/config.py +3 -1
  6. pygpt_net/controller/__init__.py +9 -2
  7. pygpt_net/controller/audio/audio.py +38 -1
  8. pygpt_net/controller/audio/ui.py +2 -2
  9. pygpt_net/controller/chat/audio.py +1 -8
  10. pygpt_net/controller/chat/common.py +23 -62
  11. pygpt_net/controller/chat/handler/__init__.py +0 -0
  12. pygpt_net/controller/chat/handler/stream_worker.py +1124 -0
  13. pygpt_net/controller/chat/output.py +8 -3
  14. pygpt_net/controller/chat/stream.py +3 -1071
  15. pygpt_net/controller/chat/text.py +3 -2
  16. pygpt_net/controller/kernel/kernel.py +11 -3
  17. pygpt_net/controller/kernel/reply.py +5 -1
  18. pygpt_net/controller/lang/custom.py +2 -2
  19. pygpt_net/controller/media/__init__.py +12 -0
  20. pygpt_net/controller/media/media.py +115 -0
  21. pygpt_net/controller/realtime/__init__.py +12 -0
  22. pygpt_net/controller/realtime/manager.py +53 -0
  23. pygpt_net/controller/realtime/realtime.py +293 -0
  24. pygpt_net/controller/ui/mode.py +23 -2
  25. pygpt_net/controller/ui/ui.py +19 -1
  26. pygpt_net/core/audio/audio.py +6 -1
  27. pygpt_net/core/audio/backend/native/__init__.py +12 -0
  28. pygpt_net/core/audio/backend/{native.py → native/native.py} +426 -127
  29. pygpt_net/core/audio/backend/native/player.py +139 -0
  30. pygpt_net/core/audio/backend/native/realtime.py +250 -0
  31. pygpt_net/core/audio/backend/pyaudio/__init__.py +12 -0
  32. pygpt_net/core/audio/backend/pyaudio/playback.py +194 -0
  33. pygpt_net/core/audio/backend/pyaudio/pyaudio.py +923 -0
  34. pygpt_net/core/audio/backend/pyaudio/realtime.py +312 -0
  35. pygpt_net/core/audio/backend/pygame/__init__.py +12 -0
  36. pygpt_net/core/audio/backend/{pygame.py → pygame/pygame.py} +130 -19
  37. pygpt_net/core/audio/backend/shared/__init__.py +38 -0
  38. pygpt_net/core/audio/backend/shared/conversions.py +211 -0
  39. pygpt_net/core/audio/backend/shared/envelope.py +38 -0
  40. pygpt_net/core/audio/backend/shared/player.py +137 -0
  41. pygpt_net/core/audio/backend/shared/rt.py +52 -0
  42. pygpt_net/core/audio/capture.py +5 -0
  43. pygpt_net/core/audio/output.py +14 -2
  44. pygpt_net/core/audio/whisper.py +6 -2
  45. pygpt_net/core/bridge/bridge.py +2 -1
  46. pygpt_net/core/bridge/worker.py +4 -1
  47. pygpt_net/core/dispatcher/dispatcher.py +37 -1
  48. pygpt_net/core/events/__init__.py +2 -1
  49. pygpt_net/core/events/realtime.py +55 -0
  50. pygpt_net/core/image/image.py +56 -5
  51. pygpt_net/core/realtime/__init__.py +0 -0
  52. pygpt_net/core/realtime/options.py +87 -0
  53. pygpt_net/core/realtime/shared/__init__.py +0 -0
  54. pygpt_net/core/realtime/shared/audio.py +213 -0
  55. pygpt_net/core/realtime/shared/loop.py +64 -0
  56. pygpt_net/core/realtime/shared/session.py +59 -0
  57. pygpt_net/core/realtime/shared/text.py +37 -0
  58. pygpt_net/core/realtime/shared/tools.py +276 -0
  59. pygpt_net/core/realtime/shared/turn.py +38 -0
  60. pygpt_net/core/realtime/shared/types.py +16 -0
  61. pygpt_net/core/realtime/worker.py +160 -0
  62. pygpt_net/core/render/web/body.py +24 -3
  63. pygpt_net/core/text/utils.py +54 -2
  64. pygpt_net/core/types/__init__.py +1 -0
  65. pygpt_net/core/types/image.py +54 -0
  66. pygpt_net/core/video/__init__.py +12 -0
  67. pygpt_net/core/video/video.py +290 -0
  68. pygpt_net/data/config/config.json +26 -5
  69. pygpt_net/data/config/models.json +221 -103
  70. pygpt_net/data/config/settings.json +244 -6
  71. pygpt_net/data/css/web-blocks.css +6 -0
  72. pygpt_net/data/css/web-chatgpt.css +6 -0
  73. pygpt_net/data/css/web-chatgpt_wide.css +6 -0
  74. pygpt_net/data/locale/locale.de.ini +35 -7
  75. pygpt_net/data/locale/locale.en.ini +56 -17
  76. pygpt_net/data/locale/locale.es.ini +35 -7
  77. pygpt_net/data/locale/locale.fr.ini +35 -7
  78. pygpt_net/data/locale/locale.it.ini +35 -7
  79. pygpt_net/data/locale/locale.pl.ini +38 -7
  80. pygpt_net/data/locale/locale.uk.ini +35 -7
  81. pygpt_net/data/locale/locale.zh.ini +31 -3
  82. pygpt_net/data/locale/plugin.audio_input.en.ini +4 -0
  83. pygpt_net/data/locale/plugin.audio_output.en.ini +4 -0
  84. pygpt_net/data/locale/plugin.cmd_web.en.ini +8 -0
  85. pygpt_net/item/model.py +22 -1
  86. pygpt_net/plugin/audio_input/plugin.py +37 -4
  87. pygpt_net/plugin/audio_input/simple.py +57 -8
  88. pygpt_net/plugin/cmd_files/worker.py +3 -0
  89. pygpt_net/provider/api/google/__init__.py +76 -7
  90. pygpt_net/provider/api/google/audio.py +8 -1
  91. pygpt_net/provider/api/google/chat.py +45 -6
  92. pygpt_net/provider/api/google/image.py +226 -86
  93. pygpt_net/provider/api/google/realtime/__init__.py +12 -0
  94. pygpt_net/provider/api/google/realtime/client.py +1945 -0
  95. pygpt_net/provider/api/google/realtime/realtime.py +186 -0
  96. pygpt_net/provider/api/google/video.py +364 -0
  97. pygpt_net/provider/api/openai/__init__.py +22 -2
  98. pygpt_net/provider/api/openai/realtime/__init__.py +12 -0
  99. pygpt_net/provider/api/openai/realtime/client.py +1828 -0
  100. pygpt_net/provider/api/openai/realtime/realtime.py +193 -0
  101. pygpt_net/provider/audio_input/google_genai.py +103 -0
  102. pygpt_net/provider/audio_output/google_genai_tts.py +229 -0
  103. pygpt_net/provider/audio_output/google_tts.py +0 -12
  104. pygpt_net/provider/audio_output/openai_tts.py +8 -5
  105. pygpt_net/provider/core/config/patch.py +241 -178
  106. pygpt_net/provider/core/model/patch.py +28 -2
  107. pygpt_net/provider/llms/google.py +8 -9
  108. pygpt_net/provider/web/duckduck_search.py +212 -0
  109. pygpt_net/ui/layout/toolbox/audio.py +55 -0
  110. pygpt_net/ui/layout/toolbox/footer.py +14 -42
  111. pygpt_net/ui/layout/toolbox/image.py +7 -13
  112. pygpt_net/ui/layout/toolbox/raw.py +52 -0
  113. pygpt_net/ui/layout/toolbox/split.py +48 -0
  114. pygpt_net/ui/layout/toolbox/toolbox.py +8 -8
  115. pygpt_net/ui/layout/toolbox/video.py +49 -0
  116. pygpt_net/ui/widget/option/combo.py +15 -1
  117. {pygpt_net-2.6.30.dist-info → pygpt_net-2.6.32.dist-info}/METADATA +46 -22
  118. {pygpt_net-2.6.30.dist-info → pygpt_net-2.6.32.dist-info}/RECORD +121 -73
  119. pygpt_net/core/audio/backend/pyaudio.py +0 -554
  120. {pygpt_net-2.6.30.dist-info → pygpt_net-2.6.32.dist-info}/LICENSE +0 -0
  121. {pygpt_net-2.6.30.dist-info → pygpt_net-2.6.32.dist-info}/WHEEL +0 -0
  122. {pygpt_net-2.6.30.dist-info → pygpt_net-2.6.32.dist-info}/entry_points.txt +0 -0
@@ -6,12 +6,18 @@
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.24 03:00:00 #
9
+ # Updated Date: 2025.09.01 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from packaging.version import parse as parse_version, Version
13
13
 
14
- from pygpt_net.core.types import MODE_RESEARCH, MODE_CHAT, MODE_AGENT_OPENAI, MODE_COMPUTER, MODE_EXPERT
14
+ from pygpt_net.core.types import (
15
+ MODE_RESEARCH,
16
+ MODE_CHAT,
17
+ MODE_AGENT_OPENAI,
18
+ MODE_COMPUTER,
19
+ MODE_EXPERT
20
+ )
15
21
 
16
22
 
17
23
  class Patch:
@@ -772,6 +778,26 @@ class Patch:
772
778
  data["imagen-4.0-generate-001"] = base_data["imagen-4.0-generate-001"]
773
779
  updated = True
774
780
 
781
+ # < 2.6.31 <--- add realtime models
782
+ if old < parse_version("2.6.31"):
783
+ print("Migrating models from < 2.6.31...")
784
+ if "gemini-2.5-flash-preview-native-audio-dialog" not in data:
785
+ data["gemini-2.5-flash-preview-native-audio-dialog"] = base_data["gemini-2.5-flash-preview-native-audio-dialog"]
786
+ if "gpt-realtime" not in data:
787
+ data["gpt-realtime"] = base_data["gpt-realtime"]
788
+ if "gpt-4o-realtime-preview" not in data:
789
+ data["gpt-4o-realtime-preview"] = base_data["gpt-4o-realtime-preview"]
790
+ updated = True
791
+
792
+ # add veo-3.0-generate-preview
793
+ if old < parse_version("2.6.32"):
794
+ print("Migrating models from < 2.6.32...")
795
+ if "veo-3.0-generate-preview" not in data:
796
+ data["veo-3.0-generate-preview"] = base_data["veo-3.0-generate-preview"]
797
+ if "veo-3.0-fast-generate-preview" not in data:
798
+ data["veo-3.0-fast-generate-preview"] = base_data["veo-3.0-fast-generate-preview"]
799
+ updated = True
800
+
775
801
  # update file
776
802
  if updated:
777
803
  data = dict(sorted(data.items()))
@@ -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.26 19:00:00 #
9
+ # Updated Date: 2025.08.30 06:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from typing import Optional, List, Dict
@@ -92,13 +92,12 @@ class GoogleLLM(BaseLLM):
92
92
  :return: list of models
93
93
  """
94
94
  items = []
95
- client = self.get_client(window)
95
+ client = window.core.api.google.get_client()
96
96
  models_list = client.models.list()
97
- if models_list.data:
98
- for item in models_list.data:
99
- id = item.id.replace("models/", "")
100
- items.append({
101
- "id": id,
102
- "name": id,
103
- })
97
+ for item in models_list:
98
+ id = item.name.replace("models/", "")
99
+ items.append({
100
+ "id": id,
101
+ "name": id, # TODO: token limit get from API
102
+ })
104
103
  return items
@@ -0,0 +1,212 @@
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: 2025.09.02 01:00:00 #
10
+ # ================================================== #
11
+
12
+ from typing import List, Dict
13
+
14
+ from .base import BaseProvider
15
+
16
+
17
+ class DuckDuckGoSearch(BaseProvider):
18
+ def __init__(self, *args, **kwargs):
19
+ """
20
+ DuckDuckGo Search provider
21
+
22
+ :param args: args
23
+ :param kwargs: kwargs
24
+ """
25
+ super(DuckDuckGoSearch, self).__init__(*args, **kwargs)
26
+ self.plugin = kwargs.get("plugin")
27
+ self.id = "duckduckgo_search"
28
+ self.name = "DuckDuckGo"
29
+ self.type = ["search_engine"]
30
+
31
+ def init_options(self):
32
+ """Initialize options"""
33
+ url_params = {
34
+ "URL parameters": "https://duckduckgo.com/duckduckgo-help-pages/settings/params/",
35
+ }
36
+ url_pkg = {
37
+ "ddgs": "https://pypi.org/project/ddgs/",
38
+ }
39
+
40
+ # Region (kl), e.g. us-en, pl-pl, wt-wt (no region)
41
+ self.plugin.add_option(
42
+ "ddg_region",
43
+ type="text",
44
+ value="us-en",
45
+ label="Region (kl)",
46
+ description="DuckDuckGo region, e.g. us-en, pl-pl, wt-wt.",
47
+ tooltip="DuckDuckGo region (kl)",
48
+ persist=True,
49
+ tab="duckduckgo_search",
50
+ urls=url_params,
51
+ )
52
+ # SafeSearch: on | moderate | off
53
+ self.plugin.add_option(
54
+ "ddg_safesearch",
55
+ type="text",
56
+ value="off",
57
+ label="SafeSearch",
58
+ description="Allowed values: on, moderate, off.",
59
+ tooltip="DuckDuckGo SafeSearch",
60
+ persist=True,
61
+ tab="duckduckgo_search",
62
+ urls=url_params,
63
+ )
64
+ # Time limit: d (day), w (week), m (month), y (year), or empty for any time
65
+ self.plugin.add_option(
66
+ "ddg_timelimit",
67
+ type="text",
68
+ value="",
69
+ label="Time limit (df)",
70
+ description="Use: d, w, m, y or leave empty for any time.",
71
+ tooltip="DuckDuckGo time filter",
72
+ tab="duckduckgo_search",
73
+ urls=url_params,
74
+ )
75
+ # Backend selection: auto | html | lite (defaults to html for stability)
76
+ self.plugin.add_option(
77
+ "ddg_backend",
78
+ type="text",
79
+ value="html",
80
+ label="Backend",
81
+ description="Engine backend: auto, html, lite.",
82
+ tooltip="DDG backend",
83
+ persist=True,
84
+ tab="duckduckgo_search",
85
+ urls=url_pkg,
86
+ )
87
+
88
+ def search(
89
+ self,
90
+ query: str,
91
+ limit: int = 10,
92
+ offset: int = 0
93
+ ) -> List[str]:
94
+ """
95
+ Execute search query and return list of urls
96
+
97
+ :param query: query
98
+ :param limit: limit
99
+ :param offset: offset
100
+ :return: list of urls
101
+ """
102
+ DDGS = self._load_ddgs()
103
+ if DDGS is None:
104
+ print("duckduckgo-search (or ddgs) package not installed.")
105
+ return []
106
+
107
+ # Normalize limits to align with other providers
108
+ if limit < 1:
109
+ limit = 1
110
+ if limit > 10:
111
+ limit = 10
112
+ if limit + offset > 100:
113
+ limit = 100 - offset
114
+ if limit < 1:
115
+ return []
116
+
117
+ region = str(self.plugin.get_option_value("ddg_region") or "us-en")
118
+ safesearch = str(self.plugin.get_option_value("ddg_safesearch") or "moderate").lower()
119
+ timelimit = str(self.plugin.get_option_value("ddg_timelimit") or "").lower() or None
120
+ backend = str(self.plugin.get_option_value("ddg_backend") or "html").lower()
121
+
122
+ urls: List[str] = []
123
+ try:
124
+ # Using a context manager to ensure proper session cleanup
125
+ with DDGS() as ddgs:
126
+ # Request enough results to satisfy offset + limit, then slice
127
+ target = limit + offset
128
+ results_iter = ddgs.text(
129
+ query,
130
+ region=region,
131
+ safesearch=safesearch,
132
+ timelimit=timelimit,
133
+ backend=backend,
134
+ max_results=target,
135
+ )
136
+
137
+ # The library may return a generator or a list; handle both
138
+ collected = []
139
+ for r in results_iter or []:
140
+ # r keys typically: title, href, body
141
+ href = r.get("href") or r.get("url")
142
+ if href:
143
+ collected.append(href)
144
+ if len(collected) >= target:
145
+ break
146
+
147
+ if offset > 0:
148
+ collected = collected[offset:offset + limit]
149
+ else:
150
+ collected = collected[:limit]
151
+
152
+ # De-dup and keep order
153
+ seen = set()
154
+ for u in collected:
155
+ if u not in seen:
156
+ urls.append(u)
157
+ seen.add(u)
158
+
159
+ except Exception as e:
160
+ # Fail safe: never raise to the app layer
161
+ print(e)
162
+
163
+ return urls
164
+
165
+ def is_configured(self, cmds: List[Dict]) -> bool:
166
+ """
167
+ Check if provider is configured (required API keys, etc.)
168
+
169
+ :param cmds: executed commands list
170
+ :return: True if configured, False if configuration is missing
171
+ """
172
+ required = ["web_search", "web_urls"]
173
+ need_backend = False
174
+ for item in cmds:
175
+ if item["cmd"] in required:
176
+ need_backend = True
177
+ break
178
+
179
+ if not need_backend:
180
+ return True
181
+
182
+ # Package presence is the only requirement (no API keys needed)
183
+ if self._load_ddgs() is None:
184
+ return False
185
+
186
+ return True
187
+
188
+ def get_config_message(self) -> str:
189
+ """
190
+ Return message to display when provider is not configured
191
+
192
+ :return: message
193
+ """
194
+ return (
195
+ "DuckDuckGo provider requires the 'duckduckgo-search' (or 'ddgs') Python package. "
196
+ "Install with: pip install -U duckduckgo-search"
197
+ )
198
+
199
+ @staticmethod
200
+ def _load_ddgs():
201
+ """
202
+ Try to import DDGS from available packages (duckduckgo-search preferred).
203
+ """
204
+ try:
205
+ from duckduckgo_search import DDGS # type: ignore
206
+ return DDGS
207
+ except Exception:
208
+ try:
209
+ from ddgs import DDGS # type: ignore
210
+ return DDGS
211
+ except Exception:
212
+ return None
@@ -0,0 +1,55 @@
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: 2025.09.01 23:00:00 #
10
+ # ================================================== #
11
+
12
+ from PySide6.QtWidgets import QHBoxLayout, QWidget
13
+
14
+ from pygpt_net.ui.widget.option.toggle_label import ToggleLabel
15
+ from pygpt_net.utils import trans
16
+
17
+
18
+ class Audio:
19
+ def __init__(self, window=None):
20
+ """
21
+ Toolbox UI
22
+
23
+ :param window: Window instance
24
+ """
25
+ self.window = window
26
+
27
+ def setup(self) -> QWidget:
28
+ """
29
+ Setup audio
30
+
31
+ :return: QWidget
32
+ :rtype: QWidget
33
+ """
34
+ self.window.ui.nodes['audio.auto_turn'] = ToggleLabel(trans('audio.auto_turn'), label_position="left",
35
+ icon=":/icons/voice.svg",
36
+ parent=self.window)
37
+ self.window.ui.nodes['audio.auto_turn'].box.toggled.connect(
38
+ self.window.controller.audio.toggle_auto_turn
39
+ )
40
+ self.window.ui.nodes['audio.loop'] = ToggleLabel(trans('audio.loop'), label_position="left",
41
+ parent=self.window)
42
+ self.window.ui.nodes['audio.loop'].box.toggled.connect(
43
+ self.window.controller.audio.toggle_loop
44
+ )
45
+
46
+ audio_layout = QHBoxLayout()
47
+ audio_layout.addStretch(1)
48
+ audio_layout.addWidget(self.window.ui.nodes['audio.auto_turn'])
49
+ audio_layout.addWidget(self.window.ui.nodes['audio.loop'])
50
+ audio_layout.setContentsMargins(5, 0, 15, 0)
51
+
52
+ audio_widget = QWidget()
53
+ audio_widget.setLayout(audio_layout)
54
+
55
+ return audio_widget
@@ -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.26 18:00:00 #
9
+ # Updated Date: 2025.09.01 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import os
@@ -23,11 +23,14 @@ from pygpt_net.utils import trans
23
23
 
24
24
  from .agent import Agent
25
25
  from .agent_llama import AgentLlama
26
+ from .audio import Audio
26
27
  from .computer_env import ComputerEnv
27
28
  from .image import Image
28
29
  from .indexes import Indexes
29
30
  from .vision import Vision
30
-
31
+ from .video import Video
32
+ from .raw import Raw
33
+ from .split import Split
31
34
 
32
35
 
33
36
  class Footer:
@@ -40,10 +43,14 @@ class Footer:
40
43
  self.window = window
41
44
  self.agent = Agent(window)
42
45
  self.agent_llama = AgentLlama(window)
46
+ self.audio = Audio(window)
43
47
  self.env = ComputerEnv(window)
44
48
  self.image = Image(window)
45
49
  self.indexes = Indexes(window)
46
50
  self.vision = Vision(window)
51
+ self.video = Video(window)
52
+ self.raw = Raw(window)
53
+ self.split = Split(window)
47
54
 
48
55
  def setup(self) -> QWidget:
49
56
  """
@@ -51,11 +58,6 @@ class Footer:
51
58
 
52
59
  :return: QHBoxLayout
53
60
  """
54
- # AI and users names
55
- # names_layout = QHBoxLayout()
56
- # names_layout.addLayout(self.setup_name_input('preset.ai_name', trans("toolbox.name.ai")))
57
- # names_layout.addLayout(self.setup_name_input('preset.user_name', trans("toolbox.name.user")))
58
-
59
61
  # bottom
60
62
  option = dict(self.window.controller.settings.editor.get_options()["temperature"])
61
63
  self.window.ui.nodes['temperature.label'] = QLabel(trans("toolbox.temperature.label"), self.window)
@@ -70,48 +72,18 @@ class Footer:
70
72
  # per mode options
71
73
  widget = QWidget(self.window)
72
74
  rows = QVBoxLayout(widget)
73
- # rows.addWidget(self.window.ui.nodes['temperature.label'])
74
- # rows.addWidget(self.window.ui.config['global']['current_temperature'])
75
75
  rows.addWidget(self.agent.setup())
76
76
  rows.addWidget(self.agent_llama.setup())
77
+ rows.addWidget(self.raw.setup())
77
78
  rows.addWidget(self.image.setup())
78
- # rows.addWidget(self.vision.setup())
79
+ rows.addWidget(self.video.setup())
79
80
  rows.addWidget(self.indexes.setup_options())
80
81
  rows.addWidget(self.env.setup())
81
82
  rows.addWidget(self.window.ui.nodes['voice.control.btn'])
82
- rows.setContentsMargins(2, 0, 0, 0)
83
+ rows.addWidget(self.audio.setup())
84
+ rows.addWidget(self.split.setup())
83
85
 
84
- self.window.ui.nodes['layout.split'] = ToggleLabel(trans('layout.split'), label_position="left",
85
- icon=":/icons/split_screen.svg",
86
- parent=self.window)
87
- self.window.ui.nodes['layout.split'].box.toggled.connect(
88
- self.window.controller.ui.tabs.toggle_split_screen
89
- )
90
- split_widget = QWidget(widget)
91
- split_layout = QHBoxLayout(split_widget)
92
-
93
- split_layout.addWidget(QLabel("", split_widget))
94
- split_layout.addStretch(1)
95
- split_layout.addWidget(self.window.ui.nodes['layout.split'])
96
- split_layout.setContentsMargins(5, 0, 15, 0)
97
- rows.addWidget(split_widget)
98
-
99
- # logo
100
- # logo_button = self.setup_logo()
101
-
102
- # bottom (options and logo)
103
- # bottom = QHBoxLayout()
104
- # bottom.addLayout(rows, 80)
105
- # bottom.addWidget(logo_button, 20)
106
- # bottom.setStretchFactor(logo_button, 1)
107
- # bottom.setAlignment(logo_button, Qt.AlignRight | Qt.AlignBottom)
108
- # bottom_widget = QWidget()
109
- # bottom_widget.setLayout(bottom)
110
-
111
- # layout rows
112
- # layout = QVBoxLayout()
113
- # layout.addLayout(names_layout)
114
- # layout.addWidget(bottom_widget)
86
+ rows.setContentsMargins(2, 0, 0, 0)
115
87
 
116
88
  return widget
117
89
 
@@ -6,13 +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: 2025.08.24 23:00:00 #
9
+ # Updated Date: 2025.09.01 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
- from PySide6.QtWidgets import QVBoxLayout, QLabel, QHBoxLayout, QWidget, QCheckBox
12
+ from PySide6.QtWidgets import QVBoxLayout, QWidget
13
13
 
14
+ from pygpt_net.ui.widget.option.combo import OptionCombo
14
15
  from pygpt_net.ui.widget.option.slider import OptionSlider
15
- from pygpt_net.utils import trans
16
16
 
17
17
 
18
18
  class Image:
@@ -48,20 +48,14 @@ class Image:
48
48
  container = QWidget()
49
49
  ui.nodes['dalle.options'] = container
50
50
 
51
- label_text = trans("toolbox.img_variants.label")
52
- ui.nodes['img_variants.label'] = QLabel(label_text, parent=container)
53
-
54
51
  conf_global['img_variants'] = OptionSlider(self.window, 'global', 'img_variants', option)
55
- conf_global['img_raw'] = QCheckBox(trans("img.raw"), parent=container)
56
- conf_global['img_raw'].toggled.connect(self.window.controller.chat.common.img_toggle_raw)
57
52
 
58
- cols = QHBoxLayout()
59
- cols.addWidget(conf_global['img_raw'])
60
- cols.addWidget(conf_global['img_variants'])
53
+ option_resolutions = self.window.core.image.get_resolution_option()
54
+ conf_global['img_resolution'] = OptionCombo(self.window, 'global', 'img_resolution', option_resolutions)
61
55
 
62
56
  rows = QVBoxLayout()
63
- rows.addWidget(ui.nodes['img_variants.label'])
64
- rows.addLayout(cols)
57
+ rows.addWidget(conf_global['img_variants'])
58
+ rows.addWidget(conf_global['img_resolution'])
65
59
  rows.setContentsMargins(2, 5, 5, 5)
66
60
 
67
61
  container.setLayout(rows)
@@ -0,0 +1,52 @@
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: 2025.09.01 23:00:00 #
10
+ # ================================================== #
11
+
12
+ from PySide6.QtWidgets import QVBoxLayout, QHBoxLayout, QWidget, QCheckBox
13
+
14
+ from pygpt_net.utils import trans
15
+
16
+
17
+ class Raw:
18
+ def __init__(self, window=None):
19
+ """
20
+ Toolbox UI
21
+
22
+ :param window: Window instance
23
+ """
24
+ self.window = window
25
+
26
+ def setup(self) -> QWidget:
27
+ """
28
+ Setup media raw
29
+
30
+ :return: QWidget
31
+ :rtype: QWidget
32
+ """
33
+ ui = self.window.ui
34
+ conf_global = ui.config['global']
35
+
36
+ container = QWidget()
37
+ ui.nodes['media.raw'] = container
38
+
39
+ conf_global['img_raw'] = QCheckBox(trans("img.raw"), parent=container)
40
+ conf_global['img_raw'].toggled.connect(self.window.controller.media.toggle_raw)
41
+
42
+ cols = QHBoxLayout()
43
+ cols.addWidget(conf_global['img_raw'])
44
+
45
+ rows = QVBoxLayout()
46
+ rows.addLayout(cols)
47
+ rows.setContentsMargins(2, 5, 5, 5)
48
+
49
+ container.setLayout(rows)
50
+ container.setContentsMargins(2, 0, 0, 0)
51
+
52
+ return container
@@ -0,0 +1,48 @@
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: 2025.09.01 23:00:00 #
10
+ # ================================================== #
11
+
12
+ from PySide6.QtWidgets import QLabel, QHBoxLayout, QWidget
13
+
14
+ from pygpt_net.ui.widget.option.toggle_label import ToggleLabel
15
+ from pygpt_net.utils import trans
16
+
17
+
18
+ class Split:
19
+ def __init__(self, window=None):
20
+ """
21
+ Toolbox UI
22
+
23
+ :param window: Window instance
24
+ """
25
+ self.window = window
26
+
27
+ def setup(self) -> QWidget:
28
+ """
29
+ Setup split screen
30
+
31
+ :return: QWidget
32
+ :rtype: QWidget
33
+ """
34
+ self.window.ui.nodes['layout.split'] = ToggleLabel(trans('layout.split'), label_position="left",
35
+ icon=":/icons/split_screen.svg",
36
+ parent=self.window)
37
+ self.window.ui.nodes['layout.split'].box.toggled.connect(
38
+ self.window.controller.ui.tabs.toggle_split_screen
39
+ )
40
+ split_widget = QWidget(self.window)
41
+ split_layout = QHBoxLayout(split_widget)
42
+
43
+ split_layout.addWidget(QLabel("", split_widget))
44
+ split_layout.addStretch(1)
45
+ split_layout.addWidget(self.window.ui.nodes['layout.split'])
46
+ split_layout.setContentsMargins(5, 0, 15, 0)
47
+
48
+ return split_widget
@@ -6,22 +6,22 @@
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.24 23:00:00 #
9
+ # Updated Date: 2025.09.01 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtGui import Qt
13
13
  from PySide6.QtWidgets import QSplitter, QVBoxLayout, QWidget, QSizePolicy
14
14
 
15
- from pygpt_net.ui.layout.toolbox.assistants import Assistants
16
- from pygpt_net.ui.layout.toolbox.indexes import Indexes
17
- from pygpt_net.ui.layout.toolbox.mode import Mode
18
- from pygpt_net.ui.layout.toolbox.model import Model
19
- from pygpt_net.ui.layout.toolbox.presets import Presets
20
- from pygpt_net.ui.layout.toolbox.prompt import Prompt
21
- from pygpt_net.ui.layout.toolbox.footer import Footer
22
15
  from pygpt_net.ui.widget.element.labels import HelpLabel
23
16
  from pygpt_net.utils import trans
24
17
 
18
+ from .assistants import Assistants
19
+ from .indexes import Indexes
20
+ from .mode import Mode
21
+ from .model import Model
22
+ from .presets import Presets
23
+ from .prompt import Prompt
24
+ from .footer import Footer
25
25
 
26
26
  class ToolboxMain:
27
27
  def __init__(self, window=None):
@@ -0,0 +1,49 @@
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: 2025.09.01 23:00:00 #
10
+ # ================================================== #
11
+
12
+ from PySide6.QtWidgets import QVBoxLayout, QWidget
13
+
14
+ from pygpt_net.ui.widget.option.combo import OptionCombo
15
+
16
+
17
+ class Video:
18
+ def __init__(self, window=None):
19
+ """
20
+ Toolbox UI
21
+
22
+ :param window: Window instance
23
+ """
24
+ self.window = window
25
+
26
+ def setup(self) -> QWidget:
27
+ """
28
+ Setup video
29
+
30
+ :return: QWidget
31
+ :rtype: QWidget
32
+ """
33
+ ui = self.window.ui
34
+ conf_global = ui.config['global']
35
+
36
+ container = QWidget()
37
+ ui.nodes['video.options'] = container
38
+
39
+ option_resolutions = self.window.core.video.get_aspect_ratio_option()
40
+ conf_global['video.aspect_ratio'] = OptionCombo(self.window, 'global', 'video.aspect_ratio', option_resolutions)
41
+
42
+ rows = QVBoxLayout()
43
+ rows.addWidget(conf_global['video.aspect_ratio'])
44
+ rows.setContentsMargins(2, 5, 5, 5)
45
+
46
+ container.setLayout(rows)
47
+ container.setContentsMargins(2, 0, 0, 0)
48
+
49
+ return container