From cb7b46c09a2e3bfad0dd8e602de9400dc855aa1e Mon Sep 17 00:00:00 2001
From: Fatih Uzunoglu <fuzun54@outlook.com>
Date: Sat, 15 Mar 2025 20:41:55 +0200
Subject: [PATCH] qt: make limit=0 behave limit=0 in `BaseModel`

limit=0 having special value, such as loading
all items is not intuitive. limit=0 should
behave as limit is 0, as what it suggests.

Not only that but it also means we need two
special values to (current case):

- Not load any items. (any negative number?)
- Load all items. (limit=0)

Where as if limit=0 behaves as limit=0,
we need only one special value to load all
items. I propose any arbitrary negative
number.

The current situation also makes mapping
more complicated, for example with a view
that has a property `itemCountToShow`, we
can not simply map `limit: view.itemCountToShow`,
because when `itemCountToShow` is 0, this
would cause the model to load all items.
---
 modules/gui/qt/medialibrary/mlbasemodel.cpp | 2 +-
 modules/gui/qt/util/base_model.cpp          | 4 ++--
 modules/gui/qt/util/base_model.hpp          | 9 +++++----
 modules/gui/qt/util/base_model_p.hpp        | 2 +-
 modules/gui/qt/util/listcache.hpp           | 6 +++---
 modules/gui/qt/util/listcache.hxx           | 6 +++---
 6 files changed, 15 insertions(+), 14 deletions(-)

diff --git a/modules/gui/qt/medialibrary/mlbasemodel.cpp b/modules/gui/qt/medialibrary/mlbasemodel.cpp
index af30a63cff27..d3f4a680f93c 100644
--- a/modules/gui/qt/medialibrary/mlbasemodel.cpp
+++ b/modules/gui/qt/medialibrary/mlbasemodel.cpp
@@ -114,7 +114,7 @@ public:
             int count = q->getCount();
             int limit = q->getLimit();
             //item doesn't exists
-            if ((limit != 0 && count >= limit) || loaded == getMaximumCount()) {
+            if ((limit >= 0 && count >= limit) || loaded == getMaximumCount()) {
                 cb(std::nullopt);
             }
             else
diff --git a/modules/gui/qt/util/base_model.cpp b/modules/gui/qt/util/base_model.cpp
index dc3e9a60a1a1..5c7b88b0e18a 100644
--- a/modules/gui/qt/util/base_model.cpp
+++ b/modules/gui/qt/util/base_model.cpp
@@ -76,13 +76,13 @@ void BaseModel::onCacheBeginMoveRows(int first, int last, int destination)
     emit beginMoveRows({}, first, last, {}, destination);
 }
 
-unsigned int BaseModel::getLimit() const
+int BaseModel::getLimit() const
 {
     Q_D(const BaseModel);
     return d->m_limit;
 }
 
-void BaseModel::setLimit(unsigned int limit)
+void BaseModel::setLimit(int limit)
 {
     Q_D(BaseModel);
     if (d->m_limit == limit)
diff --git a/modules/gui/qt/util/base_model.hpp b/modules/gui/qt/util/base_model.hpp
index 19299a2a8786..f671fe36df7d 100644
--- a/modules/gui/qt/util/base_model.hpp
+++ b/modules/gui/qt/util/base_model.hpp
@@ -39,8 +39,9 @@ class BaseModel : public QAbstractListModel, public QQmlParserStatus
                    NOTIFY sortCriteriaChanged RESET unsetSortCriteria FINAL)
 
     //maximum number of element to load
-    //limit = 0 means all elements are loaded
-    Q_PROPERTY(unsigned int limit READ getLimit WRITE setLimit NOTIFY limitChanged FINAL)
+    //limit < 0 means all elements are loaded
+	// QML does not have type ssize_t
+    Q_PROPERTY(int limit READ getLimit WRITE setLimit NOTIFY limitChanged FINAL)
 
     //skip in N first elements
     Q_PROPERTY(unsigned int offset READ getOffset WRITE setOffset NOTIFY offsetChanged FINAL)
@@ -70,8 +71,8 @@ public:
     virtual void setSortCriteria(const QString& criteria);
     virtual void unsetSortCriteria();
 
-    unsigned int getLimit() const;
-    void setLimit(unsigned int limit);
+    int getLimit() const;
+    void setLimit(int limit);
     unsigned int getOffset() const;
     void setOffset(unsigned int offset);
 
diff --git a/modules/gui/qt/util/base_model_p.hpp b/modules/gui/qt/util/base_model_p.hpp
index ebe8e38a5a1a..7a6a6aac1b6e 100644
--- a/modules/gui/qt/util/base_model_p.hpp
+++ b/modules/gui/qt/util/base_model_p.hpp
@@ -114,7 +114,7 @@ protected:
     QString m_searchPattern = {};
     Qt::SortOrder m_sortOrder = Qt::SortOrder::AscendingOrder;
     QString m_sortCriteria = {};
-    unsigned int m_limit = 0;
+    ssize_t m_limit = -1;
     unsigned int m_offset = 0;
     bool m_qmlInitializing = false;
 };
diff --git a/modules/gui/qt/util/listcache.hpp b/modules/gui/qt/util/listcache.hpp
index 3dd1f41bc773..58ccaf2e7c54 100644
--- a/modules/gui/qt/util/listcache.hpp
+++ b/modules/gui/qt/util/listcache.hpp
@@ -145,7 +145,7 @@ public:
     static constexpr ssize_t COUNT_UNINITIALIZED = -1;
 
     ListCache(std::unique_ptr<ListCacheLoader<ItemType>>&& loader,
-        bool useMove, size_t limit, size_t offset, size_t chunkSize = 100);
+        bool useMove, ssize_t limit, size_t offset, size_t chunkSize = 100);
 
     /**
      * Return the item at specified index
@@ -273,8 +273,8 @@ private:
     QSharedPointer<ListCacheLoader<ItemType>> m_loader;
     size_t m_chunkSize;
 
-    //0 limit means no limit
-    size_t m_limit = 0;
+    //negative limit means no limit
+    ssize_t m_limit = -1;
     size_t m_offset = 0;
 
     //highest index requested by the view (1 based, 0 is nothing referenced)
diff --git a/modules/gui/qt/util/listcache.hxx b/modules/gui/qt/util/listcache.hxx
index 68c069591b81..70ecaf8a981e 100644
--- a/modules/gui/qt/util/listcache.hxx
+++ b/modules/gui/qt/util/listcache.hxx
@@ -45,7 +45,7 @@ bool ListCache<T>::cacheDataCompare(const void* dataOld, uint32_t oldIndex, cons
 }
 
 template<typename T>
-ListCache<T>::ListCache(std::unique_ptr<ListCacheLoader<ListCache<T>::ItemType>>&& loader, bool useMove, size_t limit, size_t offset, size_t chunkSize)
+ListCache<T>::ListCache(std::unique_ptr<ListCacheLoader<ListCache<T>::ItemType>>&& loader, bool useMove, ssize_t limit, size_t offset, size_t chunkSize)
     : m_useMove(useMove)
     , m_loader(loader.release())
     , m_chunkSize(chunkSize)
@@ -549,8 +549,8 @@ void ListCache<T>::asyncCountAndLoad()
                 m_needReload = true;
             }
 
-            size_t queryCount = (m_limit > 0)
-                ? std::min(m_limit, maximumCount)
+            size_t queryCount = (m_limit >= 0)
+                ? std::min(static_cast<size_t>(m_limit), maximumCount)
                 : maximumCount;
 
             //note: should we drop items past queryCount?
-- 
GitLab