Browse Source

qt: allow to detect moves in MLList cache

This remains is disabled by default, The extra cost isn't really worth it as
move operations originated from the database are very rare, move operations from
the user are usually handled "a priori".
pull/134/head
Pierre Lamot 4 years ago
committed by Jean-Baptiste Kempf
parent
commit
4e67a7c03c
  1. 2
      modules/gui/qt/medialibrary/mlbasemodel.cpp
  2. 65
      modules/gui/qt/medialibrary/mllistcache.cpp
  3. 45
      modules/gui/qt/medialibrary/mllistcache.hpp

2
modules/gui/qt/medialibrary/mlbasemodel.cpp

@ -437,7 +437,7 @@ void MLBaseModel::validateCache() const
return;
auto loader = createLoader();
m_cache = std::make_unique<MLListCache>(m_mediaLib, std::move(loader));
m_cache = std::make_unique<MLListCache>(m_mediaLib, std::move(loader), false);
connect(m_cache.get(), &MLListCache::localSizeChanged,
this, &MLBaseModel::onLocalSizeChanged);

65
modules/gui/qt/medialibrary/mllistcache.cpp

@ -43,14 +43,43 @@ bool cacheDataCompare(const void* dataOld, uint32_t oldIndex, const void* dataNe
}
MLListCache::MLListCache(MediaLib* medialib, std::unique_ptr<ListCacheLoader<MLListCache::ItemType>>&& loader, size_t chunkSize)
MLListCache::MLListCache(MediaLib* medialib, std::unique_ptr<ListCacheLoader<MLListCache::ItemType>>&& loader, bool useMove, size_t chunkSize)
: m_medialib(medialib)
, m_useMove(useMove)
, m_loader(loader.release())
, m_chunkSize(chunkSize)
{
assert(medialib);
}
size_t MLListCache::fixupIndexForMove(size_t index) const
{
//theses elements have already been moved
for (const PartialIndexRedirect& hole : m_partialIndexRedirect)
{
if (hole.op == PartialIndexRedirect::Operation::DEL)
{
if (hole.index <= index)
index += hole.count;
else
break;
}
else
{
if (hole.index <= index)
{
if (index <= hole.index + hole.count - 1)
return hole.val.add.x + (index - hole.index);
else
index -= hole.count;
}
else
break;
}
}
return index;
}
const MLListCache::ItemType* MLListCache::get(size_t index) const
{
//the view may access the model while we're updating it
@ -63,7 +92,13 @@ const MLListCache::ItemType* MLListCache::get(size_t index) const
if (index >= m_partialLoadedCount)
return nullptr;
else if (index >= m_partialIndex)
return &m_oldData->list.at(index - m_partialIndex + m_partialX);
{
if (m_useMove)
{
index = fixupIndexForMove(index);
}
return &m_oldData->list.at(index + (m_partialX - m_partialIndex));
}
else
return &m_cachedData->list.at(index);
}
@ -275,9 +310,13 @@ void MLListCache::partialUpdate()
};
diffutil_snake_t* snake = vlc_diffutil_build_snake(&diffOp, &m_oldData->list, &m_cachedData->list);
int diffutilFlags = VLC_DIFFUTIL_RESULT_AGGREGATE;
if (m_useMove)
diffutilFlags |= VLC_DIFFUTIL_RESULT_MOVE;
vlc_diffutil_changelist_t* changes = vlc_diffutil_build_change_list(
snake, &diffOp, &m_oldData->list, &m_cachedData->list,
VLC_DIFFUTIL_RESULT_AGGREGATE);
diffutilFlags);
m_partialIndex = 0;
m_partialLoadedCount = m_oldData->loadedCount;
@ -311,8 +350,22 @@ void MLListCache::partialUpdate()
emit localSizeChanged(partialTotalCount);
break;
case VLC_DIFFUTIL_OP_MOVE:
emit beginMoveRows(op.op.move.from, op.op.move.from + op.count - 1, op.op.move.to);
//TODO
m_partialX = op.op.move.x;
if (op.op.move.from > op.op.move.to)
{
m_partialIndex = op.op.move.to;
emit beginMoveRows(op.op.move.from, op.op.move.from + op.count - 1, op.op.move.to);
m_partialIndexRedirect.insert(PartialIndexRedirect(PartialIndexRedirect::Operation::DEL, op.op.move.from, op.count));
m_partialIndex += op.count;
}
else
{
m_partialIndex = op.op.move.from + op.count - 1;
emit beginMoveRows(op.op.move.from, op.op.move.from + op.count - 1, op.op.move.to);
m_partialIndexRedirect.insert(PartialIndexRedirect(PartialIndexRedirect::Operation::ADD, op.op.move.to, op.count, op.op.move.x));
m_partialIndex = op.op.move.from + 1;
m_partialX += op.count;
}
emit endMoveRows();
break;
}
@ -321,6 +374,8 @@ void MLListCache::partialUpdate()
vlc_diffutil_free_snake(snake);
//ditch old model
if (m_useMove)
m_partialIndexRedirect.clear();
m_oldData.reset();
//if we have change outside our cache

45
modules/gui/qt/medialibrary/mllistcache.hpp

@ -27,6 +27,7 @@
#include <cassert>
#include <memory>
#include <vector>
#include <set>
#include <QObject>
#include <QSharedPointer>
#include "util/listcacheloader.hpp"
@ -123,7 +124,7 @@ public:
static constexpr ssize_t COUNT_UNINITIALIZED = -1;
MLListCache(MediaLib* medialib, std::unique_ptr<ListCacheLoader<ItemType>>&& loader,
size_t chunkSize = 100);
bool useMove, size_t chunkSize = 100);
/**
* Return the item at specified index
@ -212,9 +213,12 @@ private:
void asyncFetchMore();
void asyncCountAndLoad();
void partialUpdate();
size_t fixupIndexForMove(size_t index) const;
MediaLib* m_medialib = nullptr;
bool m_useMove = false;
/* Ownershipshared between this cache and the runnable spawned to execute
* loader callbacks */
QSharedPointer<ListCacheLoader<ItemType>> m_loader;
@ -251,6 +255,45 @@ private:
size_t m_partialIndex = 0;
size_t m_partialX = 0;
size_t m_partialLoadedCount = 0;
//represent a redirection of items that are after m_partialIndex
struct PartialIndexRedirect {
enum class Operation
{
ADD,
DEL
};
explicit PartialIndexRedirect(Operation op_, size_t index_, size_t count_, size_t x_ = 0)
: op(op_)
, index(index_)
, count(count_)
{
if (op == Operation::ADD)
{
val.add.x = x_;
}
}
Operation op;
union {
struct {
size_t x;
} add;
struct {
} del;
} val;
size_t index;
size_t count;
//for set ordering
friend bool operator<(const PartialIndexRedirect& l, const PartialIndexRedirect& r)
{
return l.index < r.index;
}
};
//store index redirection keeping index order
std::set<PartialIndexRedirect> m_partialIndexRedirect;
};
#endif

Loading…
Cancel
Save