Skip to content

Commit a70786c

Browse files
committed
Add simple conversation importing/exporting through context menu on tabs
1 parent 6c5e1d4 commit a70786c

File tree

4 files changed

+108
-1
lines changed

4 files changed

+108
-1
lines changed

src/chatgpt_gui/gui/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
'AppWindow',
1010
'CaptchaDialog',
1111
'ComboBox',
12+
'ConversationsContextMenu',
1213
'ConversationTabs',
1314
'ConversationView',
1415
'ExceptionLogger',
@@ -33,6 +34,7 @@
3334
from .app import GetterApp
3435
from .app import Theme
3536
from .menus import AccountContextMenu
37+
from .menus import ConversationsContextMenu
3638
from .menus import HelpContextMenu
3739
from .menus import ToolsContextMenu
3840
from .widgets import ComboBox

src/chatgpt_gui/gui/menus/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55

66
__all__ = (
77
'AccountContextMenu',
8+
'ConversationsContextMenu',
89
'HelpContextMenu',
910
'ToolsContextMenu',
1011
)
1112

1213
from .account import AccountContextMenu
14+
from .conversations import ConversationsContextMenu
1315
from .help import HelpContextMenu
1416
from .tools import ToolsContextMenu
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
###################################################################################################
2+
# MIT Licence (C) 2022 Cubicpath@Github #
3+
###################################################################################################
4+
"""Help menu implementation."""
5+
from __future__ import annotations
6+
7+
__all__ = (
8+
'ConversationsContextMenu',
9+
)
10+
11+
import json
12+
from pathlib import Path
13+
14+
from PySide6.QtGui import *
15+
from PySide6.QtWidgets import *
16+
17+
from ...constants import *
18+
from ...network.client import Conversation
19+
from ...utils import add_menu_items
20+
from ...utils import init_objects
21+
from ..aliases import tr
22+
from ..widgets import ConversationTabs
23+
from ..widgets import ConversationView
24+
25+
26+
class ConversationsContextMenu(QMenu):
27+
"""Context menu that shows actions to help the user."""
28+
29+
def __init__(self, parent: ConversationTabs, current: ConversationView) -> None:
30+
"""Create a new :py:class:`HelpContextMenu`."""
31+
super().__init__(parent)
32+
33+
self.tabs = parent
34+
self.current = current
35+
36+
init_objects({
37+
(import_conversation := QAction(self)): {
38+
'text': tr('gui.menus.conversations.import'),
39+
'triggered': self.import_conversation
40+
},
41+
(export_conversation := QAction(self)): {
42+
'disabled': current.conversation.uuid is None,
43+
'text': tr('gui.menus.conversations.export'),
44+
'triggered': self.export_conversation
45+
},
46+
# (rename_conversation := QAction(self)): {
47+
# 'text': 'gui.menus.conversations.rename',
48+
# 'triggered': self.rename_conversation
49+
# }
50+
})
51+
52+
add_menu_items(self, [
53+
'Conversations', import_conversation,
54+
'Current', export_conversation # , rename_conversation
55+
])
56+
57+
def import_conversation(self) -> None:
58+
"""Import a conversation from a given file."""
59+
file_path = Path(QFileDialog.getOpenFileName(
60+
self, caption=tr('gui.menus.conversations.import'),
61+
dir=str(CG_CACHE_PATH / 'conversations'),
62+
filter='JSON Files (*.json);;All files (*.*)')[0])
63+
64+
# Return if dialog is cancelled
65+
if not file_path.is_file():
66+
return
67+
68+
# Load messages from json data
69+
conversation = Conversation.from_json(json.loads(file_path.read_text(encoding='utf8')))
70+
view = ConversationView(conversation)
71+
for message in conversation.messages:
72+
if message.role == 'assistant':
73+
view.receive_message(message, conversation)
74+
else:
75+
view.append_to_view(tr('gui.output_text.you_prompt', message.text, key_eval=False))
76+
77+
# remove empty conversation
78+
if not self.current.conversation.messages:
79+
self.tabs.removeTab(self.tabs.currentIndex())
80+
81+
self.tabs.addTab(view, file_path.stem)
82+
self.tabs.setCurrentIndex(self.tabs.count() - 1)
83+
84+
def export_conversation(self) -> None:
85+
"""Export conversation to given filename."""
86+
file_path = Path(QFileDialog.getSaveFileName(
87+
self, caption=tr('gui.menus.conversations.export'),
88+
dir=str(CG_CACHE_PATH / f'conversations/{self.current.conversation.uuid}.json'),
89+
filter='JSON Files (*.json);;All files (*.*)')[0])
90+
91+
# Return if dialog is cancelled
92+
if str(file_path) == '.':
93+
return
94+
95+
file_path.write_text(json.dumps(self.current.conversation.to_json(), indent=2), encoding='utf8')
96+
self.tabs.setTabText(self.tabs.currentIndex(), file_path.stem)

src/chatgpt_gui/gui/widgets/conversation_tabs.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def remove_conversation(self, index: int):
5555
5656
:param index: Index of conversation to remove.
5757
"""
58-
view: ConversationView = self.conversation_tabs.widget(index) # type: ignore
58+
view: ConversationView = self.widget(index) # type: ignore
5959
view.deleteLater()
6060

6161
self.removeTab(index)
@@ -68,3 +68,10 @@ def on_custom_context_menu(self, point: QPoint) -> None:
6868
6969
:param point: The point to place the context menu.
7070
"""
71+
from ..menus import ConversationsContextMenu
72+
73+
view: ConversationView = self.currentWidget() # type: ignore
74+
75+
menu = ConversationsContextMenu(self, view)
76+
menu.exec(self.mapToGlobal(point))
77+
menu.deleteLater()

0 commit comments

Comments
 (0)