Added playlist skeleton
This commit is contained in:
@@ -21,6 +21,7 @@ lms_approot_DATA = \
|
|||||||
approot/artist.xml \
|
approot/artist.xml \
|
||||||
approot/mediaplayer.xml \
|
approot/mediaplayer.xml \
|
||||||
approot/messages.xml \
|
approot/messages.xml \
|
||||||
|
approot/playlist.xml \
|
||||||
approot/releases.xml \
|
approot/releases.xml \
|
||||||
approot/release.xml \
|
approot/release.xml \
|
||||||
approot/templates.xml \
|
approot/templates.xml \
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<messages xmlns:if="Wt.WTemplate.conditions">
|
||||||
|
<!--FORMS message blocks-->
|
||||||
|
|
||||||
|
<message id="btn-playlist-save-btn">
|
||||||
|
<i class="fa fa-upload"></i>
|
||||||
|
</message>
|
||||||
|
|
||||||
|
<message id="btn-playlist-load-btn">
|
||||||
|
<i class="fa fa-download"></i>
|
||||||
|
</message>
|
||||||
|
|
||||||
|
<message id="btn-playlist-clear-btn">
|
||||||
|
<i class="fa fa-times-circle"></i>
|
||||||
|
</message>
|
||||||
|
|
||||||
|
<message id="template-playlist">
|
||||||
|
<div class="page-header">
|
||||||
|
<h2>${tr:msg-playlist}</h2>
|
||||||
|
${save-btn} ${load-btn} ${clear-btn}
|
||||||
|
</div>
|
||||||
|
${entries}
|
||||||
|
</message>
|
||||||
|
|
||||||
|
<message id="template-playlist-entry">
|
||||||
|
<div class="media">
|
||||||
|
<div class="pull-left media-middle">
|
||||||
|
${cover class="media-object"}
|
||||||
|
</div>
|
||||||
|
<div class="media-body">
|
||||||
|
<h4 class="media-heading">${name}</h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
${<if-has-release>}${release-name}${</if-has-release>}
|
||||||
|
${<if-has-artist>}${artist-name}${</if-has-artist>}
|
||||||
|
|
||||||
|
${play-btn} ${remove-btn}
|
||||||
|
</message>
|
||||||
|
|
||||||
|
</messages>
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
<messages xmlns:if="Wt.WTemplate.conditions">
|
<messages xmlns:if="Wt.WTemplate.conditions">
|
||||||
<!--FORMS message blocks-->
|
<!--FORMS message blocks-->
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ lms_SOURCES = \
|
|||||||
$(srcdir)/ui/HomeView.cpp \
|
$(srcdir)/ui/HomeView.cpp \
|
||||||
$(srcdir)/ui/LmsApplication.cpp \
|
$(srcdir)/ui/LmsApplication.cpp \
|
||||||
$(srcdir)/ui/MediaPlayer.cpp \
|
$(srcdir)/ui/MediaPlayer.cpp \
|
||||||
|
$(srcdir)/ui/PlaylistView.cpp \
|
||||||
$(srcdir)/ui/ReleasesView.cpp \
|
$(srcdir)/ui/ReleasesView.cpp \
|
||||||
$(srcdir)/ui/ReleaseView.cpp \
|
$(srcdir)/ui/ReleaseView.cpp \
|
||||||
$(srcdir)/ui/TracksView.cpp \
|
$(srcdir)/ui/TracksView.cpp \
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ Playlist::get(Wt::Dbo::Session& session, std::string name, Wt::Dbo::ptr<User> us
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Playlist::pointer>
|
std::vector<Playlist::pointer>
|
||||||
Playlist::get(Wt::Dbo::Session& session, Wt::Dbo::ptr<User> user)
|
Playlist::getAll(Wt::Dbo::Session& session, Wt::Dbo::ptr<User> user)
|
||||||
{
|
{
|
||||||
Wt::Dbo::collection<Playlist::pointer> res = session.find<Playlist>().where("user_id = ?").bind(user.id()).orderBy("name");
|
Wt::Dbo::collection<Playlist::pointer> res = session.find<Playlist>().where("user_id = ?").bind(user.id()).orderBy("name");
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ PlaylistEntry::create(Wt::Dbo::Session& session, Wt::Dbo::ptr<Track> track, Wt::
|
|||||||
{
|
{
|
||||||
return session.add( new PlaylistEntry( track, playlist, pos) );
|
return session.add( new PlaylistEntry( track, playlist, pos) );
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
std::vector<Track::id_type>
|
std::vector<Track::id_type>
|
||||||
PlaylistEntry::getEntries(Wt::Dbo::Session& session, Playlist::pointer playlist)
|
PlaylistEntry::getEntries(Wt::Dbo::Session& session, Playlist::pointer playlist)
|
||||||
{
|
{
|
||||||
@@ -87,6 +87,6 @@ PlaylistEntry::getEntries(Wt::Dbo::Session& session, Playlist::pointer playlist)
|
|||||||
res.push_back((*it)->getTrack().id());
|
res.push_back((*it)->getTrack().id());
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
} // namespace Database
|
} // namespace Database
|
||||||
|
|||||||
@@ -40,15 +40,22 @@ class Playlist
|
|||||||
|
|
||||||
// Search utility
|
// Search utility
|
||||||
static pointer get(Wt::Dbo::Session& session, std::string name, Wt::Dbo::ptr<User> user);
|
static pointer get(Wt::Dbo::Session& session, std::string name, Wt::Dbo::ptr<User> user);
|
||||||
|
static std::vector<pointer> getAll(Wt::Dbo::Session& session, Wt::Dbo::ptr<User> user);
|
||||||
// ordered by name
|
|
||||||
static std::vector<pointer> get(Wt::Dbo::Session& session, Wt::Dbo::ptr<User> user);
|
|
||||||
|
|
||||||
// Create utility
|
// Create utility
|
||||||
static pointer create(Wt::Dbo::Session& session, std::string name, bool isPublic, Wt::Dbo::ptr<User> user);
|
static pointer create(Wt::Dbo::Session& session, std::string name, bool isPublic, Wt::Dbo::ptr<User> user);
|
||||||
|
|
||||||
// Accessors
|
// Accessors
|
||||||
std::string getName() const { return _name; }
|
std::string getName() const { return _name; }
|
||||||
|
bool isPublic() const { return _isPublic; }
|
||||||
|
|
||||||
|
// Modifiers
|
||||||
|
void addTrack(id_type trackId);
|
||||||
|
void addTracks(const std::vector<id_type>& trackIds);
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
// Get tracks, ordered by position
|
||||||
|
std::vector<Track::id_type> getEntries(Wt::Dbo::Session& session, int offset = -1, int size = -1);
|
||||||
|
|
||||||
template<class Action>
|
template<class Action>
|
||||||
void persist(Action& a)
|
void persist(Action& a)
|
||||||
@@ -77,11 +84,6 @@ class PlaylistEntry
|
|||||||
PlaylistEntry();
|
PlaylistEntry();
|
||||||
PlaylistEntry(Wt::Dbo::ptr<Track> rack, Wt::Dbo::ptr<Playlist> playlist, int position);
|
PlaylistEntry(Wt::Dbo::ptr<Track> rack, Wt::Dbo::ptr<Playlist> playlist, int position);
|
||||||
|
|
||||||
// Search utility
|
|
||||||
|
|
||||||
// Get the position ordered track id list
|
|
||||||
static std::vector<Track::id_type> getEntries(Wt::Dbo::Session& session,Wt::Dbo::ptr<Playlist> playlist);
|
|
||||||
|
|
||||||
// Create utility
|
// Create utility
|
||||||
static pointer create(Wt::Dbo::Session& session, Wt::Dbo::ptr<Track> track, Wt::Dbo::ptr<Playlist> playlist, int position);
|
static pointer create(Wt::Dbo::Session& session, Wt::Dbo::ptr<Track> track, Wt::Dbo::ptr<Playlist> playlist, int position);
|
||||||
|
|
||||||
|
|||||||
+23
-2
@@ -29,6 +29,7 @@
|
|||||||
#include "utils/Utils.hpp"
|
#include "utils/Utils.hpp"
|
||||||
|
|
||||||
#include "LmsApplication.hpp"
|
#include "LmsApplication.hpp"
|
||||||
|
#include "Filters.hpp"
|
||||||
#include "ArtistView.hpp"
|
#include "ArtistView.hpp"
|
||||||
|
|
||||||
namespace UserInterface {
|
namespace UserInterface {
|
||||||
@@ -77,11 +78,21 @@ Artist::refresh()
|
|||||||
{
|
{
|
||||||
auto playBtn = new Wt::WText(Wt::WString::tr("btn-artist-play-btn"), Wt::XHTMLText);
|
auto playBtn = new Wt::WText(Wt::WString::tr("btn-artist-play-btn"), Wt::XHTMLText);
|
||||||
t->bindWidget("play-btn", playBtn);
|
t->bindWidget("play-btn", playBtn);
|
||||||
|
|
||||||
|
playBtn->clicked().connect(std::bind([=]
|
||||||
|
{
|
||||||
|
artistPlay.emit(artistId);
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto addBtn = new Wt::WText(Wt::WString::tr("btn-artist-add-btn"), Wt::XHTMLText);
|
auto addBtn = new Wt::WText(Wt::WString::tr("btn-artist-add-btn"), Wt::XHTMLText);
|
||||||
t->bindWidget("add-btn", addBtn);
|
t->bindWidget("add-btn", addBtn);
|
||||||
|
|
||||||
|
addBtn->clicked().connect(std::bind([=]
|
||||||
|
{
|
||||||
|
artistAdd.emit(artistId);
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto releasesContainer = new Wt::WContainerWidget();
|
auto releasesContainer = new Wt::WContainerWidget();
|
||||||
@@ -90,11 +101,13 @@ Artist::refresh()
|
|||||||
auto releases = artist->getReleases(_filters->getClusterIds());
|
auto releases = artist->getReleases(_filters->getClusterIds());
|
||||||
for (auto release : releases)
|
for (auto release : releases)
|
||||||
{
|
{
|
||||||
|
auto releaseId = release.id();
|
||||||
|
|
||||||
Wt::WTemplate* entry = new Wt::WTemplate(Wt::WString::tr("template-artist-entry"), releasesContainer);
|
Wt::WTemplate* entry = new Wt::WTemplate(Wt::WString::tr("template-artist-entry"), releasesContainer);
|
||||||
entry->addFunction("tr", Wt::WTemplate::Functions::tr);
|
entry->addFunction("tr", Wt::WTemplate::Functions::tr);
|
||||||
|
|
||||||
{
|
{
|
||||||
Wt::WAnchor* coverAnchor = new Wt::WAnchor(Wt::WLink(Wt::WLink::InternalPath, "/release/" + std::to_string(release.id())));
|
Wt::WAnchor* coverAnchor = new Wt::WAnchor(Wt::WLink(Wt::WLink::InternalPath, "/release/" + std::to_string(releaseId)));
|
||||||
Wt::WImage* cover = new Wt::WImage(coverAnchor);
|
Wt::WImage* cover = new Wt::WImage(coverAnchor);
|
||||||
cover->setImageLink(SessionImageResource()->getReleaseUrl(release.id(), 128));
|
cover->setImageLink(SessionImageResource()->getReleaseUrl(release.id(), 128));
|
||||||
// Some images may not be square
|
// Some images may not be square
|
||||||
@@ -103,7 +116,7 @@ Artist::refresh()
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Wt::WAnchor* releaseAnchor = new Wt::WAnchor(Wt::WLink(Wt::WLink::InternalPath, "/release/" + std::to_string(release.id())));
|
Wt::WAnchor* releaseAnchor = new Wt::WAnchor(Wt::WLink(Wt::WLink::InternalPath, "/release/" + std::to_string(releaseId)));
|
||||||
Wt::WText* releaseName = new Wt::WText(releaseAnchor);
|
Wt::WText* releaseName = new Wt::WText(releaseAnchor);
|
||||||
releaseName->setText(Wt::WString::fromUTF8(release->getName(), Wt::PlainText));
|
releaseName->setText(Wt::WString::fromUTF8(release->getName(), Wt::PlainText));
|
||||||
entry->bindWidget("name", releaseAnchor);
|
entry->bindWidget("name", releaseAnchor);
|
||||||
@@ -128,9 +141,17 @@ Artist::refresh()
|
|||||||
|
|
||||||
auto playBtn = new Wt::WText(Wt::WString::tr("btn-artist-play-btn"), Wt::XHTMLText);
|
auto playBtn = new Wt::WText(Wt::WString::tr("btn-artist-play-btn"), Wt::XHTMLText);
|
||||||
entry->bindWidget("play-btn", playBtn);
|
entry->bindWidget("play-btn", playBtn);
|
||||||
|
playBtn->clicked().connect(std::bind([=]
|
||||||
|
{
|
||||||
|
releasePlay.emit(releaseId);
|
||||||
|
}));
|
||||||
|
|
||||||
auto addBtn = new Wt::WText(Wt::WString::tr("btn-artist-add-btn"), Wt::XHTMLText);
|
auto addBtn = new Wt::WText(Wt::WString::tr("btn-artist-add-btn"), Wt::XHTMLText);
|
||||||
entry->bindWidget("add-btn", addBtn);
|
entry->bindWidget("add-btn", addBtn);
|
||||||
|
addBtn->clicked().connect(std::bind([=]
|
||||||
|
{
|
||||||
|
releaseAdd.emit(releaseId);
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,16 +20,23 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Wt/WContainerWidget>
|
#include <Wt/WContainerWidget>
|
||||||
|
#include <Wt/WSignal>
|
||||||
#include "Filters.hpp"
|
|
||||||
|
|
||||||
namespace UserInterface {
|
namespace UserInterface {
|
||||||
|
|
||||||
|
class Filters;
|
||||||
|
|
||||||
class Artist : public Wt::WContainerWidget
|
class Artist : public Wt::WContainerWidget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Artist(Filters* filters, Wt::WContainerWidget* parent = 0);
|
Artist(Filters* filters, Wt::WContainerWidget* parent = 0);
|
||||||
|
|
||||||
|
Wt::Signal<Database::id_type> artistAdd;
|
||||||
|
Wt::Signal<Database::id_type> artistPlay;
|
||||||
|
|
||||||
|
Wt::Signal<Database::id_type> releaseAdd;
|
||||||
|
Wt::Signal<Database::id_type> releasePlay;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void refresh();
|
void refresh();
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
#include "utils/Utils.hpp"
|
#include "utils/Utils.hpp"
|
||||||
|
|
||||||
#include "LmsApplication.hpp"
|
#include "LmsApplication.hpp"
|
||||||
|
#include "Filters.hpp"
|
||||||
#include "ArtistsView.hpp"
|
#include "ArtistsView.hpp"
|
||||||
|
|
||||||
namespace UserInterface {
|
namespace UserInterface {
|
||||||
|
|||||||
@@ -20,16 +20,20 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Wt/WContainerWidget>
|
#include <Wt/WContainerWidget>
|
||||||
|
#include <Wt/WSignal>
|
||||||
#include "Filters.hpp"
|
|
||||||
|
|
||||||
namespace UserInterface {
|
namespace UserInterface {
|
||||||
|
|
||||||
|
class Filters;
|
||||||
|
|
||||||
class Artists : public Wt::WContainerWidget
|
class Artists : public Wt::WContainerWidget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Artists(Filters* filters, Wt::WContainerWidget* parent = 0);
|
Artists(Filters* filters, Wt::WContainerWidget* parent = 0);
|
||||||
|
|
||||||
|
Wt::Signal<Database::id_type> artistAdd;
|
||||||
|
Wt::Signal<Database::id_type> artistPlay;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void refresh(std::vector<std::string> searchKeywords = std::vector<std::string>());
|
void refresh(std::vector<std::string> searchKeywords = std::vector<std::string>());
|
||||||
|
|
||||||
|
|||||||
+118
-7
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include "LmsApplication.hpp"
|
#include "LmsApplication.hpp"
|
||||||
|
|
||||||
|
#include "Filters.hpp"
|
||||||
#include "ArtistsView.hpp"
|
#include "ArtistsView.hpp"
|
||||||
#include "ArtistView.hpp"
|
#include "ArtistView.hpp"
|
||||||
#include "ReleasesView.hpp"
|
#include "ReleasesView.hpp"
|
||||||
@@ -74,18 +75,47 @@ Explore::Explore(Wt::WContainerWidget* parent)
|
|||||||
{
|
{
|
||||||
auto container = new Wt::WTemplate(Wt::WString::tr("template-explore"), this);
|
auto container = new Wt::WTemplate(Wt::WString::tr("template-explore"), this);
|
||||||
|
|
||||||
auto filters = new Filters();
|
_filters = new Filters();
|
||||||
container->bindWidget("filters", filters);
|
container->bindWidget("filters", _filters);
|
||||||
|
|
||||||
// Contents
|
// Contents
|
||||||
Wt::WStackedWidget* stack = new Wt::WStackedWidget();
|
Wt::WStackedWidget* stack = new Wt::WStackedWidget();
|
||||||
container->bindWidget("contents", stack);
|
container->bindWidget("contents", stack);
|
||||||
|
|
||||||
stack->addWidget(new Artists(filters));
|
auto artists = new Artists(_filters);
|
||||||
stack->addWidget(new Artist(filters));
|
stack->addWidget(artists);
|
||||||
stack->addWidget(new Releases(filters));
|
|
||||||
stack->addWidget(new Release(filters));
|
artists->artistAdd.connect(this, &Explore::handleArtistAdd);
|
||||||
stack->addWidget(new Tracks(filters));
|
artists->artistPlay.connect(this, &Explore::handleArtistPlay);
|
||||||
|
|
||||||
|
auto artist = new Artist(_filters);
|
||||||
|
stack->addWidget(artist);
|
||||||
|
|
||||||
|
artist->artistAdd.connect(this, &Explore::handleArtistAdd);
|
||||||
|
artist->artistPlay.connect(this, &Explore::handleArtistPlay);
|
||||||
|
artist->releaseAdd.connect(this, &Explore::handleReleaseAdd);
|
||||||
|
artist->releasePlay.connect(this, &Explore::handleReleasePlay);
|
||||||
|
|
||||||
|
auto releases = new Releases(_filters);
|
||||||
|
stack->addWidget(releases);
|
||||||
|
|
||||||
|
releases->releaseAdd.connect(this, &Explore::handleReleaseAdd);
|
||||||
|
releases->releasePlay.connect(this, &Explore::handleReleasePlay);
|
||||||
|
|
||||||
|
auto release = new Release(_filters);
|
||||||
|
stack->addWidget(release);
|
||||||
|
|
||||||
|
release->releaseAdd.connect(this, &Explore::handleReleaseAdd);
|
||||||
|
release->releasePlay.connect(this, &Explore::handleReleasePlay);
|
||||||
|
release->trackAdd.connect(this, &Explore::handleTrackAdd);
|
||||||
|
release->trackPlay.connect(this, &Explore::handleTrackPlay);
|
||||||
|
|
||||||
|
auto tracks = new Tracks(_filters);
|
||||||
|
stack->addWidget(tracks);
|
||||||
|
|
||||||
|
tracks->trackAdd.connect(this, &Explore::handleTrackAdd);
|
||||||
|
tracks->trackPlay.connect(this, &Explore::handleTrackPlay);
|
||||||
|
|
||||||
|
|
||||||
wApp->internalPathChanged().connect(std::bind([=]
|
wApp->internalPathChanged().connect(std::bind([=]
|
||||||
{
|
{
|
||||||
@@ -94,5 +124,86 @@ Explore::Explore(Wt::WContainerWidget* parent)
|
|||||||
|
|
||||||
handlePathChange(stack);
|
handlePathChange(stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO SQL this?
|
||||||
|
static std::vector<Database::id_type> getArtistTracks(Wt::Dbo::Session& session, Database::id_type artistId, std::set<Database::id_type> clusters)
|
||||||
|
{
|
||||||
|
std::vector<Database::id_type> res;
|
||||||
|
|
||||||
|
Wt::Dbo::Transaction transaction(session);
|
||||||
|
|
||||||
|
auto artist = Database::Artist::getById(session, artistId);
|
||||||
|
if (!artist)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
auto releases = artist->getReleases(clusters);
|
||||||
|
for (auto release : releases)
|
||||||
|
{
|
||||||
|
auto tracks = release->getTracks(clusters);
|
||||||
|
|
||||||
|
for (auto track : tracks)
|
||||||
|
{
|
||||||
|
res.push_back(track.id());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<Database::id_type> getReleaseTracks(Wt::Dbo::Session& session, Database::id_type releaseId, std::set<Database::id_type> clusters)
|
||||||
|
{
|
||||||
|
std::vector<Database::id_type> res;
|
||||||
|
|
||||||
|
Wt::Dbo::Transaction transaction(session);
|
||||||
|
|
||||||
|
auto release = Database::Release::getById(session, releaseId);
|
||||||
|
if (!release)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
auto tracks = release->getTracks(clusters);
|
||||||
|
for (auto track : tracks)
|
||||||
|
{
|
||||||
|
res.push_back(track.id());
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Explore::handleArtistAdd(Database::id_type id)
|
||||||
|
{
|
||||||
|
tracksAdd.emit(getArtistTracks(DboSession(), id, _filters->getClusterIds()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Explore::handleArtistPlay(Database::id_type id)
|
||||||
|
{
|
||||||
|
tracksPlay.emit(getArtistTracks(DboSession(), id, _filters->getClusterIds()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Explore::handleReleaseAdd(Database::id_type id)
|
||||||
|
{
|
||||||
|
tracksAdd.emit(getReleaseTracks(DboSession(), id, _filters->getClusterIds()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Explore::handleReleasePlay(Database::id_type id)
|
||||||
|
{
|
||||||
|
tracksPlay.emit(getReleaseTracks(DboSession(), id, _filters->getClusterIds()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Explore::handleTrackAdd(Database::id_type id)
|
||||||
|
{
|
||||||
|
tracksAdd.emit(std::vector<Database::id_type>(1, id));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Explore::handleTrackPlay(Database::id_type id)
|
||||||
|
{
|
||||||
|
tracksPlay.emit(std::vector<Database::id_type>(1, id));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace UserInterface
|
} // namespace UserInterface
|
||||||
|
|
||||||
|
|||||||
@@ -21,12 +21,30 @@
|
|||||||
|
|
||||||
#include <Wt/WContainerWidget>
|
#include <Wt/WContainerWidget>
|
||||||
|
|
||||||
|
#include "database/Types.hpp"
|
||||||
|
|
||||||
namespace UserInterface {
|
namespace UserInterface {
|
||||||
|
|
||||||
|
class Filters;
|
||||||
|
|
||||||
class Explore : public Wt::WContainerWidget
|
class Explore : public Wt::WContainerWidget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Explore(Wt::WContainerWidget *parent = 0);
|
Explore(Wt::WContainerWidget *parent = 0);
|
||||||
|
|
||||||
|
Wt::Signal<std::vector<Database::id_type>> tracksAdd;
|
||||||
|
Wt::Signal<std::vector<Database::id_type>> tracksPlay;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void handleArtistAdd(Database::id_type id);
|
||||||
|
void handleArtistPlay(Database::id_type id);
|
||||||
|
void handleReleaseAdd(Database::id_type id);
|
||||||
|
void handleReleasePlay(Database::id_type id);
|
||||||
|
void handleTrackAdd(Database::id_type id);
|
||||||
|
void handleTrackPlay(Database::id_type id);
|
||||||
|
|
||||||
|
Filters* _filters;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace UserInterface
|
} // namespace UserInterface
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
#include "Explore.hpp"
|
#include "Explore.hpp"
|
||||||
#include "HomeView.hpp"
|
#include "HomeView.hpp"
|
||||||
#include "MediaPlayer.hpp"
|
#include "MediaPlayer.hpp"
|
||||||
|
#include "PlaylistView.hpp"
|
||||||
|
|
||||||
#include "LmsApplication.hpp"
|
#include "LmsApplication.hpp"
|
||||||
|
|
||||||
@@ -80,12 +81,13 @@ LmsApplication::LmsApplication(const Wt::WEnvironment& env, Wt::Dbo::SqlConnecti
|
|||||||
// Add a resource bundle
|
// Add a resource bundle
|
||||||
messageResourceBundle().use(appRoot() + "artist");
|
messageResourceBundle().use(appRoot() + "artist");
|
||||||
messageResourceBundle().use(appRoot() + "artists");
|
messageResourceBundle().use(appRoot() + "artists");
|
||||||
messageResourceBundle().use(appRoot() + "messages");
|
|
||||||
messageResourceBundle().use(appRoot() + "mediaplayer");
|
messageResourceBundle().use(appRoot() + "mediaplayer");
|
||||||
messageResourceBundle().use(appRoot() + "templates");
|
messageResourceBundle().use(appRoot() + "messages");
|
||||||
|
messageResourceBundle().use(appRoot() + "playlist");
|
||||||
messageResourceBundle().use(appRoot() + "release");
|
messageResourceBundle().use(appRoot() + "release");
|
||||||
messageResourceBundle().use(appRoot() + "releases");
|
messageResourceBundle().use(appRoot() + "releases");
|
||||||
messageResourceBundle().use(appRoot() + "tracks");
|
messageResourceBundle().use(appRoot() + "tracks");
|
||||||
|
messageResourceBundle().use(appRoot() + "templates");
|
||||||
|
|
||||||
setTitle("LMS");
|
setTitle("LMS");
|
||||||
|
|
||||||
@@ -266,10 +268,24 @@ LmsApplication::handleAuthEvent(void)
|
|||||||
main->bindWidget("contents", mainStack);
|
main->bindWidget("contents", mainStack);
|
||||||
|
|
||||||
mainStack->addWidget(new Home());
|
mainStack->addWidget(new Home());
|
||||||
mainStack->addWidget(new Explore());
|
|
||||||
mainStack->addWidget(new Wt::WText("PLAYLIST"));
|
auto explore = new Explore();
|
||||||
|
mainStack->addWidget(explore);
|
||||||
|
|
||||||
|
auto playlist = new Playlist();
|
||||||
|
mainStack->addWidget(playlist);
|
||||||
mainStack->addWidget(new Wt::WText("SETTINGS"));
|
mainStack->addWidget(new Wt::WText("SETTINGS"));
|
||||||
|
|
||||||
|
explore->tracksAdd.connect(std::bind([=] (std::vector<Database::id_type> tracks)
|
||||||
|
{
|
||||||
|
playlist->addTracks(tracks);
|
||||||
|
}, std::placeholders::_1));
|
||||||
|
|
||||||
|
explore->tracksPlay.connect(std::bind([=] (std::vector<Database::id_type> tracks)
|
||||||
|
{
|
||||||
|
playlist->playTracks(tracks);
|
||||||
|
}, std::placeholders::_1));
|
||||||
|
|
||||||
// MediaPlayer
|
// MediaPlayer
|
||||||
auto player = new MediaPlayer();
|
auto player = new MediaPlayer();
|
||||||
main->bindWidget("player", player);
|
main->bindWidget("player", player);
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* 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 <Wt/WTemplate>
|
||||||
|
#include <Wt/WText>
|
||||||
|
|
||||||
|
#include "PlaylistView.hpp"
|
||||||
|
|
||||||
|
namespace UserInterface {
|
||||||
|
|
||||||
|
Playlist::Playlist(Wt::WContainerWidget* parent)
|
||||||
|
: Wt::WContainerWidget(parent)
|
||||||
|
{
|
||||||
|
auto t = new Wt::WTemplate(Wt::WString::tr("template-playlist"), this);
|
||||||
|
t->addFunction("tr", &Wt::WTemplate::Functions::tr);
|
||||||
|
|
||||||
|
auto saveBtn = new Wt::WText(Wt::WString::tr("btn-playlist-save-btn"), Wt::XHTMLText);
|
||||||
|
t->bindWidget("save-btn", saveBtn);
|
||||||
|
|
||||||
|
auto loadBtn = new Wt::WText(Wt::WString::tr("btn-playlist-load-btn"), Wt::XHTMLText);
|
||||||
|
t->bindWidget("load-btn", loadBtn);
|
||||||
|
|
||||||
|
auto clearBtn = new Wt::WText(Wt::WString::tr("btn-playlist-clear-btn"), Wt::XHTMLText);
|
||||||
|
t->bindWidget("clear-btn", clearBtn);
|
||||||
|
|
||||||
|
_entriesContainer = new Wt::WContainerWidget();
|
||||||
|
t->bindWidget("entries", _entriesContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Playlist::addTracks(const std::vector<Database::id_type>& trackIds)
|
||||||
|
{
|
||||||
|
for (auto trackId : trackIds)
|
||||||
|
std::cerr << "Adding track " << trackId << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Playlist::playTracks(const std::vector<Database::id_type>& trackIds)
|
||||||
|
{
|
||||||
|
for (auto trackId : trackIds)
|
||||||
|
std::cerr << "Playing track " << trackId << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Playlist::refresh()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace UserInterface
|
||||||
|
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Wt/WContainerWidget>
|
||||||
|
|
||||||
|
#include "database/Types.hpp"
|
||||||
|
|
||||||
|
namespace UserInterface {
|
||||||
|
|
||||||
|
class Playlist : public Wt::WContainerWidget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Playlist(Wt::WContainerWidget* parent = 0);
|
||||||
|
|
||||||
|
void addTracks(const std::vector<Database::id_type>& trackIds);
|
||||||
|
void playTracks(const std::vector<Database::id_type>& trackIds);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void refresh();
|
||||||
|
|
||||||
|
Wt::WContainerWidget* _entriesContainer;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace UserInterface
|
||||||
|
|
||||||
@@ -29,6 +29,7 @@
|
|||||||
#include "utils/Utils.hpp"
|
#include "utils/Utils.hpp"
|
||||||
|
|
||||||
#include "LmsApplication.hpp"
|
#include "LmsApplication.hpp"
|
||||||
|
#include "Filters.hpp"
|
||||||
#include "ReleaseView.hpp"
|
#include "ReleaseView.hpp"
|
||||||
|
|
||||||
namespace UserInterface {
|
namespace UserInterface {
|
||||||
@@ -112,11 +113,19 @@ Release::refresh()
|
|||||||
{
|
{
|
||||||
auto playBtn = new Wt::WText(Wt::WString::tr("btn-release-play-btn"), Wt::XHTMLText);
|
auto playBtn = new Wt::WText(Wt::WString::tr("btn-release-play-btn"), Wt::XHTMLText);
|
||||||
t->bindWidget("play-btn", playBtn);
|
t->bindWidget("play-btn", playBtn);
|
||||||
|
playBtn->clicked().connect(std::bind([=]
|
||||||
|
{
|
||||||
|
releasePlay.emit(releaseId);
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto addBtn = new Wt::WText(Wt::WString::tr("btn-release-add-btn"), Wt::XHTMLText);
|
auto addBtn = new Wt::WText(Wt::WString::tr("btn-release-add-btn"), Wt::XHTMLText);
|
||||||
t->bindWidget("add-btn", addBtn);
|
t->bindWidget("add-btn", addBtn);
|
||||||
|
addBtn->clicked().connect(std::bind([=]
|
||||||
|
{
|
||||||
|
releaseAdd.emit(releaseId);
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto tracksContainer = new Wt::WContainerWidget();
|
auto tracksContainer = new Wt::WContainerWidget();
|
||||||
@@ -129,6 +138,8 @@ Release::refresh()
|
|||||||
|
|
||||||
for (auto track : tracks)
|
for (auto track : tracks)
|
||||||
{
|
{
|
||||||
|
auto trackId = track.id();
|
||||||
|
|
||||||
Wt::WTemplate* entry = new Wt::WTemplate(Wt::WString::tr("template-release-entry"), tracksContainer);
|
Wt::WTemplate* entry = new Wt::WTemplate(Wt::WString::tr("template-release-entry"), tracksContainer);
|
||||||
|
|
||||||
entry->bindString("name", Wt::WString::fromUTF8(track->getName()), Wt::PlainText);
|
entry->bindString("name", Wt::WString::fromUTF8(track->getName()), Wt::PlainText);
|
||||||
@@ -159,9 +170,17 @@ Release::refresh()
|
|||||||
|
|
||||||
auto playBtn = new Wt::WText(Wt::WString::tr("btn-release-play-btn"), Wt::XHTMLText);
|
auto playBtn = new Wt::WText(Wt::WString::tr("btn-release-play-btn"), Wt::XHTMLText);
|
||||||
entry->bindWidget("play-btn", playBtn);
|
entry->bindWidget("play-btn", playBtn);
|
||||||
|
playBtn->clicked().connect(std::bind([=]
|
||||||
|
{
|
||||||
|
trackPlay.emit(trackId);
|
||||||
|
}));
|
||||||
|
|
||||||
auto addBtn = new Wt::WText(Wt::WString::tr("btn-release-add-btn"), Wt::XHTMLText);
|
auto addBtn = new Wt::WText(Wt::WString::tr("btn-release-add-btn"), Wt::XHTMLText);
|
||||||
entry->bindWidget("add-btn", addBtn);
|
entry->bindWidget("add-btn", addBtn);
|
||||||
|
addBtn->clicked().connect(std::bind([=]
|
||||||
|
{
|
||||||
|
trackAdd.emit(trackId);
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,15 +21,20 @@
|
|||||||
|
|
||||||
#include <Wt/WContainerWidget>
|
#include <Wt/WContainerWidget>
|
||||||
|
|
||||||
#include "Filters.hpp"
|
|
||||||
|
|
||||||
namespace UserInterface {
|
namespace UserInterface {
|
||||||
|
|
||||||
|
class Filters;
|
||||||
class Release : public Wt::WContainerWidget
|
class Release : public Wt::WContainerWidget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Release(Filters* filters, Wt::WContainerWidget* parent = 0);
|
Release(Filters* filters, Wt::WContainerWidget* parent = 0);
|
||||||
|
|
||||||
|
Wt::Signal<Database::id_type> releaseAdd;
|
||||||
|
Wt::Signal<Database::id_type> releasePlay;
|
||||||
|
|
||||||
|
Wt::Signal<Database::id_type> trackAdd;
|
||||||
|
Wt::Signal<Database::id_type> trackPlay;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void refresh();
|
void refresh();
|
||||||
|
|
||||||
|
|||||||
+14
-3
@@ -30,6 +30,7 @@
|
|||||||
#include "utils/Utils.hpp"
|
#include "utils/Utils.hpp"
|
||||||
|
|
||||||
#include "LmsApplication.hpp"
|
#include "LmsApplication.hpp"
|
||||||
|
#include "Filters.hpp"
|
||||||
#include "ReleasesView.hpp"
|
#include "ReleasesView.hpp"
|
||||||
|
|
||||||
namespace UserInterface {
|
namespace UserInterface {
|
||||||
@@ -77,18 +78,20 @@ Releases::refresh(std::vector<std::string> searchKeywords)
|
|||||||
|
|
||||||
for (auto release : releases)
|
for (auto release : releases)
|
||||||
{
|
{
|
||||||
|
auto releaseId = release.id();
|
||||||
|
|
||||||
Wt::WTemplate* entry = new Wt::WTemplate(Wt::WString::tr("template-releases-entry"), _releasesContainer);
|
Wt::WTemplate* entry = new Wt::WTemplate(Wt::WString::tr("template-releases-entry"), _releasesContainer);
|
||||||
entry->addFunction("tr", Wt::WTemplate::Functions::tr);
|
entry->addFunction("tr", Wt::WTemplate::Functions::tr);
|
||||||
|
|
||||||
Wt::WAnchor* coverAnchor = new Wt::WAnchor(Wt::WLink(Wt::WLink::InternalPath, "/release/" + std::to_string(release.id())));
|
Wt::WAnchor* coverAnchor = new Wt::WAnchor(Wt::WLink(Wt::WLink::InternalPath, "/release/" + std::to_string(releaseId)));
|
||||||
Wt::WImage* cover = new Wt::WImage(coverAnchor);
|
Wt::WImage* cover = new Wt::WImage(coverAnchor);
|
||||||
cover->setImageLink(SessionImageResource()->getReleaseUrl(release.id(), 128));
|
cover->setImageLink(SessionImageResource()->getReleaseUrl(releaseId, 128));
|
||||||
// Some images may not be square
|
// Some images may not be square
|
||||||
cover->setWidth(128);
|
cover->setWidth(128);
|
||||||
entry->bindWidget("cover", coverAnchor);
|
entry->bindWidget("cover", coverAnchor);
|
||||||
|
|
||||||
{
|
{
|
||||||
Wt::WAnchor* releaseAnchor = new Wt::WAnchor(Wt::WLink(Wt::WLink::InternalPath, "/release/" + std::to_string(release.id())));
|
Wt::WAnchor* releaseAnchor = new Wt::WAnchor(Wt::WLink(Wt::WLink::InternalPath, "/release/" + std::to_string(releaseId)));
|
||||||
Wt::WText* releaseName = new Wt::WText(releaseAnchor);
|
Wt::WText* releaseName = new Wt::WText(releaseAnchor);
|
||||||
releaseName->setText(Wt::WString::fromUTF8(release->getName(), Wt::PlainText));
|
releaseName->setText(Wt::WString::fromUTF8(release->getName(), Wt::PlainText));
|
||||||
entry->bindWidget("release-name", releaseAnchor);
|
entry->bindWidget("release-name", releaseAnchor);
|
||||||
@@ -110,9 +113,17 @@ Releases::refresh(std::vector<std::string> searchKeywords)
|
|||||||
|
|
||||||
auto playBtn = new Wt::WText(Wt::WString::tr("btn-releases-play-btn"), Wt::XHTMLText);
|
auto playBtn = new Wt::WText(Wt::WString::tr("btn-releases-play-btn"), Wt::XHTMLText);
|
||||||
entry->bindWidget("play-btn", playBtn);
|
entry->bindWidget("play-btn", playBtn);
|
||||||
|
playBtn->clicked().connect(std::bind([=]
|
||||||
|
{
|
||||||
|
releasePlay.emit(releaseId);
|
||||||
|
}));
|
||||||
|
|
||||||
auto addBtn = new Wt::WText(Wt::WString::tr("btn-releases-add-btn"), Wt::XHTMLText);
|
auto addBtn = new Wt::WText(Wt::WString::tr("btn-releases-add-btn"), Wt::XHTMLText);
|
||||||
entry->bindWidget("add-btn", addBtn);
|
entry->bindWidget("add-btn", addBtn);
|
||||||
|
addBtn->clicked().connect(std::bind([=]
|
||||||
|
{
|
||||||
|
releaseAdd.emit(releaseId);
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,15 +21,18 @@
|
|||||||
|
|
||||||
#include <Wt/WContainerWidget>
|
#include <Wt/WContainerWidget>
|
||||||
|
|
||||||
#include "Filters.hpp"
|
|
||||||
|
|
||||||
namespace UserInterface {
|
namespace UserInterface {
|
||||||
|
|
||||||
|
class Filters;
|
||||||
|
|
||||||
class Releases : public Wt::WContainerWidget
|
class Releases : public Wt::WContainerWidget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Releases(Filters* filters, Wt::WContainerWidget* parent = 0);
|
Releases(Filters* filters, Wt::WContainerWidget* parent = 0);
|
||||||
|
|
||||||
|
Wt::Signal<Database::id_type> releaseAdd;
|
||||||
|
Wt::Signal<Database::id_type> releasePlay;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void refresh(std::vector<std::string> searchKeywords = std::vector<std::string>());
|
void refresh(std::vector<std::string> searchKeywords = std::vector<std::string>());
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
#include "utils/Utils.hpp"
|
#include "utils/Utils.hpp"
|
||||||
|
|
||||||
#include "LmsApplication.hpp"
|
#include "LmsApplication.hpp"
|
||||||
|
#include "Filters.hpp"
|
||||||
#include "TracksView.hpp"
|
#include "TracksView.hpp"
|
||||||
|
|
||||||
namespace UserInterface {
|
namespace UserInterface {
|
||||||
@@ -76,6 +77,7 @@ Tracks::refresh(std::vector<std::string> searchKeywords)
|
|||||||
|
|
||||||
for (auto track : tracks)
|
for (auto track : tracks)
|
||||||
{
|
{
|
||||||
|
auto trackId = track.id();
|
||||||
Wt::WTemplate* entry = new Wt::WTemplate(Wt::WString::tr("template-tracks-entry"), _tracksContainer);
|
Wt::WTemplate* entry = new Wt::WTemplate(Wt::WString::tr("template-tracks-entry"), _tracksContainer);
|
||||||
|
|
||||||
entry->bindString("name", Wt::WString::fromUTF8(track->getName()), Wt::PlainText);
|
entry->bindString("name", Wt::WString::fromUTF8(track->getName()), Wt::PlainText);
|
||||||
@@ -109,9 +111,17 @@ Tracks::refresh(std::vector<std::string> searchKeywords)
|
|||||||
|
|
||||||
auto playBtn = new Wt::WText(Wt::WString::tr("btn-tracks-play-btn"), Wt::XHTMLText);
|
auto playBtn = new Wt::WText(Wt::WString::tr("btn-tracks-play-btn"), Wt::XHTMLText);
|
||||||
entry->bindWidget("play-btn", playBtn);
|
entry->bindWidget("play-btn", playBtn);
|
||||||
|
playBtn->clicked().connect(std::bind([=]
|
||||||
|
{
|
||||||
|
trackPlay.emit(trackId);
|
||||||
|
}));
|
||||||
|
|
||||||
auto addBtn = new Wt::WText(Wt::WString::tr("btn-tracks-add-btn"), Wt::XHTMLText);
|
auto addBtn = new Wt::WText(Wt::WString::tr("btn-tracks-add-btn"), Wt::XHTMLText);
|
||||||
entry->bindWidget("add-btn", addBtn);
|
entry->bindWidget("add-btn", addBtn);
|
||||||
|
addBtn->clicked().connect(std::bind([=]
|
||||||
|
{
|
||||||
|
trackAdd.emit(trackId);
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,15 +21,17 @@
|
|||||||
|
|
||||||
#include <Wt/WContainerWidget>
|
#include <Wt/WContainerWidget>
|
||||||
|
|
||||||
#include "Filters.hpp"
|
|
||||||
|
|
||||||
namespace UserInterface {
|
namespace UserInterface {
|
||||||
|
|
||||||
|
class Filters;
|
||||||
class Tracks : public Wt::WContainerWidget
|
class Tracks : public Wt::WContainerWidget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Tracks(Filters* filters, Wt::WContainerWidget* parent = 0);
|
Tracks(Filters* filters, Wt::WContainerWidget* parent = 0);
|
||||||
|
|
||||||
|
Wt::Signal<Database::id_type> trackAdd;
|
||||||
|
Wt::Signal<Database::id_type> trackPlay;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void refresh(std::vector<std::string> searchKeywords = std::vector<std::string>());
|
void refresh(std::vector<std::string> searchKeywords = std::vector<std::string>());
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user