mirror of
https://github.com/nomic-ai/gpt4all.git
synced 2025-07-11 06:15:36 +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]
|
## [Unreleased]
|
||||||
|
|
||||||
## Fixed
|
### Fixed
|
||||||
- Fix the timeout error in code interpreter ([#3369](https://github.com/nomic-ai/gpt4all/pull/3369))
|
- 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))
|
- 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))
|
- 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))
|
- 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
|
## [3.6.1] - 2024-12-20
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ Window {
|
|||||||
systemTrayIcon.shouldClose = true;
|
systemTrayIcon.shouldClose = true;
|
||||||
window.shouldClose = true;
|
window.shouldClose = true;
|
||||||
savingPopup.open();
|
savingPopup.open();
|
||||||
ChatListModel.saveChats();
|
ChatListModel.saveChatsForQuit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -231,8 +231,8 @@ Window {
|
|||||||
|
|
||||||
window.shouldClose = true;
|
window.shouldClose = true;
|
||||||
savingPopup.open();
|
savingPopup.open();
|
||||||
ChatListModel.saveChats();
|
ChatListModel.saveChatsForQuit();
|
||||||
close.accepted = false
|
close.accepted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
|
@ -52,9 +52,11 @@ void ChatListModel::loadChats()
|
|||||||
connect(thread, &ChatsRestoreThread::finished, thread, &QObject::deleteLater);
|
connect(thread, &ChatsRestoreThread::finished, thread, &QObject::deleteLater);
|
||||||
thread->start();
|
thread->start();
|
||||||
|
|
||||||
ChatSaver *saver = new ChatSaver;
|
m_chatSaver = std::make_unique<ChatSaver>();
|
||||||
connect(this, &ChatListModel::requestSaveChats, saver, &ChatSaver::saveChats, Qt::QueuedConnection);
|
connect(this, &ChatListModel::requestSaveChats, m_chatSaver.get(), &ChatSaver::saveChats, Qt::QueuedConnection);
|
||||||
connect(saver, &ChatSaver::saveChatsFinished, this, &ChatListModel::saveChatsFinished, 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);
|
connect(MySettings::globalInstance(), &MySettings::serverChatChanged, this, &ChatListModel::handleServerEnabledChanged);
|
||||||
}
|
}
|
||||||
@ -78,16 +80,24 @@ ChatSaver::ChatSaver()
|
|||||||
m_thread.start();
|
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()
|
void ChatListModel::saveChats()
|
||||||
{
|
{
|
||||||
QVector<Chat*> toSave;
|
auto toSave = getChatsToSave();
|
||||||
for (Chat *chat : m_chats) {
|
|
||||||
if (chat == m_serverChat)
|
|
||||||
continue;
|
|
||||||
if (chat->isNewChat())
|
|
||||||
continue;
|
|
||||||
toSave.append(chat);
|
|
||||||
}
|
|
||||||
if (toSave.isEmpty()) {
|
if (toSave.isEmpty()) {
|
||||||
emit saveChatsFinished();
|
emit saveChatsFinished();
|
||||||
return;
|
return;
|
||||||
@ -96,8 +106,24 @@ void ChatListModel::saveChats()
|
|||||||
emit requestSaveChats(toSave);
|
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)
|
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;
|
QElapsedTimer timer;
|
||||||
timer.start();
|
timer.start();
|
||||||
const QString savePath = MySettings::globalInstance()->modelPath();
|
const QString savePath = MySettings::globalInstance()->modelPath();
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
|
#include <QMutex>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
@ -18,6 +19,9 @@
|
|||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
#include <QtLogging>
|
#include <QtLogging>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
|
||||||
class ChatsRestoreThread : public QThread
|
class ChatsRestoreThread : public QThread
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -33,6 +37,7 @@ class ChatSaver : public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit ChatSaver();
|
explicit ChatSaver();
|
||||||
|
~ChatSaver() override;
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void saveChatsFinished();
|
void saveChatsFinished();
|
||||||
@ -42,6 +47,7 @@ public Q_SLOTS:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
QThread m_thread;
|
QThread m_thread;
|
||||||
|
QMutex m_mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ChatListModel : public QAbstractListModel
|
class ChatListModel : public QAbstractListModel
|
||||||
@ -228,6 +234,7 @@ public:
|
|||||||
|
|
||||||
void removeChatFile(Chat *chat) const;
|
void removeChatFile(Chat *chat) const;
|
||||||
Q_INVOKABLE void saveChats();
|
Q_INVOKABLE void saveChats();
|
||||||
|
Q_INVOKABLE void saveChatsForQuit();
|
||||||
void restoreChat(Chat *chat);
|
void restoreChat(Chat *chat);
|
||||||
void chatsRestoredFinished();
|
void chatsRestoredFinished();
|
||||||
|
|
||||||
@ -244,6 +251,9 @@ protected:
|
|||||||
bool eventFilter(QObject *obj, QEvent *ev) override;
|
bool eventFilter(QObject *obj, QEvent *ev) override;
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
|
// Used with QCoreApplication::aboutToQuit. Does not require an event loop.
|
||||||
|
void saveChatsSync();
|
||||||
|
|
||||||
void newChatCountChanged()
|
void newChatCountChanged()
|
||||||
{
|
{
|
||||||
Q_ASSERT(m_newChat && m_newChat->chatModel()->count());
|
Q_ASSERT(m_newChat && m_newChat->chatModel()->count());
|
||||||
@ -274,11 +284,16 @@ private Q_SLOTS:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QVector<Chat *> getChatsToSave() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Chat* m_newChat = nullptr;
|
Chat* m_newChat = nullptr;
|
||||||
Chat* m_serverChat = nullptr;
|
Chat* m_serverChat = nullptr;
|
||||||
Chat* m_currentChat = nullptr;
|
Chat* m_currentChat = nullptr;
|
||||||
QList<Chat*> m_chats;
|
QList<Chat*> m_chats;
|
||||||
|
std::unique_ptr<ChatSaver> m_chatSaver;
|
||||||
|
bool m_startedFinalSave = false;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit ChatListModel();
|
explicit ChatListModel();
|
||||||
|
Loading…
Reference in New Issue
Block a user