pygpt-net 2.6.21__py3-none-any.whl → 2.6.23__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. pygpt_net/CHANGELOG.txt +12 -0
  2. pygpt_net/__init__.py +3 -3
  3. pygpt_net/app.py +3 -1
  4. pygpt_net/controller/__init__.py +4 -8
  5. pygpt_net/controller/access/voice.py +2 -2
  6. pygpt_net/controller/agent/llama.py +3 -0
  7. pygpt_net/controller/assistant/batch.py +2 -3
  8. pygpt_net/controller/assistant/editor.py +2 -2
  9. pygpt_net/controller/assistant/files.py +2 -3
  10. pygpt_net/controller/assistant/store.py +2 -2
  11. pygpt_net/controller/audio/audio.py +2 -2
  12. pygpt_net/controller/chat/response.py +4 -0
  13. pygpt_net/controller/ctx/ctx.py +2 -1
  14. pygpt_net/controller/files/files.py +24 -55
  15. pygpt_net/controller/idx/indexer.py +85 -76
  16. pygpt_net/controller/lang/lang.py +52 -34
  17. pygpt_net/controller/model/importer.py +2 -2
  18. pygpt_net/controller/notepad/notepad.py +86 -84
  19. pygpt_net/controller/plugins/settings.py +3 -4
  20. pygpt_net/controller/settings/profile.py +105 -124
  21. pygpt_net/controller/theme/menu.py +154 -57
  22. pygpt_net/controller/theme/nodes.py +51 -44
  23. pygpt_net/controller/theme/theme.py +33 -9
  24. pygpt_net/controller/tools/tools.py +2 -2
  25. pygpt_net/controller/ui/tabs.py +2 -3
  26. pygpt_net/core/agents/observer/evaluation.py +2 -2
  27. pygpt_net/core/agents/runners/loop.py +1 -0
  28. pygpt_net/core/bridge/bridge.py +2 -0
  29. pygpt_net/core/ctx/container.py +13 -12
  30. pygpt_net/core/ctx/output.py +7 -4
  31. pygpt_net/core/debug/console/console.py +2 -2
  32. pygpt_net/core/filesystem/actions.py +1 -2
  33. pygpt_net/core/filesystem/opener.py +261 -0
  34. pygpt_net/core/filesystem/url.py +13 -10
  35. pygpt_net/core/platforms/platforms.py +5 -4
  36. pygpt_net/core/render/plain/helpers.py +2 -5
  37. pygpt_net/core/render/plain/renderer.py +26 -30
  38. pygpt_net/core/render/web/body.py +1 -1
  39. pygpt_net/core/settings/settings.py +43 -13
  40. pygpt_net/core/tabs/tabs.py +20 -13
  41. pygpt_net/data/config/config.json +4 -4
  42. pygpt_net/data/config/models.json +3 -3
  43. pygpt_net/data/css/web-blocks.dark.css +7 -1
  44. pygpt_net/data/css/web-blocks.light.css +5 -2
  45. pygpt_net/data/css/web-chatgpt.dark.css +7 -1
  46. pygpt_net/data/css/web-chatgpt.light.css +3 -0
  47. pygpt_net/data/css/web-chatgpt_wide.dark.css +7 -1
  48. pygpt_net/data/css/web-chatgpt_wide.light.css +3 -0
  49. pygpt_net/data/locale/locale.de.ini +5 -1
  50. pygpt_net/data/locale/locale.en.ini +5 -1
  51. pygpt_net/data/locale/locale.es.ini +5 -1
  52. pygpt_net/data/locale/locale.fr.ini +5 -1
  53. pygpt_net/data/locale/locale.it.ini +5 -1
  54. pygpt_net/data/locale/locale.pl.ini +6 -4
  55. pygpt_net/data/locale/locale.uk.ini +5 -1
  56. pygpt_net/data/locale/locale.zh.ini +5 -1
  57. pygpt_net/plugin/twitter/plugin.py +2 -2
  58. pygpt_net/provider/core/config/patch.py +12 -1
  59. pygpt_net/tools/audio_transcriber/ui/dialogs.py +44 -54
  60. pygpt_net/tools/code_interpreter/body.py +1 -2
  61. pygpt_net/tools/code_interpreter/tool.py +7 -4
  62. pygpt_net/tools/code_interpreter/ui/html.py +1 -3
  63. pygpt_net/tools/code_interpreter/ui/widgets.py +2 -3
  64. pygpt_net/tools/html_canvas/ui/widgets.py +1 -3
  65. pygpt_net/tools/image_viewer/ui/dialogs.py +40 -37
  66. pygpt_net/tools/indexer/ui/widgets.py +2 -4
  67. pygpt_net/tools/media_player/tool.py +2 -5
  68. pygpt_net/tools/media_player/ui/widgets.py +60 -36
  69. pygpt_net/tools/text_editor/ui/widgets.py +18 -19
  70. pygpt_net/tools/translator/ui/widgets.py +39 -35
  71. pygpt_net/ui/base/context_menu.py +9 -4
  72. pygpt_net/ui/dialog/db.py +1 -3
  73. pygpt_net/ui/dialog/models.py +1 -3
  74. pygpt_net/ui/dialog/models_importer.py +2 -4
  75. pygpt_net/ui/dialogs.py +34 -30
  76. pygpt_net/ui/layout/chat/attachments.py +72 -84
  77. pygpt_net/ui/layout/chat/attachments_ctx.py +40 -44
  78. pygpt_net/ui/layout/chat/attachments_uploaded.py +36 -39
  79. pygpt_net/ui/layout/chat/calendar.py +100 -70
  80. pygpt_net/ui/layout/chat/chat.py +23 -17
  81. pygpt_net/ui/layout/chat/input.py +95 -118
  82. pygpt_net/ui/layout/chat/output.py +100 -162
  83. pygpt_net/ui/layout/chat/painter.py +89 -61
  84. pygpt_net/ui/layout/ctx/ctx_list.py +43 -52
  85. pygpt_net/ui/layout/status.py +23 -14
  86. pygpt_net/ui/layout/toolbox/agent.py +27 -38
  87. pygpt_net/ui/layout/toolbox/agent_llama.py +41 -45
  88. pygpt_net/ui/layout/toolbox/assistants.py +42 -38
  89. pygpt_net/ui/layout/toolbox/computer_env.py +32 -23
  90. pygpt_net/ui/layout/toolbox/footer.py +13 -16
  91. pygpt_net/ui/layout/toolbox/image.py +18 -21
  92. pygpt_net/ui/layout/toolbox/indexes.py +46 -89
  93. pygpt_net/ui/layout/toolbox/mode.py +20 -7
  94. pygpt_net/ui/layout/toolbox/model.py +12 -10
  95. pygpt_net/ui/layout/toolbox/presets.py +68 -52
  96. pygpt_net/ui/layout/toolbox/prompt.py +31 -58
  97. pygpt_net/ui/layout/toolbox/toolbox.py +25 -21
  98. pygpt_net/ui/layout/toolbox/vision.py +20 -22
  99. pygpt_net/ui/main.py +2 -4
  100. pygpt_net/ui/menu/about.py +64 -84
  101. pygpt_net/ui/menu/audio.py +87 -63
  102. pygpt_net/ui/menu/config.py +121 -127
  103. pygpt_net/ui/menu/debug.py +69 -76
  104. pygpt_net/ui/menu/file.py +32 -35
  105. pygpt_net/ui/menu/menu.py +2 -3
  106. pygpt_net/ui/menu/plugins.py +69 -33
  107. pygpt_net/ui/menu/theme.py +45 -46
  108. pygpt_net/ui/menu/tools.py +56 -60
  109. pygpt_net/ui/menu/video.py +20 -25
  110. pygpt_net/ui/tray.py +1 -2
  111. pygpt_net/ui/widget/audio/bar.py +1 -3
  112. pygpt_net/ui/widget/audio/input_button.py +3 -4
  113. pygpt_net/ui/widget/calendar/select.py +1 -2
  114. pygpt_net/ui/widget/dialog/base.py +12 -9
  115. pygpt_net/ui/widget/dialog/editor_file.py +20 -23
  116. pygpt_net/ui/widget/dialog/find.py +25 -24
  117. pygpt_net/ui/widget/dialog/profile.py +57 -53
  118. pygpt_net/ui/widget/draw/painter.py +62 -93
  119. pygpt_net/ui/widget/element/button.py +42 -30
  120. pygpt_net/ui/widget/element/checkbox.py +23 -15
  121. pygpt_net/ui/widget/element/group.py +6 -5
  122. pygpt_net/ui/widget/element/labels.py +1 -2
  123. pygpt_net/ui/widget/filesystem/explorer.py +93 -102
  124. pygpt_net/ui/widget/image/display.py +1 -2
  125. pygpt_net/ui/widget/lists/assistant.py +1 -2
  126. pygpt_net/ui/widget/lists/attachment.py +1 -2
  127. pygpt_net/ui/widget/lists/attachment_ctx.py +1 -2
  128. pygpt_net/ui/widget/lists/context.py +2 -4
  129. pygpt_net/ui/widget/lists/index.py +1 -2
  130. pygpt_net/ui/widget/lists/model.py +1 -2
  131. pygpt_net/ui/widget/lists/model_editor.py +1 -2
  132. pygpt_net/ui/widget/lists/model_importer.py +1 -2
  133. pygpt_net/ui/widget/lists/preset.py +1 -2
  134. pygpt_net/ui/widget/lists/preset_plugins.py +1 -2
  135. pygpt_net/ui/widget/lists/profile.py +1 -2
  136. pygpt_net/ui/widget/lists/uploaded.py +1 -2
  137. pygpt_net/ui/widget/option/checkbox.py +2 -4
  138. pygpt_net/ui/widget/option/checkbox_list.py +1 -4
  139. pygpt_net/ui/widget/option/cmd.py +1 -4
  140. pygpt_net/ui/widget/option/dictionary.py +25 -28
  141. pygpt_net/ui/widget/option/input.py +1 -3
  142. pygpt_net/ui/widget/tabs/Input.py +16 -12
  143. pygpt_net/ui/widget/tabs/body.py +5 -3
  144. pygpt_net/ui/widget/tabs/layout.py +41 -28
  145. pygpt_net/ui/widget/tabs/output.py +442 -85
  146. pygpt_net/ui/widget/textarea/calendar_note.py +1 -2
  147. pygpt_net/ui/widget/textarea/editor.py +41 -73
  148. pygpt_net/ui/widget/textarea/find.py +11 -10
  149. pygpt_net/ui/widget/textarea/html.py +3 -6
  150. pygpt_net/ui/widget/textarea/input.py +134 -69
  151. pygpt_net/ui/widget/textarea/notepad.py +54 -38
  152. pygpt_net/ui/widget/textarea/output.py +65 -54
  153. pygpt_net/ui/widget/textarea/search_input.py +5 -4
  154. pygpt_net/ui/widget/textarea/web.py +2 -4
  155. pygpt_net/ui/widget/vision/camera.py +2 -31
  156. {pygpt_net-2.6.21.dist-info → pygpt_net-2.6.23.dist-info}/METADATA +38 -174
  157. {pygpt_net-2.6.21.dist-info → pygpt_net-2.6.23.dist-info}/RECORD +160 -159
  158. {pygpt_net-2.6.21.dist-info → pygpt_net-2.6.23.dist-info}/LICENSE +0 -0
  159. {pygpt_net-2.6.21.dist-info → pygpt_net-2.6.23.dist-info}/WHEEL +0 -0
  160. {pygpt_net-2.6.21.dist-info → pygpt_net-2.6.23.dist-info}/entry_points.txt +0 -0
@@ -6,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.03 14:00:00 #
9
+ # Updated Date: 2025.08.24 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import datetime
@@ -14,7 +14,7 @@ import os
14
14
  from typing import Any, List, Dict
15
15
 
16
16
  from PySide6.QtCore import Slot, QObject
17
- from qasync import QApplication
17
+ from PySide6.QtWidgets import QApplication
18
18
 
19
19
  from pygpt_net.core.idx.worker import IndexWorker
20
20
  from pygpt_net.item.ctx import CtxMeta
@@ -83,7 +83,7 @@ class Indexer(QObject):
83
83
  """
84
84
  if not force:
85
85
  self.tmp_idx = idx # store tmp index name (for confirmation)
86
- content = trans('idx.confirm.db.content') + "\n" + trans('idx.token.warn')
86
+ content = f"{trans('idx.confirm.db.content')}\n{trans('idx.token.warn')}"
87
87
  self.window.ui.dialogs.confirm(
88
88
  type='idx.index.db',
89
89
  id=meta_id,
@@ -92,18 +92,19 @@ class Indexer(QObject):
92
92
  return
93
93
 
94
94
  meta = self.window.core.ctx.get_meta_by_id(meta_id)
95
- from_ts = meta.indexed
96
95
  self.window.update_status(trans('idx.status.indexing'))
97
96
 
98
- self.worker = IndexWorker()
99
- self.worker.window = self.window
100
- self.worker.content = meta_id
101
- self.worker.idx = idx
102
- self.worker.type = "db_meta"
103
- self.worker.from_ts = from_ts
104
- self.worker.signals.finished.connect(self.handle_finished_db_meta)
105
- self.worker.signals.error.connect(self.handle_error)
106
- self.window.threadpool.start(self.worker)
97
+ worker = IndexWorker()
98
+ worker.window = self.window
99
+ worker.content = meta_id
100
+ worker.idx = idx
101
+ worker.type = "db_meta"
102
+ worker.from_ts = meta.indexed
103
+ worker.signals.finished.connect(self.handle_finished_db_meta)
104
+ worker.signals.error.connect(self.handle_error)
105
+ self.window.threadpool.start(worker)
106
+ self.worker = worker
107
+
107
108
  self.window.controller.idx.on_idx_start() # on start
108
109
 
109
110
  def index_ctx_current(
@@ -146,15 +147,16 @@ class Indexer(QObject):
146
147
  :param idx: index name
147
148
  :param sync: sync mode
148
149
  """
149
- self.worker = IndexWorker()
150
- self.worker.window = self.window
151
- self.worker.content = meta.id
152
- self.worker.idx = idx
153
- self.worker.type = "db_meta"
154
- self.worker.from_ts = meta.indexed
155
- self.worker.silent = True
156
- self.worker.signals.finished.connect(self.handle_finished_db_meta)
157
- self.worker.signals.error.connect(self.handle_error)
150
+ worker = IndexWorker()
151
+ worker.window = self.window
152
+ worker.content = meta.id
153
+ worker.idx = idx
154
+ worker.type = "db_meta"
155
+ worker.from_ts = meta.indexed
156
+ worker.silent = True
157
+ worker.signals.finished.connect(self.handle_finished_db_meta)
158
+ worker.signals.error.connect(self.handle_error)
159
+ self.worker = worker
158
160
 
159
161
  if sync:
160
162
  self.worker.run()
@@ -204,15 +206,17 @@ class Indexer(QObject):
204
206
  )
205
207
  return
206
208
 
207
- self.worker = IndexWorker()
208
- self.worker.window = self.window
209
- self.worker.content = ts
210
- self.worker.idx = idx
211
- self.worker.type = "db_current"
212
- self.worker.silent = silent
213
- self.worker.signals.finished.connect(self.handle_finished_db_current)
214
- self.worker.signals.error.connect(self.handle_error)
215
- self.window.threadpool.start(self.worker)
209
+ worker = IndexWorker()
210
+ worker.window = self.window
211
+ worker.content = ts
212
+ worker.idx = idx
213
+ worker.type = "db_current"
214
+ worker.silent = silent
215
+ worker.signals.finished.connect(self.handle_finished_db_current)
216
+ worker.signals.error.connect(self.handle_error)
217
+ self.window.threadpool.start(worker)
218
+ self.worker = worker
219
+
216
220
  self.window.controller.idx.on_idx_start() # on start
217
221
 
218
222
  def index_path(
@@ -231,16 +235,19 @@ class Indexer(QObject):
231
235
  :param recursive: recursive indexing
232
236
  """
233
237
  self.window.update_status(trans('idx.status.indexing'))
234
- self.worker = IndexWorker()
235
- self.worker.window = self.window
236
- self.worker.content = path
237
- self.worker.idx = idx
238
- self.worker.type = "file"
239
- self.worker.replace = replace
240
- self.worker.recursive = recursive
241
- self.worker.signals.finished.connect(self.handle_finished_file)
242
- self.worker.signals.error.connect(self.handle_error)
243
- self.window.threadpool.start(self.worker)
238
+
239
+ worker = IndexWorker()
240
+ worker.window = self.window
241
+ worker.content = path
242
+ worker.idx = idx
243
+ worker.type = "file"
244
+ worker.replace = replace
245
+ worker.recursive = recursive
246
+ worker.signals.finished.connect(self.handle_finished_file)
247
+ worker.signals.error.connect(self.handle_error)
248
+ self.window.threadpool.start(worker)
249
+ self.worker = worker
250
+
244
251
  self.window.controller.idx.on_idx_start() # on start
245
252
 
246
253
  def index_paths(
@@ -259,17 +266,20 @@ class Indexer(QObject):
259
266
  :param recursive: recursive indexing
260
267
  """
261
268
  self.window.update_status(trans('idx.status.indexing'))
262
- self.worker = IndexWorker()
263
- self.worker.window = self.window
264
- self.worker.content = paths
265
- self.worker.idx = idx
266
- self.worker.type = "files"
267
- self.worker.replace = replace
268
- self.worker.recursive = recursive
269
- self.worker.silent = False
270
- self.worker.signals.finished.connect(self.handle_finished_file)
271
- self.worker.signals.error.connect(self.handle_error)
272
- self.window.threadpool.start(self.worker)
269
+
270
+ worker = IndexWorker()
271
+ worker.window = self.window
272
+ worker.content = paths
273
+ worker.idx = idx
274
+ worker.type = "files"
275
+ worker.replace = replace
276
+ worker.recursive = recursive
277
+ worker.silent = False
278
+ worker.signals.finished.connect(self.handle_finished_file)
279
+ worker.signals.error.connect(self.handle_error)
280
+ self.window.threadpool.start(worker)
281
+ self.worker = worker
282
+
273
283
  self.window.controller.idx.on_idx_start() # on start
274
284
 
275
285
  def index_all_files(
@@ -393,19 +403,21 @@ class Indexer(QObject):
393
403
  :param config: loader config
394
404
  :param replace: replace index
395
405
  """
396
- self.worker = IndexWorker()
397
- self.worker.window = self.window
398
- self.worker.content = None
399
- self.worker.loader = loader
400
- self.worker.params = params
401
- self.worker.config = config
402
- self.worker.replace = replace
403
- self.worker.silent = False
404
- self.worker.idx = idx
405
- self.worker.type = "web"
406
- self.worker.signals.finished.connect(self.handle_finished_web)
407
- self.worker.signals.error.connect(self.handle_error)
408
- self.window.threadpool.start(self.worker)
406
+ worker = IndexWorker()
407
+ worker.window = self.window
408
+ worker.content = None
409
+ worker.loader = loader
410
+ worker.params = params
411
+ worker.config = config
412
+ worker.replace = replace
413
+ worker.silent = False
414
+ worker.idx = idx
415
+ worker.type = "web"
416
+ worker.signals.finished.connect(self.handle_finished_web)
417
+ worker.signals.error.connect(self.handle_error)
418
+ self.window.threadpool.start(worker)
419
+ self.worker = worker
420
+
409
421
  self.window.controller.idx.on_idx_start() # on start
410
422
 
411
423
  def index_ctx_meta_remove(
@@ -444,8 +456,7 @@ class Indexer(QObject):
444
456
 
445
457
  :param idx: on list idx
446
458
  """
447
- idx_name = self.window.core.idx.get_by_idx(idx)
448
- self.clear(idx_name)
459
+ self.clear(self.window.core.idx.get_by_idx(idx))
449
460
 
450
461
  def truncate_by_idx(self, idx: int):
451
462
  """
@@ -453,8 +464,7 @@ class Indexer(QObject):
453
464
 
454
465
  :param idx: on list idx
455
466
  """
456
- idx_name = self.window.core.idx.get_by_idx(idx)
457
- self.clear(idx_name)
467
+ self.clear(self.window.core.idx.get_by_idx(idx))
458
468
 
459
469
  def clear(
460
470
  self,
@@ -496,7 +506,7 @@ class Indexer(QObject):
496
506
  else:
497
507
  self.window.update_status(trans('idx.status.truncate.error'))
498
508
  except Exception as e:
499
- print(e)
509
+ self.window.core.debug.log(e)
500
510
  self.window.update_status(e)
501
511
 
502
512
  self.window.tools.get("indexer").refresh()
@@ -544,7 +554,7 @@ class Indexer(QObject):
544
554
  else:
545
555
  self.window.update_status(trans('idx.status.truncate.error'))
546
556
  except Exception as e:
547
- print(e)
557
+ self.window.core.debug.log(e)
548
558
  self.window.update_status(e)
549
559
 
550
560
  self.window.tools.get("indexer").refresh()
@@ -559,7 +569,6 @@ class Indexer(QObject):
559
569
  self.window.ui.dialogs.alert(err)
560
570
  self.window.update_status(str(err))
561
571
  self.window.core.debug.log(err)
562
- print(err)
563
572
  self.window.tools.get("indexer").refresh()
564
573
  self.window.controller.idx.on_idx_error() # on error
565
574
 
@@ -580,7 +589,7 @@ class Indexer(QObject):
580
589
  :param silent: silent mode (no msg and status update)
581
590
  """
582
591
  if num > 0:
583
- msg = trans('idx.status.success') + f" {num}"
592
+ msg = f"{trans('idx.status.success')} {num}"
584
593
 
585
594
  # store last DB update timestamp
586
595
  self.window.core.config.set('llama.idx.db.index', idx)
@@ -620,7 +629,7 @@ class Indexer(QObject):
620
629
  :param silent: silent mode (no msg and status update)
621
630
  """
622
631
  if num > 0:
623
- msg = trans('idx.status.success') + f" {num}"
632
+ msg = f"{trans('idx.status.success')} {num}"
624
633
  self.update_idx_status(idx)
625
634
  self.window.controller.idx.after_index(idx) # post-actions (update UI, etc.)
626
635
  if not silent:
@@ -654,7 +663,7 @@ class Indexer(QObject):
654
663
  """
655
664
  num = len(files)
656
665
  if num > 0:
657
- msg = trans('idx.status.success') + f" {num}"
666
+ msg = f"{trans('idx.status.success')} {num}"
658
667
  self.window.core.idx.append(idx, files) # append files list to index
659
668
  self.update_idx_status(idx)
660
669
  self.window.controller.idx.after_index(idx) # post-actions (update UI, etc.)
@@ -688,7 +697,7 @@ class Indexer(QObject):
688
697
  :param silent: silent mode (no msg and status update)
689
698
  """
690
699
  if num > 0:
691
- msg = trans('idx.status.success') + f" {num}"
700
+ msg = f"{trans('idx.status.success')} {num}"
692
701
  if not silent:
693
702
  self.window.update_status(msg)
694
703
  self.window.ui.dialogs.alert(msg)
@@ -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.20 21:00:00 #
9
+ # Updated Date: 2025.08.24 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
- from PySide6.QtGui import QAction
12
+ from PySide6.QtGui import QAction, QActionGroup
13
13
 
14
14
  from pygpt_net.utils import trans, trans_reload
15
+
15
16
  from .custom import Custom
16
17
  from .mapping import Mapping
17
18
  from .plugins import Plugins
@@ -31,28 +32,48 @@ class Lang:
31
32
  self.plugins = Plugins(window)
32
33
  self.settings = Settings(window)
33
34
  self.loaded = False
35
+ self._lang_group = None
36
+
37
+ def _on_lang_triggered(self, action):
38
+ """
39
+ Handle language change triggered by menu action
40
+
41
+ :param action: QAction instance
42
+ """
43
+ self.window.controller.lang.toggle(action.data())
34
44
 
35
45
  def setup(self):
36
46
  """Setup language menu"""
37
- # get files from locale directory
38
47
  if not self.loaded:
39
- langs = self.window.core.config.get_available_langs()
48
+ w = self.window
49
+ menu = w.ui.menu
50
+ if self._lang_group is None:
51
+ self._lang_group = QActionGroup(w)
52
+ self._lang_group.setExclusive(True)
53
+ self._lang_group.triggered.connect(self._on_lang_triggered)
54
+
55
+ langs = w.core.config.get_available_langs()
56
+ menu_lang = menu['lang']
57
+ menu_root = menu['menu.lang']
40
58
  for lang in langs:
41
- self.window.ui.menu['lang'][lang] = QAction(lang.upper(), self.window, checkable=True)
42
- self.window.ui.menu['lang'][lang].triggered.connect(
43
- lambda checked=None,
44
- lang=lang: self.window.controller.lang.toggle(lang))
45
- self.window.ui.menu['menu.lang'].addAction(self.window.ui.menu['lang'][lang])
59
+ act = QAction(lang.upper(), w, checkable=True)
60
+ act.setData(lang)
61
+ menu_lang[lang] = act
62
+ self._lang_group.addAction(act)
63
+ menu_root.addAction(act)
46
64
  self.loaded = True
47
65
  self.update()
48
66
 
49
67
  def update(self):
50
68
  """Update language menu"""
51
- for lang in self.window.ui.menu['lang']:
52
- self.window.ui.menu['lang'][lang].setChecked(False)
53
- lang = self.window.core.config.get('lang')
54
- if lang in self.window.ui.menu['lang']:
55
- self.window.ui.menu['lang'][lang].setChecked(True)
69
+ menu_lang = self.window.ui.menu['lang']
70
+ current = self.window.core.config.get('lang')
71
+ act = menu_lang.get(current)
72
+ if act is not None:
73
+ act.setChecked(True)
74
+ else:
75
+ for a in menu_lang.values():
76
+ a.setChecked(False)
56
77
 
57
78
  def reload_config(self):
58
79
  """Reload language config"""
@@ -64,37 +85,34 @@ class Lang:
64
85
 
65
86
  :param id: language code to toggle
66
87
  """
67
- self.window.core.config.set('lang', id)
68
- self.window.core.config.save()
69
- trans('', True) # force reload locale
70
-
71
- self.update() # update menu
72
- self.mapping.apply() # nodes mapping
73
- self.custom.apply() # custom nodes
88
+ w = self.window
89
+ c = w.controller
90
+ conf = w.core.config
74
91
 
75
- # tabs
76
- self.window.controller.ui.tabs.reload_titles()
92
+ conf.set('lang', id)
93
+ conf.save()
94
+ trans('', True)
77
95
 
78
- # calendar
79
- self.window.controller.calendar.note.update_current()
96
+ self.update()
97
+ self.mapping.apply()
98
+ self.custom.apply()
80
99
 
81
- # settings
100
+ c.ui.tabs.reload_titles()
101
+ c.calendar.note.update_current()
82
102
  self.settings.apply()
83
103
 
84
- # plugins
85
104
  try:
86
105
  self.plugins.apply()
87
106
  except Exception as e:
88
107
  print("Error updating plugin locale", e)
89
- self.window.core.debug.log(e)
108
+ w.core.debug.log(e)
90
109
 
91
- # reload UI
92
- self.window.controller.ctx.common.update_label_by_current()
93
- self.window.controller.ctx.update(True, False)
94
- self.window.controller.ui.update() # update all (toolbox, etc.)
95
- self.window.update_status('') # clear status
110
+ w.controller.ctx.common.update_label_by_current()
111
+ w.controller.ctx.update(True, False)
112
+ w.controller.ui.update()
113
+ w.update_status('')
96
114
 
97
115
  def reload(self):
98
116
  """Reload language"""
99
117
  self.reload_config()
100
- self.setup()
118
+ self.setup()
@@ -6,14 +6,14 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2025.08.24 20:00:00 #
9
+ # Updated Date: 2025.08.24 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import copy
13
13
  import os
14
14
  from typing import List, Dict, Optional, Any
15
15
 
16
- from qasync import QApplication
16
+ from PySide6.QtWidgets import QApplication
17
17
 
18
18
  from pygpt_net.core.events import Event
19
19
  from pygpt_net.core.types import (