#pragma once #include #include #include #include #include #include #include #include #include #include #include #include namespace ZShell::models { class WallpaperImageProvider; class WallpaperEntry : public QObject { Q_OBJECT QML_ELEMENT QML_UNCREATABLE( "WallpaperEntry instances can only be retrieved from a WallpaperDb") Q_PROPERTY(QString path READ path CONSTANT) Q_PROPERTY(QString relativePath READ relativePath NOTIFY relativePathChanged) Q_PROPERTY(QString name READ name CONSTANT) Q_PROPERTY(QString baseName READ baseName CONSTANT) Q_PROPERTY(QString parentDir READ parentDir CONSTANT) Q_PROPERTY(QString suffix READ suffix CONSTANT) Q_PROPERTY(qint64 size READ size CONSTANT) Q_PROPERTY(bool isImage READ isImage CONSTANT) Q_PROPERTY(bool isVideo READ isVideo CONSTANT) Q_PROPERTY(bool hardware READ hardware NOTIFY hardwareChanged) Q_PROPERTY( QString thumbnailPath READ thumbnailPath NOTIFY thumbnailPathChanged) public: explicit WallpaperEntry( const QString& path, const QString& relativePath, QObject* parent = nullptr); [[nodiscard]] QString path() const; [[nodiscard]] QString relativePath() const; [[nodiscard]] QString name() const; [[nodiscard]] QString baseName() const; [[nodiscard]] QString parentDir() const; [[nodiscard]] QString suffix() const; [[nodiscard]] qint64 size() const; [[nodiscard]] bool isImage() const; [[nodiscard]] bool isVideo() const; [[nodiscard]] bool hardware() const; [[nodiscard]] bool cached() const; [[nodiscard]] QString thumbnailPath() const; void setRelativePath(const QString& path); void setHardware(bool hardware); void setThumbnailPath(const QString& path); signals: void relativePathChanged(); void hardwareChanged(); void thumbnailPathChanged(); private: const QFileInfo m_fileInfo; const QString m_path; QString m_relativePath; QString m_thumbnailPath; bool m_hardware = false; }; class WallpaperDb : public QObject { Q_OBJECT QML_ELEMENT Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged) Q_PROPERTY(QString dbPath READ dbPath WRITE setDbPath NOTIFY dbPathChanged) Q_PROPERTY( bool requireHardwareCodec READ requireHardwareCodec WRITE setRequireHardwareCodec NOTIFY requireHardwareCodecChanged) Q_PROPERTY( QQmlListProperty entries READ entries NOTIFY entriesChanged) Q_PROPERTY( QSize cacheSize READ cacheSize WRITE setCacheSize NOTIFY cacheSizeChanged) public: explicit WallpaperDb(QObject* parent = nullptr); ~WallpaperDb() override; [[nodiscard]] QString path() const; void setPath(const QString& path); [[nodiscard]] QString dbPath() const; void setDbPath(const QString& path); [[nodiscard]] bool requireHardwareCodec() const; void setRequireHardwareCodec(bool requireHardwareCodec); [[nodiscard]] QQmlListProperty entries(); [[nodiscard]] QSize cacheSize() const; void setCacheSize(const QSize& cacheSize); [[nodiscard]] static QString thumbnailUrl(const QString& path); signals: void pathChanged(); void dbPathChanged(); void requireHardwareCodecChanged(); void entriesChanged(); void cacheSizeChanged(); void cacheStored(const QString& path); private: struct FileEntry { QFileInfo info; bool hardware = false; }; struct ScanResult { QVector files; QDir dir; }; struct MetadataJob { WallpaperEntry* entry; QString path; bool isVideo; QByteArray existingCache; }; void openDb(); void registerProvider(); void scanDir(); void watchDir(const QString& dir); void applyScan(const ScanResult& result); void queueMetadata( WallpaperEntry* entry, bool isVideo, const QByteArray& existingCache = {}); void processQueue(); void runMetadataJob(const MetadataJob& job); void rebuildEntries(); [[nodiscard]] bool entryAllowed(const WallpaperEntry* entry) const; QDir m_dir; QString m_path; QString m_dbPath; QString m_uuid; WallpaperImageProvider* m_provider = nullptr; bool m_requireHardwareCodec = false; QSize m_cacheSize; QList m_entries; QHash m_byPath; QVector m_queue; QTimer m_queueTimer; bool m_jobRunning = false; QFileSystemWatcher m_watcher; QTimer m_watchTimer; }; } // namespace ZShell::models