From 59a2204386805c1de8632e04e2c621c4c0476aaf Mon Sep 17 00:00:00 2001 From: Digital Artifex <7929434+DigitalArtifex@users.noreply.github.com> Date: Sat, 6 Jun 2026 22:34:19 -0400 Subject: [PATCH] Added common files --- KomplexHubPlugin/WallpaperMetaData.h | 21 -- KomplexHubPlugin/common/coreservices.cpp | 18 ++ KomplexHubPlugin/common/coreservices.h | 28 ++ KomplexHubPlugin/common/fetchresult.h | 28 ++ KomplexHubPlugin/common/komplex_global.h | 15 + KomplexHubPlugin/common/logging.h | 49 +++ KomplexHubPlugin/common/paginator.cpp | 0 KomplexHubPlugin/common/paginator.h | 85 ++++++ .../common/slidingcachecontroller.cpp | 0 .../common/slidingcachecontroller.h | 284 ++++++++++++++++++ KomplexHubPlugin/common/wallpapercache.h | 38 +++ 11 files changed, 545 insertions(+), 21 deletions(-) delete mode 100644 KomplexHubPlugin/WallpaperMetaData.h create mode 100644 KomplexHubPlugin/common/coreservices.cpp create mode 100644 KomplexHubPlugin/common/coreservices.h create mode 100644 KomplexHubPlugin/common/fetchresult.h create mode 100644 KomplexHubPlugin/common/komplex_global.h create mode 100644 KomplexHubPlugin/common/logging.h create mode 100644 KomplexHubPlugin/common/paginator.cpp create mode 100644 KomplexHubPlugin/common/paginator.h create mode 100644 KomplexHubPlugin/common/slidingcachecontroller.cpp create mode 100644 KomplexHubPlugin/common/slidingcachecontroller.h create mode 100644 KomplexHubPlugin/common/wallpapercache.h diff --git a/KomplexHubPlugin/WallpaperMetaData.h b/KomplexHubPlugin/WallpaperMetaData.h deleted file mode 100644 index 917c903..0000000 --- a/KomplexHubPlugin/WallpaperMetaData.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef WALLPAPERMETADATA_H -#define WALLPAPERMETADATA_H - -#include "Komplex_global.h" - -#include -#include -#include -#include - -struct KOMPLEX_EXPORT WallpaperMetaData { - QString uri; - QString name; - QString author; - QString description; - QString thumbnail; - QDateTime installDate; -}; -Q_DECLARE_METATYPE(WallpaperMetaData) - -#endif // WALLPAPERMETADATA_H diff --git a/KomplexHubPlugin/common/coreservices.cpp b/KomplexHubPlugin/common/coreservices.cpp new file mode 100644 index 0000000..4997afb --- /dev/null +++ b/KomplexHubPlugin/common/coreservices.cpp @@ -0,0 +1,18 @@ +#include "coreservices.h" +#include "logging.h" + +QNetworkAccessManager *CoreServices::m_networkAccessManager = new QNetworkAccessManager(); + +auto CoreServices::networkAccessManager() -> QNetworkAccessManager * +{ + return m_networkAccessManager; +} + +auto CoreServices::sessionToken() -> QByteArray +{ + LOG_ERROR_X(true, + "CoreServices::sessionToken", + "User services not yet implements", + {} + ); +} diff --git a/KomplexHubPlugin/common/coreservices.h b/KomplexHubPlugin/common/coreservices.h new file mode 100644 index 0000000..dedf66a --- /dev/null +++ b/KomplexHubPlugin/common/coreservices.h @@ -0,0 +1,28 @@ +#ifndef CORESERVICES_H +#define CORESERVICES_H + +#include +#include + +class CoreServices +{ +public: + + /** + * @brief networkAccessManager + * Plugin-wide QNetworkAccessManager + * @return + */ + static auto networkAccessManager() -> QNetworkAccessManager*; + + /** + * @brief getSessionToken + * Plugin-wide access to current user session token + * @return + */ + static auto sessionToken() -> QByteArray; + +private: + static QNetworkAccessManager *m_networkAccessManager; +}; +#endif // CORESERVICES_H diff --git a/KomplexHubPlugin/common/fetchresult.h b/KomplexHubPlugin/common/fetchresult.h new file mode 100644 index 0000000..8ba45ab --- /dev/null +++ b/KomplexHubPlugin/common/fetchresult.h @@ -0,0 +1,28 @@ +#ifndef FETCHRESULT_H +#define FETCHRESULT_H +#include +#include + +template +struct FetchResult +{ + /** + * @brief total + * Total number of results in the query + */ + qsizetype total = 0; + + /** + * @brief count + * Number of results returned in this result + */ + qsizetype count = 0; + + /** + * @brief results + * Results list + */ + QList data; +}; + +#endif // FETCHRESULT_H diff --git a/KomplexHubPlugin/common/komplex_global.h b/KomplexHubPlugin/common/komplex_global.h new file mode 100644 index 0000000..62b9ab4 --- /dev/null +++ b/KomplexHubPlugin/common/komplex_global.h @@ -0,0 +1,15 @@ +#ifndef KOMPLEX_GLOBAL_H +#define KOMPLEX_GLOBAL_H + +#ifdef KOMPLEX_PLUGIN +#define KOMPLEX_EXPORT Q_DECL_EXPORT +#else +#define KOMPLEX_EXPORT Q_DECL_IMPORT +#endif + +#define SLIDING_CACHE_WINDOW_SIZE 100 +#define SLIDING_CACHE_PREFETCH_THRESHOLD 20 + +#define NETWORK_TIMEOUT 10000 + +#endif // KOMPLEX_GLOBAL_H diff --git a/KomplexHubPlugin/common/logging.h b/KomplexHubPlugin/common/logging.h new file mode 100644 index 0000000..53787e8 --- /dev/null +++ b/KomplexHubPlugin/common/logging.h @@ -0,0 +1,49 @@ +#ifndef LOGGING_H +#define LOGGING_H +// clazy:exclude=clazy-unused-headers + +#include // NOLINT(clazy-unused-headers) +#include // NOLINT(clazy-unused-headers) + +/** + * @brief LOG_ERROR + * + * When cond is true, logs where and what as an error + * @param cond + * @param where + * @param what + */ +#define LOG_ERROR(cond, where, what) \ + do { \ + if ((cond)) { \ + std::cerr << "Assertion failed: (" << #cond << ")\n" \ + << " Location: " << (where) << "\n" \ + << " Message: " << (what) << "\n" \ + << " File: " << __FILE__ << ":" << __LINE__ << "\n"; \ + } \ +} while (0) + +#define LOG_ERROR_X(cond, where, what, ret) \ + do { \ + if ((cond)) { \ + std::cout << "Assertion failed: (" << #cond << ")\n" \ + << " Location: " << (where) << "\n" \ + << " Message: " << (what) << "\n" \ + << " File: " << __FILE__ << ":" << __LINE__ << "\n"; \ + return ret; \ + } \ +} while (0) + +#ifndef ASSERT_X +#define ASSERT_X(cond, where, what) \ + do { \ + if (!(cond)) { \ + std::cout << "Assertion failed: (" << #cond << ")\n" \ + << " Location: " << (where) << "\n" \ + << " Message: " << (what) << "\n" \ + << " File: " << __FILE__ << ":" << __LINE__ << "\n"; \ + std::abort(); \ + } \ +} while (0) +#endif +#endif // LOGGING_H diff --git a/KomplexHubPlugin/common/paginator.cpp b/KomplexHubPlugin/common/paginator.cpp new file mode 100644 index 0000000..e69de29 diff --git a/KomplexHubPlugin/common/paginator.h b/KomplexHubPlugin/common/paginator.h new file mode 100644 index 0000000..0a54b3a --- /dev/null +++ b/KomplexHubPlugin/common/paginator.h @@ -0,0 +1,85 @@ +#ifndef PAGINATOR_H +#define PAGINATOR_H + +#include + +#include "komplex_global.h" +#include "slidingcachecontroller.h" + +template +class KOMPLEX_EXPORT Paginator +{ +public: + Paginator() = default; + ~Paginator() = default; + + auto next() const -> void + { + setOffset(m_offset + m_resultsPerPage); + } + + auto previous() const -> void + { + setOffset(m_offset - m_resultsPerPage); + } + + auto resultsPerPage() const -> qsizetype + { + return m_resultsPerPage; + } + + auto setResultsPerPage(qsizetype resultsPerPage) -> void + { + m_resultsPerPage = resultsPerPage; + m_data = m_cacheController.chunk(m_offset, m_resultsPerPage); + } + + auto data() const -> QList + { + return m_data; + } + + auto count() const -> qsizetype + { + return m_data.count(); + } + + auto at(qsizetype index) const -> T* + { + if(index < 0 || index >= m_data.count()) + { + return nullptr; + } + + return m_data.at(index); + } + + auto controller() -> SlidingCacheController* + { + return &m_cacheController; + } + + auto offset() const -> qsizetype + { + return m_offset; + } + + auto setOffset(qsizetype offset) -> void + { + m_offset = offset; + + if(m_offset < 0 || m_offset == std::numeric_limits::max()) + m_offset = 0; + + m_data = m_cacheController.chunk(m_offset, m_resultsPerPage); + } + +private: + qsizetype m_offset = 0; + qsizetype m_resultsPerPage = 0; + + SlidingCacheController m_cacheController; + QList m_data; +}; + +#endif // PAGINATOR_H diff --git a/KomplexHubPlugin/common/slidingcachecontroller.cpp b/KomplexHubPlugin/common/slidingcachecontroller.cpp new file mode 100644 index 0000000..e69de29 diff --git a/KomplexHubPlugin/common/slidingcachecontroller.h b/KomplexHubPlugin/common/slidingcachecontroller.h new file mode 100644 index 0000000..b1bfc77 --- /dev/null +++ b/KomplexHubPlugin/common/slidingcachecontroller.h @@ -0,0 +1,284 @@ +#ifndef SLIDINGCACHECONTROLLER_H +#define SLIDINGCACHECONTROLLER_H + +#include +#include +#include +#include "fetchresult.h" +#include "komplex_global.h" + +template +class KOMPLEX_EXPORT SlidingCacheController +{ +public: + + explicit SlidingCacheController() + { + m_cache.reserve(SLIDING_CACHE_WINDOW_SIZE); + } + + ~SlidingCacheController() + { + clear(); + } + + /** + * @brief setFetch + * Used to set the fetch method for the cache controller. Method should return a QList + * of CacheObjects based on the offset and limit provided. CacheObject must derive from + * QObject + * + * @param fetch + */ + auto setFetch( + const std::function (qsizetype offset, qsizetype limit)> &fetch + ) -> void + { + m_fetch = std::move(fetch); + } + + /** + * @brief at + * Retrieves the CacheObject reference at the specified index. If data is outside the + * current window, a fetch will be attempted + * @param index + * @return CacheObject* or nullptr + */ + [[nodiscard]] + auto at(qsizetype index) const -> T* + { + //OOB check for expected index + if (index < 0 || + (m_totalCount != std::numeric_limits::infinity() && + index >= m_totalCount)) + { + return nullptr; + } + + while (index >= m_windowOffset + (SLIDING_CACHE_WINDOW_SIZE - SLIDING_CACHE_PREFETCH_THRESHOLD)) + { + if(!slideForward()) + { + break; + } + } + + while (index <= m_windowOffset - (SLIDING_CACHE_WINDOW_SIZE - SLIDING_CACHE_PREFETCH_THRESHOLD)) + { + if(!slideBackward()) + { + break; + } + } + + index = trueIndex(index); + + //OOB check for actual index + if(index < 0 || index >= m_cache.count()) + { + return nullptr; + } + + return m_cache.at(index); + } + + /** + * @brief chunk + * Returns a chunk of data from cache. If data is outside the current window, a + * fetch will be attempted + * @param index + * @param count + * @return + */ + [[nodiscard]] + auto chunk(qsizetype index, qsizetype count) -> QList + { + QList dataChunk; + + for(qsizetype i = index; i < count; ++i) + { + T* data = at(i); + + if(data == nullptr) + { + break; + } + + dataChunk.append(data); + } + + return dataChunk; + } + + /** + * @brief count + * + * @return The total number of results available + */ + [[nodiscard]] + auto count() const -> qsizetype + { + return m_totalCount; + } + + /** + * @brief clear + * Clears the current cache + */ + auto clear() -> void + { + while(!m_cache.isEmpty()) + { + T *object = m_cache.takeFirst(); + delete object; + } + } + +signals: + +private: + /** + * @brief slideForward + * Attempts to slide the cache window forward + * @return true if successful + */ + auto slideForward() -> bool + { + qsizetype movementSize = SLIDING_CACHE_WINDOW_SIZE; + + //after initial inflation we should only arrive here when the prefetch threshold is reached + if(!m_cache.isEmpty()) + { + movementSize -= SLIDING_CACHE_PREFETCH_THRESHOLD; + } + + m_windowOffset += movementSize; + + QList newCache = m_fetch( + m_windowOffset, + movementSize + ); + + if(newCache.isEmpty()) + { + m_windowOffset -= movementSize; + return false; + } + + while(!newCache.isEmpty() && !m_cache.isEmpty()) + { + T *object = newCache.takeFirst(); + T *oldObject = m_cache.takeFirst(); + + delete oldObject; + m_cache.append(object); + } + + if(!newCache.isEmpty()) + { + LOG_ERROR_X((newCache.count() + m_cache.count()) > SLIDING_CACHE_WINDOW_SIZE, + "SlidingCacheController::slideForward", + "Cache size imbalance", + false + ); + + m_cache.append(newCache); + } + + return true; + } + + /** + * @brief slideBackward + * Attempts to slide the cache window backward + * @return true if successful + */ + auto slideBackward() -> bool + { + LOG_ERROR_X(!m_fetch, + "SlidingCacheController::slideBackward", + "Fetch function not set", + false + ); + + qsizetype movementSize = SLIDING_CACHE_WINDOW_SIZE - SLIDING_CACHE_PREFETCH_THRESHOLD; + m_windowOffset -= movementSize; + + if(m_windowOffset < 0) + { + m_windowOffset = 0; + } + + FetchResult result = m_fetch( + m_windowOffset, + movementSize + ); + + if(result.count == 0) + { + m_windowOffset += movementSize; + return false; + } + + while(!result.data.isEmpty() && !m_cache.isEmpty()) + { + T *object = result.data.takeLast(); + T *oldObject = m_cache.takeLast(); + + delete oldObject; + m_cache.push_front(object); + } + + if(!result.results.isEmpty()) + { + LOG_ERROR_X((result.count + m_cache.count()) > SLIDING_CACHE_WINDOW_SIZE, + "SlidingCacheController::slideBackward", + "Cache size imbalance", + false + ); + + m_cache.push_front(std::move(result.data)); + } + + return true; + } + + /** + * @brief trueIndex + * Translates the global object index to the current cache index + * @param index Global object index + * @return + */ + auto trueIndex(qsizetype index) -> qsizetype + { + return index - m_windowOffset; + } + + /** + * @brief m_windowOffset + * Current window offset + */ + qsizetype m_windowOffset = 0; + + /** + * @brief m_totalCount + * Total number of results available. Data comes from the return data of + * m_fetch + */ + qsizetype m_totalCount = std::numeric_limits::infinity(); + + /** + * @brief m_fetch + * The fetch function for retreiving external data. This must be set by the paginator + * or other controller class for the cachecontroller to work + */ + std::function(qsizetype offset, qsizetype limit)> m_fetch; + + /** + * @brief m_cache + * The working cache + */ + QVector m_cache; +}; + +#endif // SLIDINGCACHECONTROLLER_H diff --git a/KomplexHubPlugin/common/wallpapercache.h b/KomplexHubPlugin/common/wallpapercache.h new file mode 100644 index 0000000..1f5e7da --- /dev/null +++ b/KomplexHubPlugin/common/wallpapercache.h @@ -0,0 +1,38 @@ +#ifndef WALLPAPERCACHE_H +#define WALLPAPERCACHE_H + +#include "komplex_global.h" + +#include +#include +#include +#include + +struct KOMPLEX_EXPORT WallpaperInstallData +{ + QString uri; + QString name; + QString author; + QString description; + QString thumbnail; + QDateTime installDate; +}; +Q_DECLARE_METATYPE(WallpaperInstallData) + +struct KOMPLEX_EXPORT WallpaperCache +{ + QString uri; + QString name; + QString author; + QString authorId; + QString description; + QString thumbnail; + QDateTime createdDate; + qreal price = 0; + QString currency; + quint64 downloadCount = 0; + qint8 type = -1; +}; +Q_DECLARE_METATYPE(WallpaperCache) + +#endif // WALLPAPERCACHE_H