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 (9)
Showing
with 507 additions and 225 deletions
...@@ -251,6 +251,9 @@ typedef struct vlc_ml_playlist_t ...@@ -251,6 +251,9 @@ typedef struct vlc_ml_playlist_t
char* psz_artwork_mrl; char* psz_artwork_mrl;
unsigned int i_nb_media;
unsigned int i_nb_present_media;
uint32_t i_creation_date; uint32_t i_creation_date;
bool b_is_read_only; bool b_is_read_only;
......
...@@ -163,6 +163,8 @@ libqt_plugin_la_SOURCES = \ ...@@ -163,6 +163,8 @@ libqt_plugin_la_SOURCES = \
gui/qt/medialibrary/mlgrouplistmodel.hpp \ gui/qt/medialibrary/mlgrouplistmodel.hpp \
gui/qt/medialibrary/mlhelper.cpp \ gui/qt/medialibrary/mlhelper.cpp \
gui/qt/medialibrary/mlhelper.hpp \ gui/qt/medialibrary/mlhelper.hpp \
gui/qt/medialibrary/mlitemcover.cpp \
gui/qt/medialibrary/mlitemcover.hpp \
gui/qt/medialibrary/mlqmltypes.hpp \ gui/qt/medialibrary/mlqmltypes.hpp \
gui/qt/medialibrary/mlqueryparams.cpp \ gui/qt/medialibrary/mlqueryparams.cpp \
gui/qt/medialibrary/mlqueryparams.hpp \ gui/qt/medialibrary/mlqueryparams.hpp \
...@@ -353,7 +355,6 @@ nodist_libqt_plugin_la_SOURCES = \ ...@@ -353,7 +355,6 @@ nodist_libqt_plugin_la_SOURCES = \
gui/qt/medialibrary/mlurlmodel.moc.cpp \ gui/qt/medialibrary/mlurlmodel.moc.cpp \
gui/qt/medialibrary/mlvideo.moc.cpp \ gui/qt/medialibrary/mlvideo.moc.cpp \
gui/qt/medialibrary/mlvideomodel.moc.cpp \ gui/qt/medialibrary/mlvideomodel.moc.cpp \
gui/qt/medialibrary/mlplaylist.moc.cpp \
gui/qt/medialibrary/mlplaylistlistmodel.moc.cpp \ gui/qt/medialibrary/mlplaylistlistmodel.moc.cpp \
gui/qt/medialibrary/mlplaylistmodel.moc.cpp \ gui/qt/medialibrary/mlplaylistmodel.moc.cpp \
gui/qt/menus/custom_menus.moc.cpp \ gui/qt/menus/custom_menus.moc.cpp \
......
...@@ -199,7 +199,6 @@ void MainUI::registerQMLTypes() ...@@ -199,7 +199,6 @@ void MainUI::registerQMLTypes()
registerAnonymousType<MLAlbum>("org.videolan.medialib", 1); registerAnonymousType<MLAlbum>("org.videolan.medialib", 1);
registerAnonymousType<MLArtist>("org.videolan.medialib", 1); registerAnonymousType<MLArtist>("org.videolan.medialib", 1);
registerAnonymousType<MLAlbumTrack>("org.videolan.medialib", 1); registerAnonymousType<MLAlbumTrack>("org.videolan.medialib", 1);
registerAnonymousType<MLPlaylist>("org.videolan.medialib", 1);
qmlRegisterType<AlbumContextMenu>( "org.videolan.medialib", 0, 1, "AlbumContextMenu" ); qmlRegisterType<AlbumContextMenu>( "org.videolan.medialib", 0, 1, "AlbumContextMenu" );
qmlRegisterType<ArtistContextMenu>( "org.videolan.medialib", 0, 1, "ArtistContextMenu" ); qmlRegisterType<ArtistContextMenu>( "org.videolan.medialib", 0, 1, "ArtistContextMenu" );
......
...@@ -19,9 +19,8 @@ ...@@ -19,9 +19,8 @@
#include "mlgenre.hpp" #include "mlgenre.hpp"
MLGenre::MLGenre(vlc_medialibrary_t* ml, const vlc_ml_genre_t *_data ) MLGenre::MLGenre(vlc_medialibrary_t* ml, const vlc_ml_genre_t *_data )
: MLItem ( MLItemId( _data->i_id, VLC_ML_PARENT_GENRE ) ) : MLItemCover( MLItemId( _data->i_id, VLC_ML_PARENT_GENRE ) )
, m_ml ( ml ) , m_ml ( ml )
, m_generator( nullptr )
, m_name ( QString::fromUtf8( _data->psz_name ) ) , m_name ( QString::fromUtf8( _data->psz_name ) )
, m_nbTracks ( (unsigned int)_data->i_nb_tracks ) , m_nbTracks ( (unsigned int)_data->i_nb_tracks )
...@@ -29,16 +28,6 @@ MLGenre::MLGenre(vlc_medialibrary_t* ml, const vlc_ml_genre_t *_data ) ...@@ -29,16 +28,6 @@ MLGenre::MLGenre(vlc_medialibrary_t* ml, const vlc_ml_genre_t *_data )
assert(_data); assert(_data);
} }
bool MLGenre::hasGenerator() const
{
return m_generator.get();
}
void MLGenre::setGenerator(CoverGenerator * generator)
{
m_generator.reset(generator);
}
QString MLGenre::getName() const QString MLGenre::getName() const
{ {
return m_name; return m_name;
...@@ -48,14 +37,3 @@ unsigned int MLGenre::getNbTracks() const ...@@ -48,14 +37,3 @@ unsigned int MLGenre::getNbTracks() const
{ {
return m_nbTracks; return m_nbTracks;
} }
QString MLGenre::getCover() const
{
return m_cover;
}
void MLGenre::setCover(const QString & fileName)
{
m_cover = fileName;
}
...@@ -23,36 +23,22 @@ ...@@ -23,36 +23,22 @@
#include "config.h" #include "config.h"
#endif #endif
// Util includes
#include "util/covergenerator.hpp"
// MediaLibrary includes // MediaLibrary includes
#include "mlqmltypes.hpp" #include "mlitemcover.hpp"
class MLGenre : public MLItem class MLGenre : public MLItemCover
{ {
public: public:
MLGenre( vlc_medialibrary_t* _ml, const vlc_ml_genre_t *_data ); MLGenre(vlc_medialibrary_t * _ml, const vlc_ml_genre_t * _data);
bool hasGenerator() const;
void setGenerator(CoverGenerator * generator);
QString getName() const; QString getName() const;
unsigned int getNbTracks() const;
QString getCover() const; unsigned int getNbTracks() const;
void setCover(const QString & fileName);
private slots:
void generateThumbnail();
private: private:
vlc_medialibrary_t* m_ml; vlc_medialibrary_t * m_ml;
TaskHandle<CoverGenerator> m_generator;
QString m_name; QString m_name;
QString m_cover;
unsigned int m_nbTracks; unsigned int m_nbTracks;
}; };
......
...@@ -28,9 +28,8 @@ ...@@ -28,9 +28,8 @@
//------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------
MLGroup::MLGroup(vlc_medialibrary_t * ml, const vlc_ml_group_t * data) MLGroup::MLGroup(vlc_medialibrary_t * ml, const vlc_ml_group_t * data)
: MLItem(MLItemId(data->i_id, VLC_ML_PARENT_GROUP)) : MLItemCover(MLItemId(data->i_id, VLC_ML_PARENT_GROUP))
, m_ml(ml) , m_ml(ml)
, m_generator(nullptr)
, m_name(qfu(data->psz_name)) , m_name(qfu(data->psz_name))
, m_duration(data->i_duration) , m_duration(data->i_duration)
, m_date(data->i_creation_date) , m_date(data->i_creation_date)
...@@ -43,18 +42,6 @@ MLGroup::MLGroup(vlc_medialibrary_t * ml, const vlc_ml_group_t * data) ...@@ -43,18 +42,6 @@ MLGroup::MLGroup(vlc_medialibrary_t * ml, const vlc_ml_group_t * data)
// Interface // Interface
//------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------
bool MLGroup::hasGenerator() const
{
return m_generator.get();
}
void MLGroup::setGenerator(CoverGenerator * generator)
{
m_generator.reset(generator);
}
//-------------------------------------------------------------------------------------------------
QString MLGroup::getName() const QString MLGroup::getName() const
{ {
return m_name; return m_name;
...@@ -62,18 +49,6 @@ QString MLGroup::getName() const ...@@ -62,18 +49,6 @@ QString MLGroup::getName() const
//------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------
QString MLGroup::getCover() const
{
return m_cover;
}
void MLGroup::setCover(const QString & fileName)
{
m_cover = fileName;
}
//-------------------------------------------------------------------------------------------------
int64_t MLGroup::getDuration() const int64_t MLGroup::getDuration() const
{ {
return m_duration; return m_duration;
......
...@@ -25,26 +25,17 @@ ...@@ -25,26 +25,17 @@
#include "config.h" #include "config.h"
#endif #endif
// Util includes
#include "util/covergenerator.hpp"
// MediaLibrary includes // MediaLibrary includes
#include "mlqmltypes.hpp" #include "mlitemcover.hpp"
class MLGroup : public MLItem class MLGroup : public MLItemCover
{ {
public: public:
MLGroup(vlc_medialibrary_t * ml, const vlc_ml_group_t * data); MLGroup(vlc_medialibrary_t * ml, const vlc_ml_group_t * data);
public: // Interface public: // Interface
bool hasGenerator() const;
void setGenerator(CoverGenerator * generator);
QString getName() const; QString getName() const;
QString getCover() const;
void setCover(const QString & fileName);
int64_t getDuration() const; int64_t getDuration() const;
unsigned int getDate() const; unsigned int getDate() const;
...@@ -54,12 +45,8 @@ public: // Interface ...@@ -54,12 +45,8 @@ public: // Interface
private: private:
vlc_medialibrary_t * m_ml; vlc_medialibrary_t * m_ml;
TaskHandle<CoverGenerator> m_generator;
QString m_name; QString m_name;
QString m_cover;
int64_t m_duration; int64_t m_duration;
unsigned int m_date; unsigned int m_date;
......
/*****************************************************************************
* Copyright (C) 2021 VLC authors and VideoLAN
*
* Authors: Benjamin Arnaud <bunjee@omega.gg>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* ( at your option ) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include "mlitemcover.hpp"
//-------------------------------------------------------------------------------------------------
// Ctor / dtor
//-------------------------------------------------------------------------------------------------
MLItemCover::MLItemCover(const MLItemId & id)
: MLItem(id)
, m_generator(nullptr) {}
//-------------------------------------------------------------------------------------------------
// Interface
//-------------------------------------------------------------------------------------------------
bool MLItemCover::hasGenerator() const
{
return m_generator.get();
}
void MLItemCover::setGenerator(CoverGenerator * generator)
{
m_generator.reset(generator);
}
//-------------------------------------------------------------------------------------------------
QString MLItemCover::getCover() const
{
return m_cover;
}
void MLItemCover::setCover(const QString & fileName)
{
m_cover = fileName;
}
/*****************************************************************************
* Copyright (C) 2021 VLC authors and VideoLAN
*
* Authors: Benjamin Arnaud <bunjee@omega.gg>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* ( at your option ) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifndef MLITEMCOVER_HPP
#define MLITEMCOVER_HPP
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
// Util includes
#include "util/covergenerator.hpp"
// MediaLibrary includes
#include "mlqmltypes.hpp"
class MLItemCover : public MLItem
{
public:
/* explicit */ MLItemCover(const MLItemId & id);
public: // Interface
bool hasGenerator() const;
void setGenerator(CoverGenerator * generator);
QString getCover() const;
void setCover(const QString & fileName);
private:
TaskHandle<CoverGenerator> m_generator;
QString m_cover;
};
#endif
...@@ -25,19 +25,14 @@ ...@@ -25,19 +25,14 @@
// Ctor / dtor // Ctor / dtor
//------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------
MLPlaylist::MLPlaylist(vlc_medialibrary_t * ml, const vlc_ml_playlist_t * data, QObject * parent) MLPlaylist::MLPlaylist(vlc_medialibrary_t * ml, const vlc_ml_playlist_t * data)
: QObject(parent) : MLItemCover(MLItemId(data->i_id, VLC_ML_PARENT_PLAYLIST))
, MLItem(MLItemId(data->i_id, VLC_ML_PARENT_PLAYLIST))
, m_ml(ml) , m_ml(ml)
, m_name(qfu(data->psz_name))
, m_duration(0) // TODO m_duration
, m_count(data->i_nb_media)
{ {
assert(data); assert(data);
m_name = qfu(data->psz_name);
// TODO m_cover
// TODO m_count
m_count = 0;//data->i_nb_tracks;
} }
//------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------
...@@ -49,9 +44,11 @@ QString MLPlaylist::getName() const ...@@ -49,9 +44,11 @@ QString MLPlaylist::getName() const
return m_name; return m_name;
} }
QString MLPlaylist::getCover() const //-------------------------------------------------------------------------------------------------
int64_t MLPlaylist::getDuration() const
{ {
return m_cover; return m_duration;
} }
unsigned int MLPlaylist::getCount() const unsigned int MLPlaylist::getCount() const
......
...@@ -24,22 +24,17 @@ ...@@ -24,22 +24,17 @@
#endif #endif
// MediaLibrary includes // MediaLibrary includes
#include "mlqmltypes.hpp" #include "mlitemcover.hpp"
// Qt includes class MLPlaylist : public MLItemCover
#include <QObject>
class MLPlaylist : public QObject, public MLItem
{ {
Q_OBJECT
public: public:
MLPlaylist(vlc_medialibrary_t * ml, MLPlaylist(vlc_medialibrary_t * ml, const vlc_ml_playlist_t * data);
const vlc_ml_playlist_t * data, QObject * parent = nullptr);
public: // Interface public: // Interface
QString getName () const; QString getName() const;
QString getCover() const;
int64_t getDuration() const;
unsigned int getCount() const; unsigned int getCount() const;
...@@ -47,7 +42,8 @@ private: ...@@ -47,7 +42,8 @@ private:
vlc_medialibrary_t * m_ml; vlc_medialibrary_t * m_ml;
QString m_name; QString m_name;
QString m_cover;
int64_t m_duration;
unsigned int m_count; unsigned int m_count;
}; };
......
...@@ -30,18 +30,27 @@ ...@@ -30,18 +30,27 @@
#include "mlhelper.hpp" #include "mlhelper.hpp"
#include "mlplaylist.hpp" #include "mlplaylist.hpp"
//-------------------------------------------------------------------------------------------------
// Static variables
// NOTE: We multiply by 2 to cover most dpi settings.
static const int MLPLAYLISTMODEL_COVER_WIDTH = 512 * 2; // 16 / 10 ratio
static const int MLPLAYLISTMODEL_COVER_HEIGHT = 320 * 2;
//================================================================================================= //=================================================================================================
// MLPlaylistListModel // MLPlaylistListModel
//================================================================================================= //=================================================================================================
MLPlaylistListModel::MLPlaylistListModel(vlc_medialibrary_t * ml, QObject * parent) MLPlaylistListModel::MLPlaylistListModel(vlc_medialibrary_t * ml, QObject * parent)
: MLBaseModel(parent) : MLBaseModel(parent)
, m_coverDefault(":/noart_videoCover.svg")
{ {
m_ml = ml; m_ml = ml;
} }
/* explicit */ MLPlaylistListModel::MLPlaylistListModel(QObject * parent) /* explicit */ MLPlaylistListModel::MLPlaylistListModel(QObject * parent)
: MLBaseModel(parent) {} : MLBaseModel(parent)
, m_coverSize(MLPLAYLISTMODEL_COVER_WIDTH, MLPLAYLISTMODEL_COVER_HEIGHT) {}
//------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------
...@@ -156,16 +165,19 @@ QHash<int, QByteArray> MLPlaylistListModel::roleNames() const /* override */ ...@@ -156,16 +165,19 @@ QHash<int, QByteArray> MLPlaylistListModel::roleNames() const /* override */
{ {
return return
{ {
{ PLAYLIST_ID, "id" }, { PLAYLIST_ID, "id" },
{ PLAYLIST_NAME, "name" }, { PLAYLIST_NAME, "name" },
{ PLAYLIST_COVER, "cover" }, { PLAYLIST_THUMBNAIL, "thumbnail" },
{ PLAYLIST_COUNT, "count" } { PLAYLIST_DURATION, "duration" },
{ PLAYLIST_COUNT, "count" }
}; };
} }
QVariant MLPlaylistListModel::data(const QModelIndex & index, int role) const /* override */ QVariant MLPlaylistListModel::data(const QModelIndex & index, int role) const /* override */
{ {
const MLPlaylist * playlist = static_cast<MLPlaylist *>(item(index.row())); int row = index.row();
MLPlaylist * playlist = static_cast<MLPlaylist *>(item(row));
if (playlist == nullptr) if (playlist == nullptr)
return QVariant(); return QVariant();
...@@ -175,16 +187,18 @@ QVariant MLPlaylistListModel::data(const QModelIndex & index, int role) const /* ...@@ -175,16 +187,18 @@ QVariant MLPlaylistListModel::data(const QModelIndex & index, int role) const /*
// NOTE: This is the condition for QWidget view(s). // NOTE: This is the condition for QWidget view(s).
case Qt::DisplayRole: case Qt::DisplayRole:
if (index.column() == 0) if (index.column() == 0)
return QVariant::fromValue(playlist->getName()); return playlist->getName();
else else
return QVariant(); return QVariant();
// NOTE: These are the conditions for QML view(s). // NOTE: These are the conditions for QML view(s).
case PLAYLIST_ID: case PLAYLIST_ID:
return QVariant::fromValue(playlist->getId()); return QVariant::fromValue(playlist->getId());
case PLAYLIST_NAME: case PLAYLIST_NAME:
return QVariant::fromValue(playlist->getName()); return playlist->getName();
case PLAYLIST_COVER: case PLAYLIST_THUMBNAIL:
return QVariant::fromValue(playlist->getCover()); return getCover(playlist, row);
case PLAYLIST_DURATION:
return QVariant::fromValue(playlist->getDuration());
case PLAYLIST_COUNT: case PLAYLIST_COUNT:
return QVariant::fromValue(playlist->getCount()); return QVariant::fromValue(playlist->getCount());
default: default:
...@@ -225,6 +239,36 @@ ListCacheLoader<std::unique_ptr<MLItem>> * MLPlaylistListModel::createLoader() c ...@@ -225,6 +239,36 @@ ListCacheLoader<std::unique_ptr<MLItem>> * MLPlaylistListModel::createLoader() c
return new Loader(*this); return new Loader(*this);
} }
//-------------------------------------------------------------------------------------------------
// Private functions
//-------------------------------------------------------------------------------------------------
QString MLPlaylistListModel::getCover(MLPlaylist * playlist, int index) const
{
QString cover = playlist->getCover();
// NOTE: Making sure we're not already generating a cover.
if (cover.isNull() == false || playlist->hasGenerator())
return cover;
CoverGenerator * generator = new CoverGenerator(m_ml, playlist->getId(), index);
generator->setSize(m_coverSize);
generator->setDefaultThumbnail(m_coverDefault);
generator->setPrefix(m_coverPrefix);
// NOTE: We'll apply the new thumbnail once it's loaded.
connect(generator, &CoverGenerator::result, this, &MLPlaylistListModel::onCover);
generator->start(*QThreadPool::globalInstance());
playlist->setGenerator(generator);
return cover;
}
//------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------
// Private MLBaseModel reimplementation // Private MLBaseModel reimplementation
//------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------
...@@ -246,6 +290,94 @@ void MLPlaylistListModel::onVlcMlEvent(const MLEvent & event) /* override */ ...@@ -246,6 +290,94 @@ void MLPlaylistListModel::onVlcMlEvent(const MLEvent & event) /* override */
MLBaseModel::onVlcMlEvent(event); MLBaseModel::onVlcMlEvent(event);
} }
void MLPlaylistListModel::thumbnailUpdated(int idx) /* override */
{
QModelIndex index = this->index(idx);
emit dataChanged(index, index, { PLAYLIST_THUMBNAIL });
}
//-------------------------------------------------------------------------------------------------
// Private slots
//-------------------------------------------------------------------------------------------------
void MLPlaylistListModel::onCover()
{
CoverGenerator * generator = static_cast<CoverGenerator *> (sender());
int index = generator->getIndex();
// NOTE: We want to avoid calling 'MLBaseModel::item' for performance issues.
MLItem * item = this->itemCache(index);
// NOTE: When the item is no longer cached or has been moved we return right away.
if (item == nullptr || item->getId() != generator->getId())
{
generator->deleteLater();
return;
}
MLPlaylist * playlist = static_cast<MLPlaylist *> (item);
QString fileName = QUrl::fromLocalFile(generator->takeResult()).toString();
playlist->setCover(fileName);
playlist->setGenerator(nullptr);
thumbnailUpdated(index);
}
//-------------------------------------------------------------------------------------------------
// Properties
//-------------------------------------------------------------------------------------------------
QSize MLPlaylistListModel::coverSize() const
{
return m_coverSize;
}
void MLPlaylistListModel::setCoverSize(const QSize & size)
{
if (m_coverSize == size)
return;
m_coverSize = size;
emit coverSizeChanged();
}
QString MLPlaylistListModel::coverDefault() const
{
return m_coverDefault;
}
void MLPlaylistListModel::setCoverDefault(const QString & fileName)
{
if (m_coverDefault == fileName)
return;
m_coverDefault = fileName;
emit coverDefaultChanged();
}
QString MLPlaylistListModel::coverPrefix() const
{
return m_coverPrefix;
}
void MLPlaylistListModel::setCoverPrefix(const QString & prefix)
{
if (m_coverPrefix == prefix)
return;
m_coverPrefix = prefix;
emit coverPrefixChanged();
}
//================================================================================================= //=================================================================================================
// Loader // Loader
//================================================================================================= //=================================================================================================
......
...@@ -24,18 +24,26 @@ ...@@ -24,18 +24,26 @@
// Forward declarations // Forward declarations
class vlc_medialibrary_t; class vlc_medialibrary_t;
class vlc_ml_playlist_t; class MLPlaylist;
class MLPlaylistListModel : public MLBaseModel class MLPlaylistListModel : public MLBaseModel
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QSize coverSize READ coverSize WRITE setCoverSize NOTIFY coverSizeChanged)
Q_PROPERTY(QString coverDefault READ coverDefault WRITE setCoverDefault
NOTIFY coverDefaultChanged)
Q_PROPERTY(QString coverPrefix READ coverPrefix WRITE setCoverPrefix NOTIFY coverPrefixChanged)
public: public:
enum Roles enum Roles
{ {
PLAYLIST_ID = Qt::UserRole + 1, PLAYLIST_ID = Qt::UserRole + 1,
PLAYLIST_NAME, PLAYLIST_NAME,
PLAYLIST_COVER, PLAYLIST_THUMBNAIL,
PLAYLIST_DURATION,
PLAYLIST_COUNT PLAYLIST_COUNT
}; };
...@@ -67,9 +75,37 @@ protected: // MLBaseModel implementation ...@@ -67,9 +75,37 @@ protected: // MLBaseModel implementation
ListCacheLoader<std::unique_ptr<MLItem>> * createLoader() const override; ListCacheLoader<std::unique_ptr<MLItem>> * createLoader() const override;
private: // Functions
QString getCover(MLPlaylist * playlist, int index) const;
private: // MLBaseModel implementation private: // MLBaseModel implementation
void onVlcMlEvent(const MLEvent & event) override; void onVlcMlEvent(const MLEvent & event) override;
void thumbnailUpdated(int idx) override;
private slots:
void onCover();
signals:
void coverSizeChanged ();
void coverDefaultChanged();
void coverPrefixChanged ();
public: // Properties
QSize coverSize() const;
void setCoverSize(const QSize & size);
QString coverDefault() const;
void setCoverDefault(const QString & fileName);
QString coverPrefix() const;
void setCoverPrefix(const QString & prefix);
private: // Variables
QSize m_coverSize;
QString m_coverDefault;
QString m_coverPrefix;
private: private:
struct Loader : public MLBaseModel::BaseLoader struct Loader : public MLBaseModel::BaseLoader
{ {
......
...@@ -92,6 +92,8 @@ Widgets.PageLoader { ...@@ -92,6 +92,8 @@ Widgets.PageLoader {
PlaylistMediaList { PlaylistMediaList {
anchors.fill: parent anchors.fill: parent
isMusic: true
onCurrentIndexChanged: _updateHistoryList(currentIndex) onCurrentIndexChanged: _updateHistoryList(currentIndex)
onShowList: history.push(["mc", "music", "playlists", "list", onShowList: history.push(["mc", "music", "playlists", "list",
......
...@@ -37,6 +37,8 @@ Widgets.NavigableFocusScope { ...@@ -37,6 +37,8 @@ Widgets.NavigableFocusScope {
readonly property int currentIndex: currentItem.currentIndex readonly property int currentIndex: currentItem.currentIndex
property bool isMusic: false
property int initialIndex: 0 property int initialIndex: 0
property var sortModel: [{ text: i18n.qtr("Alphabetic"), criteria: "title" }] property var sortModel: [{ text: i18n.qtr("Alphabetic"), criteria: "title" }]
...@@ -44,15 +46,23 @@ Widgets.NavigableFocusScope { ...@@ -44,15 +46,23 @@ Widgets.NavigableFocusScope {
//--------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------
// Private // Private
property int _width: VLCStyle.colWidth(2) property int _width: (isMusic) ? VLCStyle.gridItem_music_width
: VLCStyle.gridItem_video_width
property int _height: Math.round(_width / 2) property int _height: (isMusic) ? VLCStyle.gridItem_music_height
: VLCStyle.gridItem_video_height
property int _widthColumn: property int _widthColumn:
Math.max(VLCStyle.gridColumnsForWidth(tableView.availableRowWidth Math.max(VLCStyle.gridColumnsForWidth(tableView.availableRowWidth
- VLCStyle.listAlbumCover_width - VLCStyle.listAlbumCover_width
- VLCStyle.column_margin_width) - 1, 1) - VLCStyle.column_margin_width) - 1, 1)
property int _widthCover: (isMusic) ? VLCStyle.gridCover_music_width
: VLCStyle.gridCover_video_width
property int _heightCover: (isMusic) ? VLCStyle.gridCover_music_height
: VLCStyle.gridCover_video_height
//--------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------
// Alias // Alias
//--------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------
...@@ -145,6 +155,16 @@ Widgets.NavigableFocusScope { ...@@ -145,6 +155,16 @@ Widgets.NavigableFocusScope {
} }
} }
function _getCount(model)
{
var count = model.count;
if (count < 100)
return count;
else
return i18n.qtr("99+");
}
//--------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------
// Childs // Childs
//--------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------
...@@ -154,6 +174,13 @@ Widgets.NavigableFocusScope { ...@@ -154,6 +174,13 @@ Widgets.NavigableFocusScope {
ml: medialib ml: medialib
coverSize: (isMusic) ? Qt.size(512, 512)
: Qt.size(1024, 640)
coverDefault: (isMusic) ? ":/noart_album.svg" : ":/noart_videoCover.svg"
coverPrefix: (isMusic) ? "playlist-music" : "playlist-video"
onCountChanged: { onCountChanged: {
if (count === 0 || modelSelect.hasSelection) return; if (count === 0 || modelSelect.hasSelection) return;
...@@ -183,7 +210,7 @@ Widgets.NavigableFocusScope { ...@@ -183,7 +210,7 @@ Widgets.NavigableFocusScope {
}) })
var covers = items.map(function (item) { var covers = items.map(function (item) {
return { artwork: item.cover || VLCStyle.noArtCover }; return { artwork: item.thumbnail || VLCStyle.noArtCover };
}) })
var title = items.map(function (item) { var title = items.map(function (item) {
...@@ -237,21 +264,7 @@ Widgets.NavigableFocusScope { ...@@ -237,21 +264,7 @@ Widgets.NavigableFocusScope {
focus: true focus: true
//------------------------------------------------------------------------------------- delegate: VideoGridItem {
// Events
onSelectAll: modelSelect.selectAll()
onSelectionUpdated: modelSelect.updateSelection(keyModifiers, oldIndex, newIndex)
onActionAtIndex: _actionAtIndex()
//-------------------------------------------------------------------------------------
// Childs
delegate: Widgets.GridItem {
id: item
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
// Properties // Properties
...@@ -262,76 +275,70 @@ Widgets.NavigableFocusScope { ...@@ -262,76 +275,70 @@ Widgets.NavigableFocusScope {
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
// Settings // Settings
width : _width pictureWidth : _widthCover
height: _height pictureHeight: _heightCover
title: (model.name) ? model.name
: i18n.qtr("Unknown title")
pictureWidth : width labels: (model.count > 1) ? [ i18n.qtr("%1 Tracks").arg(_getCount(model)) ]
pictureHeight: height : [ i18n.qtr("%1 Track") .arg(_getCount(model)) ]
image: VLCStyle.noArtAlbum // NOTE: We don't want to show the new indicator for a playlist.
showNewIndicator: false
dragItem: dragItemPlaylist dragItem: dragItemPlaylist
selectedUnderlay : shadows.selected
unselectedUnderlay: shadows.unselected unselectedUnderlay: shadows.unselected
selectedUnderlay: shadows.selected
pictureOverlay: Item {
Column {
anchors.centerIn: parent
Label {
width: item.width
horizontalAlignment: Text.AlignHCenter //---------------------------------------------------------------------------------
// Events
text: model.name
elide: Text.ElideRight
color: "white" onItemClicked: gridView.leftClickOnItem(modifier, index)
font.pixelSize: VLCStyle.fontSize_large onItemDoubleClicked: showList(model)
font.weight : Font.DemiBold
}
Widgets.CaptionLabel { onPlayClicked: if (model.id) medialib.addAndPlay(model.id)
width: item.width
horizontalAlignment: Text.AlignHCenter onContextMenuButtonClicked: {
gridView.rightClickOnItem(index);
opacity: 0.7 contextMenu.popup(modelSelect.selectedIndexes, globalMousePos);
}
text: (model.count > 1) ? i18n.qtr("%1 Tracks").arg(model.count) //---------------------------------------------------------------------------------
: i18n.qtr("%1 Track") .arg(model.count) // Animations
color: "white" Behavior on opacity { NumberAnimation { duration: 100 } }
} }
}
}
playCoverBorderWidth: VLCStyle.dp(3, VLCStyle.scale) //-------------------------------------------------------------------------------------
// Events
//--------------------------------------------------------------------------------- // NOTE: Define the initial position and selection. This is done on activeFocus rather
// Events // than Component.onCompleted because modelSelect.selectedGroup update itself
// after this event.
onActiveFocusChanged: {
if (activeFocus == false || model.count === 0 || modelSelect.hasSelection) return;
onItemDoubleClicked: showList(model) modelSelect.select(model.index(0,0), ItemSelectionModel.ClearAndSelect)
}
onItemClicked: gridView.leftClickOnItem(modifier, index) onSelectAll: modelSelect.selectAll()
onPlayClicked: if (model.id) medialib.addAndPlay(model.id) onSelectionUpdated: modelSelect.updateSelection(keyModifiers, oldIndex, newIndex)
onContextMenuButtonClicked: { onActionAtIndex: _actionAtIndex()
gridView.rightClickOnItem(index);
contextMenu.popup(modelSelect.selectedIndexes, globalMousePos); //-------------------------------------------------------------------------------------
} // Childs
}
Widgets.GridShadows { Widgets.GridShadows {
id: shadows id: shadows
coverWidth: root._width coverWidth : _widthCover
coverHeight: root._height coverHeight: _heightCover
} }
} }
} }
...@@ -371,7 +378,7 @@ Widgets.NavigableFocusScope { ...@@ -371,7 +378,7 @@ Widgets.NavigableFocusScope {
sortModel: [{ sortModel: [{
isPrimary: true, isPrimary: true,
criteria: "cover", criteria: "thumbnail",
width: VLCStyle.listAlbumCover_width, width: VLCStyle.listAlbumCover_width,
...@@ -409,9 +416,24 @@ Widgets.NavigableFocusScope { ...@@ -409,9 +416,24 @@ Widgets.NavigableFocusScope {
showTitleText: false showTitleText: false
titleCover_width : VLCStyle.listAlbumCover_width //---------------------------------------------------------------------------------
titleCover_height: VLCStyle.listAlbumCover_height // NOTE: When it's music we want the cover to be square
titleCover_radius: VLCStyle.listAlbumCover_radius
titleCover_width: (isMusic) ? VLCStyle.trackListAlbumCover_width
: VLCStyle.listAlbumCover_width
titleCover_height: (isMusic) ? VLCStyle.trackListAlbumCover_heigth
: VLCStyle.listAlbumCover_height
titleCover_radius: (isMusic) ? VLCStyle.trackListAlbumCover_radius
: VLCStyle.listAlbumCover_radius
//---------------------------------------------------------------------------------
// NOTE: This makes sure we display the playlist count on the item.
function titlecoverLabels(model) {
return [ _getCount(model) ];
}
} }
} }
} }
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
// Qt includes // Qt includes
#include <QDir> #include <QDir>
#include <QImageReader>
#include <QGraphicsScene> #include <QGraphicsScene>
#include <QGraphicsPixmapItem> #include <QGraphicsPixmapItem>
#include <QGraphicsBlurEffect> #include <QGraphicsBlurEffect>
...@@ -107,6 +108,11 @@ CoverGenerator::CoverGenerator(vlc_medialibrary_t * ml, const MLItemId & itemId, ...@@ -107,6 +108,11 @@ CoverGenerator::CoverGenerator(vlc_medialibrary_t * ml, const MLItemId & itemId,
m_default = fileName; m_default = fileName;
} }
/* Q_INVOKABLE */ void CoverGenerator::setPrefix(const QString & prefix)
{
m_prefix = prefix;
}
//------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------
// QRunnable implementation // QRunnable implementation
//------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------
...@@ -121,9 +127,15 @@ QString CoverGenerator::execute() /* override */ ...@@ -121,9 +127,15 @@ QString CoverGenerator::execute() /* override */
int64_t id = m_id.id; int64_t id = m_id.id;
QString string = getStringType(type); QString fileName;
QString fileName = QString("%1_thumbnail_%2.jpg").arg(string).arg(id); // NOTE: If we don't have a valid prefix we generate one based on the item type.
if (m_prefix.isEmpty())
{
m_prefix = getPrefix(type);
}
fileName = QString("%1_thumbnail_%2.jpg").arg(m_prefix).arg(id);
fileName = dir.absoluteFilePath(fileName); fileName = dir.absoluteFilePath(fileName);
...@@ -141,6 +153,9 @@ QString CoverGenerator::execute() /* override */ ...@@ -141,6 +153,9 @@ QString CoverGenerator::execute() /* override */
else else
thumbnails = getMedias(count, id, type); thumbnails = getMedias(count, id, type);
int countX;
int countY;
if (thumbnails.isEmpty()) if (thumbnails.isEmpty())
{ {
if (m_split == CoverGenerator::Duplicate) if (m_split == CoverGenerator::Duplicate)
...@@ -149,13 +164,16 @@ QString CoverGenerator::execute() /* override */ ...@@ -149,13 +164,16 @@ QString CoverGenerator::execute() /* override */
{ {
thumbnails.append(m_default); thumbnails.append(m_default);
} }
countX = m_countX;
countY = m_countY;
} }
else else
{ {
thumbnails.append(m_default); thumbnails.append(m_default);
m_countX = 1; countX = 1;
m_countY = 1; countY = 1;
} }
} }
else if (m_split == CoverGenerator::Duplicate) else if (m_split == CoverGenerator::Duplicate)
...@@ -168,15 +186,16 @@ QString CoverGenerator::execute() /* override */ ...@@ -168,15 +186,16 @@ QString CoverGenerator::execute() /* override */
index++; index++;
} }
countX = m_countX;
countY = m_countY;
} }
else // if (m_split == CoverGenerator::Divide) else // if (m_split == CoverGenerator::Divide)
{ {
// NOTE: This handles the 2x2 case. countX = m_countX;
if (thumbnails.count() == 2)
{ // NOTE: We try to divide thumbnails as far as we can based on their total count.
m_countX = 2; countY = std::ceil((qreal) thumbnails.count() / m_countX);
m_countY = 1;
}
} }
QImage image(m_size, QImage::Format_RGB32); QImage image(m_size, QImage::Format_RGB32);
...@@ -187,7 +206,7 @@ QString CoverGenerator::execute() /* override */ ...@@ -187,7 +206,7 @@ QString CoverGenerator::execute() /* override */
painter.begin(&image); painter.begin(&image);
draw(painter, thumbnails); draw(painter, thumbnails, countX, countY);
painter.end(); painter.end();
...@@ -203,57 +222,89 @@ QString CoverGenerator::execute() /* override */ ...@@ -203,57 +222,89 @@ QString CoverGenerator::execute() /* override */
// Private functions // Private functions
//------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------
void CoverGenerator::draw(QPainter & painter, const QStringList & fileNames) void CoverGenerator::draw(QPainter & painter,
const QStringList & fileNames, int countX, int countY)
{ {
int count = fileNames.count(); int count = fileNames.count();
int width = m_size.width() / m_countX; int width = m_size.width() / countX;
int height = m_size.height() / m_countY; int height = m_size.height() / countY;
for (int y = 0; y < m_countY; y++) for (int y = 0; y < countY; y++)
{ {
for (int x = 0; x < m_countX; x++) for (int x = 0; x < countX; x++)
{ {
int index = m_countX * y + x; int index = countX * y + x;
if (index == count) return; if (index == count) return;
QRect rect; QRect rect;
// NOTE: This handles the wider thumbnail case (e.g. for a 2x1 grid). // NOTE: This handles the wider thumbnail case (e.g. for a 2x1 grid).
if (index == count - 1 && x != m_countX - 1) if (index == count - 1 && x != countX - 1)
{ {
rect = QRect(width * x, height * y, width * m_countX - x, height); rect = QRect(width * x, height * y, width * countX - x, height);
} }
else else
rect = QRect(width * x, height * y, width, height); rect = QRect(width * x, height * y, width, height);
drawImage(painter, fileNames.at(index), rect); QString fileName = fileNames.at(index);
if (fileName.isEmpty())
drawImage(painter, m_default, rect);
else
drawImage(painter, fileName, rect);
} }
} }
} }
void CoverGenerator::drawImage(QPainter & painter, const QString & fileName, const QRect & target) void CoverGenerator::drawImage(QPainter & painter, const QString & fileName, const QRect & target)
{ {
QImage image; QFile file(fileName);
if (fileName.isEmpty())
image.load(m_default);
else
image.load(fileName);
// NOTE: This image does not seem valid so we paint the placeholder instead. if (file.open(QIODevice::ReadOnly) == false)
if (image.isNull())
{ {
image.load(m_default); // NOTE: This image does not seem valid so we paint the placeholder instead.
if (fileName != m_default)
drawImage(painter, m_default, target);
return;
} }
// NOTE: Should we use Qt::SmoothTransformation or favor efficiency ? QImageReader reader(&file);
if (m_smooth)
image = image.scaled(target.size(), Qt::KeepAspectRatioByExpanding, if (reader.canRead() == false)
Qt::SmoothTransformation); return;
QSize size = reader.size().scaled(target.width(),
target.height(), Qt::KeepAspectRatioByExpanding);
QImage image;
if (fileName.endsWith(".svg", Qt::CaseInsensitive))
{
if (size.isEmpty() == false)
{
reader.setScaledSize(size);
}
if (reader.read(&image) == false)
return;
}
else else
image = image.scaled(target.size(), Qt::KeepAspectRatioByExpanding); {
if (reader.read(&image) == false)
return;
if (size.isEmpty() == false)
{
// NOTE: Should we use Qt::SmoothTransformation or favor efficiency ?
if (m_smooth)
image = image.scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
else
image = image.scaled(size, Qt::IgnoreAspectRatio);
}
}
int x = (image.width () - target.width ()) / 2; int x = (image.width () - target.width ()) / 2;
int y = (image.height() - target.height()) / 2; int y = (image.height() - target.height()) / 2;
...@@ -295,7 +346,7 @@ void CoverGenerator::blur(QImage * image) ...@@ -295,7 +346,7 @@ void CoverGenerator::blur(QImage * image)
//------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------
QString CoverGenerator::getStringType(vlc_ml_parent_type type) const QString CoverGenerator::getPrefix(vlc_ml_parent_type type) const
{ {
switch (type) switch (type)
{ {
......
...@@ -75,17 +75,20 @@ public: // Interface ...@@ -75,17 +75,20 @@ public: // Interface
Q_INVOKABLE void setDefaultThumbnail(const QString & fileName); Q_INVOKABLE void setDefaultThumbnail(const QString & fileName);
// NOTE: This lets us enforce a specific prefix for the cover fileName.
Q_INVOKABLE void setPrefix(const QString & prefix);
public: // AsyncTask implementation public: // AsyncTask implementation
QString execute() override; QString execute() override;
private: // Functions private: // Functions
void draw(QPainter & painter, const QStringList & fileNames); void draw(QPainter & painter, const QStringList & fileNames, int countX, int countY);
void drawImage(QPainter & painter, const QString & fileName, const QRect & rect); void drawImage(QPainter & painter, const QString & fileName, const QRect & rect);
void blur(QImage * image); void blur(QImage * image);
QString getStringType(vlc_ml_parent_type type) const; QString getPrefix(vlc_ml_parent_type type) const;
QStringList getMedias(int count, int64_t id, vlc_ml_parent_type type) const; QStringList getMedias(int count, int64_t id, vlc_ml_parent_type type) const;
QStringList getGenre (int count, int64_t id) const; QStringList getGenre (int count, int64_t id) const;
...@@ -109,6 +112,8 @@ private: ...@@ -109,6 +112,8 @@ private:
int m_blur; int m_blur;
QString m_default; QString m_default;
QString m_prefix;
}; };
#endif // COVERGENERATOR_HPP #endif // COVERGENERATOR_HPP
...@@ -429,6 +429,9 @@ bool Convert( const medialibrary::IPlaylist* input, vlc_ml_playlist_t& output ) ...@@ -429,6 +429,9 @@ bool Convert( const medialibrary::IPlaylist* input, vlc_ml_playlist_t& output )
{ {
output.i_id = input->id(); output.i_id = input->id();
output.i_nb_media = input->nbMedia();
output.i_nb_present_media = input->nbPresentMedia();
output.i_creation_date = input->creationDate(); output.i_creation_date = input->creationDate();
output.b_is_read_only = input->isReadOnly(); output.b_is_read_only = input->isReadOnly();
......
...@@ -777,6 +777,8 @@ modules/gui/qt/medialibrary/mlgroup.cpp ...@@ -777,6 +777,8 @@ modules/gui/qt/medialibrary/mlgroup.cpp
modules/gui/qt/medialibrary/mlgroup.hpp modules/gui/qt/medialibrary/mlgroup.hpp
modules/gui/qt/medialibrary/mlgrouplistmodel.cpp modules/gui/qt/medialibrary/mlgrouplistmodel.cpp
modules/gui/qt/medialibrary/mlgrouplistmodel.hpp modules/gui/qt/medialibrary/mlgrouplistmodel.hpp
modules/gui/qt/medialibrary/mlitemcover.cpp
modules/gui/qt/medialibrary/mlitemcover.hpp
modules/gui/qt/medialibrary/mlplaylistlistmodel.cpp modules/gui/qt/medialibrary/mlplaylistlistmodel.cpp
modules/gui/qt/medialibrary/mlplaylistlistmodel.hpp modules/gui/qt/medialibrary/mlplaylistlistmodel.hpp
modules/gui/qt/medialibrary/mlplaylistmedia.cpp modules/gui/qt/medialibrary/mlplaylistmedia.cpp
......