diff --git a/Plugins/ZShell/Models/wallpaperdb.cpp b/Plugins/ZShell/Models/wallpaperdb.cpp index ce2e631..b69fd50 100644 --- a/Plugins/ZShell/Models/wallpaperdb.cpp +++ b/Plugins/ZShell/Models/wallpaperdb.cpp @@ -17,6 +17,8 @@ #include #include +#include +#include Q_LOGGING_CATEGORY(dbLog, "ZShell.Internal.wallpaper.db", QtWarningMsg) @@ -27,11 +29,21 @@ class WallpaperImageProvider : public QQuickImageProvider { explicit WallpaperImageProvider(const QString& dbPath) : QQuickImageProvider(QQuickImageProvider::Image), m_dbPath(dbPath) {} + void setDbPath(const QString& dbPath) { + std::lock_guard lock(m_mutex); + if (m_dbPath == dbPath) { + return; + } + + m_dbPath = dbPath; + m_generation.fetch_add(1, std::memory_order_relaxed); + } + QImage requestImage( const QString& id, QSize* size, const QSize& requestedSize) override { const QString path = QString::fromUtf8(QByteArray::fromHex(id.toUtf8())); - if (path.isEmpty() || !openThreadDb()) { + if (path.isEmpty() || !openThreadDb(currentDbPath())) { return {}; } @@ -68,12 +80,31 @@ class WallpaperImageProvider : public QQuickImageProvider { } private: - bool openThreadDb() { - if (!m_threadUuid.isEmpty()) { + QString currentDbPath() const { + std::lock_guard lock(m_mutex); + return m_dbPath; + } + + bool openThreadDb(const QString& dbPath) { + const quint64 generation = m_generation.load(std::memory_order_relaxed); + + if (!m_threadUuid.isEmpty() && m_threadGeneration == generation) { return true; } - if (m_dbPath.isEmpty()) { + if (!m_threadUuid.isEmpty()) { + { + auto db = QSqlDatabase::database(m_threadUuid, false); + if (db.isValid()) { + db.close(); + } + } + + QSqlDatabase::removeDatabase(m_threadUuid); + m_threadUuid.clear(); + } + + if (dbPath.isEmpty()) { return false; } @@ -81,7 +112,7 @@ class WallpaperImageProvider : public QQuickImageProvider { auto db = QSqlDatabase::addDatabase("QSQLITE", uuid); db.setConnectOptions("QSQLITE_OPEN_READONLY"); - db.setDatabaseName(m_dbPath); + db.setDatabaseName(dbPath); if (!db.open()) { return false; @@ -91,14 +122,20 @@ class WallpaperImageProvider : public QQuickImageProvider { query.exec("PRAGMA journal_mode=WAL"); m_threadUuid = uuid; + m_threadGeneration = generation; return true; } - const QString m_dbPath; + mutable std::mutex m_mutex; + QString m_dbPath; + std::atomic m_generation = 0; + thread_local static QString m_threadUuid; + thread_local static quint64 m_threadGeneration; }; thread_local QString WallpaperImageProvider::m_threadUuid; +thread_local quint64 WallpaperImageProvider::m_threadGeneration; WallpaperEntry::WallpaperEntry( const QString& path, const QString& relativePath, QObject* parent) @@ -326,6 +363,7 @@ void WallpaperDb::setCacheSize(const QSize& cacheSize) { void WallpaperDb::registerProvider() { if (m_provider != nullptr) { + m_provider->setDbPath(m_dbPath); return; }