184 lines
4.9 KiB
C++
184 lines
4.9 KiB
C++
/*
|
|
* Copyright (C) 2018 Emeric Poupon
|
|
*
|
|
* This file is part of LMS.
|
|
*
|
|
* LMS 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 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* LMS 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 LMS. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "ArtistView.hpp"
|
|
|
|
#include <Wt/WAnchor.h>
|
|
#include <Wt/WImage.h>
|
|
#include <Wt/WTemplate.h>
|
|
#include <Wt/WText.h>
|
|
|
|
#include "database/Artist.hpp"
|
|
#include "database/Release.hpp"
|
|
#include "database/ScanSettings.hpp"
|
|
#include "recommendation/IEngine.hpp"
|
|
#include "utils/Logger.hpp"
|
|
#include "utils/String.hpp"
|
|
|
|
#include "resource/ImageResource.hpp"
|
|
#include "ArtistListHelpers.hpp"
|
|
#include "Filters.hpp"
|
|
#include "LmsApplication.hpp"
|
|
#include "LmsApplicationException.hpp"
|
|
#include "ReleaseListHelpers.hpp"
|
|
|
|
using namespace Database;
|
|
|
|
namespace UserInterface {
|
|
|
|
Artist::Artist(Filters* filters)
|
|
: Wt::WTemplate {Wt::WString::tr("Lms.Explore.Artist.template")}
|
|
, _filters(filters)
|
|
{
|
|
addFunction("tr", &Wt::WTemplate::Functions::tr);
|
|
|
|
LmsApp->internalPathChanged().connect([=]
|
|
{
|
|
refreshView();
|
|
});
|
|
|
|
filters->updated().connect([=]
|
|
{
|
|
refreshView();
|
|
});
|
|
|
|
refreshView();
|
|
}
|
|
|
|
void
|
|
Artist::refreshView()
|
|
{
|
|
if (!wApp->internalPathMatches("/artist/"))
|
|
return;
|
|
|
|
clear();
|
|
|
|
const auto artistId {StringUtils::readAs<Database::IdType>(wApp->internalPathNextPart("/artist/"))};
|
|
if (!artistId)
|
|
return;
|
|
|
|
const std::vector<Database::IdType> similarArtistIds {Service<Recommendation::IEngine>::get()->getSimilarArtists(LmsApp->getDbSession(), *artistId, 5)};
|
|
|
|
auto transaction {LmsApp->getDbSession().createSharedTransaction()};
|
|
|
|
const Database::Artist::pointer artist {Database::Artist::getById(LmsApp->getDbSession(), *artistId)};
|
|
if (!artist)
|
|
throw ArtistNotFoundException {*artistId};
|
|
|
|
refreshLinks(artist);
|
|
refreshSimilarArtists(similarArtistIds);
|
|
|
|
Wt::WContainerWidget* clusterContainers = bindNew<Wt::WContainerWidget>("clusters");
|
|
|
|
{
|
|
auto clusterTypes = ScanSettings::get(LmsApp->getDbSession())->getClusterTypes();
|
|
auto clusterGroups = artist->getClusterGroups(clusterTypes, 3);
|
|
|
|
for (auto clusters : clusterGroups)
|
|
{
|
|
for (auto cluster : clusters)
|
|
{
|
|
auto clusterId = cluster.id();
|
|
auto entry = clusterContainers->addWidget(LmsApp->createCluster(cluster));
|
|
entry->clicked().connect([=]
|
|
{
|
|
_filters->add(clusterId);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
bindString("name", Wt::WString::fromUTF8(artist->getName()), Wt::TextFormat::Plain);
|
|
{
|
|
Wt::WText* playBtn = bindNew<Wt::WText>("play-btn", Wt::WString::tr("Lms.Explore.template.play-btn"), Wt::TextFormat::XHTML);
|
|
|
|
playBtn->clicked().connect([=]
|
|
{
|
|
artistsAction.emit(PlayQueueAction::Play, {*artistId});
|
|
});
|
|
}
|
|
|
|
{
|
|
Wt::WText* moreBtn = bindNew<Wt::WText>("more-btn", Wt::WString::tr("Lms.Explore.template.more-btn"), Wt::TextFormat::XHTML);
|
|
|
|
moreBtn->clicked().connect([=]
|
|
{
|
|
Wt::WPopupMenu* popup {LmsApp->createPopupMenu()};
|
|
|
|
popup->addItem(Wt::WString::tr("Lms.Explore.play-shuffled"))
|
|
->triggered().connect(this, [=]
|
|
{
|
|
artistsAction.emit(PlayQueueAction::PlayShuffled, {*artistId});
|
|
});
|
|
popup->addItem(Wt::WString::tr("Lms.Explore.play-last"))
|
|
->triggered().connect(this, [=]
|
|
{
|
|
artistsAction.emit(PlayQueueAction::PlayLast, {*artistId});
|
|
});
|
|
|
|
popup->exec(moreBtn);
|
|
});
|
|
}
|
|
|
|
Wt::WContainerWidget* releasesContainer = bindNew<Wt::WContainerWidget>("releases");
|
|
|
|
auto releases = artist->getReleases(_filters->getClusterIds());
|
|
for (const auto& release : releases)
|
|
{
|
|
releasesContainer->addWidget(ReleaseListHelpers::createEntryForArtist(release, artist));
|
|
}
|
|
}
|
|
|
|
void
|
|
Artist::refreshSimilarArtists(const std::vector<Database::IdType>& similarArtistsId)
|
|
{
|
|
if (similarArtistsId.empty())
|
|
return;
|
|
|
|
setCondition("if-has-similar-artists", true);
|
|
Wt::WContainerWidget* similarArtistsContainer {bindNew<Wt::WContainerWidget>("similar-artists")};
|
|
|
|
for (Database::IdType artistId : similarArtistsId)
|
|
{
|
|
const Database::Artist::pointer similarArtist{Database::Artist::getById(LmsApp->getDbSession(), artistId)};
|
|
if (!similarArtist)
|
|
continue;
|
|
|
|
similarArtistsContainer->addWidget(ArtistListHelpers::createEntrySmall(similarArtist));
|
|
}
|
|
}
|
|
|
|
void
|
|
Artist::refreshLinks(const Database::Artist::pointer& artist)
|
|
{
|
|
const auto mbid {artist->getMBID()};
|
|
if (mbid)
|
|
{
|
|
setCondition("if-has-mbid", true);
|
|
|
|
Wt::WLink link {"https://musicbrainz.org/artist/" + std::string {mbid->getAsString()}};
|
|
link.setTarget(Wt::LinkTarget::NewWindow);
|
|
|
|
bindNew<Wt::WAnchor>("mbid-link", link, Wt::WString::tr("Lms.Explore.musicbrainz-artist"));
|
|
}
|
|
}
|
|
|
|
} // namespace UserInterface
|
|
|