mirror of
https://github.com/nomic-ai/gpt4all.git
synced 2025-04-27 19:35:20 +00:00
Save chats on quit, even if window isn't closed first (#3387)
Signed-off-by: Jared Van Bortel <jared@nomic.ai>
This commit is contained in:
parent
cc5ed4737f
commit
4812ddf1f2
@ -6,11 +6,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## Fixed
|
||||
### Fixed
|
||||
- Fix the timeout error in code interpreter ([#3369](https://github.com/nomic-ai/gpt4all/pull/3369))
|
||||
- Fix code interpreter console.log not accepting multiple arguments ([#3371](https://github.com/nomic-ai/gpt4all/pull/3371))
|
||||
- Remove 'X is defined' checks from templates as they work incorrectly with Jinja2Cpp ([#3372](https://github.com/nomic-ai/gpt4all/pull/3372))
|
||||
- Jinja2Cpp: Add 'if' requirement for 'else' parsing to fix crash ([#3373](https://github.com/nomic-ai/gpt4all/pull/3373))
|
||||
- Save chats on quit, even if the window isn't closed first ([#3387](https://github.com/nomic-ai/gpt4all/pull/3387))
|
||||
|
||||
## [3.6.1] - 2024-12-20
|
||||
|
||||
|
@ -54,7 +54,7 @@ Window {
|
||||
systemTrayIcon.shouldClose = true;
|
||||
window.shouldClose = true;
|
||||
savingPopup.open();
|
||||
ChatListModel.saveChats();
|
||||
ChatListModel.saveChatsForQuit();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -231,8 +231,8 @@ Window {
|
||||
|
||||
window.shouldClose = true;
|
||||
savingPopup.open();
|
||||
ChatListModel.saveChats();
|
||||
close.accepted = false
|
||||
ChatListModel.saveChatsForQuit();
|
||||
close.accepted = false;
|
||||
}
|
||||
|
||||
Connections {
|
||||
|
@ -52,9 +52,11 @@ void ChatListModel::loadChats()
|
||||
connect(thread, &ChatsRestoreThread::finished, thread, &QObject::deleteLater);
|
||||
thread->start();
|
||||
|
||||
ChatSaver *saver = new ChatSaver;
|
||||
connect(this, &ChatListModel::requestSaveChats, saver, &ChatSaver::saveChats, Qt::QueuedConnection);
|
||||
connect(saver, &ChatSaver::saveChatsFinished, this, &ChatListModel::saveChatsFinished, Qt::QueuedConnection);
|
||||
m_chatSaver = std::make_unique<ChatSaver>();
|
||||
connect(this, &ChatListModel::requestSaveChats, m_chatSaver.get(), &ChatSaver::saveChats, Qt::QueuedConnection);
|
||||
connect(m_chatSaver.get(), &ChatSaver::saveChatsFinished, this, &ChatListModel::saveChatsFinished, Qt::QueuedConnection);
|
||||
// save chats on application quit
|
||||
connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this, &ChatListModel::saveChatsSync);
|
||||
|
||||
connect(MySettings::globalInstance(), &MySettings::serverChatChanged, this, &ChatListModel::handleServerEnabledChanged);
|
||||
}
|
||||
@ -78,16 +80,24 @@ ChatSaver::ChatSaver()
|
||||
m_thread.start();
|
||||
}
|
||||
|
||||
ChatSaver::~ChatSaver()
|
||||
{
|
||||
m_thread.quit();
|
||||
m_thread.wait();
|
||||
}
|
||||
|
||||
QVector<Chat *> ChatListModel::getChatsToSave() const
|
||||
{
|
||||
QVector<Chat *> toSave;
|
||||
for (auto *chat : m_chats)
|
||||
if (chat != m_serverChat && !chat->isNewChat())
|
||||
toSave << chat;
|
||||
return toSave;
|
||||
}
|
||||
|
||||
void ChatListModel::saveChats()
|
||||
{
|
||||
QVector<Chat*> toSave;
|
||||
for (Chat *chat : m_chats) {
|
||||
if (chat == m_serverChat)
|
||||
continue;
|
||||
if (chat->isNewChat())
|
||||
continue;
|
||||
toSave.append(chat);
|
||||
}
|
||||
auto toSave = getChatsToSave();
|
||||
if (toSave.isEmpty()) {
|
||||
emit saveChatsFinished();
|
||||
return;
|
||||
@ -96,8 +106,24 @@ void ChatListModel::saveChats()
|
||||
emit requestSaveChats(toSave);
|
||||
}
|
||||
|
||||
void ChatListModel::saveChatsForQuit()
|
||||
{
|
||||
saveChats();
|
||||
m_startedFinalSave = true;
|
||||
}
|
||||
|
||||
void ChatListModel::saveChatsSync()
|
||||
{
|
||||
auto toSave = getChatsToSave();
|
||||
if (!m_startedFinalSave && !toSave.isEmpty())
|
||||
m_chatSaver->saveChats(toSave);
|
||||
}
|
||||
|
||||
void ChatSaver::saveChats(const QVector<Chat *> &chats)
|
||||
{
|
||||
// we can be called from the main thread instead of a worker thread at quit time, so take a lock
|
||||
QMutexLocker locker(&m_mutex);
|
||||
|
||||
QElapsedTimer timer;
|
||||
timer.start();
|
||||
const QString savePath = MySettings::globalInstance()->modelPath();
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <QDebug>
|
||||
#include <QHash>
|
||||
#include <QList>
|
||||
#include <QMutex>
|
||||
#include <QObject>
|
||||
#include <QThread>
|
||||
#include <QVariant>
|
||||
@ -18,6 +19,9 @@
|
||||
#include <QtGlobal>
|
||||
#include <QtLogging>
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
||||
class ChatsRestoreThread : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -33,6 +37,7 @@ class ChatSaver : public QObject
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ChatSaver();
|
||||
~ChatSaver() override;
|
||||
|
||||
Q_SIGNALS:
|
||||
void saveChatsFinished();
|
||||
@ -42,6 +47,7 @@ public Q_SLOTS:
|
||||
|
||||
private:
|
||||
QThread m_thread;
|
||||
QMutex m_mutex;
|
||||
};
|
||||
|
||||
class ChatListModel : public QAbstractListModel
|
||||
@ -228,6 +234,7 @@ public:
|
||||
|
||||
void removeChatFile(Chat *chat) const;
|
||||
Q_INVOKABLE void saveChats();
|
||||
Q_INVOKABLE void saveChatsForQuit();
|
||||
void restoreChat(Chat *chat);
|
||||
void chatsRestoredFinished();
|
||||
|
||||
@ -244,6 +251,9 @@ protected:
|
||||
bool eventFilter(QObject *obj, QEvent *ev) override;
|
||||
|
||||
private Q_SLOTS:
|
||||
// Used with QCoreApplication::aboutToQuit. Does not require an event loop.
|
||||
void saveChatsSync();
|
||||
|
||||
void newChatCountChanged()
|
||||
{
|
||||
Q_ASSERT(m_newChat && m_newChat->chatModel()->count());
|
||||
@ -274,11 +284,16 @@ private Q_SLOTS:
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
QVector<Chat *> getChatsToSave() const;
|
||||
|
||||
private:
|
||||
Chat* m_newChat = nullptr;
|
||||
Chat* m_serverChat = nullptr;
|
||||
Chat* m_currentChat = nullptr;
|
||||
QList<Chat*> m_chats;
|
||||
std::unique_ptr<ChatSaver> m_chatSaver;
|
||||
bool m_startedFinalSave = false;
|
||||
|
||||
private:
|
||||
explicit ChatListModel();
|
||||
|
Loading…
Reference in New Issue
Block a user