Move saving chats to a thread and display what we're doing to the user.

This commit is contained in:
Adam Treat 2023-06-20 17:14:11 -04:00
parent c8a590bc6f
commit 968868415e
5 changed files with 75 additions and 15 deletions

View File

@ -63,11 +63,17 @@ void ChatListModel::removeChatFile(Chat *chat) const
qWarning() << "ERROR: Couldn't remove chat file:" << file.fileName(); qWarning() << "ERROR: Couldn't remove chat file:" << file.fileName();
} }
void ChatListModel::saveChats() const ChatSaver::ChatSaver()
: QObject(nullptr)
{
moveToThread(&m_thread);
m_thread.start();
}
void ChatListModel::saveChats()
{ {
QElapsedTimer timer;
timer.start();
const QString savePath = Download::globalInstance()->downloadLocalModelsPath(); const QString savePath = Download::globalInstance()->downloadLocalModelsPath();
QVector<Chat*> toSave;
for (Chat *chat : m_chats) { for (Chat *chat : m_chats) {
if (chat == m_serverChat) if (chat == m_serverChat)
continue; continue;
@ -76,6 +82,23 @@ void ChatListModel::saveChats() const
continue; continue;
if (isChatGPT && !m_shouldSaveChatGPTChats) if (isChatGPT && !m_shouldSaveChatGPTChats)
continue; continue;
toSave.append(chat);
}
if (toSave.isEmpty())
return;
ChatSaver *saver = new ChatSaver;
connect(this, &ChatListModel::requestSaveChats, saver, &ChatSaver::saveChats, Qt::QueuedConnection);
connect(saver, &ChatSaver::saveChatsFinished, this, &ChatListModel::saveChatsFinished, Qt::QueuedConnection);
emit requestSaveChats(toSave);
}
void ChatSaver::saveChats(const QVector<Chat *> &chats)
{
QElapsedTimer timer;
timer.start();
const QString savePath = Download::globalInstance()->downloadLocalModelsPath();
for (Chat *chat : chats) {
QString fileName = "gpt4all-" + chat->id() + ".chat"; QString fileName = "gpt4all-" + chat->id() + ".chat";
QFile file(savePath + "/" + fileName); QFile file(savePath + "/" + fileName);
bool success = file.open(QIODevice::WriteOnly); bool success = file.open(QIODevice::WriteOnly);
@ -98,6 +121,7 @@ void ChatListModel::saveChats() const
} }
qint64 elapsedTime = timer.elapsed(); qint64 elapsedTime = timer.elapsed();
qDebug() << "serializing chats took:" << elapsedTime << "ms"; qDebug() << "serializing chats took:" << elapsedTime << "ms";
emit saveChatsFinished();
} }
void ChatsRestoreThread::run() void ChatsRestoreThread::run()

View File

@ -14,6 +14,23 @@ Q_SIGNALS:
void chatRestored(Chat *chat); void chatRestored(Chat *chat);
}; };
class ChatSaver : public QObject
{
Q_OBJECT
public:
explicit ChatSaver();
void stop();
Q_SIGNALS:
void saveChatsFinished();
public Q_SLOTS:
void saveChats(const QVector<Chat*> &chats);
private:
QThread m_thread;
};
class ChatListModel : public QAbstractListModel class ChatListModel : public QAbstractListModel
{ {
Q_OBJECT Q_OBJECT
@ -190,7 +207,7 @@ public:
int count() const { return m_chats.size(); } int count() const { return m_chats.size(); }
void removeChatFile(Chat *chat) const; void removeChatFile(Chat *chat) const;
void saveChats() const; Q_INVOKABLE void saveChats();
void restoreChat(Chat *chat); void restoreChat(Chat *chat);
void chatsRestoredFinished(); void chatsRestoredFinished();
@ -202,6 +219,9 @@ Q_SIGNALS:
void currentChatChanged(); void currentChatChanged();
void shouldSaveChatsChanged(); void shouldSaveChatsChanged();
void shouldSaveChatGPTChatsChanged(); void shouldSaveChatGPTChatsChanged();
void chatsSavedFinished();
void requestSaveChats(const QVector<Chat*> &);
void saveChatsFinished();
private Q_SLOTS: private Q_SLOTS:
void newChatCountChanged() void newChatCountChanged()

View File

@ -38,9 +38,6 @@ LLM::LLM()
llmodelSearchPaths += ";" + frameworksDir; llmodelSearchPaths += ";" + frameworksDir;
#endif #endif
LLModel::setImplementationsSearchPath(llmodelSearchPaths.toStdString()); LLModel::setImplementationsSearchPath(llmodelSearchPaths.toStdString());
connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit,
this, &LLM::aboutToQuit);
connect(this, &LLM::serverEnabledChanged, connect(this, &LLM::serverEnabledChanged,
m_chatListModel, &ChatListModel::handleServerEnabledChanged); m_chatListModel, &ChatListModel::handleServerEnabledChanged);
@ -123,8 +120,3 @@ void LLM::setServerEnabled(bool enabled)
m_serverEnabled = enabled; m_serverEnabled = enabled;
emit serverEnabledChanged(); emit serverEnabledChanged();
} }
void LLM::aboutToQuit()
{
m_chatListModel->saveChats();
}

View File

@ -34,9 +34,6 @@ Q_SIGNALS:
void serverEnabledChanged(); void serverEnabledChanged();
void compatHardwareChanged(); void compatHardwareChanged();
private Q_SLOTS:
void aboutToQuit();
private: private:
ChatListModel *m_chatListModel; ChatListModel *m_chatListModel;
int32_t m_threadCount; int32_t m_threadCount;

View File

@ -24,6 +24,25 @@ Window {
property var currentChat: LLM.chatListModel.currentChat property var currentChat: LLM.chatListModel.currentChat
property var chatModel: currentChat.chatModel property var chatModel: currentChat.chatModel
property bool hasSaved: false
onClosing: function(close) {
if (window.hasSaved)
return;
savingPopup.open();
LLM.chatListModel.saveChats();
close.accepted = false
}
Connections {
target: LLM.chatListModel
function onSaveChatsFinished() {
window.hasSaved = true;
savingPopup.close();
window.close()
}
}
color: theme.backgroundDarkest color: theme.backgroundDarkest
@ -406,6 +425,14 @@ Window {
} }
} }
PopupDialog {
id: savingPopup
anchors.centerIn: parent
shouldTimeOut: false
shouldShowBusy: true
text: qsTr("Saving chats.")
}
MyToolButton { MyToolButton {
id: copyButton id: copyButton
anchors.right: settingsButton.left anchors.right: settingsButton.left