[vlc-commits] [Git][videolan/vlc][master] 3 commits: qt: batch insert/move/remove operations on ML playlist

Steve Lhomme (@robUx4) gitlab at videolan.org
Wed Oct 2 09:58:03 UTC 2024



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
b89dc845 by Pierre Lamot at 2024-10-02T08:46:07+00:00
qt: batch insert/move/remove operations on ML playlist

- - - - -
4161e99e by Pierre Lamot at 2024-10-02T08:46:07+00:00
qt: allow inserting element in the model cache

- - - - -
1fdf9c9f by Pierre Lamot at 2024-10-02T08:46:07+00:00
qt: improve ml playlist insertion perceived reactivity

As we have the element content when inserting them in the library, so we can
insert them "a priori" in our cache and update the interface before the
medialibrary notifies us with the actual content ("a posteriori"). If assumption
was wrong, diffutil will correct it

- - - - -


5 changed files:

- modules/gui/qt/medialibrary/mlbasemodel.cpp
- modules/gui/qt/medialibrary/mlbasemodel.hpp
- modules/gui/qt/medialibrary/mlplaylistmodel.cpp
- modules/gui/qt/util/listcache.hpp
- modules/gui/qt/util/listcache.hxx


Changes:

=====================================
modules/gui/qt/medialibrary/mlbasemodel.cpp
=====================================
@@ -412,6 +412,28 @@ void MLBaseModel::deleteItemInCache(const MLItemId& mlid)
 }
 
 
+void MLBaseModel::insertItemInCache(std::unique_ptr<MLItem> mlItem, int position)
+{
+    Q_D(MLBaseModel);
+    if (!d->m_cache)
+    {
+        emit resetRequested();
+        return;
+    }
+    d->m_cache->insertItem(std::move(mlItem), position);
+}
+
+void MLBaseModel::insertItemListInCache(std::vector<std::unique_ptr<MLItem>>&& items, int position)
+{
+    Q_D(MLBaseModel);
+    if (!d->m_cache)
+    {
+        emit resetRequested();
+        return;
+    }
+    d->m_cache->insertItemList(items.begin(), items.end(), position);
+}
+
 void MLBaseModel::moveRangeInCache(int first, int last, int to)
 {
     Q_D(MLBaseModel);


=====================================
modules/gui/qt/medialibrary/mlbasemodel.hpp
=====================================
@@ -106,6 +106,12 @@ protected:
     //update and notify changes on an item if this item is in the cache
     void updateItemInCache(const MLItemId& id);
 
+    //insert item at position @p position in the cache and notify changes
+    void insertItemInCache(std::unique_ptr<MLItem> mlItem, int position);
+
+    //insert items from list @p items at position @p position in the cache and notify changes
+    void insertItemListInCache(std::vector<std::unique_ptr<MLItem>>&& items, int position);
+
     //delete and notify deletion of an item if this item is in the cache
     //this is only to reflect changes from the ML, it won't alter the database
     void deleteItemInCache(const MLItemId& mlid);


=====================================
modules/gui/qt/medialibrary/mlplaylistmodel.cpp
=====================================
@@ -59,10 +59,13 @@
 
     setTransactionPending(true);
 
-    m_mediaLib->runOnMLThread(this,
+    struct Ctx {
+        std::vector<std::unique_ptr<MLItem>> medias;
+    };
+    m_mediaLib->runOnMLThread<Ctx>(this,
     //ML thread
-    [medias, id, at](vlc_medialibrary_t* ml) {
-        int insertPos = at;
+    [medias, id, at](vlc_medialibrary_t* ml, Ctx& ctx) {
+        std::vector<int64_t> mediaIdList;
         for (const auto& media : medias)
         {
             assert(media.raw());
@@ -77,16 +80,18 @@
                 if (ml_media == nullptr)
                     continue;
             }
-
-            vlc_ml_playlist_insert(ml, id, &ml_media->i_id, 1, insertPos);
+            mediaIdList.push_back(ml_media->i_id);
+            ctx.medias.emplace_back(std::make_unique<MLPlaylistMedia>(ml_media));
             vlc_ml_media_release(ml_media);
-
-            insertPos++;
         }
+        if (mediaIdList.size() == 0)
+            return;
 
+        vlc_ml_playlist_insert(ml, id, mediaIdList.data(), mediaIdList.size(), at);
     },
     //UI thread
-    [this]() {
+    [this, at](quint64, Ctx& ctx) {
+        insertItemListInCache(std::move(ctx.medias), at);
         m_need_reset = true;
         endTransaction();
     });
@@ -109,13 +114,9 @@ void MLPlaylistModel::moveImpl(int64_t playlistId, HighLowRanges&& ranges)
         //ML thread
         [playlistId, high, low, to = ranges.lowTo]
         (vlc_medialibrary_t* ml, Ctx& ctx) {
-            int localTo = to;
-            for (int i = high; i >= low; i--)
-            {
-                vlc_ml_playlist_move(ml, playlistId, i, localTo  - 1, 1);
-                localTo--;
-            }
-            ctx.newTo = localTo;
+            int nbElement = high - low + 1;
+            vlc_ml_playlist_move(ml, playlistId, low, to - 1, nbElement);
+            ctx.newTo = to - nbElement;
         },
         //UI thread
         [this, playlistId, high, low, r = std::move(ranges)](quint64, Ctx& ctx) mutable {
@@ -133,13 +134,9 @@ void MLPlaylistModel::moveImpl(int64_t playlistId, HighLowRanges&& ranges)
         m_mediaLib->runOnMLThread<Ctx>(this,
         //ML thread
         [playlistId, high, low, to = ranges.highTo](vlc_medialibrary_t* ml, Ctx& ctx) {
-            int localTo = to;
-            for (int i = low; i <= high; i++)
-            {
-                vlc_ml_playlist_move(ml, playlistId, i, localTo, 1);
-                localTo++;
-            }
-            ctx.newTo = localTo;
+            int nbElement = high - low + 1;
+            vlc_ml_playlist_move(ml, playlistId, low, to, nbElement);
+            ctx.newTo = to + nbElement;
         },
         //UI thread
         [this, playlistId, low, high, r = std::move(ranges)](quint64, Ctx& ctx) mutable {
@@ -236,10 +233,7 @@ void MLPlaylistModel::removeImpl(int64_t playlistId, const std::vector<std::pair
     m_mediaLib->runOnMLThread(this,
     //ML thread
     [playlistId, range](vlc_medialibrary_t* ml) {
-        for (int i = range.second; i >= range.first; i--)
-        {
-            vlc_ml_playlist_remove(ml, playlistId, i, 1);
-        }
+        vlc_ml_playlist_remove(ml, playlistId, range.first, range.second - range.first + 1);
     },
     //UI thread
     [this, playlistId, range, rows = std::move(rangeList), index]() {


=====================================
modules/gui/qt/util/listcache.hpp
=====================================
@@ -170,6 +170,22 @@ public:
      */
     int updateItem(ItemType&& newItem);
 
+    /**
+     * insert an item in the cache and notify changes
+     */
+    void insertItem(ItemType&& item, int position);
+
+    /**
+     * @brief insertItemList insert items in the cache at position p position and
+     * notify changes
+     * @param first iterator to the first element to insert (list.begin)
+     * @param last iterator past the last element to insert (list.end())
+     * @param position insertion position 0 is equivalent to push_front
+     * @note items are "moved" into the cache
+     */
+    template<typename IterType>
+    void insertItemList(IterType first, IterType last, int position);
+
     /**
      * Removes from the cache list given its item id
      *


=====================================
modules/gui/qt/util/listcache.hxx
=====================================
@@ -200,6 +200,58 @@ int ListCache<T>::deleteItem(const std::function<bool (const ItemType&)>&& f)
     return pos;
 }
 
+
+template<typename T>
+void ListCache<T>::insertItem(ItemType&& item, int position)
+{
+    //we can't update an item locally while the model has pending updates
+    //no worry, we'll receive the update once the actual model notifies us
+    if (m_oldData)
+        return;
+
+    //we can't insert an item before we have any cache
+    if (unlikely(!m_cachedData))
+        return;
+
+    if (unlikely(position < 0 || position > (int)m_cachedData->list.size()))
+        return;
+
+    emit beginInsertRows(position, position);
+    m_cachedData->list.insert(m_cachedData->list.begin() + position, std::move(item));
+    m_cachedData->loadedCount++;
+    m_cachedData->maximumCount++;
+    m_cachedData->queryCount++;
+    emit endInsertRows();
+    emit localSizeChanged(m_cachedData->queryCount, m_cachedData->maximumCount);
+}
+
+template<typename T>
+template<typename IterType>
+void ListCache<T>::insertItemList(IterType first, IterType last, int position)
+{
+    //we can't update an item locally while the model has pending updates
+    //no worry, we'll receive the update once the actual model notifies us
+    if (m_oldData)
+        return;
+
+    //we can't insert an item before we have any cache
+    if (unlikely(!m_cachedData))
+        return;
+
+    if (unlikely(position < 0 || position > (int)m_cachedData->list.size()))
+        return;
+
+    size_t count = std::distance(first, last);
+    emit beginInsertRows(position, position + (int)count - 1);
+    std::move(first, last, std::inserter(m_cachedData->list, m_cachedData->list.begin() + position));
+    m_cachedData->loadedCount += count;
+    m_cachedData->maximumCount += count;
+    m_cachedData->queryCount += count;
+    emit endInsertRows();
+    emit localSizeChanged(m_cachedData->queryCount, m_cachedData->maximumCount);
+}
+
+
 template<typename T>
 void ListCache<T>::moveRange(int first, int last, int to)
 {



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/4353c2f21697463e1dd10c0feed1bdce79931266...1fdf9c9f7c7643b6b87084b170c1b68390ec27bd

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/4353c2f21697463e1dd10c0feed1bdce79931266...1fdf9c9f7c7643b6b87084b170c1b68390ec27bd
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