pygpt-net 2.4.38__py3-none-any.whl → 2.4.40__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- CHANGELOG.md +19 -0
- README.md +25 -2
- pygpt_net/CHANGELOG.txt +19 -0
- pygpt_net/__init__.py +3 -3
- pygpt_net/controller/__init__.py +7 -3
- pygpt_net/controller/audio/__init__.py +9 -1
- pygpt_net/controller/calendar/__init__.py +3 -1
- pygpt_net/controller/chat/input.py +2 -1
- pygpt_net/controller/chat/render.py +8 -5
- pygpt_net/controller/ctx/__init__.py +33 -25
- pygpt_net/controller/ctx/common.py +3 -2
- pygpt_net/controller/debug/__init__.py +13 -2
- pygpt_net/controller/dialogs/confirm.py +2 -2
- pygpt_net/controller/kernel/__init__.py +2 -1
- pygpt_net/controller/lang/custom.py +2 -7
- pygpt_net/controller/lang/mapping.py +2 -2
- pygpt_net/controller/layout.py +2 -2
- pygpt_net/controller/notepad.py +14 -10
- pygpt_net/controller/theme/nodes.py +2 -5
- pygpt_net/controller/tools/__init__.py +37 -1
- pygpt_net/controller/ui/__init__.py +1 -5
- pygpt_net/controller/ui/tabs.py +295 -60
- pygpt_net/core/command.py +3 -1
- pygpt_net/core/ctx/__init__.py +16 -2
- pygpt_net/core/ctx/container.py +18 -11
- pygpt_net/core/ctx/output.py +86 -67
- pygpt_net/core/debug/tabs.py +5 -2
- pygpt_net/core/filesystem/url.py +7 -3
- pygpt_net/core/render/base.py +14 -3
- pygpt_net/core/render/markdown/renderer.py +3 -1
- pygpt_net/core/render/plain/renderer.py +3 -3
- pygpt_net/core/render/web/body.py +10 -4
- pygpt_net/core/render/web/renderer.py +213 -41
- pygpt_net/core/tabs/__init__.py +268 -98
- pygpt_net/core/tabs/tab.py +16 -4
- pygpt_net/core/web.py +127 -1
- pygpt_net/data/config/config.json +12 -5
- pygpt_net/data/config/models.json +3 -3
- pygpt_net/data/config/modes.json +3 -3
- pygpt_net/data/css/web-blocks.css +18 -0
- pygpt_net/data/css/web-blocks.light.css +7 -0
- pygpt_net/data/css/web-chatgpt.css +8 -0
- pygpt_net/data/css/web-chatgpt_wide.css +8 -0
- pygpt_net/data/icons/split_screen.svg +1 -0
- pygpt_net/data/locale/locale.de.ini +3 -0
- pygpt_net/data/locale/locale.en.ini +6 -1
- pygpt_net/data/locale/locale.es.ini +3 -0
- pygpt_net/data/locale/locale.fr.ini +3 -0
- pygpt_net/data/locale/locale.it.ini +3 -0
- pygpt_net/data/locale/locale.pl.ini +4 -1
- pygpt_net/data/locale/locale.uk.ini +3 -0
- pygpt_net/data/locale/locale.zh.ini +3 -0
- pygpt_net/data/locale/plugin.cmd_web.de.ini +2 -0
- pygpt_net/data/locale/plugin.cmd_web.en.ini +20 -10
- pygpt_net/data/locale/plugin.cmd_web.es.ini +2 -0
- pygpt_net/data/locale/plugin.cmd_web.fr.ini +2 -0
- pygpt_net/data/locale/plugin.cmd_web.it.ini +2 -0
- pygpt_net/data/locale/plugin.cmd_web.pl.ini +2 -0
- pygpt_net/data/locale/plugin.cmd_web.uk.ini +2 -0
- pygpt_net/data/locale/plugin.cmd_web.zh.ini +2 -0
- pygpt_net/icons.qrc +1 -0
- pygpt_net/icons_rc.py +165 -136
- pygpt_net/item/ctx.py +46 -24
- pygpt_net/plugin/audio_input/simple.py +4 -2
- pygpt_net/plugin/audio_output/__init__.py +4 -1
- pygpt_net/plugin/base/plugin.py +18 -4
- pygpt_net/plugin/cmd_code_interpreter/__init__.py +39 -37
- pygpt_net/plugin/cmd_code_interpreter/runner.py +25 -12
- pygpt_net/plugin/cmd_web/__init__.py +46 -6
- pygpt_net/plugin/cmd_web/config.py +74 -48
- pygpt_net/plugin/cmd_web/websearch.py +61 -28
- pygpt_net/plugin/cmd_web/worker.py +79 -13
- pygpt_net/provider/core/config/patch.py +29 -1
- pygpt_net/provider/core/ctx/base.py +4 -1
- pygpt_net/provider/core/ctx/db_sqlite/__init__.py +10 -1
- pygpt_net/provider/core/ctx/db_sqlite/storage.py +22 -1
- pygpt_net/tools/__init__.py +9 -1
- pygpt_net/tools/base.py +15 -1
- pygpt_net/tools/code_interpreter/__init__.py +174 -75
- pygpt_net/tools/code_interpreter/ui/dialogs.py +21 -103
- pygpt_net/tools/code_interpreter/ui/widgets.py +284 -9
- pygpt_net/tools/html_canvas/__init__.py +78 -23
- pygpt_net/tools/html_canvas/ui/dialogs.py +46 -62
- pygpt_net/tools/html_canvas/ui/widgets.py +96 -3
- pygpt_net/ui/base/context_menu.py +2 -2
- pygpt_net/ui/layout/chat/input.py +10 -18
- pygpt_net/ui/layout/chat/output.py +26 -44
- pygpt_net/ui/layout/ctx/ctx_list.py +13 -4
- pygpt_net/ui/layout/toolbox/footer.py +18 -2
- pygpt_net/ui/main.py +2 -2
- pygpt_net/ui/menu/debug.py +11 -1
- pygpt_net/ui/widget/filesystem/explorer.py +2 -2
- pygpt_net/ui/widget/lists/context.py +26 -5
- pygpt_net/ui/widget/tabs/Input.py +2 -2
- pygpt_net/ui/widget/tabs/body.py +2 -1
- pygpt_net/ui/widget/tabs/layout.py +195 -0
- pygpt_net/ui/widget/tabs/output.py +209 -55
- pygpt_net/ui/widget/textarea/html.py +11 -1
- pygpt_net/ui/widget/textarea/output.py +10 -1
- pygpt_net/ui/widget/textarea/web.py +49 -9
- {pygpt_net-2.4.38.dist-info → pygpt_net-2.4.40.dist-info}/METADATA +26 -3
- {pygpt_net-2.4.38.dist-info → pygpt_net-2.4.40.dist-info}/RECORD +105 -103
- {pygpt_net-2.4.38.dist-info → pygpt_net-2.4.40.dist-info}/LICENSE +0 -0
- {pygpt_net-2.4.38.dist-info → pygpt_net-2.4.40.dist-info}/WHEEL +0 -0
- {pygpt_net-2.4.38.dist-info → pygpt_net-2.4.40.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: 2024.
|
9
|
+
# Updated Date: 2024.12.12 04:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
import datetime
|
@@ -402,11 +402,32 @@ class ImportantItemDelegate(QtWidgets.QStyledItemDelegate):
|
|
402
402
|
super(ImportantItemDelegate, self).paint(painter, option, index)
|
403
403
|
|
404
404
|
# pin (>= 10)
|
405
|
-
if index.data(QtCore.Qt.ItemDataRole.UserRole)
|
406
|
-
|
405
|
+
if index.data(QtCore.Qt.ItemDataRole.UserRole):
|
406
|
+
data = index.data(QtCore.Qt.ItemDataRole.UserRole)
|
407
|
+
label = 0
|
408
|
+
is_important = False
|
409
|
+
is_attachment = False
|
410
|
+
if "label" in data:
|
411
|
+
label = data["label"]
|
412
|
+
if "is_important" in data and data["is_important"]:
|
413
|
+
is_important = True
|
414
|
+
if "is_attachment" in data and data["is_attachment"]:
|
415
|
+
is_attachment = True
|
416
|
+
|
407
417
|
painter.save()
|
408
418
|
|
409
|
-
if
|
419
|
+
if is_attachment:
|
420
|
+
icon = QtGui.QIcon(":/icons/attachment.svg")
|
421
|
+
icon_size = option.decorationSize or QtCore.QSize(16, 16)
|
422
|
+
icon_rect = QtCore.QRect(
|
423
|
+
option.rect.right() - icon_size.width(),
|
424
|
+
option.rect.top() + (option.rect.height() - icon_size.height()) / 2,
|
425
|
+
icon_size.width(),
|
426
|
+
icon_size.height()
|
427
|
+
)
|
428
|
+
icon.paint(painter, icon_rect, QtCore.Qt.AlignCenter)
|
429
|
+
|
430
|
+
if is_important:
|
410
431
|
color = self.get_color_for_status(3)
|
411
432
|
square_size = 3
|
412
433
|
square_margin = 0
|
@@ -426,7 +447,7 @@ class ImportantItemDelegate(QtWidgets.QStyledItemDelegate):
|
|
426
447
|
)
|
427
448
|
painter.drawRect(square_rect)
|
428
449
|
|
429
|
-
label = label - 10 # remove pin status
|
450
|
+
#label = label - 10 # remove pin status
|
430
451
|
|
431
452
|
# label (0-9)
|
432
453
|
if label > 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: 2024.
|
9
|
+
# Updated Date: 2024.12.09 23:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
from PySide6.QtWidgets import QTabWidget, QMenu
|
@@ -40,7 +40,7 @@ class InputTabs(QTabWidget):
|
|
40
40
|
|
41
41
|
:param global_pos: QPoint
|
42
42
|
"""
|
43
|
-
context_menu = QMenu()
|
43
|
+
context_menu = QMenu(self)
|
44
44
|
actions = {}
|
45
45
|
actions['clear'] = QAction(QIcon(":/icons/delete.svg"), trans('attachments.btn.clear'), self)
|
46
46
|
actions['clear'].triggered.connect(
|
pygpt_net/ui/widget/tabs/body.py
CHANGED
@@ -6,10 +6,11 @@
|
|
6
6
|
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
7
7
|
# MIT License #
|
8
8
|
# Created By : Marcin Szczygliński #
|
9
|
-
# Updated Date: 2024.
|
9
|
+
# Updated Date: 2024.12.09 23:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
from PySide6.QtWidgets import QTabWidget
|
13
|
+
|
13
14
|
from pygpt_net.core.tabs.tab import Tab
|
14
15
|
|
15
16
|
|
@@ -0,0 +1,195 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
# ================================================== #
|
4
|
+
# This file is a part of PYGPT package #
|
5
|
+
# Website: https://pygpt.net #
|
6
|
+
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
7
|
+
# MIT License #
|
8
|
+
# Created By : Marcin Szczygliński #
|
9
|
+
# Updated Date: 2024.12.09 03:00:00 #
|
10
|
+
# ================================================== #
|
11
|
+
|
12
|
+
from PySide6.QtCore import Qt, QObject, QEvent
|
13
|
+
from PySide6.QtWidgets import QTabWidget, QWidget, QVBoxLayout, QSplitter, QSizePolicy
|
14
|
+
|
15
|
+
from pygpt_net.ui.widget.tabs.output import OutputTabs
|
16
|
+
|
17
|
+
|
18
|
+
class OutputColumn(QWidget):
|
19
|
+
def __init__(self, window=None):
|
20
|
+
"""
|
21
|
+
Output column
|
22
|
+
|
23
|
+
:param window: window instance
|
24
|
+
"""
|
25
|
+
super(OutputColumn, self).__init__(window)
|
26
|
+
self.window = window
|
27
|
+
self.idx = -1
|
28
|
+
self.tabs = OutputTabs(self.window, column=self)
|
29
|
+
self.layout = QVBoxLayout()
|
30
|
+
self.layout.addWidget(self.tabs)
|
31
|
+
self.layout.setContentsMargins(0, 0, 0, 0)
|
32
|
+
self.setLayout(self.layout)
|
33
|
+
self.filter = FocusEventFilter(self, self.on_focus)
|
34
|
+
self.installEventFilter(self.filter)
|
35
|
+
self.setFocusPolicy(Qt.StrongFocus)
|
36
|
+
|
37
|
+
def on_focus(self, widget):
|
38
|
+
"""
|
39
|
+
On widget clicked
|
40
|
+
|
41
|
+
:param widget: widget
|
42
|
+
"""
|
43
|
+
self.window.controller.ui.tabs.on_column_focus(self.idx)
|
44
|
+
widget.setFocus()
|
45
|
+
|
46
|
+
def set_idx(self, idx: int):
|
47
|
+
"""
|
48
|
+
Set index
|
49
|
+
|
50
|
+
:param idx: int
|
51
|
+
"""
|
52
|
+
self.idx = idx
|
53
|
+
|
54
|
+
def get_idx(self) -> int:
|
55
|
+
"""
|
56
|
+
Get index
|
57
|
+
|
58
|
+
:return: int
|
59
|
+
"""
|
60
|
+
return self.idx
|
61
|
+
|
62
|
+
def set_tabs(self, tabs: QTabWidget):
|
63
|
+
"""
|
64
|
+
Set tabs widget
|
65
|
+
|
66
|
+
:param tabs: QTabWidget
|
67
|
+
"""
|
68
|
+
self.tabs = tabs
|
69
|
+
|
70
|
+
def get_tabs(self) -> OutputTabs:
|
71
|
+
"""
|
72
|
+
Get tabs
|
73
|
+
|
74
|
+
:return: OutputTabs
|
75
|
+
"""
|
76
|
+
return self.tabs
|
77
|
+
|
78
|
+
|
79
|
+
class OutputLayout(QWidget):
|
80
|
+
def __init__(self, window=None):
|
81
|
+
"""
|
82
|
+
Output layout
|
83
|
+
|
84
|
+
:param window: window instance
|
85
|
+
"""
|
86
|
+
super(OutputLayout, self).__init__(window)
|
87
|
+
self.window = window
|
88
|
+
self.columns = []
|
89
|
+
|
90
|
+
column1 = OutputColumn(self.window)
|
91
|
+
column2 = OutputColumn(self.window)
|
92
|
+
self.add_column(column1)
|
93
|
+
self.add_column(column2)
|
94
|
+
|
95
|
+
self.splitter = QSplitter(Qt.Horizontal)
|
96
|
+
self.splitter.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
97
|
+
for column in self.columns:
|
98
|
+
self.splitter.addWidget(column)
|
99
|
+
|
100
|
+
self.window.ui.splitters['columns'] = self.splitter
|
101
|
+
|
102
|
+
self.layout = QVBoxLayout()
|
103
|
+
self.layout.addWidget(self.splitter, stretch=1)
|
104
|
+
self.layout.setContentsMargins(0, 0, 0, 0)
|
105
|
+
self.setLayout(self.layout)
|
106
|
+
|
107
|
+
def get_next_idx(self) -> int:
|
108
|
+
"""
|
109
|
+
Get next index
|
110
|
+
|
111
|
+
:return: int
|
112
|
+
"""
|
113
|
+
return len(self.columns)
|
114
|
+
|
115
|
+
def add_column(self, column: OutputColumn):
|
116
|
+
"""
|
117
|
+
Add column
|
118
|
+
|
119
|
+
:param column: OutputColumn
|
120
|
+
"""
|
121
|
+
idx = self.get_next_idx()
|
122
|
+
column.set_idx(idx)
|
123
|
+
self.columns.append(column)
|
124
|
+
|
125
|
+
def get_tabs_by_idx(self, idx: int) -> OutputTabs:
|
126
|
+
"""
|
127
|
+
Get tabs by column index
|
128
|
+
|
129
|
+
:param idx: int
|
130
|
+
:return: OutputTabs
|
131
|
+
"""
|
132
|
+
for column in self.columns:
|
133
|
+
if column.idx == idx:
|
134
|
+
return column.tabs
|
135
|
+
return None
|
136
|
+
|
137
|
+
def get_active_tabs(self) -> OutputTabs:
|
138
|
+
"""
|
139
|
+
Get active tabs
|
140
|
+
|
141
|
+
:return: OutputTabs
|
142
|
+
"""
|
143
|
+
current = self.window.controller.ui.tabs.get_current_column_idx()
|
144
|
+
for column in self.columns:
|
145
|
+
if column.idx == current:
|
146
|
+
return column.tabs
|
147
|
+
|
148
|
+
def get_column_by_idx(self, idx: int) -> OutputColumn:
|
149
|
+
"""
|
150
|
+
Get column by index
|
151
|
+
|
152
|
+
:param idx: int
|
153
|
+
:return: OutputColumn
|
154
|
+
"""
|
155
|
+
for column in self.columns:
|
156
|
+
if column.idx == idx:
|
157
|
+
return column
|
158
|
+
return None
|
159
|
+
|
160
|
+
def get_active_column(self) -> OutputColumn:
|
161
|
+
"""
|
162
|
+
Get active column
|
163
|
+
|
164
|
+
:return: OutputColumn
|
165
|
+
"""
|
166
|
+
current = self.window.controller.ui.tabs.get_current_column_idx()
|
167
|
+
for column in self.columns:
|
168
|
+
if column.idx == current:
|
169
|
+
return column
|
170
|
+
|
171
|
+
class FocusEventFilter(QObject):
|
172
|
+
def __init__(self, column, callback):
|
173
|
+
"""
|
174
|
+
Column event filter
|
175
|
+
|
176
|
+
:param column: parent column
|
177
|
+
:param callback: callback
|
178
|
+
"""
|
179
|
+
super().__init__()
|
180
|
+
self.column = column
|
181
|
+
self.callback = callback
|
182
|
+
|
183
|
+
def eventFilter(self, obj, event):
|
184
|
+
"""
|
185
|
+
Click event filter
|
186
|
+
|
187
|
+
:param obj: object
|
188
|
+
:param event: event
|
189
|
+
"""
|
190
|
+
if event.type() == QEvent.MouseButtonPress or event.type() == QEvent.FocusIn:
|
191
|
+
widget = obj
|
192
|
+
if widget is not None:
|
193
|
+
self.callback(widget)
|
194
|
+
return False
|
195
|
+
return False
|
@@ -6,10 +6,10 @@
|
|
6
6
|
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
7
7
|
# MIT License #
|
8
8
|
# Created By : Marcin Szczygliński #
|
9
|
-
# Updated Date: 2024.
|
9
|
+
# Updated Date: 2024.12.12 01:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
|
-
from PySide6.QtWidgets import QTabWidget, QMenu
|
12
|
+
from PySide6.QtWidgets import QTabWidget, QMenu, QPushButton
|
13
13
|
from PySide6.QtCore import Qt, Slot
|
14
14
|
from PySide6.QtGui import QAction, QIcon
|
15
15
|
|
@@ -18,17 +18,119 @@ from pygpt_net.utils import trans
|
|
18
18
|
import pygpt_net.icons_rc
|
19
19
|
|
20
20
|
|
21
|
+
class AddButton(QPushButton):
|
22
|
+
def __init__(self, window=None, column=None, tabs=None):
|
23
|
+
super(AddButton, self).__init__(QIcon(":/icons/add.svg"), "", window)
|
24
|
+
self.window = window
|
25
|
+
self.column = column
|
26
|
+
self.tabs = tabs
|
27
|
+
self.setFixedSize(30, 25)
|
28
|
+
self.setFlat(True)
|
29
|
+
self.clicked.connect(
|
30
|
+
lambda: self.window.controller.ui.tabs.new_tab(self.column.get_idx())
|
31
|
+
)
|
32
|
+
self.setObjectName('tab-add')
|
33
|
+
self.setProperty('tabAdd', True)
|
34
|
+
self.setToolTip(trans('action.tab.add.chat'))
|
35
|
+
|
36
|
+
def mousePressEvent(self, event):
|
37
|
+
"""
|
38
|
+
Mouse press event
|
39
|
+
|
40
|
+
:param event: event
|
41
|
+
"""
|
42
|
+
if event.button() == Qt.RightButton:
|
43
|
+
idx = 0
|
44
|
+
column_idx = self.column.get_idx()
|
45
|
+
self.show_menu(idx, column_idx, event.globalPos())
|
46
|
+
super(AddButton, self).mousePressEvent(event)
|
47
|
+
|
48
|
+
def show_menu(self, index: int, column_idx: int, global_pos):
|
49
|
+
"""
|
50
|
+
Show context menu
|
51
|
+
|
52
|
+
:param index: index
|
53
|
+
:param column_idx: column index
|
54
|
+
:param global_pos: global position
|
55
|
+
"""
|
56
|
+
context_menu = self.prepare_menu(index, column_idx)
|
57
|
+
context_menu.exec(global_pos)
|
58
|
+
|
59
|
+
def prepare_menu(self, index: int, column_idx: int) -> QMenu:
|
60
|
+
"""
|
61
|
+
Prepare and return context menu
|
62
|
+
|
63
|
+
:param index: index
|
64
|
+
:param column_idx: column index
|
65
|
+
:return: menu
|
66
|
+
"""
|
67
|
+
menu = QMenu(self)
|
68
|
+
|
69
|
+
actions = {}
|
70
|
+
actions['add_chat'] = QAction(QIcon(":/icons/add.svg"), trans('action.tab.add.chat'), self)
|
71
|
+
actions['add_chat'].triggered.connect(
|
72
|
+
lambda: self.tabs.add_tab(index, column_idx, Tab.TAB_CHAT)
|
73
|
+
)
|
74
|
+
actions['add_notepad'] = QAction(QIcon(":/icons/add.svg"), trans('action.tab.add.notepad'), self)
|
75
|
+
actions['add_notepad'].triggered.connect(
|
76
|
+
lambda: self.tabs.add_tab(index, column_idx, Tab.TAB_NOTEPAD)
|
77
|
+
)
|
78
|
+
|
79
|
+
# add chat, add notepad
|
80
|
+
menu.addAction(actions['add_chat'])
|
81
|
+
menu.addAction(actions['add_notepad'])
|
82
|
+
|
83
|
+
# add tools submenu
|
84
|
+
self.window.controller.tools.append_tab_menu(self, menu, index, column_idx)
|
85
|
+
|
86
|
+
return menu
|
87
|
+
|
21
88
|
class OutputTabs(QTabWidget):
|
22
|
-
def __init__(self, window=None):
|
89
|
+
def __init__(self, window=None, column=None):
|
23
90
|
super(OutputTabs, self).__init__(window)
|
24
91
|
self.window = window
|
92
|
+
self.column = column
|
25
93
|
self.setMinimumHeight(1)
|
26
94
|
self.owner = None
|
27
95
|
self.setMovable(True)
|
96
|
+
self.init()
|
97
|
+
|
98
|
+
def init(self):
|
99
|
+
"""Initialize"""
|
100
|
+
# create the [+] button
|
101
|
+
add_button = AddButton(self.window, self.column, self)
|
102
|
+
|
103
|
+
# add the button to the top right corner of the tab bar
|
104
|
+
self.setCornerWidget(add_button, corner=Qt.TopRightCorner)
|
105
|
+
|
106
|
+
# connect signals
|
107
|
+
self.currentChanged.connect(
|
108
|
+
lambda: self.window.controller.ui.tabs.on_tab_changed(self.currentIndex(), self.column.get_idx())
|
109
|
+
)
|
110
|
+
self.tabBarClicked.connect(
|
111
|
+
lambda: self.window.controller.ui.tabs.on_tab_clicked(self.currentIndex(), self.column.get_idx())
|
112
|
+
)
|
113
|
+
self.tabBarDoubleClicked.connect(
|
114
|
+
lambda: self.window.controller.ui.tabs.on_tab_dbl_clicked(self.currentIndex(), self.column.get_idx())
|
115
|
+
)
|
116
|
+
self.tabCloseRequested.connect(
|
117
|
+
lambda: self.window.controller.ui.tabs.on_tab_closed(self.currentIndex(), self.column.get_idx())
|
118
|
+
)
|
119
|
+
self.tabBar().tabMoved.connect(
|
120
|
+
lambda: self.window.controller.ui.tabs.on_tab_moved(self.currentIndex(), self.column.get_idx())
|
121
|
+
)
|
122
|
+
|
123
|
+
def get_column(self):
|
124
|
+
"""
|
125
|
+
Get column
|
126
|
+
|
127
|
+
:return: OutputColumn
|
128
|
+
"""
|
129
|
+
return self.column
|
28
130
|
|
29
131
|
def setOwner(self, owner: Tab):
|
30
132
|
"""
|
31
|
-
Set
|
133
|
+
Set internal tab instance
|
32
134
|
|
33
135
|
:param owner: parent tab instance
|
34
136
|
"""
|
@@ -42,158 +144,210 @@ class OutputTabs(QTabWidget):
|
|
42
144
|
"""
|
43
145
|
if event.button() == Qt.RightButton:
|
44
146
|
idx = self.tabBar().tabAt(event.pos())
|
45
|
-
|
147
|
+
column_idx = self.column.get_idx()
|
148
|
+
tab = self.window.core.tabs.get_tab_by_index(idx, column_idx)
|
46
149
|
if tab is not None:
|
47
150
|
if tab.type == Tab.TAB_NOTEPAD:
|
48
|
-
self.show_notepad_menu(idx, event.globalPos()) # notepad
|
151
|
+
self.show_notepad_menu(idx, column_idx, event.globalPos()) # notepad
|
49
152
|
elif tab.type == Tab.TAB_CHAT:
|
50
|
-
self.show_chat_menu(idx, event.globalPos()) # chat
|
153
|
+
self.show_chat_menu(idx, column_idx, event.globalPos()) # chat
|
51
154
|
elif tab.type == Tab.TAB_FILES:
|
52
|
-
self.show_files_menu(idx, event.globalPos()) # files
|
155
|
+
self.show_files_menu(idx, column_idx, event.globalPos()) # files
|
156
|
+
elif tab.type == Tab.TAB_TOOL:
|
157
|
+
self.show_tool_menu(idx, column_idx, event.globalPos()) # tool
|
53
158
|
else:
|
54
|
-
self.show_default_menu(idx, event.globalPos()) # default
|
159
|
+
self.show_default_menu(idx, column_idx, event.globalPos()) # default
|
55
160
|
super(OutputTabs, self).mousePressEvent(event)
|
56
161
|
|
57
|
-
def
|
162
|
+
def prepare_menu(self, index: int, column_idx: int) -> QMenu:
|
58
163
|
"""
|
59
|
-
|
164
|
+
Prepare and return context menu
|
60
165
|
|
61
166
|
:param index: index
|
62
|
-
:
|
167
|
+
:param column_idx: column index
|
168
|
+
:return: menu
|
63
169
|
"""
|
170
|
+
menu = QMenu(self)
|
171
|
+
|
64
172
|
actions = {}
|
65
173
|
actions['add_chat'] = QAction(QIcon(":/icons/add.svg"), trans('action.tab.add.chat'), self)
|
66
174
|
actions['add_chat'].triggered.connect(
|
67
|
-
lambda: self.add_tab(index, Tab.TAB_CHAT)
|
175
|
+
lambda: self.add_tab(index, column_idx, Tab.TAB_CHAT)
|
68
176
|
)
|
69
177
|
actions['add_notepad'] = QAction(QIcon(":/icons/add.svg"), trans('action.tab.add.notepad'), self)
|
70
178
|
actions['add_notepad'].triggered.connect(
|
71
|
-
lambda: self.add_tab(index, Tab.TAB_NOTEPAD)
|
179
|
+
lambda: self.add_tab(index, column_idx, Tab.TAB_NOTEPAD)
|
72
180
|
)
|
73
181
|
actions['edit'] = QAction(QIcon(":/icons/edit.svg"), trans('action.rename'), self)
|
74
182
|
actions['edit'].triggered.connect(
|
75
|
-
lambda: self.rename_tab(index)
|
183
|
+
lambda: self.rename_tab(index, column_idx)
|
184
|
+
)
|
185
|
+
actions['move_right'] = QAction(QIcon(":/icons/forward"), trans('action.tab.move.right'), self)
|
186
|
+
actions['move_right'].triggered.connect(
|
187
|
+
lambda: self.window.controller.ui.tabs.move_tab(index, column_idx, 1)
|
188
|
+
)
|
189
|
+
actions['move_left'] = QAction(QIcon(":/icons/back"), trans('action.tab.move.left'), self)
|
190
|
+
actions['move_left'].triggered.connect(
|
191
|
+
lambda: self.window.controller.ui.tabs.move_tab(index, column_idx, 0)
|
76
192
|
)
|
77
|
-
return actions
|
78
193
|
|
79
|
-
|
194
|
+
# add chat, add notepad
|
195
|
+
menu.addAction(actions['add_chat'])
|
196
|
+
menu.addAction(actions['add_notepad'])
|
197
|
+
|
198
|
+
# add tools submenu
|
199
|
+
self.window.controller.tools.append_tab_menu(self, menu, index, column_idx)
|
200
|
+
|
201
|
+
# rename tab
|
202
|
+
menu.addAction(actions['edit'])
|
203
|
+
|
204
|
+
# move tab left, move tab right
|
205
|
+
if column_idx != 0:
|
206
|
+
menu.addAction(actions['move_left'])
|
207
|
+
if column_idx != 1:
|
208
|
+
menu.addAction(actions['move_right'])
|
209
|
+
|
210
|
+
return menu
|
211
|
+
|
212
|
+
def show_notepad_menu(self, index: int, column_idx: int, global_pos):
|
80
213
|
"""
|
81
214
|
Show notepad menu
|
82
215
|
|
83
216
|
:param index: index
|
217
|
+
:param column_idx: column index
|
84
218
|
:param global_pos: global position
|
85
219
|
"""
|
86
|
-
context_menu =
|
87
|
-
actions =
|
220
|
+
context_menu = self.prepare_menu(index, column_idx)
|
221
|
+
actions = {}
|
88
222
|
actions['close'] = QAction(QIcon(":/icons/close.svg"), trans('action.tab.close'), self)
|
89
223
|
actions['close'].triggered.connect(
|
90
|
-
lambda: self.close_tab(index)
|
224
|
+
lambda: self.close_tab(index, column_idx)
|
91
225
|
)
|
92
226
|
actions['close_all'] = QAction(QIcon(":/icons/close.svg"), trans('action.tab.close_all.notepad'), self)
|
93
227
|
actions['close_all'].triggered.connect(
|
94
|
-
lambda: self.close_all(Tab.TAB_NOTEPAD)
|
228
|
+
lambda: self.close_all(Tab.TAB_NOTEPAD, column_idx)
|
95
229
|
)
|
96
|
-
context_menu.addAction(actions['add_chat'])
|
97
|
-
context_menu.addAction(actions['add_notepad'])
|
98
|
-
context_menu.addAction(actions['edit'])
|
99
230
|
context_menu.addAction(actions['close'])
|
100
231
|
|
101
232
|
if self.window.core.tabs.count_by_type(Tab.TAB_NOTEPAD) > 1:
|
102
233
|
context_menu.addAction(actions['close_all'])
|
234
|
+
|
103
235
|
context_menu.exec(global_pos)
|
104
236
|
|
105
|
-
def show_chat_menu(self, index, global_pos):
|
237
|
+
def show_chat_menu(self, index: int, column_idx: int, global_pos):
|
106
238
|
"""
|
107
239
|
Show chat menu
|
108
240
|
|
109
241
|
:param index: index
|
242
|
+
:param column_idx: column index
|
110
243
|
:param global_pos: global position
|
111
244
|
"""
|
112
|
-
context_menu =
|
113
|
-
actions =
|
245
|
+
context_menu = self.prepare_menu(index, column_idx)
|
246
|
+
actions = {}
|
114
247
|
actions['close'] = QAction(QIcon(":/icons/close.svg"), trans('action.tab.close'), self)
|
115
248
|
actions['close'].triggered.connect(
|
116
|
-
lambda: self.close_tab(index)
|
249
|
+
lambda: self.close_tab(index, column_idx)
|
117
250
|
)
|
118
251
|
actions['close_all'] = QAction(QIcon(":/icons/close.svg"), trans('action.tab.close_all.chat'), self)
|
119
252
|
actions['close_all'].triggered.connect(
|
120
|
-
lambda: self.close_all(Tab.TAB_CHAT)
|
253
|
+
lambda: self.close_all(Tab.TAB_CHAT, column_idx)
|
121
254
|
)
|
122
|
-
context_menu.addAction(actions['add_chat'])
|
123
|
-
context_menu.addAction(actions['add_notepad'])
|
124
|
-
context_menu.addAction(actions['edit'])
|
125
255
|
|
126
256
|
# at least one chat tab must be open
|
127
257
|
if self.window.core.tabs.count_by_type(Tab.TAB_CHAT) > 1:
|
128
258
|
context_menu.addAction(actions['close'])
|
129
|
-
|
130
|
-
if self.window.core.tabs.count_by_type(Tab.TAB_CHAT) > 1:
|
131
259
|
context_menu.addAction(actions['close_all'])
|
132
260
|
|
133
261
|
context_menu.exec(global_pos)
|
134
262
|
|
135
|
-
def show_files_menu(self, index, global_pos):
|
263
|
+
def show_files_menu(self, index: int, column_idx: int, global_pos):
|
136
264
|
"""
|
137
265
|
Show files menu
|
138
266
|
|
139
267
|
:param index: index
|
268
|
+
:param column_idx: column index
|
140
269
|
:param global_pos: global position
|
141
270
|
"""
|
142
|
-
context_menu =
|
143
|
-
actions =
|
271
|
+
context_menu = self.prepare_menu(index, column_idx)
|
272
|
+
actions = {}
|
144
273
|
actions['refresh'] = QAction(QIcon(":/icons/reload.svg"), trans('action.refresh'), self)
|
145
274
|
actions['refresh'].triggered.connect(
|
146
275
|
lambda: self.window.controller.files.update_explorer()
|
147
276
|
)
|
148
|
-
context_menu.addAction(actions['add_chat'])
|
149
|
-
context_menu.addAction(actions['add_notepad'])
|
150
277
|
context_menu.addAction(actions['refresh'])
|
151
|
-
context_menu.addAction(actions['edit'])
|
152
278
|
context_menu.exec(global_pos)
|
153
279
|
|
154
|
-
def
|
280
|
+
def show_tool_menu(self, index: int, column_idx: int, global_pos):
|
281
|
+
"""
|
282
|
+
Show tool menu
|
283
|
+
|
284
|
+
:param index: index
|
285
|
+
:param column_idx: column index
|
286
|
+
:param global_pos: global position
|
287
|
+
"""
|
288
|
+
context_menu = self.prepare_menu(index, column_idx)
|
289
|
+
actions = {}
|
290
|
+
actions['close'] = QAction(QIcon(":/icons/close.svg"), trans('action.tab.close'), self)
|
291
|
+
actions['close'].triggered.connect(
|
292
|
+
lambda: self.close_tab(index, column_idx)
|
293
|
+
)
|
294
|
+
context_menu.addAction(actions['close'])
|
295
|
+
context_menu.exec(global_pos)
|
296
|
+
|
297
|
+
def show_default_menu(self, index: int, column_idx: int, global_pos):
|
155
298
|
"""
|
156
299
|
Show default menu
|
157
300
|
|
158
301
|
:param index: index
|
302
|
+
:param column_idx: column index
|
159
303
|
:param global_pos: global position
|
160
304
|
"""
|
161
|
-
context_menu =
|
162
|
-
actions = self.get_common_actions(index)
|
163
|
-
context_menu.addAction(actions['add_chat'])
|
164
|
-
context_menu.addAction(actions['add_notepad'])
|
165
|
-
context_menu.addAction(actions['edit'])
|
305
|
+
context_menu = self.prepare_menu(index, column_idx)
|
166
306
|
context_menu.exec(global_pos)
|
167
307
|
|
168
308
|
@Slot()
|
169
|
-
def rename_tab(self, index):
|
309
|
+
def rename_tab(self, index: int, column_idx: int):
|
170
310
|
"""
|
171
311
|
Rename tab
|
312
|
+
|
172
313
|
:param index: index
|
314
|
+
:param column_idx: column index
|
173
315
|
"""
|
174
|
-
self.window.controller.ui.tabs.rename(index)
|
316
|
+
self.window.controller.ui.tabs.rename(index, column_idx)
|
175
317
|
|
176
318
|
@Slot()
|
177
|
-
def close_tab(self, index):
|
319
|
+
def close_tab(self, index: int, column_idx: int):
|
178
320
|
"""
|
179
321
|
Close tab
|
322
|
+
|
180
323
|
:param index: index
|
324
|
+
:param column_idx: column index
|
181
325
|
"""
|
182
|
-
self.window.controller.ui.tabs.close(index)
|
326
|
+
self.window.controller.ui.tabs.close(index, column_idx)
|
183
327
|
|
184
328
|
@Slot()
|
185
|
-
def close_all(self, type):
|
329
|
+
def close_all(self, type, column_idx: int):
|
186
330
|
"""
|
187
331
|
Close all tabs
|
332
|
+
|
188
333
|
:param type: type
|
334
|
+
:param column_idx: column index
|
189
335
|
"""
|
190
|
-
self.window.controller.ui.tabs.close_all(type)
|
336
|
+
self.window.controller.ui.tabs.close_all(type, column_idx)
|
191
337
|
|
192
338
|
@Slot()
|
193
|
-
def add_tab(self, index, type):
|
339
|
+
def add_tab(self, index: int, column_idx: int, type: int, tool_id: str = None):
|
194
340
|
"""
|
195
|
-
Add tab
|
341
|
+
Add a new tab
|
342
|
+
|
196
343
|
:param index: index
|
344
|
+
:param column_idx: column index
|
197
345
|
:param type: type
|
346
|
+
:param tool_id: tool id
|
198
347
|
"""
|
199
|
-
self.window.controller.ui.tabs.append(
|
348
|
+
self.window.controller.ui.tabs.append(
|
349
|
+
type=type,
|
350
|
+
tool_id=tool_id,
|
351
|
+
idx=index,
|
352
|
+
column_idx=column_idx,
|
353
|
+
)
|