[vlc-commits] [Git][videolan/vlc][master] 9 commits: qt: add loaded count property in base model
Steve Lhomme (@robUx4)
gitlab at videolan.org
Tue Mar 4 08:25:10 UTC 2025
Steve Lhomme pushed to branch master at VideoLAN / VLC
Commits:
def2a480 by Prince Gupta at 2025-03-04T08:10:57+00:00
qt: add loaded count property in base model
- - - - -
cede5b60 by Prince Gupta at 2025-03-04T08:10:57+00:00
qt: fix index retrieval from out of cache in ml model
fixes artist loading with large medialibrary
- - - - -
a4b686d5 by Prince Gupta at 2025-03-04T08:10:57+00:00
qt: fix ml test with empty list
- - - - -
fb8b74bb by Prince Gupta at 2025-03-04T08:10:57+00:00
qml: fix find artist index spam on base model chunk loading
- - - - -
6f25bc0d by Prince Gupta at 2025-03-04T08:10:57+00:00
qt: fix warning and typo
- - - - -
e554856e by Prince Gupta at 2025-03-04T08:10:57+00:00
qt: fix misplaced assert
- - - - -
c27e95f2 by Prince Gupta at 2025-03-04T08:10:57+00:00
qt: fix asyncFetchMore in between partial update in list cache
- - - - -
63dea8c7 by Prince Gupta at 2025-03-04T08:10:57+00:00
qt: refactor getIndexFromId of ml model
- - - - -
bb649eb3 by Prince Gupta at 2025-03-04T08:10:57+00:00
qt: add tests for getIndexFromID of ml model
- - - - -
9 changed files:
- modules/gui/qt/medialibrary/mlbasemodel.cpp
- modules/gui/qt/medialibrary/mlbasemodel.hpp
- modules/gui/qt/medialibrary/qml/MusicArtistsAlbums.qml
- modules/gui/qt/tests/test_ml_model.cpp
- modules/gui/qt/util/base_model.cpp
- modules/gui/qt/util/base_model.hpp
- modules/gui/qt/util/base_model_p.hpp
- modules/gui/qt/util/listcache.hpp
- modules/gui/qt/util/listcache.hxx
Changes:
=====================================
modules/gui/qt/medialibrary/mlbasemodel.cpp
=====================================
@@ -98,29 +98,32 @@ public:
}
//this will load data until id is in the cache, then returns its position
- void getIndexFromIdImpl(MLItemId id, QJSValue resolve, QJSValue reject) const
+ void getIndexFromIdImpl(MLItemId id, std::function<void (std::optional<int> index)> cb) const
{
Q_Q(const MLBaseModel);
- auto jsEngine = qjsEngine(q);
int index;
MLItem* item = q->findInCache(id, &index);
+
if (item) {
- resolve.call({index});
+ cb(index);
}
else
{
+ unsigned int loaded = q->getLoadedCount();
int count = q->getCount();
int limit = q->getLimit();
//item doesn't exists
- if ((limit != 0 && count >= limit) || count == getMaximumCount())
- reject.call(); //not present
+ if ((limit != 0 && count >= limit) || loaded == getMaximumCount()) {
+ cb(std::nullopt);
+ }
else
{
//load data until we have our item in cache
- QObject::connect(q, &MLBaseModel::countChanged, q, [this, id, resolve = resolve, reject = reject](){
- getIndexFromIdImpl(id, resolve, reject);
+ QObject::connect(q, &MLBaseModel::dataChanged, q, [this, id, cb](){
+ getIndexFromIdImpl(id, cb);
}, Qt::SingleShotConnection);
+
if (m_cache)
m_cache->fetchMore();
}
@@ -280,8 +283,10 @@ Q_INVOKABLE QJSValue MLBaseModel::getDataById(MLItemId id)
m_itemLoader->loadItemByIdTask(
id,
- [this, resolve=std::move(resolve), reject=std::move(reject)](size_t taksId, MLListCache::ItemType&& item)
+ [this, resolve=std::move(resolve), reject=std::move(reject)](size_t taskId, MLListCache::ItemType&& item)
{
+ Q_UNUSED(taskId);
+
if (!item)
{
reject.call();
@@ -301,10 +306,25 @@ Q_INVOKABLE QJSValue MLBaseModel::getIndexFromId(MLItemId id)
Q_D(const MLBaseModel);
auto [p, resolve, reject] = d->makeJSPromise();
- d->getIndexFromIdImpl(id, resolve, reject);
+ auto cb = [resolve = resolve, reject = reject](std::optional<int> index)
+ {
+ if (index.has_value())
+ resolve.call({*index});
+ else
+ reject.call(); //not present
+ };
+
+ getIndexFromId2(id, cb);
return p;
}
+void MLBaseModel::getIndexFromId2(MLItemId id, std::function<void (std::optional<int>)> cb)
+{
+ Q_D(const MLBaseModel);
+
+ d->getIndexFromIdImpl(id, cb);
+}
+
QVariant MLBaseModel::data(const QModelIndex &index, int role) const
{
Q_D(const MLBaseModel);
=====================================
modules/gui/qt/medialibrary/mlbasemodel.hpp
=====================================
@@ -86,6 +86,8 @@ public:
*/
Q_INVOKABLE QJSValue getIndexFromId(MLItemId id);
+ void getIndexFromId2(MLItemId id, std::function<void(std::optional<int> index)> cb);
+
public:
// properties functions
=====================================
modules/gui/qt/medialibrary/qml/MusicArtistsAlbums.qml
=====================================
@@ -44,6 +44,8 @@ FocusScope {
property int initialAlbumIndex: 0
property var artistId: undefined
+ property var _requestedArtistId: undefined
+
//behave like a page
property var pagePrefix: []
@@ -110,12 +112,32 @@ FocusScope {
onLoadingChanged: {
if (loading)
return
- artistModel.getIndexFromId(root.artistId)
+
+ const defined = v => typeof v !== "undefined"
+
+ if ((root._requestedArtistId === root.artistId)
+ && defined(root._requestedArtistId))
+ return
+
+ root._requestedArtistId = root.artistId
+ if (!defined(root._requestedArtistId))
+ return
+
+ const thisRequestID = root._requestedArtistId
+ artistModel.getIndexFromId(root._requestedArtistId)
.then((row) => {
+ if ((root._requestedArtistId !== thisRequestID)
+ || (root._requestedArtistId !== root.artistId))
+ return
+
artistList.currentIndex = row
artistList._sidebarInitialyPositioned = true
})
.catch(() => {
+ if ((root._requestedArtistId !== thisRequestID)
+ || (root._requestedArtistId !== root.artistId))
+ return
+
artistList._sidebarInitialyPositioned = true
})
}
=====================================
modules/gui/qt/tests/test_ml_model.cpp
=====================================
@@ -83,6 +83,10 @@ protected:
std::vector<std::unique_ptr<MLItem>> load(vlc_medialibrary_t* ml, const vlc_ml_query_params_t* queryParams) const override
{
VLC_UNUSED(ml);
+
+ if (m_mlTestModel.m_items.empty())
+ return {};
+
uint32_t offset = queryParams->i_offset;
uint32_t count = queryParams->i_nbResults;
size_t maxIndex = std::min(
@@ -163,6 +167,47 @@ private slots:
m_model->appendRange(1, 1000);
QTRY_COMPARE_WITH_TIMEOUT(m_model->getCount(), 1000u, 100);
}
+
+
+ void testGetIndexFromID()
+ {
+ const int low = 1;
+ const int high = 300;
+ m_model->appendRange(low, high);
+
+ const int timeout = 1000;
+
+ // let loading complete, getIndexFromID won't work for 'loading' model
+ QVERIFY(QTest::qWaitFor([this] () { return !m_model->loading(); }, timeout));
+
+ std::optional<int> row = -1;
+ auto cb = [&row](std::optional<int> index)
+ {
+ row = index;
+ };
+
+ // bug of MR6926, here model tries to get index for data outside the initial chunk size
+ m_model->getIndexFromId2(MLItemId{high, VLC_ML_PARENT_UNKNOWN}, cb);
+
+ // NOTE: CI fails with QTRY_COMPARE_WITH_TIMEOUT
+ QVERIFY(QTest::qWaitFor([&row]() { return row != -1; }, timeout));
+ QCOMPARE(row, high - 1);
+
+ // above we must have loaded all the data, following this we should not need to wait for results
+ m_model->getIndexFromId2(MLItemId{low - 1, VLC_ML_PARENT_UNKNOWN}, cb);
+ QCOMPARE(row, std::nullopt);
+
+ m_model->getIndexFromId2(MLItemId{low, VLC_ML_PARENT_UNKNOWN}, cb);
+ QCOMPARE(row, low - 1);
+
+ m_model->getIndexFromId2(MLItemId{high + 1, VLC_ML_PARENT_UNKNOWN}, cb);
+ QCOMPARE(row, std::nullopt);
+
+ const int mid = (low + high) / 2;
+ m_model->getIndexFromId2(MLItemId{mid, VLC_ML_PARENT_UNKNOWN}, cb);
+ QCOMPARE(row, mid - 1);
+ }
+
private:
std::unique_ptr<VLCTestingEnv> m_env;
std::unique_ptr<MediaLib> m_medialib;
=====================================
modules/gui/qt/util/base_model.cpp
=====================================
@@ -196,6 +196,12 @@ unsigned int BaseModel::getCount() const
return d->getCount();
}
+unsigned int BaseModel::getLoadedCount() const
+{
+ Q_D(const BaseModel);
+ return d->getLoadedCount();
+}
+
unsigned int BaseModel::getMaximumCount() const
{
Q_D(const BaseModel);
=====================================
modules/gui/qt/util/base_model.hpp
=====================================
@@ -76,6 +76,7 @@ public:
void setOffset(unsigned int offset);
unsigned int getCount() const;
+ unsigned int getLoadedCount() const;
unsigned int getMaximumCount() const;
virtual bool loading() const;
=====================================
modules/gui/qt/util/base_model_p.hpp
=====================================
@@ -36,6 +36,8 @@ public:
virtual void resetCache() = 0;
virtual void invalidateCache() = 0;
virtual bool loading() const = 0;
+
+ virtual unsigned int getLoadedCount() const = 0;
virtual unsigned int getCount() const = 0;
virtual unsigned int getMaximumCount() const = 0;
@@ -134,6 +136,7 @@ public:
const T* item(int signedidx) const;
unsigned int getCount() const override;
+ unsigned int getLoadedCount() const override;
unsigned int getMaximumCount() const override;
virtual std::unique_ptr<ListCacheLoader<T>> createLoader() const = 0;
@@ -156,6 +159,19 @@ unsigned BaseModelPrivateT<T>::getCount() const
return static_cast<unsigned>(queryCount);
}
+template<typename T>
+unsigned BaseModelPrivateT<T>::getLoadedCount() const
+{
+ if (!m_cache)
+ return 0;
+
+ ssize_t loadedCount = m_cache->loadedCount();
+ if (loadedCount == ListCache<T>::COUNT_UNINITIALIZED)
+ return 0;
+
+ return static_cast<unsigned>(loadedCount);
+}
+
template<typename T>
unsigned BaseModelPrivateT<T>::getMaximumCount() const
{
=====================================
modules/gui/qt/util/listcache.hpp
=====================================
@@ -222,6 +222,14 @@ public:
*/
ssize_t maximumCount() const;
+ /**
+ * @return underlying list size
+ * COUNT_UNINITIALIZED is returned if the list isn't initialized
+ *
+ * This may be usefull to know loaded size
+ */
+ ssize_t loadedCount() const;
+
/**
* Init the list size
*
=====================================
modules/gui/qt/util/listcache.hxx
=====================================
@@ -390,7 +390,8 @@ void ListCache<T>::fetchMore()
return;
m_maxReferedIndex = std::min(cache->loadedCount + m_chunkSize, cache->queryCount);
- if (!m_appendTask)
+ if (!m_appendTask
+ && cache != m_oldData.get()) // data will be loaded after completing pending updates
asyncFetchMore();
}
@@ -599,10 +600,10 @@ void ListCache<T>::asyncCountAndLoad()
template<typename T>
void ListCache<T>::asyncFetchMore()
{
+ assert(m_cachedData);
if (m_maxReferedIndex <= m_cachedData->loadedCount)
return;
- assert(m_cachedData);
if (m_appendTask)
m_loader->cancelTask(m_appendTask);
@@ -635,4 +636,11 @@ void ListCache<T>::asyncFetchMore()
});
}
+
+template<typename T>
+inline ssize_t ListCache<T>::loadedCount() const
+{
+ return m_cachedData ? m_cachedData->loadedCount : COUNT_UNINITIALIZED;
+}
+
#endif /* LISTCACHE_HXX */
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/aa15eaa7d8051e1223d6eba226857d9dbcf7756f...bb649eb31fe839fd3241e02acd85edba401d69f6
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/aa15eaa7d8051e1223d6eba226857d9dbcf7756f...bb649eb31fe839fd3241e02acd85edba401d69f6
You're receiving this email because of your account on code.videolan.org.
VideoLAN code repository instance
More information about the vlc-commits
mailing list