Skip to content

Commit 5af51b0

Browse files
authored
Merge pull request #123 from yjg30737/feature/general
Feature/general -> Dev 2
2 parents 6faa494 + 4327369 commit 5af51b0

File tree

13 files changed

+137
-57
lines changed

13 files changed

+137
-57
lines changed

pyqt_openai/chatNavWidget.py

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from qtpy.QtCore import Signal, QSortFilterProxyModel, Qt
22
from qtpy.QtSql import QSqlTableModel, QSqlQuery
3-
from qtpy.QtWidgets import QWidget, QVBoxLayout, QMessageBox, QStyledItemDelegate, QTableView, \
3+
from qtpy.QtWidgets import QWidget, QVBoxLayout, QMessageBox, QPushButton, QStyledItemDelegate, QTableView, \
44
QAbstractItemView, \
55
QHBoxLayout, \
66
QLabel, QSpacerItem, QSizePolicy, QFileDialog, QComboBox, QDialog
@@ -61,6 +61,7 @@ class ChatNavWidget(QWidget):
6161
onImport = Signal(str)
6262
onExport = Signal(list)
6363
onChatGPTImport = Signal(list)
64+
onFavoriteClicked = Signal(bool)
6465

6566
def __init__(self, columns, table_nm):
6667
super().__init__()
@@ -146,7 +147,7 @@ def __initUi(self):
146147
self.__model.setHeaderData(i, Qt.Orientation.Horizontal, self.__columns[i])
147148
self.__model.select()
148149
# descending order by insert date
149-
idx = self.__columns.index('insert_dt')
150+
idx = self.__columns.index(THREAD_ORDERBY)
150151
self.__model.sort(idx, Qt.SortOrder.DescendingOrder)
151152

152153
# init the proxy model
@@ -174,9 +175,14 @@ def __initUi(self):
174175
self.__tableView.clicked.connect(self.__clicked)
175176
self.__tableView.activated.connect(self.__clicked)
176177

178+
self.__favoriteBtn = QPushButton('Favorite List')
179+
self.__favoriteBtn.setCheckable(True)
180+
self.__favoriteBtn.toggled.connect(self.__onFavoriteClicked)
181+
177182
lay = QVBoxLayout()
178183
lay.addWidget(menuWidget)
179184
lay.addWidget(self.__tableView)
185+
lay.addWidget(self.__favoriteBtn)
180186
self.setLayout(lay)
181187

182188
self.refreshData()
@@ -231,11 +237,15 @@ def refreshData(self, title=None):
231237
self.__proxyModel.setFilterRegularExpression(title)
232238

233239
def __clicked(self, idx):
234-
# get id of record
235-
id = self.__model.data(self.__proxyModel.mapToSource(idx.siblingAtColumn(0)), role=Qt.ItemDataRole.DisplayRole)
236-
title = self.__model.data(self.__proxyModel.mapToSource(idx.siblingAtColumn(1)), role=Qt.ItemDataRole.DisplayRole)
240+
# get the source index
241+
source_idx = self.__proxyModel.mapToSource(idx)
242+
# get the primary key value of the row
243+
cur_id = self.__model.record(source_idx.row()).value("id")
244+
clicked_thread = DB.selectThread(cur_id)
245+
# get the title
246+
title = clicked_thread['name']
237247

238-
self.clicked.emit(id, title)
248+
self.clicked.emit(cur_id, title)
239249

240250
def __getSelectedIds(self):
241251
selected_idx_s = self.__tableView.selectedIndexes()
@@ -285,4 +295,10 @@ def setColumns(self, columns):
285295
self.__model.clear()
286296
self.__model.setTable(self.__table_nm)
287297
self.__model.setQuery(QSqlQuery(f"SELECT {','.join(self.__columns)} FROM {self.__table_nm}"))
288-
self.__model.select()
298+
self.__model.select()
299+
300+
def __onFavoriteClicked(self, f):
301+
self.onFavoriteClicked.emit(f)
302+
303+
def activateFavoriteFromParent(self, f):
304+
self.__favoriteBtn.setChecked(f)

pyqt_openai/chat_widget/aiChatUnit.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -127,17 +127,16 @@ def __initUi(self):
127127
def __copy(self):
128128
pyperclip.copy(self.text())
129129

130-
def __favorite(self, f):
130+
def __favorite(self, f, insert_f=True):
131131
favorite = 1 if f else 0
132132
if favorite:
133133
self.__favoriteBtn.setStyleAndIcon('ico/favorite_yes.svg')
134134
else:
135135
self.__favoriteBtn.setStyleAndIcon('ico/favorite_no.svg')
136-
if self.__result_info.id:
137-
DB.updateMessage(self.__result_info.id, favorite)
136+
if insert_f:
137+
current_date = DB.updateMessage(self.__result_info.id, favorite)
138138
self.__result_info.favorite = favorite
139-
else:
140-
QMessageBox.warning(self, 'Warning', 'Working for providing ID for this message. Please try again later.')
139+
self.__result_info.favorite_set_date = current_date
141140

142141
def __showInfo(self):
143142
dialog = MessageResultDialog(self.__result_info)
@@ -168,13 +167,16 @@ def setAlignment(self, a0):
168167
widget.setAlignment(a0)
169168

170169
def disableGUIDuringGenerateResponse(self):
170+
self.__favoriteBtn.setEnabled(False)
171171
self.__copyBtn.setEnabled(False)
172172
self.__infoBtn.setEnabled(False)
173173

174174
def showConvResultInfo(self, arg: ChatMessageContainer):
175+
self.__favoriteBtn.setEnabled(True)
175176
self.__copyBtn.setEnabled(True)
176177
self.__infoBtn.setEnabled(True)
177178
self.__result_info = arg
179+
self.__favorite(True if arg.favorite else False, insert_f=False)
178180

179181
def setText(self, text: str):
180182
self.__lbl = QLabel(text)

pyqt_openai/chat_widget/chatBrowser.py

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from pyqt_openai.chat_widget.aiChatUnit import AIChatUnit
88
from pyqt_openai.chat_widget.userChatUnit import UserChatUnit
99
from pyqt_openai.models import ChatMessageContainer
10-
from pyqt_openai.pyqt_openai_data import get_message_obj
10+
from pyqt_openai.pyqt_openai_data import get_message_obj, DB
1111
from pyqt_openai.util.script import is_valid_regex
1212

1313

@@ -39,13 +39,15 @@ def __initUi(self):
3939
self.setWidgetResizable(True)
4040

4141
def showLabel(self, text, stream_f, arg: ChatMessageContainer):
42-
arg.thread_id = self.__cur_id
43-
# for question & response below the menu
42+
arg.thread_id = arg.thread_id if arg.thread_id else self.__cur_id
4443
unit = self.__setLabel(text, stream_f, arg.role)
4544
if not stream_f:
45+
arg.id = DB.insertMessage(arg)
4646
self.__showConvResultInfo(unit, arg)
47-
# change user_f type from bool to int to insert in db
48-
self.messageUpdated.emit(arg)
47+
48+
def showLabelForFavorite(self, arg: ChatMessageContainer):
49+
unit = self.__setLabel(arg.content, False, arg.role)
50+
self.__showConvResultInfo(unit, arg)
4951

5052
def __getLastUnit(self) -> AIChatUnit | None:
5153
item = self.widget().layout().itemAt(self.widget().layout().count() - 1)
@@ -60,9 +62,9 @@ def __showConvResultInfo(self, unit, arg: ChatMessageContainer):
6062

6163
def streamFinished(self, arg: ChatMessageContainer):
6264
unit = self.__getLastUnit()
63-
self.__showConvResultInfo(unit, arg)
6465
arg.content = self.getLastResponse()
65-
self.messageUpdated.emit(arg)
66+
arg.id = DB.insertMessage(arg)
67+
self.__showConvResultInfo(unit, arg)
6668

6769
def __setLabel(self, text, stream_f, role):
6870
chatUnit = QLabel()
@@ -90,7 +92,6 @@ def __setLabel(self, text, stream_f, role):
9092

9193
def event(self, e):
9294
if e.type() == 43:
93-
print('scroll')
9495
self.verticalScrollBar().setSliderPosition(self.verticalScrollBar().maximum())
9596
return super().event(e)
9697

@@ -213,9 +214,9 @@ def setCurrentLabelIncludingTextBySliderPosition(self, text, case_sensitive=Fals
213214

214215
return res_lbl
215216

216-
def replaceThread(self, id, args: List[ChatMessageContainer]):
217+
def replaceThread(self, args: List[ChatMessageContainer], id):
217218
"""
218-
for showing old conversation
219+
For showing messages from the thread
219220
"""
220221
self.clear()
221222
self.setCurId(id)
@@ -226,6 +227,18 @@ def replaceThread(self, id, args: List[ChatMessageContainer]):
226227
unit = self.__setLabel(arg.content, False, arg.role)
227228
self.__showConvResultInfo(unit, arg)
228229

230+
def replaceThreadForFavorite(self, args: List[ChatMessageContainer]):
231+
"""
232+
For showing favorite messages
233+
"""
234+
self.clear()
235+
self.onReplacedCurrentPage.emit(1)
236+
for i in range(len(args)):
237+
arg = args[i]
238+
# stream is False no matter what
239+
unit = self.__setLabel(arg.content, False, arg.role)
240+
self.__showConvResultInfo(unit, arg)
241+
229242
def setUserImage(self, img):
230243
self.__user_image = img
231244
lbls = self.__getEveryUserLabels()

pyqt_openai/chat_widget/conv.db

-132 KB
Binary file not shown.

pyqt_openai/chat_widget/findTextWidget.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from qtpy.QtCore import Signal
44
from qtpy.QtWidgets import QWidget, QLabel, \
5-
QHBoxLayout, QGridLayout, QLineEdit
5+
QHBoxLayout, QGridLayout, QLineEdit, QMessageBox
66

77
from pyqt_openai.chat_widget.chatBrowser import ChatBrowser
88
from pyqt_openai.widgets.button import Button
@@ -104,7 +104,7 @@ def widgetTextChanged(self):
104104
def __findInit(self, text):
105105
# show "bad pattern" message if text is "\"
106106
if self.__regexBtn.isChecked() and re.escape(text) == re.escape('\\'):
107-
print('bad pattern!')
107+
QMessageBox.warning(self, 'Warning', 'Bad pattern')
108108
else:
109109
self.__selections = self.__chatBrowser.setCurrentLabelIncludingTextBySliderPosition(text,
110110
case_sensitive=self.__caseBtn.isChecked(),

pyqt_openai/constants.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# APP
22
IMAGE_FILE_EXT = 'Image file (*.jpg *.png)'
33
DEFAULT_ICON_SIZE = (24, 24)
4+
COLUMN_TO_EXCLUDE_FROM_SHOW_HIDE = ['id']
45

56
PAYPAL_URL = 'https://paypal.me/yjg30737'
67
BUYMEACOFFEE_URL = 'https://www.buymeacoffee.com/yjg30737'
@@ -16,6 +17,8 @@
1617
THREAD_TRIGGER_NAME = 'thread_tr'
1718
MESSAGE_TABLE_NAME = 'message_tb'
1819

20+
IMAGE_TABLE_NAME = 'image_tb'
21+
1922
THREAD_MESSAGE_INSERTED_TR_NAME_OLD = 'conv_tb_updated_by_unit_inserted_tr'
2023
THREAD_MESSAGE_UPDATED_TR_NAME_OLD = 'conv_tb_updated_by_unit_updated_tr'
2124
THREAD_MESSAGE_DELETED_TR_NAME_OLD = 'conv_tb_updated_by_unit_deleted_tr'

pyqt_openai/dalle_widget/dallEWidget.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from qtpy.QtCore import Qt, QSettings
44
from qtpy.QtWidgets import QHBoxLayout, QVBoxLayout, QFrame, QWidget, QSplitter
55

6+
from pyqt_openai.constants import IMAGE_TABLE_NAME
67
from pyqt_openai.dalle_widget.dallEControlWidget import DallEControlWidget
78
from pyqt_openai.models import ImagePromptContainer
89
from pyqt_openai.pyqt_openai_data import DB
@@ -39,7 +40,7 @@ def __initVal(self):
3940
self.__settings_ini.endGroup()
4041

4142
def __initUi(self):
42-
self.__imageNavWidget = ImageNavWidget(ImagePromptContainer.get_keys(), 'image_tb')
43+
self.__imageNavWidget = ImageNavWidget(ImagePromptContainer.get_keys(), IMAGE_TABLE_NAME)
4344
self.__viewWidget = ThumbnailView()
4445
self.__rightSideBarWidget = DallEControlWidget()
4546

pyqt_openai/models.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,14 @@ def __init__(self, **kwargs):
1717
setattr(self, key, value)
1818

1919
@classmethod
20-
def get_keys(cls):
21-
return [field.name for field in fields(cls)]
22-
23-
@classmethod
24-
def get_keys_for_insert(cls, excludes: list = None):
20+
def get_keys(cls, excludes: list = None):
2521
"""
2622
Function that returns the keys of the target data type as a list.
2723
Exclude the keys in the "excludes" list.
2824
"""
2925
if excludes is None:
3026
excludes = []
31-
arr = cls.get_keys()
27+
arr = [field.name for field in fields(cls)]
3228
for exclude in excludes:
3329
if exclude in arr:
3430
arr.remove(exclude)
@@ -40,7 +36,7 @@ def get_values_for_insert(self, excludes: list = None):
4036
"""
4137
if excludes is None:
4238
excludes = []
43-
arr = [getattr(self, key) for key in self.get_keys_for_insert(excludes)]
39+
arr = [getattr(self, key) for key in self.get_keys(excludes)]
4440
return arr
4541

4642
def get_items(self, excludes: list = None):
@@ -49,7 +45,7 @@ def get_items(self, excludes: list = None):
4945
"""
5046
if excludes is None:
5147
excludes = []
52-
return {key: getattr(self, key) for key in self.get_keys_for_insert(excludes)}.items()
48+
return {key: getattr(self, key) for key in self.get_keys(excludes)}.items()
5349

5450
def create_insert_query(self, table_name: str, excludes: list = None):
5551
if excludes is None:
@@ -58,7 +54,7 @@ def create_insert_query(self, table_name: str, excludes: list = None):
5854
Function to dynamically generate an SQLite insert statement.
5955
Takes the table name as a parameter.
6056
"""
61-
field_names = self.get_keys_for_insert(excludes)
57+
field_names = self.get_keys(excludes)
6258
columns = ', '.join(field_names)
6359
placeholders = ', '.join(['?' for _ in field_names])
6460
query = f'INSERT INTO {table_name} ({columns}) VALUES ({placeholders})'
@@ -85,6 +81,7 @@ class ChatMessageContainer(Container):
8581
completion_tokens: str = ""
8682
total_tokens: str = ""
8783
favorite: int = 0
84+
favorite_set_date: str = ""
8885

8986
def __init__(self, **kwargs):
9087
super().__init__(**kwargs)

pyqt_openai/openAiChatBotWidget.py

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
QFileDialog, QMessageBox, QPushButton
99

1010
from pyqt_openai.chatNavWidget import ChatNavWidget
11+
from pyqt_openai.chat_widget.chatBrowser import ChatBrowser
1112
from pyqt_openai.chat_widget.chatWidget import ChatWidget
1213
from pyqt_openai.chat_widget.prompt import Prompt
1314
from pyqt_openai.constants import THREAD_TABLE_NAME
@@ -45,6 +46,8 @@ def __initVal(self):
4546
self.__show_setting = self.__settings_ini.value('show_setting', type=bool)
4647
self.__show_prompt = self.__settings_ini.value('show_prompt', type=bool)
4748

49+
self.__is_showing_favorite = False
50+
4851
def __initUi(self):
4952
self.__chatNavWidget = ChatNavWidget(ChatThreadContainer.get_keys(), THREAD_TABLE_NAME)
5053
self.__chatWidget = ChatWidget()
@@ -118,10 +121,11 @@ def __initUi(self):
118121
self.__chatNavWidget.onImport.connect(self.__importChat)
119122
self.__chatNavWidget.onChatGPTImport.connect(self.__chatGPTImport)
120123
self.__chatNavWidget.onExport.connect(self.__exportChat)
124+
self.__chatNavWidget.onFavoriteClicked.connect(self.__showFavorite)
121125

122126
self.__lineEdit.returnPressed.connect(self.__chat)
123127

124-
self.__browser.messageUpdated.connect(self.__updateMessage)
128+
# self.__browser.messageUpdated.connect(self.__updateMessage)
125129

126130
lay = QHBoxLayout()
127131
lay.addWidget(self.__prompt)
@@ -266,7 +270,7 @@ def __chat(self, continue_f=False):
266270
# Conversation result information after response
267271
container = ChatMessageContainer(**container_param)
268272

269-
# For make GPT continue to respond
273+
# For make chatbot continue to respond
270274
if continue_f:
271275
query_text = 'Continue to respond.'
272276
else:
@@ -333,9 +337,11 @@ def __afterGenerated(self):
333337
self.__notifierWidget.doubleClicked.connect(self.window().show)
334338

335339
def __showChat(self, id, title):
340+
self.__showFavorite(False)
341+
self.__chatNavWidget.activateFavoriteFromParent(False)
336342
conv_data = DB.selectCertainThreadMessages(id)
337343
self.__chatWidget.showTitle(title)
338-
self.__browser.replaceThread(id, conv_data)
344+
self.__browser.replaceThread(conv_data, id)
339345
self.__prompt.activateDuringGeneratingWidget(False)
340346
self.__prompt.activateAfterResponseWidget(False)
341347

@@ -350,7 +356,7 @@ def __addThread(self):
350356
cur_id = DB.insertThread(title)
351357
self.__browser.resetChatWidget(cur_id)
352358
self.__chatWidget.showTitle(title)
353-
self.__browser.replaceThread(cur_id, DB.selectCertainThreadMessages(cur_id))
359+
self.__browser.replaceThread(DB.selectCertainThreadMessages(cur_id), cur_id)
354360
self.__lineEdit.setFocus()
355361
self.__chatNavWidget.add(called_from_parent=True)
356362

@@ -407,9 +413,25 @@ def __exportChat(self, ids):
407413
DB.export(ids, filename)
408414
open_directory(os.path.dirname(filename))
409415

410-
def __updateMessage(self, arg: ChatMessageContainer):
411-
if arg.content:
412-
DB.insertMessage(arg)
416+
# def __updateMessage(self, arg: ChatMessageContainer):
417+
# if arg.content:
418+
# DB.insertMessage(arg)
413419

414420
def setColumns(self, columns):
415-
self.__chatNavWidget.setColumns(columns)
421+
self.__chatNavWidget.setColumns(columns)
422+
423+
def __showFavorite(self, f):
424+
if f:
425+
lst = DB.selectFavorite()
426+
if len(lst) == 0:
427+
return
428+
else:
429+
lst = [ChatMessageContainer(**dict(c)) for c in lst]
430+
self.__browser.replaceThreadForFavorite(lst)
431+
# self.__browser.show()
432+
# self.__browser.setWindowTitle('Favorite')
433+
# self.__browser.setWindowModality(Qt.WindowModality.ApplicationModal)
434+
# else:
435+
# self.__browser.messageUpdated.connect(self.__updateMessage)
436+
self.__prompt.setEnabled(not f)
437+
self.__is_showing_favorite = f

0 commit comments

Comments
 (0)