From 3a039c8dc101e3ba584ecfcb5b3169fd61a11999 Mon Sep 17 00:00:00 2001 From: Adam Treat Date: Sun, 7 May 2023 09:20:09 -0400 Subject: [PATCH] Deserialize one at a time and don't block gui until all of them are done. --- chatlistmodel.cpp | 125 +++++++++++++++++++++++++++++++--------------- chatlistmodel.h | 5 +- 2 files changed, 87 insertions(+), 43 deletions(-) diff --git a/chatlistmodel.cpp b/chatlistmodel.cpp index 8cb115d1..3ba80df5 100644 --- a/chatlistmodel.cpp +++ b/chatlistmodel.cpp @@ -17,7 +17,8 @@ ChatListModel::ChatListModel(QObject *parent) addDummyChat(); ChatsRestoreThread *thread = new ChatsRestoreThread; - connect(thread, &ChatsRestoreThread::chatsRestored, this, &ChatListModel::restoreChats); + connect(thread, &ChatsRestoreThread::chatRestored, this, &ChatListModel::restoreChat); + connect(thread, &ChatsRestoreThread::finished, this, &ChatListModel::chatsRestoredFinished); connect(thread, &ChatsRestoreThread::finished, thread, &QObject::deleteLater); thread->start(); } @@ -83,7 +84,12 @@ void ChatsRestoreThread::run() { QElapsedTimer timer; timer.start(); - QList chats; + struct FileInfo { + bool oldFile; + qint64 creationDate; + QString file; + }; + QList files; { // Look for any files in the original spot which was the settings config directory QSettings settings; @@ -101,16 +107,11 @@ void ChatsRestoreThread::run() continue; } QDataStream in(&file); - Chat *chat = new Chat; - chat->moveToThread(qApp->thread()); - if (!chat->deserialize(in)) { - qWarning() << "ERROR: Couldn't deserialize chat from file:" << file.fileName(); - file.remove(); - } else { - chats.append(chat); - } - qDebug() << "deserializing chat" << f; - file.remove(); // No longer storing in this directory + FileInfo info; + info.oldFile = true; + info.file = filePath; + in >> info.creationDate; + files.append(info); file.close(); } } @@ -147,51 +148,93 @@ void ChatsRestoreThread::run() if (version <= 100) in.setVersion(QDataStream::Qt_6_2); + FileInfo info; + info.oldFile = false; + info.file = filePath; + in >> info.creationDate; + files.append(info); + file.close(); + } + } + std::sort(files.begin(), files.end(), [](const FileInfo &a, const FileInfo &b) { + return a.creationDate > b.creationDate; + }); + + for (FileInfo &f : files) { + QFile file(f.file); + bool success = file.open(QIODevice::ReadOnly); + if (!success) { + qWarning() << "ERROR: Couldn't restore chat from file:" << file.fileName(); + continue; + } + QDataStream in(&file); + + if (!f.oldFile) { + // Read and check the header + quint32 magic; + in >> magic; + if (magic != CHAT_FORMAT_MAGIC) { + qWarning() << "ERROR: Chat file has bad magic:" << file.fileName(); + continue; + } + + // Read the version + qint32 version; + in >> version; + if (version < 100) { + qWarning() << "ERROR: Chat file has non supported version:" << file.fileName(); + continue; + } + + if (version <= 100) + in.setVersion(QDataStream::Qt_6_2); + } + + qDebug() << "deserializing chat" << f.file; + Chat *chat = new Chat; chat->moveToThread(qApp->thread()); if (!chat->deserialize(in)) { qWarning() << "ERROR: Couldn't deserialize chat from file:" << file.fileName(); file.remove(); } else { - chats.append(chat); + emit chatRestored(chat); } - qDebug() << "deserializing chat" << f; + if (f.oldFile) + file.remove(); // No longer storing in this directory file.close(); - } } - std::sort(chats.begin(), chats.end(), [](const Chat* a, const Chat* b) { - return a->creationDate() > b->creationDate(); - }); + qint64 elapsedTime = timer.elapsed(); qDebug() << "deserializing chats took:" << elapsedTime << "ms"; - - emit chatsRestored(chats); } -void ChatListModel::restoreChats(const QList &chats) +void ChatListModel::restoreChat(Chat *chat) { - for (Chat* chat : chats) { - chat->setParent(this); - connect(chat, &Chat::nameChanged, this, &ChatListModel::nameChanged); + chat->setParent(this); + connect(chat, &Chat::nameChanged, this, &ChatListModel::nameChanged); + + if (m_dummyChat) { + beginResetModel(); + m_chats = QList({chat}); + setCurrentChat(chat); + delete m_dummyChat; + m_dummyChat = nullptr; + endResetModel(); + } else { + beginInsertRows(QModelIndex(), m_chats.size(), m_chats.size()); + m_chats.append(chat); + endInsertRows(); } +} - beginResetModel(); - - // Setup the new chats - m_chats = chats; +void ChatListModel::chatsRestoredFinished() +{ + if (m_dummyChat) { + removeChat(m_dummyChat); + m_dummyChat = nullptr; + } - if (!m_chats.isEmpty()) { - Chat *firstChat = m_chats.first(); - if (firstChat->chatModel()->count() < 2) - setNewChat(firstChat); - else - setCurrentChat(firstChat); - } else + if (m_chats.isEmpty()) addChat(); - - // Clean up the dummy - delete m_dummyChat; - m_dummyChat = nullptr; - - endResetModel(); } diff --git a/chatlistmodel.h b/chatlistmodel.h index f2e89135..1dd05f3b 100644 --- a/chatlistmodel.h +++ b/chatlistmodel.h @@ -11,7 +11,7 @@ public: void run() override; Q_SIGNALS: - void chatsRestored(QList chats); + void chatRestored(Chat *chat); }; class ChatListModel : public QAbstractListModel @@ -174,7 +174,8 @@ public: void removeChatFile(Chat *chat) const; void saveChats() const; - void restoreChats(const QList &chats); + void restoreChat(Chat *chat); + void chatsRestoredFinished(); Q_SIGNALS: void countChanged();