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();
}
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();
QVector<Chat*> toSave;
for (Chat *chat : m_chats) {
if (chat == m_serverChat)
continue;
@ -76,6 +82,23 @@ void ChatListModel::saveChats() const
continue;
if (isChatGPT && !m_shouldSaveChatGPTChats)
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";
QFile file(savePath + "/" + fileName);
bool success = file.open(QIODevice::WriteOnly);
@ -98,6 +121,7 @@ void ChatListModel::saveChats() const
}
qint64 elapsedTime = timer.elapsed();
qDebug() << "serializing chats took:" << elapsedTime << "ms";
emit saveChatsFinished();
}
void ChatsRestoreThread::run()

View File

@ -14,6 +14,23 @@ Q_SIGNALS:
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
{
Q_OBJECT
@ -190,7 +207,7 @@ public:
int count() const { return m_chats.size(); }
void removeChatFile(Chat *chat) const;
void saveChats() const;
Q_INVOKABLE void saveChats();
void restoreChat(Chat *chat);
void chatsRestoredFinished();
@ -202,6 +219,9 @@ Q_SIGNALS:
void currentChatChanged();
void shouldSaveChatsChanged();
void shouldSaveChatGPTChatsChanged();
void chatsSavedFinished();
void requestSaveChats(const QVector<Chat*> &);
void saveChatsFinished();
private Q_SLOTS:
void newChatCountChanged()

View File

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

View File

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

View File

@ -24,6 +24,25 @@ Window {
property var currentChat: LLM.chatListModel.currentChat
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
@ -406,6 +425,14 @@ Window {
}
}
PopupDialog {
id: savingPopup
anchors.centerIn: parent
shouldTimeOut: false
shouldShowBusy: true
text: qsTr("Saving chats.")
}
MyToolButton {
id: copyButton
anchors.right: settingsButton.left