Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • videolan/vlc
  • chouquette/vlc
  • bakiewicz.marek122/vlc
  • devnexen/vlc
  • rohanrajpal/vlc
  • blurrrb/vlc
  • gsoc/gsoc2019/darkapex/vlc
  • b1ue/vlc
  • fkuehne/vlc
  • magsoft/vlc
  • chub/vlc
  • cramiro9/vlc
  • robUx4/vlc
  • rom1v/vlc
  • akshayaky/vlc
  • tmk907/vlc
  • akymaster/vlc
  • govind.sharma/vlc
  • psilokos/vlc
  • xjbeta/vlc
  • jahan/vlc
  • 1480c1/vlc
  • amanchande/vlc
  • aaqib/vlc
  • rist/vlc
  • apol/vlc
  • mindfreeze/vlc
  • alexandre-janniaux/vlc
  • sandsmark/vlc
  • jagannatharjun/vlc
  • gsoc/gsoc2020/matiaslgonzalez/vlc
  • gsoc/gsoc2020/jagannatharjun/vlc
  • mstorsjo/vlc
  • gsoc/gsoc2020/vedenta/vlc
  • gsoc/gsoc2020/arnav-ishaan/vlc
  • gsoc/gsoc2020/andreduong/vlc
  • fuzun/vlc
  • gsoc/gsoc2020/vatsin/vlc
  • gsoc/gsoc2020/sagid/vlc
  • yaron/vlc
  • Phoenix/vlc
  • Garf/vlc
  • ePiratWorkarounds/vlc
  • tguillem/vlc
  • jnqnfe/vlc
  • mdc/vlc
  • Vedaa/vlc
  • rasa/vlc
  • quink/vlc
  • yealo/vlc
  • aleksey_ak/vlc
  • ePirat/vlc
  • ilya.yanok/vlc
  • asenat/vlc
  • m/vlc
  • bunjee/vlc
  • BLumia/vlc
  • sagudev/vlc
  • hamedmonji30/vlc
  • nullgemm/vlc
  • DivyamAhuja/vlc
  • thesamesam/vlc
  • dag7/vlc
  • snehil101/vlc
  • haasn/vlc
  • jbk/vlc
  • ValZapod/vlc
  • mfkl/vlc
  • WangChuan/vlc
  • core1024/vlc
  • GhostVaibhav/vlc
  • dfuhrmann/vlc
  • davide.prade/vlc
  • tmatth/vlc
  • Courmisch/vlc
  • zouya/vlc
  • hpi/vlc
  • EwoutH/vlc
  • aleung27/vlc
  • hengwu0/vlc
  • saladin/vlc
  • ashuio/vlc
  • richselwood/vlc
  • verma16Ayush/vlc
  • chemicalflash/vlc
  • PoignardAzur/vlc
  • huangjieNT/vlc
  • Blake-Haydon/vlc
  • AnuthaDev/vlc
  • gsoc/gsoc2021/mpd/vlc
  • nicolas_lequec/vlc
  • sambassaly/vlc
  • thresh/vlc
  • bonniegong/vlc
  • myaashish/vlc
  • stavros.vagionitis/vlc
  • ileoo/vlc
  • louis-santucci/vlc
  • cchristiansen/vlc
  • sabyasachi07/vlc
  • AbduAmeen/vlc
  • ashishb0410/vlc
  • urbanhusky/vlc
  • davidepietrasanta/vlc
  • riksleutelstad/vlc
  • jeremyVignelles/vlc
  • komh/vlc
  • iamjithinjohn/vlc
  • JohannesKauffmann/vlc2
  • kunglao/vlc
  • natzberg/vlc
  • jill/vlc
  • cwendling/vlc
  • adufou/vlc
  • ErwanAirone/vlc
  • HasinduDilshan10/vlc
  • vagrantc/vlc
  • rafiv/macos-bigsur-icon
  • Aymeriic/vlc
  • saranshg20/vlc
  • metzlove24/vlc
  • linkfanel/vlc
  • Ds886/vlc
  • metehan-arslan/vlc
  • Skantes/vlc
  • kgsandundananjaya96/vlc
  • mitchcapper/vlc
  • advaitgupta/vlc
  • StefanBruens/vlc
  • ratajs/vlc
  • T.M.F.B.3761/vlc
  • m222059/vlc
  • casemerrick/vlc
  • joshuaword2alt/vlc
  • sjwaddy/vlc
  • dima/vlc
  • Ybalrid/vlc
  • umxprime/vlc
  • eschmidt/vlc
  • vannieuwenhuysenmichelle/vlc
  • badcf00d/vlc
  • wesinator/vlc
  • louis/vlc
  • xqq/vlc
  • EmperorYP7/vlc
  • NicoLiam/vlc
  • loveleen/vlc
  • rofferom/vlc
  • rbultje/vlc
  • TheUnamed/vlc
  • pratiksharma341/vlc
  • Saurab17/vlc
  • purist.coder/vlc
  • Shuicheng/vlc
  • mdrrubel292/vlc
  • silverbleu00/vlc
  • metif12/vlc
  • asher-m/vlc
  • jeffk/vlc
  • Brandonbr1/vlc
  • beautyyuyanli/vlc
  • rego21/vlc
  • muyangren907/vlc
  • collectionbylawrencejason/vlc
  • evelez/vlc
  • GSMgeeth/vlc
  • Oneric/vlc
  • TJ5/vlc
  • XuanTung95/vlc
  • darrenjenny21/vlc
  • Trenly/vlc
  • RockyTDR/vlc
  • mjakubowski/vlc
  • caprica/vlc
  • ForteFrankie/vlc
  • seannamiller19/vlc
  • junlon2006/vlc
  • kiwiren6666/vlc
  • iuseiphonexs/vlc
  • fenngtun/vlc
  • Rajdutt999/vlc
  • typx/vlc
  • leon.vitanos/vlc
  • robertogarci0938/vlc
  • gsoc/gsoc2022/luc65r/vlc-mpd
  • skeller/vlc
  • MCJack123/vlc
  • luc65r/vlc-mpd
  • popov895/vlc
  • claucambra/vlc
  • brad/vlc
  • matthewmurua88/vlc
  • Tomas8874/vlc
  • philenotfound/vlc
  • makita-do3/vlc
  • LZXCorp/vlc
  • mar0x/vlc
  • senojetkennedy0102/vlc
  • shaneb243/vlc
  • ahmadbader/vlc
  • rajduttcse26/vlc-audio-filters
  • Juniorzito8415/vlc
  • achernyakov/vlc
  • lucasjetgroup/vlc
  • pupdoggy666/vlc
  • gmde9363/vlc
  • alexnwayne/vlc
  • bahareebrahimi781/vlc
  • hamad633666/vlc
  • umghof3112/vlc
  • joe0199771874/vlc
  • Octocats66666666/vlc
  • jjm_223/vlc
  • btech10110.19/vlc
  • sunnykfc028/vlc-audio-filters
  • loic/vlc
  • nguyenminhducmx1/vlc
  • JanekKrueger/vlc
  • bstubbington2/vlc
  • rcombs/vlc
  • Ordissimo/vlc
  • king7532/vlc
  • noobsauce101/vlc
  • schong0525/vlc
  • myQwil/vlc
  • apisbg91/vlc
  • geeboy0101017/vlc
  • kim.faughey/vlc
  • nurupo/vlc
  • yyusea/vlc
  • 0711235879.khco/vlc
  • ialo/vlc
  • iloveyeye2/vlc
  • gdtdftdqtd/vlc
  • leandroconsiglio/vlc
  • AndyHTML2012/vlc
  • ncz/vlc
  • lucenticus/vlc
  • knr1931/vlc
  • kjoonlee/vlc
  • chandrakant100/vlc-qt
  • johge42/vlc
  • polter/vlc
  • hexchain/vlc
  • Tushwrld/vlc
  • mztea928/vlc
  • jbelloncastro/vlc
  • alvinhochun/vlc
  • ghostpiratecrow/vlc
  • ujjwaltwitx/vlc
  • alexsonarin06/vlc
  • adrianbon76/vlc
  • altsod/vlc
  • damien.lucas44/vlc
  • dmytrivtaisa/vlc
  • utk202/vlc
  • aaxhrj/vlc
  • thomas.hermes/vlc
  • structurenewworldorder/vlc
  • slomo/vlc
  • wantlamy/vlc
  • musc.o3cminc/vlc
  • thebarshablog/vlc
  • kerrick/vlc
  • kratos142518/vlc
  • leogps/vlc
  • vacantron/vlc
  • luna_koly/vlc
  • Ratio2/vlc
  • anuoshemohammad/vlc
  • apsun/vlc
  • aaa1115910/vlc
  • alimotmoyo/vlc
  • Ambossmann/vlc
  • Sam-LearnsToCode/vlc
  • Chilledheart/vlc
  • Labnann/vlc
  • ktcoooot1/vlc
  • mohit-marathe/vlc
  • johnddx/vlc
  • manstabuk/vlc
  • Omar-ahmed314/vlc
  • vineethkm/vlc
  • 9Enemi86/vlc
  • radoslav.m.panteleev/vlc
  • ashishami2002/vlc
  • Corbax/vlc
  • firnasahmed/vlc
  • pelayarmalam4/vlc
  • c0ff330k/vlc
  • shikhindahikar/vlc
  • l342723951/vlc
  • christianschwandner/vlc
  • douniwan5788/vlc
  • 7damian7/vlc
  • ferdnyc/vlc
  • f.ales1/vlc
  • pandagby/vlc
  • BaaBaa/vlc
  • jewe37/vlc
  • w00drow/vlc
  • russelltg/vlc
  • ironicallygod/vlc
  • soumyaDghosh/vlc
  • linzihao1999/vlc
  • deyayush6/vlc
  • mibi88/vlc
  • newabdallah10/vlc
  • jhorbincolombia/vlc
  • rimvihaqueshupto/vlc
  • andrewkhon98/vlc
  • fab78/vlc
  • lapaz17/vlc
  • amanna13/vlc
  • mdakram28/vlc
  • 07jw1980/vlc
  • sohamgupta/vlc
  • Eson-Jia1/vlc
  • Sumou/vlc
  • vikram-kangotra/vlc
  • chalice191/vlc
  • olivercalder/vlc
  • aaasg4001/vlc
  • zipdox/vlc
  • kwizart/vlc
  • Dragon-S/vlc
  • jdemeule/vlc
  • gabriel_lt/vlc
  • locutusofborg/vlc
  • sammirata/vlc-librist
  • another/vlc
  • Benjamin_Loison/vlc
  • ahmedmoselhi/vlc
  • petergaal/vlc
  • huynhsontung/vlc
  • dariusmihut/vlc
  • tvermaashutosh/vlc
  • buti/vlc
  • Niram7777/vlc
  • rohan-here/vlc
  • balaji-sivasakthi/vlc
  • rlindner81/vlc
  • Kakadus/vlc
  • djain/vlc
  • ABBurmeister/vlc
  • craighuggins/vlc
  • orbea/vlc
  • maxos/vlc
  • aakarshmj/vlc
  • kblaschke/vlc
  • ankitm/vlc
  • advait-0/vlc
  • mohak2003/vlc
  • yselkowitz/vlc
  • AZM999/vlc-azm
  • andrey.turkin/vlc
  • Disha-Baghel/vlc
  • nowrep/vlc
  • Apeng/vlc
  • Choucroute_melba/vlc
  • autra/vlc
  • eclipseo/vlc
  • fhuber/vlc
  • olafhering/vlc
  • sdasda7777/vlc
  • 1div0/vlc
  • skosnits/vlc-extended-playlist-support
  • dnicolson/vlc
  • Timshel/vlc
  • octopols/vlc
  • MangalK/vlc
  • nima64/vlc
  • misawai/vlc
  • Alexander-Wilms/vlc
  • Maxime2/vlc-fork-for-visualizer
  • ww/vlc
  • jeske/vlc
  • sgross-emlix/vlc
  • morenonatural/vlc
  • freakingLovesVLC/vlc
  • borisgolovnev/vlc
  • mpromonet/vlc
  • diogo.simao-marques/vlc
  • masstock/vlc
  • pratikpatel8982/vlc
  • hugok79/vlc
  • longervision/vlc
  • abhiudaysurya/vlc
  • rishabhgarg/vlc
  • tumic/vlc
  • cart/vlc
  • shubham442/vlc
  • Aditya692005/vlc
  • sammirata/vlc4
  • syrykh/vlc
  • Vvorcun/macos-new-icon
  • AyaanshC/vlc
  • nasso/vlc
  • Quark/vlc
  • sebastinas/vlc
  • rhstone/vlc
  • talregev/vlc
  • Managor/vlc
403 results
Show changes
Commits on Source (12)
Showing
with 294 additions and 148 deletions
......@@ -883,6 +883,7 @@ libqt_plugin_la_QML = \
gui/qt/widgets/qml/MenuExt.qml \
gui/qt/widgets/qml/MenuItemExt.qml \
gui/qt/widgets/qml/MenuLabel.qml \
gui/qt/widgets/qml/MLDragItem.qml \
gui/qt/widgets/qml/NavigableCol.qml \
gui/qt/widgets/qml/NavigableRow.qml \
gui/qt/widgets/qml/PlayCover.qml \
......
......@@ -200,6 +200,41 @@ void MediaLib::reload()
m_threadPool.start(new Task(m_ml));
}
QVariantList MediaLib::mlInputItem(const MLItemId mlId)
{
QVariantList items;
// NOTE: When we have a parent it's a collection of media(s).
if (mlId.type == VLC_ML_PARENT_UNKNOWN)
{
QmlInputItem input(vlc_ml_get_input_item(m_ml, mlId.id), false);
items.append(QVariant::fromValue(input));
}
else
{
ml_unique_ptr<vlc_ml_media_list_t> list;
vlc_ml_query_params_t query;
memset(&query, 0, sizeof(vlc_ml_query_params_t));
list.reset(vlc_ml_list_media_of(m_ml, &query, mlId.type, mlId.id));
if (list == nullptr)
return {};
for (const vlc_ml_media_t & media : ml_range_iterate<vlc_ml_media_t>(list))
{
QmlInputItem input(vlc_ml_get_input_item(m_ml, media.i_id), false);
items.append(QVariant::fromValue(input));
}
}
return items;
}
vlc_medialibrary_t* MediaLib::vlcMl()
{
return vlc_ml_instance_get( m_intf );
......
......@@ -35,6 +35,8 @@
#include "qt.hpp"
#include "mlqmltypes.hpp"
#include "util/qmlinputitem.hpp"
namespace vlc {
namespace playlist {
class Media;
......@@ -66,6 +68,8 @@ public:
Q_INVOKABLE void reload();
Q_INVOKABLE QVariantList mlInputItem(MLItemId mlId);
inline bool idle() const { return m_idle; }
inline int discoveryPending() const { return m_discoveryPending; }
inline QString discoveryEntryPoint() const { return m_discoveryEntryPoint; }
......
......@@ -32,42 +32,6 @@ MLAlbumModel::MLAlbumModel(QObject *parent)
{
}
QVariant MLAlbumModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid() || index.row() < 0)
return QVariant();
const MLAlbum* ml_item = static_cast<MLAlbum *>(item(index.row()));
if ( ml_item == NULL )
return QVariant();
switch (role)
{
case ALBUM_ID :
return QVariant::fromValue( ml_item->getId() );
case ALBUM_TITLE :
return QVariant::fromValue( ml_item->getTitle() );
case ALBUM_RELEASE_YEAR :
return QVariant::fromValue( ml_item->getReleaseYear() );
case ALBUM_SHORT_SUMMARY :
return QVariant::fromValue( ml_item->getShortSummary() );
case ALBUM_COVER :
return QVariant::fromValue( ml_item->getCover() );
case ALBUM_MAIN_ARTIST :
return QVariant::fromValue( ml_item->getArtist() );
case ALBUM_NB_TRACKS :
return QVariant::fromValue( ml_item->getNbTracks() );
case ALBUM_DURATION:
return QVariant::fromValue( ml_item->getDuration() );
case ALBUM_TITLE_FIRST_SYMBOL:
return QVariant::fromValue( getFirstSymbol( ml_item->getTitle() ) );
case ALBUM_MAIN_ARTIST_FIRST_SYMBOL:
return QVariant::fromValue( getFirstSymbol( ml_item->getArtist() ) );
default:
return QVariant();
}
}
QHash<int, QByteArray> MLAlbumModel::roleNames() const
{
return {
......@@ -141,6 +105,38 @@ vlc_ml_sorting_criteria_t MLAlbumModel::roleToCriteria(int role) const
}
}
QVariant MLAlbumModel::itemRoleData(MLItem *item, const int role) const
{
auto ml_item = static_cast<MLAlbum *>(item);
assert(ml_item);
switch (role)
{
case ALBUM_ID :
return QVariant::fromValue( ml_item->getId() );
case ALBUM_TITLE :
return QVariant::fromValue( ml_item->getTitle() );
case ALBUM_RELEASE_YEAR :
return QVariant::fromValue( ml_item->getReleaseYear() );
case ALBUM_SHORT_SUMMARY :
return QVariant::fromValue( ml_item->getShortSummary() );
case ALBUM_COVER :
return QVariant::fromValue( ml_item->getCover() );
case ALBUM_MAIN_ARTIST :
return QVariant::fromValue( ml_item->getArtist() );
case ALBUM_NB_TRACKS :
return QVariant::fromValue( ml_item->getNbTracks() );
case ALBUM_DURATION:
return QVariant::fromValue( ml_item->getDuration() );
case ALBUM_TITLE_FIRST_SYMBOL:
return QVariant::fromValue( getFirstSymbol( ml_item->getTitle() ) );
case ALBUM_MAIN_ARTIST_FIRST_SYMBOL:
return QVariant::fromValue( getFirstSymbol( ml_item->getArtist() ) );
default:
return QVariant();
}
}
ListCacheLoader<std::unique_ptr<MLItem>> *
MLAlbumModel::createLoader() const
{
......
......@@ -53,10 +53,11 @@ public:
explicit MLAlbumModel(QObject *parent = nullptr);
virtual ~MLAlbumModel() = default;
Q_INVOKABLE QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
Q_INVOKABLE QHash<int, QByteArray> roleNames() const override;
protected:
QVariant itemRoleData(MLItem *item, int role) const override;
ListCacheLoader<std::unique_ptr<MLItem>> *createLoader() const override;
private:
......
......@@ -33,14 +33,10 @@ MLAlbumTrackModel::MLAlbumTrackModel(QObject *parent)
{
}
QVariant MLAlbumTrackModel::data(const QModelIndex &index, int role) const
QVariant MLAlbumTrackModel::itemRoleData(MLItem *item, const int role) const
{
if (!index.isValid() || index.row() < 0)
return QVariant();
const MLAlbumTrack* ml_track = static_cast<MLAlbumTrack *>(item(index.row()));
if ( !ml_track )
return QVariant();
const MLAlbumTrack* ml_track = static_cast<MLAlbumTrack *>(item);
assert( ml_track );
switch (role)
{
......
......@@ -53,10 +53,11 @@ public:
virtual ~MLAlbumTrackModel() = default;
QVariant data(const QModelIndex &index, int role) const override;
QHash<int, QByteArray> roleNames() const override;
protected:
QVariant itemRoleData(MLItem *item, int role) const override;
ListCacheLoader<std::unique_ptr<MLItem>> *createLoader() const override;
private:
......
......@@ -27,14 +27,10 @@ MLArtistModel::MLArtistModel(QObject *parent)
{
}
QVariant MLArtistModel::data(const QModelIndex &index, int role) const
QVariant MLArtistModel::itemRoleData(MLItem *item, const int role) const
{
if (!index.isValid() || index.row() < 0)
return QVariant();
const MLArtist* ml_artist = static_cast<MLArtist *>(item(index.row()));
if ( !ml_artist )
return QVariant();
const MLArtist* ml_artist = static_cast<MLArtist *>(item);
assert( ml_artist );
switch (role)
{
......
......@@ -45,10 +45,11 @@ public:
explicit MLArtistModel(QObject *parent = nullptr);
virtual ~MLArtistModel() = default;
QVariant data(const QModelIndex &index, int role) const override;
QHash<int, QByteArray> roleNames() const override;
protected:
QVariant itemRoleData(MLItem *item, int role) const override;
ListCacheLoader<std::unique_ptr<MLItem>> *createLoader() const override;
private:
......
......@@ -27,6 +27,64 @@
#include "mlbasemodel.hpp"
#include "mlhelper.hpp"
#include "util/asynctask.hpp"
class BulkTaskLoader : public AsyncTask<std::vector<std::unique_ptr<MLItem>>>
{
public:
BulkTaskLoader(QSharedPointer<ListCacheLoader<std::unique_ptr<MLItem>>> loader, QVector<int> indexes)
: m_loader(loader)
, m_indexes {indexes}
{
}
std::vector<std::unique_ptr<MLItem>> execute() override
{
if (m_indexes.isEmpty())
return {};
auto sortedIndexes = m_indexes;
std::sort(sortedIndexes.begin(), sortedIndexes.end());
struct Range
{
int low, high; // [low, high] (all inclusive)
};
QVector<Range> ranges;
ranges.push_back(Range {sortedIndexes[0], sortedIndexes[0]});
const int MAX_DIFFERENCE = 4;
for (const auto index : sortedIndexes)
{
if ((index - ranges.back().high) < MAX_DIFFERENCE)
ranges.back().high = index;
else
ranges.push_back(Range {index, index});
}
std::vector<std::unique_ptr<MLItem>> r(m_indexes.size());
for (const auto range : ranges)
{
auto data = m_loader->load(range.low, range.high - range.low + 1);
for (int i = 0; i < m_indexes.size(); ++i)
{
const auto targetIndex = m_indexes[i];
if (targetIndex >= range.low && targetIndex <= range.high)
{
r.at(i) = std::move(data.at(targetIndex - range.low));
}
}
}
return r;
}
private:
QSharedPointer<ListCacheLoader<std::unique_ptr<MLItem>>> m_loader;
QVector<int> m_indexes;
};
static constexpr ssize_t COUNT_UNINITIALIZED =
ListCache<std::unique_ptr<MLItem>>::COUNT_UNINITIALIZED;
......@@ -73,6 +131,81 @@ void MLBaseModel::sortByColumn(QByteArray name, Qt::SortOrder order)
return getDataAt(index(idx));
}
void MLBaseModel::getData(const QModelIndexList &indexes, QJSValue callback)
{
if (!callback.isCallable()) // invalid argument
return;
QVector<int> indx;
std::transform(indexes.begin(), indexes.end(), std::back_inserter(indx), [](const auto &index)
{
return index.row();
});
TaskHandle<BulkTaskLoader> loader(new BulkTaskLoader(QSharedPointer<ListCacheLoader<std::unique_ptr<MLItem>>>(createLoader()), indx));
connect(loader.get(), &BaseAsyncTask::result, this, [this, callback, indx]() mutable
{
auto loader = (BulkTaskLoader *)sender();
auto freeSender = [this, &loader]()
{
m_externalLoaders.erase(std::find_if(std::begin(m_externalLoaders), std::end(m_externalLoaders), [&](auto &v)
{
if (v.get() != loader)
return false;
v.release();
loader->deleteLater();
loader = nullptr;
return true;
}));
assert(!loader);
};
auto jsEngine = qjsEngine(this);
if (!jsEngine)
{
freeSender();
return;
}
const auto loadedItems = loader->takeResult();
assert((int)loadedItems.size() == indx.size());
const QHash<int, QByteArray> roles = roleNames();
auto jsArray = jsEngine->newArray(loadedItems.size());
for (size_t i = 0; i < loadedItems.size(); ++i)
{
const auto &item = loadedItems[i];
QMap<QString, QVariant> dataDict;
for (int role: roles.keys())
{
if (item) // item may fail to load
dataDict[roles[role]] = itemRoleData(item.get(), role);
}
jsArray.setProperty(i, qjsEngine(this)->toScriptValue(dataDict));
}
callback.call({jsArray});
freeSender();
});
loader->start(*QThreadPool::globalInstance());
m_externalLoaders.push_back(std::move(loader));
}
QVariant MLBaseModel::data(const QModelIndex &index, int role) const
{
const auto mlItem = item(index.row());
if (mlItem)
return itemRoleData(mlItem, role);
return {};
}
//-------------------------------------------------------------------------------------------------
void MLBaseModel::onResetRequested()
......@@ -124,21 +257,12 @@ void MLBaseModel::onVlcMlEvent(const MLEvent &event)
if (stotal == COUNT_UNINITIALIZED)
break;
size_t total = static_cast<size_t>(stotal);
for (size_t i = 0; i < total; ++i)
{
const std::unique_ptr<MLItem> *item = m_cache->get(i);
if (!item)
/* Only consider items available locally in cache */
break;
MLItem *localItem = item->get();
if (localItem->getId().id == event.media_thumbnail_generated.i_media_id)
{
thumbnailUpdated(i);
break;
}
}
int index = 0;
/* Only consider items available locally in cache */
const auto item = findInCache(event.media_thumbnail_generated.i_media_id, &index);
if (item)
thumbnailUpdated(index);
}
break;
}
......@@ -447,6 +571,16 @@ MLItem *MLBaseModel::itemCache(int signedidx) const
return item->get();
}
MLItem *MLBaseModel::findInCache(const int id, int *index) const
{
const auto item = m_cache->find([id](const auto &item)
{
return item->getId().id == id;
}, index);
return item ? item->get() : nullptr;
}
//-------------------------------------------------------------------------------------------------
MLBaseModel::BaseLoader::BaseLoader(vlc_medialibrary_t *ml, MLItemId parent, QString searchPattern,
......
......@@ -34,6 +34,7 @@
#include <memory>
#include "mlevent.hpp"
#include "mlqueryparams.hpp"
#include "util/asynctask.hpp"
#include "util/listcacheloader.hpp"
template <typename T>
......@@ -41,6 +42,8 @@ class ListCache;
class MediaLib;
class BulkTaskLoader;
class MLBaseModel : public QAbstractListModel
{
Q_OBJECT
......@@ -77,6 +80,12 @@ public: // Interface
Q_INVOKABLE QMap<QString, QVariant> getDataAt(const QModelIndex & index);
Q_INVOKABLE QMap<QString, QVariant> getDataAt(int idx);
Q_INVOKABLE void getData(const QModelIndexList &indexes, QJSValue callback);
QVariant data(const QModelIndex &index, int role) const override final;
virtual QVariant itemRoleData(MLItem *item, int role) const = 0;
signals:
void parentIdChanged();
void resetRequested();
......@@ -113,6 +122,8 @@ protected:
// NOTE: This is faster because it only returns items available in cache.
MLItem *itemCache(int signedidx) const;
MLItem *findInCache(int id, int *index = nullptr) const;
virtual void onVlcMlEvent( const MLEvent &event );
virtual ListCacheLoader<std::unique_ptr<MLItem>> *createLoader() const = 0;
......@@ -170,6 +181,7 @@ protected:
bool m_need_reset = false;
mutable std::unique_ptr<ListCache<std::unique_ptr<MLItem>>> m_cache;
std::vector<TaskHandle<BulkTaskLoader>> m_externalLoaders;
};
#endif // MLBASEMODEL_HPP
......@@ -47,14 +47,9 @@ MLGenreModel::MLGenreModel(QObject *parent)
{
}
QVariant MLGenreModel::data(const QModelIndex &index, int role) const
QVariant MLGenreModel::itemRoleData(MLItem *item, const int role) const
{
int row = index.row();
if (!index.isValid() || row < 0)
return QVariant();
MLGenre* ml_genre = static_cast<MLGenre *>(item(row));
MLGenre* ml_genre = static_cast<MLGenre *>(item);
if (!ml_genre)
return QVariant();
......@@ -170,27 +165,24 @@ void MLGenreModel::onCover()
const int mlId = generator->getId().id;
const int count = getCount();
for (int i = 0; i < count; ++i)
{
const auto item = itemCache(i);
if (item && (item->getId().id == mlId))
{
MLGenre * genre = static_cast<MLGenre *> (item);
genre->setCover(generator->takeResult());
genre->setGenerator(nullptr);
int itemIndex = 0;
vlc_ml_media_set_genre_thumbnail(ml()->vlcMl(), item->getId().id
, qtu(genre->getCover()), VLC_ML_THUMBNAIL_SMALL);
auto genre = static_cast<MLGenre *>(findInCache(mlId, &itemIndex));
thumbnailUpdated(i);
return;
}
if (!genre)
{
// item is not in the cache anymore
generator->deleteLater();
return;
}
// item is not in the cache anymore
generator->deleteLater();
genre->setCover(generator->takeResult());
genre->setGenerator(nullptr);
vlc_ml_media_set_genre_thumbnail(ml()->vlcMl(), mlId
, qtu(genre->getCover()), VLC_ML_THUMBNAIL_SMALL);
thumbnailUpdated(itemIndex);
}
//-------------------------------------------------------------------------------------------------
......
......@@ -49,9 +49,10 @@ public:
virtual ~MLGenreModel() = default;
QHash<int, QByteArray> roleNames() const override;
QVariant data(const QModelIndex &index, int role) const override;
protected:
QVariant itemRoleData(MLItem *item, int role) const override;
ListCacheLoader<std::unique_ptr<MLItem>> *createLoader() const override;
private:
......
......@@ -91,12 +91,8 @@ QHash<int, QByteArray> MLGroupListModel::roleNames() const /* override */
};
}
QVariant MLGroupListModel::data(const QModelIndex & index, int role) const /* override */
QVariant MLGroupListModel::itemRoleData(MLItem *item, const int role) const /* override */
{
int row = index.row();
MLItem * item = this->item(row);
if (item == nullptr)
return QVariant();
......@@ -108,17 +104,14 @@ QVariant MLGroupListModel::data(const QModelIndex & index, int role) const /* ov
{
// NOTE: This is the condition for QWidget view(s).
case Qt::DisplayRole:
if (index.column() == 0)
return QVariant::fromValue(group->getName());
else
return QVariant();
return QVariant::fromValue(group->getName());
// NOTE: These are the conditions for QML view(s).
case GROUP_ID:
return QVariant::fromValue(group->getId());
case GROUP_NAME:
return QVariant::fromValue(group->getName());
case GROUP_THUMBNAIL:
return getCover(group, row);
return getCover(group);
case GROUP_DURATION:
return QVariant::fromValue(group->getDuration());
case GROUP_DATE:
......@@ -135,13 +128,8 @@ QVariant MLGroupListModel::data(const QModelIndex & index, int role) const /* ov
switch (role)
{
// NOTE: This is the condition for QWidget view(s).
case Qt::DisplayRole:
if (index.column() == 0)
return QVariant::fromValue(video->getTitle());
else
return QVariant();
// NOTE: These are the conditions for QML view(s).
return QVariant::fromValue(video->getTitle());
case GROUP_ID:
return QVariant::fromValue(video->getId());
case GROUP_NAME:
......@@ -222,7 +210,7 @@ ListCacheLoader<std::unique_ptr<MLItem>> * MLGroupListModel::createLoader() cons
// Private functions
//-------------------------------------------------------------------------------------------------
QString MLGroupListModel::getCover(MLGroup * group, int index) const
QString MLGroupListModel::getCover(MLGroup * group) const
{
QString cover = group->getCover();
......@@ -230,7 +218,7 @@ QString MLGroupListModel::getCover(MLGroup * group, int index) const
if (cover.isNull() == false || group->hasGenerator())
return cover;
CoverGenerator * generator = new CoverGenerator(m_ml, group->getId(), index);
CoverGenerator * generator = new CoverGenerator(m_ml, group->getId());
generator->setSize(QSize(MLGROUPLISTMODEL_COVER_WIDTH,
MLGROUPLISTMODEL_COVER_HEIGHT));
......@@ -290,16 +278,15 @@ void MLGroupListModel::onCover()
{
CoverGenerator * generator = static_cast<CoverGenerator *> (sender());
int index = generator->getIndex();
int index = 0;
// NOTE: We want to avoid calling 'MLBaseModel::item' for performance issues.
MLItem * item = this->itemCache(index);
MLItem * item = this->findInCache(generator->getId().id, &index);
// NOTE: When the item is no longer cached or has been moved we return right away.
if (item == nullptr || item->getId() != generator->getId())
if (!item)
{
generator->deleteLater();
return;
}
......
......@@ -63,9 +63,9 @@ public:
public: // QAbstractItemModel implementation
QHash<int, QByteArray> roleNames() const override;
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override;
protected: // MLBaseModel implementation
QVariant itemRoleData(MLItem *item, int role = Qt::DisplayRole) const override;
vlc_ml_sorting_criteria_t roleToCriteria(int role) const override;
vlc_ml_sorting_criteria_t nameToCriteria(QByteArray name) const override;
......@@ -75,7 +75,7 @@ protected: // MLBaseModel implementation
ListCacheLoader<std::unique_ptr<MLItem>> * createLoader() const override;
private: // Functions
QString getCover(MLGroup * group, int index) const;
QString getCover(MLGroup * group) const;
private: // MLBaseModel implementation
void onVlcMlEvent(const MLEvent & event) override;
......
......@@ -173,12 +173,9 @@ QHash<int, QByteArray> MLPlaylistListModel::roleNames() const /* override */
};
}
QVariant MLPlaylistListModel::data(const QModelIndex & index, int role) const /* override */
QVariant MLPlaylistListModel::itemRoleData(MLItem *item, int role) const /* override */
{
int row = index.row();
MLPlaylist * playlist = static_cast<MLPlaylist *>(item(row));
MLPlaylist * playlist = static_cast<MLPlaylist *>(item);
if (playlist == nullptr)
return QVariant();
......@@ -186,17 +183,14 @@ QVariant MLPlaylistListModel::data(const QModelIndex & index, int role) const /*
{
// NOTE: This is the condition for QWidget view(s).
case Qt::DisplayRole:
if (index.column() == 0)
return playlist->getName();
else
return QVariant();
return playlist->getName();
// NOTE: These are the conditions for QML view(s).
case PLAYLIST_ID:
return QVariant::fromValue(playlist->getId());
case PLAYLIST_NAME:
return playlist->getName();
case PLAYLIST_THUMBNAIL:
return getCover(playlist, row);
return getCover(playlist);
case PLAYLIST_DURATION:
return QVariant::fromValue(playlist->getDuration());
case PLAYLIST_COUNT:
......@@ -243,7 +237,7 @@ ListCacheLoader<std::unique_ptr<MLItem>> * MLPlaylistListModel::createLoader() c
// Private functions
//-------------------------------------------------------------------------------------------------
QString MLPlaylistListModel::getCover(MLPlaylist * playlist, int index) const
QString MLPlaylistListModel::getCover(MLPlaylist * playlist) const
{
QString cover = playlist->getCover();
......@@ -251,7 +245,7 @@ QString MLPlaylistListModel::getCover(MLPlaylist * playlist, int index) const
if (cover.isNull() == false || playlist->hasGenerator())
return cover;
CoverGenerator * generator = new CoverGenerator(m_ml, playlist->getId(), index);
CoverGenerator * generator = new CoverGenerator(m_ml, playlist->getId());
generator->setSize(m_coverSize);
......@@ -310,18 +304,17 @@ void MLPlaylistListModel::thumbnailUpdated(int idx) /* override */
void MLPlaylistListModel::onCover()
{
CoverGenerator * generator = static_cast<CoverGenerator *> (sender());
CoverGenerator * generator = static_cast<CoverGenerator *>(sender());
int index = generator->getIndex();
int index = 0;
// NOTE: We want to avoid calling 'MLBaseModel::item' for performance issues.
MLItem * item = this->itemCache(index);
MLItem * item = this->findInCache(generator->getId().id, &index);
// NOTE: When the item is no longer cached or has been moved we return right away.
if (item == nullptr || item->getId() != generator->getId())
if (!item)
{
generator->deleteLater();
return;
}
......
......@@ -64,19 +64,19 @@ public: // Interface
public: // QAbstractItemModel implementation
QHash<int, QByteArray> roleNames() const override;
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override;
public: // QAbstractItemModel reimplementation
QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const override;
protected: // MLBaseModel implementation
QVariant itemRoleData(MLItem* item, int role = Qt::DisplayRole) const override;
vlc_ml_sorting_criteria_t roleToCriteria(int role) const override;
ListCacheLoader<std::unique_ptr<MLItem>> * createLoader() const override;
private: // Functions
QString getCover(MLPlaylist * playlist, int index) const;
QString getCover(MLPlaylist * playlist) const;
private: // MLBaseModel implementation
void onVlcMlEvent(const MLEvent & event) override;
......
......@@ -189,10 +189,9 @@ QHash<int, QByteArray> MLPlaylistModel::roleNames() const /* override */
};
}
QVariant MLPlaylistModel::data(const QModelIndex & index, int role) const /* override */
QVariant MLPlaylistModel::itemRoleData(MLItem *item, int role) const /* override */
{
MLPlaylistMedia * media = static_cast<MLPlaylistMedia *>(item(index.row()));
MLPlaylistMedia * media = static_cast<MLPlaylistMedia *>(item);
if (media == nullptr)
return QVariant();
......
......@@ -58,9 +58,9 @@ public: // Interface
public: // QAbstractItemModel implementation
QHash<int, QByteArray> roleNames() const override;
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override;
protected: // MLBaseModel implementation
QVariant itemRoleData(MLItem *item, int role = Qt::DisplayRole) const override;
protected: // MLBaseModel implementation
vlc_ml_sorting_criteria_t roleToCriteria(int role) const override;
vlc_ml_sorting_criteria_t nameToCriteria(QByteArray name) const override;
......
......@@ -38,12 +38,9 @@ MLRecentsModel::MLRecentsModel( QObject* parent )
{
}
QVariant MLRecentsModel::data( const QModelIndex& index , int role ) const
QVariant MLRecentsModel::itemRoleData(MLItem *item , int role ) const
{
if (!index.isValid() || index.row() < 0)
return QVariant();
const MLRecentMedia* media = static_cast<MLRecentMedia *>(item(index.row()));
const MLRecentMedia* media = static_cast<MLRecentMedia *>(item);
if ( !media )
return QVariant();
......