pygpt-net 2.4.37__py3-none-any.whl → 2.4.39__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 (81) hide show
  1. CHANGELOG.md +11 -0
  2. README.md +24 -5
  3. pygpt_net/CHANGELOG.txt +11 -0
  4. pygpt_net/__init__.py +3 -3
  5. pygpt_net/controller/__init__.py +3 -1
  6. pygpt_net/controller/calendar/__init__.py +3 -1
  7. pygpt_net/controller/chat/render.py +8 -5
  8. pygpt_net/controller/config/placeholder.py +29 -0
  9. pygpt_net/controller/ctx/__init__.py +32 -24
  10. pygpt_net/controller/ctx/common.py +3 -2
  11. pygpt_net/controller/dialogs/confirm.py +2 -2
  12. pygpt_net/controller/lang/custom.py +2 -7
  13. pygpt_net/controller/lang/mapping.py +2 -2
  14. pygpt_net/controller/layout.py +2 -2
  15. pygpt_net/controller/notepad.py +8 -5
  16. pygpt_net/controller/settings/editor.py +6 -0
  17. pygpt_net/controller/theme/__init__.py +33 -8
  18. pygpt_net/controller/theme/common.py +22 -1
  19. pygpt_net/controller/theme/markdown.py +26 -14
  20. pygpt_net/controller/theme/menu.py +26 -5
  21. pygpt_net/controller/ui/tabs.py +201 -58
  22. pygpt_net/core/attachments/context.py +14 -12
  23. pygpt_net/core/audio/__init__.py +59 -1
  24. pygpt_net/core/ctx/__init__.py +11 -1
  25. pygpt_net/core/ctx/container.py +16 -9
  26. pygpt_net/core/ctx/output.py +86 -67
  27. pygpt_net/core/debug/tabs.py +3 -2
  28. pygpt_net/core/filesystem/__init__.py +5 -19
  29. pygpt_net/core/filesystem/url.py +7 -3
  30. pygpt_net/core/render/base.py +14 -3
  31. pygpt_net/core/render/markdown/renderer.py +3 -1
  32. pygpt_net/core/render/plain/renderer.py +3 -3
  33. pygpt_net/core/render/web/body.py +39 -17
  34. pygpt_net/core/render/web/renderer.py +7 -5
  35. pygpt_net/core/tabs/__init__.py +180 -71
  36. pygpt_net/core/tabs/tab.py +13 -4
  37. pygpt_net/data/config/config.json +14 -4
  38. pygpt_net/data/config/models.json +3 -3
  39. pygpt_net/data/config/modes.json +3 -3
  40. pygpt_net/data/config/settings.json +55 -10
  41. pygpt_net/data/config/settings_section.json +3 -0
  42. pygpt_net/data/css/style.light.css +1 -0
  43. pygpt_net/data/css/{web.css → web-blocks.css} +144 -133
  44. pygpt_net/data/css/web-chatgpt.css +342 -0
  45. pygpt_net/data/css/web-chatgpt.dark.css +64 -0
  46. pygpt_net/data/css/web-chatgpt.light.css +75 -0
  47. pygpt_net/data/css/web-chatgpt_wide.css +342 -0
  48. pygpt_net/data/css/web-chatgpt_wide.dark.css +64 -0
  49. pygpt_net/data/css/web-chatgpt_wide.light.css +75 -0
  50. pygpt_net/data/locale/locale.de.ini +12 -0
  51. pygpt_net/data/locale/locale.en.ini +14 -1
  52. pygpt_net/data/locale/locale.es.ini +12 -0
  53. pygpt_net/data/locale/locale.fr.ini +12 -0
  54. pygpt_net/data/locale/locale.it.ini +12 -0
  55. pygpt_net/data/locale/locale.pl.ini +12 -0
  56. pygpt_net/data/locale/locale.uk.ini +12 -0
  57. pygpt_net/data/locale/locale.zh.ini +12 -0
  58. pygpt_net/plugin/audio_input/simple.py +21 -5
  59. pygpt_net/provider/core/config/patch.py +22 -1
  60. pygpt_net/provider/core/ctx/base.py +4 -1
  61. pygpt_net/provider/core/ctx/db_sqlite/__init__.py +10 -1
  62. pygpt_net/provider/core/ctx/db_sqlite/storage.py +22 -1
  63. pygpt_net/ui/layout/chat/input.py +10 -18
  64. pygpt_net/ui/layout/chat/output.py +26 -44
  65. pygpt_net/ui/layout/toolbox/footer.py +18 -2
  66. pygpt_net/ui/menu/config.py +7 -11
  67. pygpt_net/ui/menu/theme.py +9 -2
  68. pygpt_net/ui/widget/lists/context.py +1 -0
  69. pygpt_net/ui/widget/tabs/layout.py +195 -0
  70. pygpt_net/ui/widget/tabs/output.py +124 -35
  71. pygpt_net/ui/widget/textarea/html.py +11 -1
  72. pygpt_net/ui/widget/textarea/output.py +10 -1
  73. pygpt_net/ui/widget/textarea/search_input.py +4 -1
  74. pygpt_net/ui/widget/textarea/web.py +49 -9
  75. {pygpt_net-2.4.37.dist-info → pygpt_net-2.4.39.dist-info}/METADATA +25 -6
  76. {pygpt_net-2.4.37.dist-info → pygpt_net-2.4.39.dist-info}/RECORD +81 -74
  77. /pygpt_net/data/css/{web.dark.css → web-blocks.dark.css} +0 -0
  78. /pygpt_net/data/css/{web.light.css → web-blocks.light.css} +0 -0
  79. {pygpt_net-2.4.37.dist-info → pygpt_net-2.4.39.dist-info}/LICENSE +0 -0
  80. {pygpt_net-2.4.37.dist-info → pygpt_net-2.4.39.dist-info}/WHEEL +0 -0
  81. {pygpt_net-2.4.37.dist-info → pygpt_net-2.4.39.dist-info}/entry_points.txt +0 -0
CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 2.4.39 (2024-12-09)
4
+
5
+ - Added "Split Screen" mode (accessible via the switch in the bottom-right corner of the screen), which allows you to work in two windows simultaneously. It is currently experimental (beta). Future updates will include Code Interpreter and Canvas running in tabs.
6
+
7
+ - Fixed: Language switch.
8
+
9
+ ## 2.4.38 (2024-12-08)
10
+
11
+ - Added the ability to select a style for chat display between: Blocks, ChatGPT-like, and ChatGPT-like Wide. New option in the menu: Config -> Theme -> Style...
12
+ - Added configuration options for audio input in Settings -> Audio -> Audio Input Device, Channels, and Sampling rate.
13
+
3
14
  ## 2.4.37 (2024-11-30)
4
15
 
5
16
  - The `Query only` mode in `Uploaded` tab has been renamed to `RAG`.
README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![pygpt](https://snapcraft.io/pygpt/badge.svg)](https://snapcraft.io/pygpt)
4
4
 
5
- Release: **2.4.37** | build: **2024.11.30** | Python: **>=3.10, <3.12**
5
+ Release: **2.4.39** | build: **2024.12.09** | Python: **>=3.10, <3.12**
6
6
 
7
7
  > Official website: https://pygpt.net | Documentation: https://pygpt.readthedocs.io
8
8
  >
@@ -2680,6 +2680,8 @@ Config -> Settings...
2680
2680
 
2681
2681
  - `Zoom`: Adjusts the zoom in chat window (web render view). `WebEngine / Chromium` render mode only.
2682
2682
 
2683
+ - `Style (chat)`: Chat style (Blocks, or ChatGPT-like, or ChatGPT-like Wide. `WebEngine / Chromium` render mode only.
2684
+
2683
2685
  - `Code syntax highlight`: Syntax highlight theme in code blocks. `WebEngine / Chromium` render mode only.
2684
2686
 
2685
2687
  - `Font Size (chat window)`: Adjusts the font size in the chat window (plain-text) and notepads.
@@ -2702,8 +2704,6 @@ Config -> Settings...
2702
2704
 
2703
2705
  - `Use theme colors in chat window`: Use color theme in chat window, Default: True.
2704
2706
 
2705
- - `Disable markdown formatting in output`: Enables plain-text display in output window, Default: False.
2706
-
2707
2707
  **Files and attachments**
2708
2708
 
2709
2709
  - `Store attachments in the workdir upload directory`: Enable to store a local copy of uploaded attachments for future use. Default: True
@@ -2814,14 +2814,22 @@ Config -> Settings...
2814
2814
 
2815
2815
  **Vision**
2816
2816
 
2817
+ - `Vision: Camera Input Device`: Video capture camera index (index of the camera, default: 0).
2818
+
2817
2819
  - `Vision: Camera capture width (px)`: Video capture resolution (width).
2818
2820
 
2819
2821
  - `Vision: Camera capture height (px)`: Video capture resolution (height).
2820
2822
 
2821
- - `Vision: Camera IDX (number)`: Video capture camera index (number of camera).
2822
-
2823
2823
  - `Vision: Image capture quality`: Video capture image JPEG quality (%).
2824
2824
 
2825
+ **Audio**
2826
+
2827
+ - `Audio Input Device`: Selects the audio device for Microphone input.
2828
+
2829
+ - `Channels`: Input channels, default: 1
2830
+
2831
+ - `Sampling Rate`: Sampling rate, default: 44100
2832
+
2825
2833
  **Indexes (LlamaIndex)**
2826
2834
 
2827
2835
  - `Indexes`: List of created indexes.
@@ -3865,6 +3873,17 @@ may consume additional tokens that are not displayed in the main window.
3865
3873
 
3866
3874
  ## Recent changes:
3867
3875
 
3876
+ **2.4.39 (2024-12-09)**
3877
+
3878
+ - Added "Split Screen" mode (accessible via the switch in the bottom-right corner of the screen), which allows you to work in two windows simultaneously. It is currently experimental (beta). Future updates will include Code Interpreter and Canvas running in tabs.
3879
+
3880
+ - Fixed: Language switch.
3881
+
3882
+ **2.4.38 (2024-12-08)**
3883
+
3884
+ - Added the ability to select a style for chat display between: Blocks, ChatGPT-like, and ChatGPT-like Wide. New option in the menu: Config -> Theme -> Style...
3885
+ - Added configuration options for audio input in Settings -> Audio -> Audio Input Device, Channels, and Sampling rate.
3886
+
3868
3887
  **2.4.37 (2024-11-30)**
3869
3888
 
3870
3889
  - The `Query only` mode in `Uploaded` tab has been renamed to `RAG`.
pygpt_net/CHANGELOG.txt CHANGED
@@ -1,3 +1,14 @@
1
+ 2.4.39 (2024-12-09)
2
+
3
+ - Added "Split Screen" mode (accessible via the switch in the bottom-right corner of the screen), which allows you to work in two windows simultaneously. It is currently experimental (beta). Future updates will include Code Interpreter and Canvas running in tabs.
4
+
5
+ - Fixed: Language switch.
6
+
7
+ 2.4.38 (2024-12-08)
8
+
9
+ - Added the ability to select a style for chat display between: Blocks, ChatGPT-like, and ChatGPT-like Wide. New option in the menu: Config -> Theme -> Style...
10
+ - Added configuration options for audio input in Settings -> Audio -> Audio Input Device, Channels, and Sampling rate.
11
+
1
12
  2.4.37 (2024-11-30)
2
13
 
3
14
  - The `Query only` mode in `Uploaded` tab has been renamed to `RAG`.
pygpt_net/__init__.py CHANGED
@@ -6,15 +6,15 @@
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.30 01:00:00 #
9
+ # Updated Date: 2024.12.08 01:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  __author__ = "Marcin Szczygliński"
13
13
  __copyright__ = "Copyright 2024, Marcin Szczygliński"
14
14
  __credits__ = ["Marcin Szczygliński"]
15
15
  __license__ = "MIT"
16
- __version__ = "2.4.37"
17
- __build__ = "2024.11.30"
16
+ __version__ = "2.4.39"
17
+ __build__ = "2024.12.09"
18
18
  __maintainer__ = "Marcin Szczygliński"
19
19
  __github__ = "https://github.com/szczyglis-dev/py-gpt"
20
20
  __website__ = "https://pygpt.net"
@@ -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.21 17:00:00 #
9
+ # Updated Date: 2024.12.09 00:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from pygpt_net.controller.access import Access
@@ -116,6 +116,7 @@ class Controller:
116
116
  self.calendar.setup() # after everything is loaded
117
117
  self.painter.setup() # load previous image if exists
118
118
  self.debug.post_setup() # post setup debug after all loaded
119
+ self.ui.tabs.restore_data() # restore opened tabs data
119
120
 
120
121
  # show license terms dialog
121
122
  if not self.window.core.config.get('license.accepted'):
@@ -168,6 +169,7 @@ class Controller:
168
169
  # post-reload
169
170
  self.ui.tabs.reload_after()
170
171
  self.ctx.reload_after()
172
+ self.ui.tabs.restore_data() # restore opened tabs data
171
173
  self.kernel.restart()
172
174
 
173
175
  self.reloading = False # unlock
@@ -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.05 23:00:00 #
9
+ # Updated Date: 2024.12.09 00:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from pygpt_net.core.tabs.tab import Tab
@@ -48,6 +48,8 @@ class Calendar:
48
48
 
49
49
  :param all: reload all notes
50
50
  """
51
+ if not self.is_loaded():
52
+ return
51
53
  year = self.window.ui.calendar['select'].currentYear
52
54
  month = self.window.ui.calendar['select'].currentMonth
53
55
  self.on_page_changed(year, month, all=all) # load notes for current month
@@ -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.20 03:00:00 #
9
+ # Updated Date: 2024.12.09 03:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtCore import Slot, QTimer
@@ -16,6 +16,7 @@ from pygpt_net.core.render.base import BaseRenderer
16
16
  from pygpt_net.core.render.markdown.renderer import Renderer as MarkdownRenderer
17
17
  from pygpt_net.core.render.plain.renderer import Renderer as PlainTextRenderer
18
18
  from pygpt_net.core.render.web.renderer import Renderer as WebRenderer
19
+ from pygpt_net.core.tabs import Tab
19
20
  from pygpt_net.core.text.utils import output_html2text, output_clean_html
20
21
  from pygpt_net.item.ctx import CtxItem, CtxMeta
21
22
 
@@ -67,6 +68,7 @@ class Render:
67
68
  append = data.get("append", False)
68
69
  footer = data.get("footer", False)
69
70
  initialized = data.get("initialized", False)
71
+ tab = data.get("tab")
70
72
 
71
73
  if name == RenderEvent.BEGIN:
72
74
  self.begin(meta, ctx, stream)
@@ -87,7 +89,7 @@ class Render:
87
89
  self.stream_end(meta, ctx)
88
90
 
89
91
  elif name == RenderEvent.ON_PAGE_LOAD:
90
- self.on_page_loaded(meta)
92
+ self.on_page_loaded(meta, tab)
91
93
  elif name ==RenderEvent.ON_THEME_CHANGE:
92
94
  self.on_theme_change()
93
95
  elif name == RenderEvent.ON_LOAD:
@@ -375,13 +377,14 @@ class Render:
375
377
  self.instance().on_reply_submit(ctx)
376
378
  self.update()
377
379
 
378
- def on_page_loaded(self, meta: CtxMeta):
380
+ def on_page_loaded(self, meta: CtxMeta, tab: Tab = None):
379
381
  """
380
382
  On page loaded callback
381
383
 
382
384
  :param meta: context meta
385
+ :param tab: Tab
383
386
  """
384
- self.instance().on_page_loaded(meta) # TODO: send ID with callback
387
+ self.instance().on_page_loaded(meta, tab)
385
388
  self.update()
386
389
 
387
390
  def on_theme_change(self):
@@ -491,7 +494,7 @@ class Render:
491
494
  if plain:
492
495
  self.window.controller.theme.markdown.clear()
493
496
  for pid in self.window.ui.nodes['output_plain']:
494
- if self.window.ui.nodes['output'][pid] is not None:
497
+ if self.window.ui.nodes['output_plain'][pid] is not None:
495
498
  self.window.ui.nodes['output'][pid].setVisible(False)
496
499
  self.window.ui.nodes['output_plain'][pid].setVisible(True)
497
500
  else:
@@ -86,6 +86,8 @@ class Placeholder:
86
86
  return self.get_agent_providers()
87
87
  elif id == "syntax_styles":
88
88
  return self.get_syntax_styles()
89
+ elif id == "styles":
90
+ return self.get_styles()
89
91
  elif id == "idx":
90
92
  return self.get_idx()
91
93
  elif id == "keys":
@@ -98,9 +100,23 @@ class Placeholder:
98
100
  return self.get_speech_synthesis_actions()
99
101
  elif id == "voice_control_actions":
100
102
  return self.get_voice_control_actions()
103
+ elif id == "audio_input_devices":
104
+ return self.get_audio_input_devices()
101
105
  else:
102
106
  return []
103
107
 
108
+ def get_audio_input_devices(self) -> list:
109
+ """
110
+ Get audio input devices list
111
+
112
+ :return: placeholders list
113
+ """
114
+ devices = self.window.core.audio.get_input_devices()
115
+ data = []
116
+ for device in devices:
117
+ data.append({str(device[0]): device[1]})
118
+ return data
119
+
104
120
  def get_langchain_providers(self) -> list:
105
121
  """
106
122
  Get Langchain LLM provider placeholders list
@@ -276,6 +292,19 @@ class Placeholder:
276
292
  data.append({id: id})
277
293
  return data
278
294
 
295
+ def get_styles(self) -> list:
296
+ """
297
+ Get styles list
298
+
299
+ :return: placeholders list
300
+ """
301
+ styles = self.window.controller.theme.common.get_styles_list()
302
+ styles.sort()
303
+ data = []
304
+ for id in styles:
305
+ data.append({id: id})
306
+ return data
307
+
279
308
  def get_keys(self) -> list:
280
309
  """
281
310
  Get keys
@@ -6,7 +6,7 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2024.11.24 00:00:00 #
9
+ # Updated Date: 2024.12.09 00:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtCore import QModelIndex
@@ -60,20 +60,6 @@ class Ctx:
60
60
  # if no ctx then get first ctx
61
61
  self.window.core.ctx.set_current(self.window.core.ctx.get_first())
62
62
 
63
- # restore previous ctx
64
- # 1) try to load from tabs data - if not exists, load from current
65
- tab = self.window.core.tabs.get_first_by_type(Tab.TAB_CHAT)
66
- loaded = False
67
- if tab is not None:
68
- meta_id = tab.data_id
69
- if meta_id is not None:
70
- self.load(meta_id)
71
- loaded = True
72
-
73
- # 2) load from current if not loaded yet
74
- if not loaded:
75
- self.load(self.window.core.ctx.get_current())
76
-
77
63
  # restore search string if exists
78
64
  if self.window.core.config.has("ctx.search.string"):
79
65
  string = self.window.core.config.get("ctx.search.string")
@@ -144,6 +130,19 @@ class Ctx:
144
130
  # update additional context attachments
145
131
  self.window.controller.chat.attachment.update()
146
132
 
133
+ def select_on_list_only(self, id: int):
134
+ """
135
+ Select ctx by id only on list
136
+
137
+ :param id: context meta id
138
+ """
139
+ self.window.core.ctx.select(id, restore_model=True)
140
+ self.window.core.ctx.set_current(id)
141
+ self.update_list(True)
142
+ self.select_by_current()
143
+ self.reload_config(all=False)
144
+ self.update()
145
+
147
146
  def select_by_idx(self, idx: int):
148
147
  """
149
148
  Select ctx by index
@@ -348,6 +347,21 @@ class Ctx:
348
347
  event = RenderEvent(RenderEvent.ON_LOAD, data)
349
348
  self.window.dispatch(event)
350
349
 
350
+ self.reload_config()
351
+
352
+ # reload ctx list and select current ctx on list, without reloading all
353
+ self.update(reload=False, all=True)
354
+
355
+ # update tab title
356
+ if meta is not None:
357
+ self.window.controller.ui.tabs.update_title_current(meta.name)
358
+
359
+ def reload_config(self, all: bool = True):
360
+ """
361
+ Reload config
362
+
363
+ :param all: reload all
364
+ """
351
365
  # get current settings stored in ctx
352
366
  thread = self.window.core.ctx.get_thread()
353
367
  mode = self.window.core.ctx.get_mode()
@@ -358,8 +372,9 @@ class Ctx:
358
372
  # restore thread from ctx
359
373
  self.window.core.config.set('assistant_thread', thread)
360
374
 
361
- # clear before output and append ctx to output
362
- self.refresh_output()
375
+ if all:
376
+ # clear before output and append ctx to output
377
+ self.refresh_output()
363
378
 
364
379
  # switch mode to ctx mode
365
380
  if mode is not None:
@@ -384,16 +399,9 @@ class Ctx:
384
399
  if model is not None and self.window.core.models.has_model(mode, model):
385
400
  self.window.controller.model.set(mode, model)
386
401
 
387
- # reload ctx list and select current ctx on list, without reloading all
388
- self.update(reload=False, all=True)
389
-
390
402
  # update current ctx label in UI
391
403
  self.common.update_label(mode, assistant_id)
392
404
 
393
- # update tab title
394
- if meta is not None:
395
- self.window.controller.ui.tabs.update_title_current(meta.name)
396
-
397
405
  def update_ctx(self):
398
406
  """Update current ctx mode if allowed"""
399
407
  mode = self.window.core.config.get('mode')
@@ -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.23 00:00:00 #
9
+ # Updated Date: 2024.12.09 00:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtWidgets import QApplication
@@ -91,10 +91,11 @@ class Common:
91
91
 
92
92
  def focus_chat(self):
93
93
  """Focus chat"""
94
+ tabs = self.window.ui.layout.get_active_tabs()
94
95
  if self.window.controller.ui.tabs.get_current_type() != Tab.TAB_CHAT:
95
96
  idx = self.window.core.tabs.get_min_idx_by_type(Tab.TAB_CHAT)
96
97
  if idx is not None:
97
- self.window.ui.tabs['output'].setCurrentIndex(idx)
98
+ tabs.setCurrentIndex(idx)
98
99
 
99
100
  def restore_display_filter(self):
100
101
  """Restore display filter"""
@@ -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.26 02:00:00 #
9
+ # Updated Date: 2024.12.09 03:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  class Confirm:
@@ -154,7 +154,7 @@ class Confirm:
154
154
 
155
155
  # tab close all
156
156
  elif type == 'tab.close_all':
157
- self.window.controller.ui.tabs.close_all(id, True) # by type
157
+ self.window.controller.ui.tabs.close_all(id, 0, True) # by type
158
158
 
159
159
  # editor
160
160
  elif type == 'editor.changed.clear':
@@ -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.26 19:00:00 #
9
+ # Updated Date: 2024.12.09 00:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtCore import Qt
@@ -37,12 +37,7 @@ class Custom:
37
37
 
38
38
  def apply(self):
39
39
  """Apply custom mappings"""
40
- # output: tabs
41
- # self.window.ui.tabs['output'].setTabText(0, trans('output.tab.chat'))
42
- # self.window.ui.tabs['output'].setTabText(1, trans('output.tab.files'))
43
- # self.window.ui.tabs['output'].setTabText(2, trans('output.tab.calendar'))
44
- # self.window.ui.tabs['output'].setTabText(3, trans('output.tab.painter'))
45
-
40
+
46
41
  # tool: indexer
47
42
  self.window.ui.tabs['tool.indexer'].setTabText(0, trans('tool.indexer.tab.files'))
48
43
  self.window.ui.tabs['tool.indexer'].setTabText(1, trans('tool.indexer.tab.web'))
@@ -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.23 00:00:00 #
9
+ # Updated Date: 2024.12.09 03:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from pygpt_net.utils import trans
@@ -332,6 +332,7 @@ class Mapping:
332
332
  menu_title['theme.light'] = 'menu.theme.light'
333
333
  menu_title['theme.syntax'] = 'menu.theme.syntax'
334
334
  menu_title['theme.density'] = 'menu.theme.density'
335
+ menu_title['theme.style'] = 'menu.theme.style'
335
336
  menu_title['menu.plugins'] = 'menu.plugins'
336
337
  menu_title['menu.plugins.presets'] = 'menu.plugins.presets'
337
338
  menu_title['menu.about'] = 'menu.info'
@@ -357,7 +358,6 @@ class Mapping:
357
358
  menu_text['config.profile.new'] = 'menu.config.profile.new'
358
359
  menu_text['config.save'] = 'menu.config.save'
359
360
  menu_text['theme.tooltips'] = 'menu.theme.tooltips'
360
- menu_text['theme.blocks'] = 'menu.theme.blocks'
361
361
  menu_text['theme.settings'] = 'menu.theme.settings'
362
362
  menu_text['plugins.presets.new'] = 'menu.plugins.presets.new'
363
363
  menu_text['plugins.presets.edit'] = 'menu.plugins.presets.edit'
@@ -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.17 03:00:00 #
9
+ # Updated Date: 2024.12.09 03:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import os
@@ -26,7 +26,7 @@ class Layout:
26
26
  """
27
27
  self.window = window
28
28
  # self.splitters = ["main", "main.output", "toolbox", "toolbox.mode", "toolbox.presets"]
29
- self.splitters = ["main", "main.output", "toolbox", "toolbox.mode", "calendar", "interpreter", "interpreter.columns"]
29
+ self.splitters = ["main", "main.output", "toolbox", "toolbox.mode", "calendar", "interpreter", "interpreter.columns", "columns"]
30
30
  self.text_nodes = ["input"]
31
31
 
32
32
  def setup(self):
@@ -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.17 17:00:00 #
9
+ # Updated Date: 2024.12.09 00:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtGui import QTextCursor
@@ -183,10 +183,11 @@ class Notepad:
183
183
  return
184
184
 
185
185
  # switch to first notepad tab if current tab is not notepad
186
+ tabs = self.window.ui.layout.get_active_tabs()
186
187
  if self.window.controller.ui.tabs.get_current_type() != Tab.TAB_NOTEPAD:
187
188
  idx = self.window.core.tabs.get_min_idx_by_type(Tab.TAB_NOTEPAD)
188
189
  if idx is not None:
189
- self.window.ui.tabs['output'].setCurrentIndex(idx)
190
+ tabs.setCurrentIndex(idx)
190
191
 
191
192
  self.window.activateWindow() # focus
192
193
 
@@ -209,11 +210,12 @@ class Notepad:
209
210
  """
210
211
  if idx is None:
211
212
  idx = self.get_first_notepad_tab_idx()
213
+ tabs = self.window.ui.layout.get_active_tabs()
212
214
  tab = self.window.core.tabs.get_tab_by_index(idx)
213
215
  if tab is not None:
214
- self.window.ui.tabs['output'].setCurrentIndex(idx)
216
+ tabs.setCurrentIndex(idx)
215
217
  else:
216
- self.window.ui.tabs['output'].setCurrentIndex(self.get_first_notepad_tab_idx())
218
+ tabs.setCurrentIndex(self.get_first_notepad_tab_idx())
217
219
 
218
220
  def get_first_notepad_tab_idx(self) -> int:
219
221
  """
@@ -257,11 +259,12 @@ class Notepad:
257
259
  return True
258
260
  return False
259
261
 
260
- def on_open(self, tab_idx: int):
262
+ def on_open(self, tab_idx: int, column_idx: int = 0):
261
263
  """
262
264
  On open notepad tab
263
265
 
264
266
  :param tab_idx: current tab idx
267
+ :param column_idx: column idx
265
268
  """
266
269
  tab = self.window.controller.ui.tabs.get_current_tab()
267
270
  if tab is None:
@@ -63,6 +63,7 @@ class Editor:
63
63
  self.window.ui.add_hook("update.config.debug", self.hook_update)
64
64
  self.window.ui.add_hook("update.config.notepad.num", self.hook_update)
65
65
  self.window.ui.add_hook("update.config.render.code_syntax", self.hook_update)
66
+ self.window.ui.add_hook("update.config.theme.style", self.hook_update)
66
67
  # self.window.ui.add_hook("llama.idx.storage", self.hook_update) # vector store update
67
68
  # self.window.ui.add_hook("update.config.llama.idx.list", self.hook_update)
68
69
 
@@ -163,6 +164,11 @@ class Editor:
163
164
  value = self.window.core.config.get('render.code_syntax')
164
165
  self.window.controller.theme.toggle_syntax(value, update_menu=True)
165
166
 
167
+ # style
168
+ if self.config_changed('theme.style'):
169
+ value = self.window.core.config.get('theme.style')
170
+ self.window.controller.theme.toggle_style(value)
171
+
166
172
  # convert lists
167
173
  if self.config_changed('ctx.convert_lists'):
168
174
  self.window.controller.ctx.refresh()
@@ -6,17 +6,17 @@
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: 2024.12.07 21:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import os
13
13
 
14
+ from pygpt_net.core.events import RenderEvent
15
+
14
16
  from .common import Common
15
17
  from .markdown import Markdown
16
18
  from .menu import Menu
17
19
  from .nodes import Nodes
18
- from ...core.events import RenderEvent
19
-
20
20
 
21
21
  class Theme:
22
22
  def __init__(self, window=None):
@@ -68,11 +68,22 @@ class Theme:
68
68
  # update themes menu
69
69
  self.menu.update_list()
70
70
  self.menu.update_syntax()
71
- self.window.ui.menu['theme.blocks'].setChecked(self.window.core.config.get("render.blocks"))
72
71
 
73
72
  if force:
74
73
  self.window.controller.ui.restore_state() # restore state after theme change
75
74
 
75
+ def toggle_style(self, name: str):
76
+ """
77
+ Toggle theme style (web)
78
+
79
+ :param name: web style name
80
+ """
81
+ self.window.core.config.set('theme.style', name)
82
+ self.window.core.config.save()
83
+ event = RenderEvent(RenderEvent.ON_THEME_CHANGE)
84
+ self.window.dispatch(event)
85
+ self.reload()
86
+
76
87
  def toggle_option(self, name: str, value: any = None):
77
88
  """
78
89
  Toggle theme menu option
@@ -120,10 +131,24 @@ class Theme:
120
131
  if update_menu:
121
132
  self.menu.update_syntax()
122
133
 
134
+ def update_style(self):
135
+ """Update style"""
136
+ current = self.window.core.config.get('theme.style')
137
+ self.toggle_style(current)
138
+
139
+ def update_theme(self, force: bool = True):
140
+ """
141
+ Update theme
142
+
143
+ :param force: force theme change (manual trigger)
144
+ """
145
+ current = self.window.core.config.get('theme')
146
+ self.toggle(current, force=force)
147
+
123
148
  def update_syntax(self):
124
149
  """Update syntax menu"""
125
- curr = self.window.core.config.get('render.code_syntax')
126
- self.toggle_syntax(curr, update_menu=True)
150
+ current = self.window.core.config.get('render.code_syntax')
151
+ self.toggle_syntax(current, update_menu=True)
127
152
 
128
153
  def reload(self, force: bool = True):
129
154
  """
@@ -131,8 +156,7 @@ class Theme:
131
156
 
132
157
  :param force: force theme change (manual trigger)
133
158
  """
134
- current = self.window.core.config.get('theme')
135
- self.toggle(current, force=force)
159
+ self.update_theme(force=force)
136
160
 
137
161
  def apply(self, theme: str = 'dark_teal.xml', custom: str = None):
138
162
  """
@@ -183,4 +207,5 @@ class Theme:
183
207
  def reload_all(self):
184
208
  """Reload all"""
185
209
  self.setup()
210
+ self.update_style()
186
211
  self.update_syntax()