/*
* Komplex Wallpaper Engine
* Copyright (C) 2026 @DigitalArtifex
* https://digitalartifex.dev - https://github.com/DigitalArtifex
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see
*/
#ifndef PAGINATOR_H
#define PAGINATOR_H
#include
#include "komplex_global.h"
#include "slidingcachecontroller.h"
/**
* @brief The PaginatorNotifier class
*
* Qt does not support templated QObjects. Pushing it to a notifier class
* that the template can inherit fixes this
*/
class KOMPLEX_EXPORT PaginatorNotifier : public QObject
{
Q_OBJECT
signals:
auto dataChanged() -> void;
auto resultsPerPageChanged() -> void;
auto totalResultsChanged() -> void;
auto totalPagesChanged() -> void;
auto pageChanged() -> void;
auto countChanged() -> void;
};
/**
* @brief The Paginator class is a type agnostic pagination controller that uses
* the SlidingCacheController as it's backend
*/
template
class KOMPLEX_EXPORT Paginator : public PaginatorNotifier
{
public:
/**
* @brief next
*
* Attempts to get the next page and notifies pageChanged
*/
auto next() const -> void
{
setOffset(m_offset + m_resultsPerPage);
Q_EMIT static_cast(this)->pageChanged();
}
/**
* @brief previous
*
* Attempts to get the previous page and notifies pageChanged
*/
auto previous() const -> void
{
setOffset(m_offset - m_resultsPerPage);
Q_EMIT static_cast(this)->pageChanged();
}
/**
* @brief resultsPerPage
* @return
*/
auto resultsPerPage() const -> qsizetype
{
return m_resultsPerPage;
}
/**
* @brief setResultsPerPage
* @param resultsPerPage
*/
auto setResultsPerPage(qsizetype resultsPerPage) -> void
{
m_resultsPerPage = resultsPerPage;
Q_EMIT static_cast(this)->resultsPerPageChanged();
m_data = m_cacheController.chunk(m_offset, m_resultsPerPage);
Q_EMIT static_cast(this)->dataChanged();
}
/**
* @brief data
* @return a copy of the list of pointers
*/
auto data() const -> QList
{
return m_data;
}
/**
* @brief count
* @return
*/
auto count() const -> qsizetype
{
return m_data.count();
}
/**
* @brief at
* @param index
* @return
*/
auto at(qsizetype index) const -> T
{
if(index < 0 || index >= m_data.count())
{
return {};
}
return m_data.at(index);
}
/**
* @brief totalResults
*
* The total number of results as reported by the controller
* @return
*/
auto totalResults() -> qsizetype
{
return m_cacheController.count();
}
/**
* @brief page
* @return
*/
auto page() const -> qsizetype
{
return std::floor(
static_cast(m_offset) / m_resultsPerPage
);
}
/**
* @brief totalPages
* @return
*/
auto totalPages() const -> qsizetype
{
return std::ceil(
static_cast(totalResults()) / m_resultsPerPage
);
}
protected:
auto controller() -> SlidingCacheController*
{
return &m_cacheController;
}
auto setOffset(qsizetype offset) -> void
{
m_offset = offset;
if(m_offset >= m_totalResults)
{
m_offset = m_totalResults - m_resultsPerPage;
}
if(m_offset < 0)
{
m_offset = 0;
}
m_data = m_cacheController.chunk(m_offset, m_resultsPerPage);
Q_EMIT this->countChanged();
Q_EMIT this->dataChanged();
Q_EMIT this->pageChanged();
Q_EMIT this->totalPagesChanged();
}
auto onControllerTotalResultsChanged() -> void
{
Q_EMIT this->totalResultsChanged();
}
private:
qsizetype m_page = 0;
qsizetype m_totalPages = 0;
qsizetype m_offset = 0;
qsizetype m_resultsPerPage = 0;
qsizetype m_totalResults = 0;
SlidingCacheController m_cacheController;
QList m_data;
};
#endif // PAGINATOR_H