diff --git a/modules/gui/qt/Makefile.am b/modules/gui/qt/Makefile.am index 32a4c3de7e3f..3a0b6fa3c77b 100644 --- a/modules/gui/qt/Makefile.am +++ b/modules/gui/qt/Makefile.am @@ -191,6 +191,8 @@ libqt_plugin_la_SOURCES = \ gui/qt/medialibrary/mlurlmodel.hpp \ gui/qt/medialibrary/mlvideo.cpp \ gui/qt/medialibrary/mlvideo.hpp \ + gui/qt/medialibrary/mlvideofoldersmodel.cpp \ + gui/qt/medialibrary/mlvideofoldersmodel.hpp \ gui/qt/medialibrary/mlvideogroupsmodel.cpp \ gui/qt/medialibrary/mlvideogroupsmodel.hpp \ gui/qt/medialibrary/mlvideomodel.cpp \ @@ -403,6 +405,7 @@ nodist_libqt_plugin_la_SOURCES = \ gui/qt/medialibrary/mlvideomodel.moc.cpp \ gui/qt/medialibrary/mlplaylistlistmodel.moc.cpp \ gui/qt/medialibrary/mlplaylistmodel.moc.cpp \ + gui/qt/medialibrary/mlvideofoldersmodel.moc.cpp \ gui/qt/medialibrary/mlvideogroupsmodel.moc.cpp \ gui/qt/menus/custom_menus.moc.cpp \ gui/qt/menus/qml_menu_wrapper.moc.cpp \ diff --git a/modules/gui/qt/maininterface/mainui.cpp b/modules/gui/qt/maininterface/mainui.cpp index 874f25a254fd..8d426df7dc34 100644 --- a/modules/gui/qt/maininterface/mainui.cpp +++ b/modules/gui/qt/maininterface/mainui.cpp @@ -14,6 +14,7 @@ #include "medialibrary/mlrecentsvideomodel.hpp" #include "medialibrary/mlfoldersmodel.hpp" #include "medialibrary/mlvideogroupsmodel.hpp" +#include "medialibrary/mlvideofoldersmodel.hpp" #include "medialibrary/mlplaylistlistmodel.hpp" #include "medialibrary/mlplaylistmodel.hpp" #include "medialibrary/mlplaylist.hpp" @@ -325,6 +326,7 @@ void MainUI::registerQMLTypes() qmlRegisterType( uri, versionMajor, versionMinor, "MLVideoModel" ); qmlRegisterType( uri, versionMajor, versionMinor, "MLRecentsVideoModel" ); qmlRegisterType( uri, versionMajor, versionMinor, "MLVideoGroupsModel" ); + qmlRegisterType( uri, versionMajor, versionMinor, "MLVideoFoldersModel" ); qmlRegisterType( uri, versionMajor, versionMinor, "MLPlaylistListModel" ); qmlRegisterType( uri, versionMajor, versionMinor, "MLPlaylistModel" ); diff --git a/modules/gui/qt/medialibrary/mlvideofoldersmodel.cpp b/modules/gui/qt/medialibrary/mlvideofoldersmodel.cpp new file mode 100644 index 000000000000..31e099d6b168 --- /dev/null +++ b/modules/gui/qt/medialibrary/mlvideofoldersmodel.cpp @@ -0,0 +1,169 @@ +/***************************************************************************** + * Copyright (C) 2021 VLC authors and VideoLAN + * + * Authors: Benjamin Arnaud + * + * 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. + *****************************************************************************/ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "mlvideofoldersmodel.hpp" + +// VLC includes +#include + +// Util includes +#include "util/covergenerator.hpp" + +// MediaLibrary includes +#include "mlhelper.hpp" +#include "mlfolder.hpp" + +// Static variables + +// NOTE: We multiply by 2 to cover most dpi settings. +static const int MLVIDEOFOLDERSMODEL_COVER_WIDTH = 512 * 2; // 16 / 10 ratio +static const int MLVIDEOFOLDERSMODEL_COVER_HEIGHT = 320 * 2; + +static const QHash criterias = +{ + { "title", VLC_ML_SORTING_ALPHA }, + { "duration", VLC_ML_SORTING_DURATION } +}; + +// Ctor / dtor + +/* explicit */ MLVideoFoldersModel::MLVideoFoldersModel(QObject * parent) : MLBaseModel(parent) {} + +// MLBaseModel reimplementation + +QHash MLVideoFoldersModel::roleNames() const /* override */ +{ + return { + { FOLDER_ID, "id" }, + { FOLDER_IS_NEW, "isNew" }, + { FOLDER_TITLE, "title" }, + { FOLDER_THUMBNAIL, "thumbnail" }, + { FOLDER_DURATION, "duration" }, + { FOLDER_PROGRESS, "progress" }, + { FOLDER_COUNT, "count"}, + }; +} + +// Protected MLVideoModel implementation + +QVariant MLVideoFoldersModel::itemRoleData(MLItem * item, const int role) const /* override */ +{ + if (item == nullptr) + return QVariant(); + + MLFolder * folder = static_cast (item); + + switch (role) + { + // NOTE: This is the condition for QWidget view(s). + case Qt::DisplayRole: + return QVariant::fromValue(folder->getTitle()); + // NOTE: These are the conditions for QML view(s). + case FOLDER_ID: + return QVariant::fromValue(folder->getId()); + case FOLDER_TITLE: + return QVariant::fromValue(folder->getTitle()); + case FOLDER_THUMBNAIL: + return getVideoListCover(this, folder, MLVIDEOFOLDERSMODEL_COVER_WIDTH, + MLVIDEOFOLDERSMODEL_COVER_HEIGHT, FOLDER_THUMBNAIL); + case FOLDER_DURATION: + return QVariant::fromValue(folder->getDuration()); + case FOLDER_COUNT: + return QVariant::fromValue(folder->getCount()); + default: + return QVariant(); + } +} + +vlc_ml_sorting_criteria_t MLVideoFoldersModel::roleToCriteria(int role) const /* override */ +{ + switch (role) + { + case FOLDER_TITLE: + return VLC_ML_SORTING_ALPHA; + case FOLDER_DURATION: + return VLC_ML_SORTING_DURATION; + default: + return VLC_ML_SORTING_DEFAULT; + } +} + +vlc_ml_sorting_criteria_t MLVideoFoldersModel::nameToCriteria(QByteArray name) const /* override */ +{ + return criterias.value(name, VLC_ML_SORTING_DEFAULT); +} + +QByteArray MLVideoFoldersModel::criteriaToName(vlc_ml_sorting_criteria_t criteria) const +/* override */ +{ + return criterias.key(criteria, ""); +} + +ListCacheLoader> * MLVideoFoldersModel::createLoader() const /* override */ +{ + return new Loader(*this); +} + +// Protected MLBaseModel reimplementation + +void MLVideoFoldersModel::onVlcMlEvent(const MLEvent & event) /* override */ +{ + // FIXME: Add support for folder events once the MediaLibrary supports them. + + MLBaseModel::onVlcMlEvent(event); +} + +// Loader + +MLVideoFoldersModel::Loader::Loader(const MLVideoFoldersModel & model) + : MLBaseModel::BaseLoader(model) {} + +size_t MLVideoFoldersModel::Loader::count(vlc_medialibrary_t * ml) const /* override */ +{ + vlc_ml_query_params_t params = getParams().toCQueryParams(); + + return vlc_ml_count_folders_by_type(ml, ¶ms, VLC_ML_MEDIA_TYPE_VIDEO); +} + +std::vector> +MLVideoFoldersModel::Loader::load(vlc_medialibrary_t * ml, + size_t index, size_t count) const /* override */ +{ + vlc_ml_query_params_t params = getParams(index, count).toCQueryParams(); + + ml_unique_ptr list(vlc_ml_list_folders_by_type(ml, ¶ms, + VLC_ML_MEDIA_TYPE_VIDEO)); + + if (list == nullptr) + return {}; + + std::vector> result; + + for (const vlc_ml_folder_t & folder : ml_range_iterate(list)) + { + result.emplace_back(std::make_unique(&folder)); + } + + return result; +} diff --git a/modules/gui/qt/medialibrary/mlvideofoldersmodel.hpp b/modules/gui/qt/medialibrary/mlvideofoldersmodel.hpp new file mode 100644 index 000000000000..dd968776ceb4 --- /dev/null +++ b/modules/gui/qt/medialibrary/mlvideofoldersmodel.hpp @@ -0,0 +1,78 @@ +/***************************************************************************** + * Copyright (C) 2021 VLC authors and VideoLAN + * + * Authors: Benjamin Arnaud + * + * 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 MLVIDEOFOLDERSMODEL_HPP +#define MLVIDEOFOLDERSMODEL_HPP + +// MediaLibrary includes +#include "mlvideomodel.hpp" + +// Forward declarations +class MLFolder; + +class MLVideoFoldersModel : public MLBaseModel +{ + Q_OBJECT + +public: + enum Roles + { + FOLDER_ID = Qt::UserRole + 1, + FOLDER_IS_NEW, + FOLDER_TITLE, + FOLDER_THUMBNAIL, + FOLDER_DURATION, + FOLDER_PROGRESS, + FOLDER_COUNT + }; + +public: + explicit MLVideoFoldersModel(QObject * parent = nullptr); + +public: // MLBaseModel reimplementation + QHash roleNames() const override; + +protected: + 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; + + QByteArray criteriaToName(vlc_ml_sorting_criteria_t criteria) const override; + + ListCacheLoader> * createLoader() const override; + +protected: // MLBaseModel reimplementation + void onVlcMlEvent(const MLEvent & event) override; + +private: + struct Loader : public BaseLoader + { + Loader(const MLVideoFoldersModel & model); + + size_t count(vlc_medialibrary_t * ml) const override; + + std::vector> load(vlc_medialibrary_t * ml, + size_t index, size_t count) const override; + }; +}; + +#endif // MLVIDEOFOLDERSMODEL_HPP diff --git a/po/POTFILES.in b/po/POTFILES.in index 9080dc30ecc8..3a6d10f58495 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -784,6 +784,8 @@ modules/gui/qt/medialibrary/mlplaylistmedia.cpp modules/gui/qt/medialibrary/mlplaylistmedia.hpp modules/gui/qt/medialibrary/mlplaylistmodel.cpp modules/gui/qt/medialibrary/mlplaylistmodel.hpp +modules/gui/qt/medialibrary/mlvideofoldersmodel.cpp +modules/gui/qt/medialibrary/mlvideofoldersmodel.hpp modules/gui/qt/medialibrary/mlvideogroupsmodel.cpp modules/gui/qt/medialibrary/mlvideogroupsmodel.hpp modules/gui/qt/menus/menus.cpp