Upgrade from Wt3 to Wt4

This commit is contained in:
emeric
2018-04-16 16:56:51 +02:00
parent b743127076
commit 9cb4918f44
87 changed files with 954 additions and 2057 deletions
+22 -25
View File
@@ -17,10 +17,10 @@
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Wt/WFormModel>
#include <Wt/WLineEdit>
#include <Wt/WCheckBox>
#include <Wt/WPushButton>
#include <Wt/WFormModel.h>
#include <Wt/WLineEdit.h>
#include <Wt/WCheckBox.h>
#include <Wt/WPushButton.h>
#include "utils/Logger.hpp"
@@ -31,10 +31,10 @@
namespace UserInterface {
Auth::Auth(Wt::WContainerWidget *parent)
: Wt::WTemplateFormView(parent)
Auth::Auth()
: Wt::WTemplateFormView()
{
_model = new Wt::Auth::AuthModel(DbHandler().getAuthService(), DbHandler().getUserDatabase());
_model = std::make_shared<Wt::Auth::AuthModel>(LmsApp->getDb().getAuthService(), LmsApp->getDb().getUserDatabase());
_model->addPasswordAuth(&Database::Handler::getPasswordService());
@@ -43,50 +43,47 @@ Auth::Auth(Wt::WContainerWidget *parent)
addFunction("id", &WTemplate::Functions::id);
// LoginName
auto loginName = new Wt::WLineEdit();
setFormWidget(Wt::Auth::AuthModel::LoginNameField, loginName);
setFormWidget(Wt::Auth::AuthModel::LoginNameField, std::make_unique<Wt::WLineEdit>());
// Password
auto password = new Wt::WLineEdit();
setFormWidget(Wt::Auth::AuthModel::PasswordField, password);
password->setEchoMode(Wt::WLineEdit::Password);
auto password = std::make_unique<Wt::WLineEdit>();
password->setEchoMode(Wt::EchoMode::Password);
password->enterPressed().connect(this, &Auth::processAuth);
setFormWidget(Wt::Auth::AuthModel::PasswordField, std::move(password));
// Remember Me
auto rememberMe = new Wt::WCheckBox();
setFormWidget(Wt::Auth::AuthModel::RememberMeField, rememberMe);
setFormWidget(Wt::Auth::AuthModel::RememberMeField, std::make_unique<Wt::WCheckBox>());
auto loginBtn = new Wt::WPushButton(Wt::WString::tr("Lms.login"));
bindWidget("login-btn", loginBtn);
Wt::WPushButton* loginBtn = bindNew<Wt::WPushButton>("login-btn", Wt::WString::tr("Lms.login"));
loginBtn->clicked().connect(this, &Auth::processAuth);
password->enterPressed().connect(this, &Auth::processAuth);
DbHandler().getLogin().changed().connect(std::bind([=]
LmsApp->getDb().getLogin().changed().connect(std::bind([=]
{
if (DbHandler().getLogin().loggedIn())
if (LmsApp->getDb().getLogin().loggedIn())
this->setHidden(true);
}));
Wt::Auth::User user = _model->processAuthToken();
_model->loginUser(DbHandler().getLogin(), user, Wt::Auth::WeakLogin);
_model->loginUser(LmsApp->getDb().getLogin(), user, Wt::Auth::LoginState::Weak);
updateView(_model);
updateView(_model.get());
}
void
Auth::processAuth()
{
updateModel(_model);
updateModel(_model.get());
if (_model->validate())
_model->login(DbHandler().getLogin());
_model->login(LmsApp->getDb().getLogin());
else
updateView(_model);
updateView(_model.get());
}
void
Auth::logout()
{
_model->logout(DbHandler().getLogin());
_model->logout(LmsApp->getDb().getLogin());
}
} // namespace UserInterface
+4 -6
View File
@@ -19,24 +19,22 @@
#pragma once
#include <Wt/WContainerWidget>
#include <Wt/WTemplateFormView>
#include <Wt/Auth/Login>
#include <Wt/Auth/AuthModel>
#include <Wt/WTemplateFormView.h>
#include <Wt/Auth/AuthModel.h>
namespace UserInterface {
class Auth : public Wt::WTemplateFormView
{
public:
Auth(Wt::WContainerWidget *parent = 0);
Auth();
void logout();
private:
void processAuth();
Wt::Auth::AuthModel* _model;
std::shared_ptr<Wt::Auth::AuthModel> _model;
};
+5 -4
View File
@@ -17,7 +17,7 @@
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Wt/WTemplate>
#include <Wt/WTemplate.h>
#include "utils/Logger.hpp"
@@ -28,12 +28,13 @@
namespace UserInterface {
Home::Home(Wt::WContainerWidget *parent)
: Wt::WContainerWidget(parent)
Home::Home()
: Wt::WContainerWidget()
{
auto t = new Wt::WTemplate(Wt::WString::tr("Lms.Home.template"), this);
auto t = std::make_unique<Wt::WTemplate>(Wt::WString::tr("Lms.Home.template"));
t->addFunction("tr", &Wt::WTemplate::Functions::tr);
this->addWidget(std::move(t));
}
} // namespace UserInterface
+2 -2
View File
@@ -19,14 +19,14 @@
#pragma once
#include <Wt/WContainerWidget>
#include <Wt/WContainerWidget.h>
namespace UserInterface {
class Home : public Wt::WContainerWidget
{
public:
Home(Wt::WContainerWidget *parent = 0);
Home();
private:
+60 -110
View File
@@ -17,15 +17,16 @@
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Wt/WAnchor>
#include <Wt/WBootstrapTheme>
#include <Wt/WEnvironment>
#include <Wt/WMenu>
#include <Wt/WNavigationBar>
#include <Wt/WPopupMenu>
#include <Wt/WStackedWidget>
#include <Wt/WText>
#include <Wt/Auth/Identity>
#include <Wt/WAnchor.h>
#include <Wt/WBootstrapTheme.h>
#include <Wt/WEnvironment.h>
#include <Wt/WMenu.h>
#include <Wt/WNavigationBar.h>
#include <Wt/WPopupMenu.h>
#include <Wt/WServer.h>
#include <Wt/WStackedWidget.h>
#include <Wt/WText.h>
#include <Wt/Auth/Identity.h>
#include "config/config.h"
#include "utils/Logger.hpp"
@@ -49,14 +50,14 @@
namespace UserInterface {
Wt::WApplication*
std::unique_ptr<Wt::WApplication>
LmsApplication::create(const Wt::WEnvironment& env, Wt::Dbo::SqlConnectionPool& connectionPool, Scanner::MediaScanner& scanner)
{
/*
* You could read information from the environment to decide whether
* the user has permission to start a new application
*/
return new LmsApplication(env, connectionPool, scanner);
return std::make_unique<LmsApplication>(env, connectionPool, scanner);
}
LmsApplication*
@@ -78,10 +79,10 @@ LmsApplication::LmsApplication(const Wt::WEnvironment& env, Wt::Dbo::SqlConnecti
_imageResource(nullptr),
_transcodeResource(nullptr)
{
Wt::WBootstrapTheme *bootstrapTheme = new Wt::WBootstrapTheme(this);
bootstrapTheme->setVersion(Wt::WBootstrapTheme::Version3);
auto bootstrapTheme = std::make_unique<Wt::WBootstrapTheme>();
bootstrapTheme->setVersion(Wt::BootstrapVersion::v3);
bootstrapTheme->setResponsive(true);
setTheme(bootstrapTheme);
setTheme(std::move(bootstrapTheme));
useStyleSheet("css/lms.css");
useStyleSheet("resources/font-awesome/css/font-awesome.min.css");
@@ -90,7 +91,7 @@ LmsApplication::LmsApplication(const Wt::WEnvironment& env, Wt::Dbo::SqlConnecti
messageResourceBundle().use(appRoot() + "admin-database");
messageResourceBundle().use(appRoot() + "admin-user");
messageResourceBundle().use(appRoot() + "admin-users");
messageResourceBundle().use(appRoot() + "admin-wizard");
messageResourceBundle().use(appRoot() + "admin-initwizard");
messageResourceBundle().use(appRoot() + "artist");
messageResourceBundle().use(appRoot() + "artists");
messageResourceBundle().use(appRoot() + "home");
@@ -113,20 +114,22 @@ LmsApplication::LmsApplication(const Wt::WEnvironment& env, Wt::Dbo::SqlConnecti
// If here is no account in the database, launch the first connection wizard
bool firstConnection;
{
Wt::Dbo::Transaction transaction(DboSession());
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
firstConnection = (Database::User::getAll(DboSession()).size() == 0);
firstConnection = (Database::User::getAll(LmsApp->getDboSession()).size() == 0);
}
LMS_LOG(UI, DEBUG) << "Creating root widget. First connection = " << std::boolalpha << firstConnection;
if (firstConnection)
{
root()->addWidget(new InitWizardView());
root()->addWidget(std::make_unique<InitWizardView>());
}
else
{
DbHandler().getLogin().changed().connect(std::bind([=]
_auth = root()->addNew<Auth>();
LmsApp->getDb().getLogin().changed().connect(std::bind([=]
{
try
{
@@ -138,68 +141,31 @@ LmsApplication::LmsApplication(const Wt::WEnvironment& env, Wt::Dbo::SqlConnecti
throw std::runtime_error("Internal error");
}
}));
_auth = new Auth();
root()->addWidget(_auth);
}
}
Database::Handler& DbHandler()
{
return LmsApplication::instance()->getDbHandler();
}
Wt::Dbo::Session& DboSession()
{
return DbHandler().getSession();
}
const Wt::Auth::User& CurrentAuthUser()
{
return DbHandler().getLogin().user();
}
Database::User::pointer CurrentUser()
{
return DbHandler().getCurrentUser();
}
ImageResource* SessionImageResource()
{
return LmsApplication::instance()->getImageResource();
}
TranscodeResource* SessionTranscodeResource()
{
return LmsApplication::instance()->getTranscodeResource();
}
Scanner::MediaScanner& MediaScanner()
{
return LmsApplication::instance()->getMediaScanner();
}
Wt::WAnchor*
std::unique_ptr<Wt::WAnchor>
LmsApplication::createArtistAnchor(Database::Artist::pointer artist, bool addText)
{
auto res = new Wt::WAnchor(Wt::WLink(Wt::WLink::InternalPath, "/artist/" + std::to_string(artist.id())));
auto res = std::make_unique<Wt::WAnchor>(Wt::WLink(Wt::LinkType::InternalPath, "/artist/" + std::to_string(artist.id())));
if (addText)
{
res->setTextFormat(Wt::PlainText);
res->setTextFormat(Wt::TextFormat::Plain);
res->setText(Wt::WString::fromUTF8(artist->getName()));
}
return res;
}
Wt::WAnchor*
std::unique_ptr<Wt::WAnchor>
LmsApplication::createReleaseAnchor(Database::Release::pointer release, bool addText)
{
auto res = new Wt::WAnchor(Wt::WLink(Wt::WLink::InternalPath, "/release/" + std::to_string(release.id())));
auto res = std::make_unique<Wt::WAnchor>(Wt::WLink(Wt::LinkType::InternalPath, "/release/" + std::to_string(release.id())));
if (addText)
{
res->setTextFormat(Wt::PlainText);
res->setTextFormat(Wt::TextFormat::Plain);
res->setText(Wt::WString::fromUTF8(release->getName()));
}
@@ -274,7 +240,7 @@ handlePathChange(Wt::WStackedWidget* stack, bool isAdmin)
void
LmsApplication::handleAuthEvent(void)
{
if (!DbHandler().getLogin().loggedIn())
if (!LmsApp->getDb().getLogin().loggedIn())
{
LMS_LOG(UI, INFO) << "User logged out, session = " << Wt::WApplication::instance()->sessionId();
@@ -282,73 +248,69 @@ LmsApplication::handleAuthEvent(void)
return;
}
LMS_LOG(UI, INFO) << "User '" << CurrentAuthUser().identity(Wt::Auth::Identity::LoginName) << "' logged in from '" << Wt::WApplication::instance()->environment().clientAddress() << "', user agent = " << Wt::WApplication::instance()->environment().agent() << ", session = " << Wt::WApplication::instance()->sessionId();
LMS_LOG(UI, INFO) << "User '" << LmsApp->getCurrentAuthUser().identity(Wt::Auth::Identity::LoginName) << "' logged in from '" << Wt::WApplication::instance()->environment().clientAddress() << "', user agent = " << Wt::WApplication::instance()->environment().userAgent() << ", session = " << Wt::WApplication::instance()->sessionId();
{
Wt::Dbo::Transaction transaction (DboSession());
_isAdmin = CurrentUser()->isAdmin();
Wt::Dbo::Transaction transaction (LmsApp->getDboSession());
_isAdmin = LmsApp->getCurrentUser()->isAdmin();
}
_imageResource = new ImageResource(_db, root());
_transcodeResource = new TranscodeResource(_db, root());
_imageResource = std::make_shared<ImageResource>(_db);
_transcodeResource = std::make_shared<TranscodeResource>(_db);
setConfirmCloseMessage(Wt::WString::tr("Lms.quit-confirm"));
auto main = new Wt::WTemplate(Wt::WString::tr("Lms.template"), root());
Wt::WTemplate* main = root()->addWidget(std::make_unique<Wt::WTemplate>(Wt::WString::tr("Lms.template")));
// Navbar
auto navbar = new Wt::WNavigationBar();
navbar->setTitle("LMS", Wt::WLink(Wt::WLink::InternalPath, "/home"));
Wt::WNavigationBar* navbar = main->bindNew<Wt::WNavigationBar>("navbar-top");
navbar->setTitle("LMS", Wt::WLink(Wt::LinkType::InternalPath, "/home"));
navbar->setResponsive(true);
main->bindWidget("navbar-top", navbar);
auto menu = new Wt::WMenu();
Wt::WMenu* menu = navbar->addMenu(std::make_unique<Wt::WMenu>());
{
auto menuItem = menu->insertItem(0, Wt::WString::tr("Lms.Explore.artists"));
menuItem->setLink(Wt::WLink(Wt::WLink::InternalPath, "/artists"));
menuItem->setLink(Wt::WLink(Wt::LinkType::InternalPath, "/artists"));
menuItem->setSelectable(false);
}
{
auto menuItem = menu->insertItem(1, Wt::WString::tr("Lms.Explore.releases"));
menuItem->setLink(Wt::WLink(Wt::WLink::InternalPath, "/releases"));
menuItem->setLink(Wt::WLink(Wt::LinkType::InternalPath, "/releases"));
menuItem->setSelectable(false);
}
{
auto menuItem = menu->insertItem(2, Wt::WString::tr("Lms.Explore.tracks"));
menuItem->setLink(Wt::WLink(Wt::WLink::InternalPath, "/tracks"));
menuItem->setLink(Wt::WLink(Wt::LinkType::InternalPath, "/tracks"));
menuItem->setSelectable(false);
}
{
auto menuItem = menu->insertItem(3, Wt::WString::tr("Lms.PlayQueue.playqueue"));
menuItem->setLink(Wt::WLink(Wt::WLink::InternalPath, "/playqueue"));
menuItem->setLink(Wt::WLink(Wt::LinkType::InternalPath, "/playqueue"));
menuItem->setSelectable(false);
}
navbar->addMenu(menu);
auto rightMenu = new Wt::WMenu();
Wt::WMenu* rightMenu = navbar->addMenu(std::make_unique<Wt::WMenu>(), Wt::AlignmentFlag::Right);
std::size_t itemCounter = 0;
if (_isAdmin)
{
auto menuItem = rightMenu->insertItem(itemCounter++, Wt::WString::tr("Lms.administration"));
menuItem->setSelectable(false);
Wt::WPopupMenu *admin = new Wt::WPopupMenu();
auto admin = std::make_unique<Wt::WPopupMenu>();
auto dbSettings = admin->insertItem(0, Wt::WString::tr("Lms.Admin.Database.database"));
dbSettings->setLink(Wt::WLink(Wt::WLink::InternalPath, "/admin/database"));
dbSettings->setLink(Wt::WLink(Wt::LinkType::InternalPath, "/admin/database"));
dbSettings->setSelectable(false);
auto usersSettings = admin->insertItem(1, Wt::WString::tr("Lms.Admin.Users.users"));
usersSettings->setLink(Wt::WLink(Wt::WLink::InternalPath, "/admin/users"));
usersSettings->setLink(Wt::WLink(Wt::LinkType::InternalPath, "/admin/users"));
usersSettings->setSelectable(false);
menuItem->setMenu(admin);
menuItem->setMenu(std::move(admin));
}
{
auto menuItem = rightMenu->insertItem(itemCounter++, Wt::WString::tr("Lms.Settings.settings"));
menuItem->setLink(Wt::WLink(Wt::WLink::InternalPath, "/settings"));
menuItem->setLink(Wt::WLink(Wt::LinkType::InternalPath, "/settings"));
menuItem->setSelectable(false);
}
{
@@ -360,34 +322,22 @@ LmsApplication::handleAuthEvent(void)
_auth->logout();
}));
}
navbar->addMenu(rightMenu, Wt::AlignRight);
// Contents
Wt::WStackedWidget* mainStack = new Wt::WStackedWidget();
main->bindWidget("contents", mainStack);
// Order is important in mainStack, see IdxRoot!
Wt::WStackedWidget* mainStack = main->bindNew<Wt::WStackedWidget>("contents");
mainStack->addWidget(new Home());
auto explore = new Explore();
mainStack->addWidget(explore);
auto playqueue = new PlayQueue();
mainStack->addWidget(playqueue);
auto settings = new SettingsView();
mainStack->addWidget(settings);
mainStack->addNew<Home>();
Explore* explore = mainStack->addNew<Explore>();
PlayQueue* playqueue = mainStack->addNew<PlayQueue>();
mainStack->addNew<SettingsView>();
// Admin stuff
if (_isAdmin)
{
auto databaseSettings = new DatabaseSettingsView();
mainStack->addWidget(databaseSettings);
auto users = new UsersView();
mainStack->addWidget(users);
auto user = new UserView();
mainStack->addWidget(user);
mainStack->addNew<DatabaseSettingsView>();
mainStack->addNew<UsersView>();
mainStack->addNew<UserView>();
}
explore->tracksAdd.connect(std::bind([=] (std::vector<Database::Track::pointer> tracks)
@@ -400,9 +350,9 @@ LmsApplication::handleAuthEvent(void)
playqueue->playTracks(tracks);
}, std::placeholders::_1));
// MediaPlayer
auto player = new MediaPlayer();
main->bindWidget("player", player);
MediaPlayer* player = main->bindNew<MediaPlayer>("player");
// Events from MediaPlayer
player->playNext.connect(std::bind([=]
@@ -468,7 +418,7 @@ void
LmsApplication::notifyMsg(const Wt::WString& message)
{
LMS_LOG(UI, INFO) << "Notifying message '" << message.toUTF8() << "'";
root()->addWidget(new Wt::WText(message));
root()->addNew<Wt::WText>(message);
}
} // namespace UserInterface
+18 -19
View File
@@ -20,8 +20,8 @@
#ifndef LMS_APPLICATION_HPP
#define LMS_APPLICATION_HPP
#include <Wt/WApplication>
#include <Wt/Dbo/SqlConnectionPool>
#include <Wt/WApplication.h>
#include <Wt/Dbo/SqlConnectionPool.h>
#include "database/DatabaseHandler.hpp"
#include "scanner/MediaScanner.hpp"
@@ -36,13 +36,20 @@ class ImageResource;
class LmsApplication : public Wt::WApplication
{
public:
static Wt::WApplication *create(const Wt::WEnvironment& env, Wt::Dbo::SqlConnectionPool& connectionPool, Scanner::MediaScanner& scanner);
LmsApplication(const Wt::WEnvironment& env, Wt::Dbo::SqlConnectionPool& connectionPool, Scanner::MediaScanner& scanner);
static std::unique_ptr<Wt::WApplication> create(const Wt::WEnvironment& env,
Wt::Dbo::SqlConnectionPool& connectionPool, Scanner::MediaScanner& scanner);
static LmsApplication* instance();
// Session application data
ImageResource* getImageResource() { return _imageResource; }
TranscodeResource* getTranscodeResource() { return _transcodeResource; }
Database::Handler& getDbHandler() { return _db;}
std::shared_ptr<ImageResource> getImageResource() { return _imageResource; }
std::shared_ptr<TranscodeResource> getTranscodeResource() { return _transcodeResource; }
Database::Handler& getDb() { return _db;}
Wt::Dbo::Session& getDboSession() { return _db.getSession();}
const Wt::Auth::User& getCurrentAuthUser() { return _db.getLogin().user(); }
Database::User::pointer getCurrentUser() { return _db.getCurrentUser(); }
Scanner::MediaScanner& getMediaScanner() { return _scanner; }
@@ -51,33 +58,25 @@ class LmsApplication : public Wt::WApplication
void goHomeAndQuit();
void notifyMsg(const Wt::WString& message);
static Wt::WAnchor* createArtistAnchor(Database::Artist::pointer artist, bool addText = true);
static Wt::WAnchor* createReleaseAnchor(Database::Release::pointer release, bool addText = true);
static std::unique_ptr<Wt::WAnchor> createArtistAnchor(Database::Artist::pointer artist, bool addText = true);
static std::unique_ptr<Wt::WAnchor> createReleaseAnchor(Database::Release::pointer release, bool addText = true);
private:
LmsApplication(const Wt::WEnvironment& env, Wt::Dbo::SqlConnectionPool& connectionPool, Scanner::MediaScanner& scanner);
void handleAuthEvent(void);
void notify(const Wt::WEvent& event) override;
Database::Handler _db;
Auth* _auth;
Scanner::MediaScanner& _scanner;
ImageResource* _imageResource;
TranscodeResource* _transcodeResource;
std::shared_ptr<ImageResource> _imageResource;
std::shared_ptr<TranscodeResource> _transcodeResource;
bool _isAdmin = false;
};
// Helpers to get session data
// Helper to get session data
#define LmsApp LmsApplication::instance()
Database::Handler& DbHandler();
Wt::Dbo::Session& DboSession();
const Wt::Auth::User& CurrentAuthUser();
Database::User::pointer CurrentUser();
} // namespace UserInterface
#endif
+5 -5
View File
@@ -30,8 +30,8 @@
namespace UserInterface {
MediaPlayer::MediaPlayer(Wt::WContainerWidget* parent)
: Wt::WTemplate(Wt::WString::tr("template-mediaplayer"), parent),
MediaPlayer::MediaPlayer()
: Wt::WTemplate(Wt::WString::tr("template-mediaplayer")),
playbackEnded(this, "playbackEnded"),
playPrevious(this, "playPrevious"),
playNext(this, "playNext")
@@ -49,8 +49,8 @@ MediaPlayer::playTrack(Database::Track::id_type trackId)
{
LMS_LOG(UI, DEBUG) << "Playing track ID = " << trackId;
Wt::Dbo::Transaction transaction(DboSession());
auto track = Database::Track::getById(DboSession(), trackId);
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
auto track = Database::Track::getById(LmsApp->getDboSession(), trackId);
try
{
@@ -66,7 +66,7 @@ MediaPlayer::playTrack(Database::Track::id_type trackId)
<< " release: " << (track->getRelease() ? "\"" + escape(track->getRelease()->getName()) + "\"" : "undefined" ) << ","
<< " artist: " << (track->getArtist() ? "\"" + escape(track->getArtist()->getName()) + "\"" : "undefined" ) << ","
<< " resource: \"" << resource << "\","
<< " duration: " << track->getDuration().total_seconds() << ","
<< " duration: " << std::chrono::duration_cast<std::chrono::seconds>(track->getDuration()).count() << ","
<< " imgResource: \"" << imgResource << "\","
<< "};";
oss << "LMS.mediaplayer.loadTrack(params, true)"; // true to autoplay
+6 -6
View File
@@ -19,8 +19,8 @@
#pragma once
#include <Wt/WJavaScript>
#include <Wt/WTemplate>
#include <Wt/WJavaScript.h>
#include <Wt/WTemplate.h>
#include "database/Types.hpp"
@@ -29,15 +29,15 @@ namespace UserInterface {
class MediaPlayer : public Wt::WTemplate
{
public:
MediaPlayer(Wt::WContainerWidget* parent = 0);
MediaPlayer();
void stop();
void playTrack(Database::Track::id_type);
// Signals
Wt::JSignal<void> playbackEnded;
Wt::JSignal<void> playPrevious;
Wt::JSignal<void> playNext;
Wt::JSignal<> playbackEnded;
Wt::JSignal<> playPrevious;
Wt::JSignal<> playNext;
private:
+47 -58
View File
@@ -17,9 +17,9 @@
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Wt/WAnchor>
#include <Wt/WImage>
#include <Wt/WText>
#include <Wt/WAnchor.h>
#include <Wt/WImage.h>
#include <Wt/WText.h>
#include "utils/Logger.hpp"
@@ -30,26 +30,39 @@ namespace UserInterface {
static const std::string currentPlayQueueName = "__current__playqueue__";
PlayQueue::PlayQueue(Wt::WContainerWidget* parent)
: Wt::WContainerWidget(parent)
PlayQueue::PlayQueue()
: Wt::WTemplate(Wt::WString::tr("Lms.PlayQueue.template"))
{
auto container = new Wt::WTemplate(Wt::WString::tr("Lms.PlayQueue.template"), this);
container->addFunction("tr", &Wt::WTemplate::Functions::tr);
addFunction("tr", &Wt::WTemplate::Functions::tr);
auto saveBtn = new Wt::WText(Wt::WString::tr("Lms.PlayQueue.save-to-playlist"), Wt::XHTMLText);
container->bindWidget("save-btn", saveBtn);
bindNew<Wt::WText>("save-btn", Wt::WString::tr("Lms.PlayQueue.save-to-playlist"), Wt::TextFormat::XHTML);
bindNew<Wt::WText>("load-btn", Wt::WString::tr("Lms.PlayQueue.load-from-playlist"), Wt::TextFormat::XHTML);
Wt::WText* clearBtn = bindNew<Wt::WText>("clear-btn", Wt::WString::tr("Lms.PlayQueue.clear"), Wt::TextFormat::XHTML);
auto loadBtn = new Wt::WText(Wt::WString::tr("Lms.PlayQueue.load-from-playlist"), Wt::XHTMLText);
container->bindWidget("load-btn", loadBtn);
_entriesContainer = bindNew<Wt::WContainerWidget>("entries");
_showMore = bindNew<Wt::WTemplate>("show-more", Wt::WString::tr("Lms.Explore.show-more"));
_showMore->addFunction("tr", &Wt::WTemplate::Functions::tr);
_showMore->setHidden(true);
_nbTracks = bindNew<Wt::WText>("nb-tracks");
{
Wt::Dbo::Transaction transaction (LmsApp->getDboSession());
auto playlist = Database::Playlist::get(LmsApp->getDboSession(), currentPlayQueueName, LmsApp->getCurrentUser());
if (!playlist)
playlist = Database::Playlist::create(LmsApp->getDboSession(), currentPlayQueueName, false, LmsApp->getCurrentUser());
_trackPos = LmsApp->getCurrentUser()->getCurPlayingTrackPos();
}
auto clearBtn = new Wt::WText(Wt::WString::tr("Lms.PlayQueue.clear"), Wt::XHTMLText);
container->bindWidget("clear-btn", clearBtn);
clearBtn->clicked().connect(std::bind([=]
{
{
Wt::Dbo::Transaction transaction(DboSession());
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
auto playlist = Database::Playlist::get(DboSession(), currentPlayQueueName, CurrentUser());
auto playlist = Database::Playlist::get(LmsApp->getDboSession(), currentPlayQueueName, LmsApp->getCurrentUser());
playlist.modify()->clear();
_showMore->setHidden(true);
}
@@ -58,27 +71,6 @@ PlayQueue::PlayQueue(Wt::WContainerWidget* parent)
updateInfo();
}));
_entriesContainer = new Wt::WContainerWidget();
container->bindWidget("entries", _entriesContainer);
_showMore = new Wt::WTemplate(Wt::WString::tr("Lms.Explore.show-more"));
_showMore->addFunction("tr", &Wt::WTemplate::Functions::tr);
_showMore->setHidden(true);
container->bindWidget("show-more", _showMore);
_nbTracks = new Wt::WText();
container->bindWidget("nb-tracks", _nbTracks);
{
Wt::Dbo::Transaction transaction (DboSession());
auto playlist = Database::Playlist::get(DboSession(), currentPlayQueueName, CurrentUser());
if (!playlist)
playlist = Database::Playlist::create(DboSession(), currentPlayQueueName, false, CurrentUser());
_trackPos = CurrentUser()->getCurPlayingTrackPos();
}
_showMore->clicked().connect(std::bind([=]
{
addSome();
@@ -103,9 +95,9 @@ PlayQueue::play(std::size_t pos)
Database::Track::id_type trackId;
{
Wt::Dbo::Transaction transaction(DboSession());
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
auto playlist = Database::Playlist::get(DboSession(), currentPlayQueueName, CurrentUser());
auto playlist = Database::Playlist::get(LmsApp->getDboSession(), currentPlayQueueName, LmsApp->getCurrentUser());
// If out of range, stop playing
if (pos >= playlist->getCount())
@@ -149,9 +141,9 @@ PlayQueue::playNext()
void
PlayQueue::updateInfo()
{
Wt::Dbo::Transaction transaction(DboSession());
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
auto playlist = Database::Playlist::get(DboSession(), currentPlayQueueName, CurrentUser());
auto playlist = Database::Playlist::get(LmsApp->getDboSession(), currentPlayQueueName, LmsApp->getCurrentUser());
_nbTracks->setText(Wt::WString::tr("Lms.PlayQueue.nb-tracks").arg(playlist->getCount()));
}
@@ -179,10 +171,10 @@ PlayQueue::addTracks(const std::vector<Database::Track::pointer>& tracks)
LMS_LOG(UI, DEBUG) << "Adding tracks to the current queue";
auto playlist = Database::Playlist::get(DboSession(), currentPlayQueueName, CurrentUser());
auto playlist = Database::Playlist::get(LmsApp->getDboSession(), currentPlayQueueName, LmsApp->getCurrentUser());
for (auto track : tracks)
Database::PlaylistEntry::create(DboSession(), track, playlist);
Database::PlaylistEntry::create(LmsApp->getDboSession(), track, playlist);
updateInfo();
addSome();
@@ -193,9 +185,9 @@ PlayQueue::playTracks(const std::vector<Database::Track::pointer>& tracks)
{
LMS_LOG(UI, DEBUG) << "Emptying current queue to play new tracks";
Wt::Dbo::Transaction transaction(DboSession());
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
auto playqueue = Database::Playlist::get(DboSession(), currentPlayQueueName, CurrentUser());
auto playqueue = Database::Playlist::get(LmsApp->getDboSession(), currentPlayQueueName, LmsApp->getCurrentUser());
playqueue.modify()->clear();
_entriesContainer->clear();
@@ -209,9 +201,9 @@ PlayQueue::playTracks(const std::vector<Database::Track::pointer>& tracks)
void
PlayQueue::addSome()
{
Wt::Dbo::Transaction transaction (DboSession());
Wt::Dbo::Transaction transaction (LmsApp->getDboSession());
auto playlist = Database::Playlist::get(DboSession(), currentPlayQueueName, CurrentUser());
auto playlist = Database::Playlist::get(LmsApp->getDboSession(), currentPlayQueueName, LmsApp->getCurrentUser());
bool moreResults;
auto playlistEntries = playlist->getEntries(_entriesContainer->count(), 50, moreResults);
@@ -220,27 +212,24 @@ PlayQueue::addSome()
auto playlistEntryId = playlistEntry.id();
auto track = playlistEntry->getTrack();
Wt::WTemplate* entry = new Wt::WTemplate(Wt::WString::tr("Lms.PlayQueue.template.entry"), _entriesContainer);
Wt::WTemplate* entry = _entriesContainer->addNew<Wt::WTemplate>(Wt::WString::tr("Lms.PlayQueue.template.entry"));
entry->bindString("name", Wt::WString::fromUTF8(track->getName()), Wt::PlainText);
entry->bindString("name", Wt::WString::fromUTF8(track->getName()), Wt::TextFormat::Plain);
auto artist = track->getArtist();
if (artist)
{
entry->setCondition("if-has-artist", true);
Wt::WAnchor *artistAnchor = LmsApplication::createArtistAnchor(track->getArtist());
entry->bindWidget("artist-name", artistAnchor);
entry->bindWidget("artist-name", LmsApplication::createArtistAnchor(track->getArtist()));
}
auto release = track->getRelease();
if (release)
{
entry->setCondition("if-has-release", true);
Wt::WAnchor *releaseAnchor = LmsApplication::createReleaseAnchor(track->getRelease());
entry->bindWidget("release-name", releaseAnchor);
entry->bindWidget("release-name", LmsApplication::createReleaseAnchor(track->getRelease()));
}
auto playBtn = new Wt::WText(Wt::WString::tr("Lms.PlayQueue.play"), Wt::XHTMLText);
entry->bindWidget("play-btn", playBtn);
Wt::WText* playBtn = entry->bindNew<Wt::WText>("play-btn", Wt::WString::tr("Lms.PlayQueue.play"), Wt::TextFormat::XHTML);
playBtn->clicked().connect(std::bind([=]
{
auto pos = _entriesContainer->indexOf(entry);
@@ -248,15 +237,14 @@ PlayQueue::addSome()
play(pos);
}));
auto delBtn = new Wt::WText(Wt::WString::tr("Lms.PlayQueue.delete"), Wt::XHTMLText);
entry->bindWidget("del-btn", delBtn);
Wt::WText* delBtn = entry->bindNew<Wt::WText>("del-btn", Wt::WString::tr("Lms.PlayQueue.delete"), Wt::TextFormat::XHTML);
delBtn->clicked().connect(std::bind([=]
{
// Remove the entry n both the widget tree and the playqueue
{
Wt::Dbo::Transaction transaction (DboSession());
Wt::Dbo::Transaction transaction (LmsApp->getDboSession());
auto entryToRemove = Database::PlaylistEntry::getById(DboSession(), playlistEntryId);
auto entryToRemove = Database::PlaylistEntry::getById(LmsApp->getDboSession(), playlistEntryId);
entryToRemove.remove();
}
@@ -271,6 +259,7 @@ PlayQueue::addSome()
updateInfo();
}));
}
_showMore->setHidden(!moreResults);
+7 -7
View File
@@ -19,10 +19,10 @@
#pragma once
#include <Wt/WContainerWidget>
#include <Wt/WSignal>
#include <Wt/WTemplate>
#include <Wt/WText>
#include <Wt/WContainerWidget.h>
#include <Wt/WSignal.h>
#include <Wt/WTemplate.h>
#include <Wt/WText.h>
#include <boost/optional.hpp>
@@ -30,10 +30,10 @@
namespace UserInterface {
class PlayQueue : public Wt::WContainerWidget
class PlayQueue : public Wt::WTemplate
{
public:
PlayQueue(Wt::WContainerWidget* parent = 0);
PlayQueue();
void addTracks(const std::vector<Database::Track::pointer>& tracks);
void playTracks(const std::vector<Database::Track::pointer>& tracks);
@@ -48,7 +48,7 @@ class PlayQueue : public Wt::WContainerWidget
Wt::Signal<Database::Track::id_type> playTrack;
// Signal emitted when play has to be stopped
Wt::Signal<void> playbackStop;
Wt::Signal<> playbackStop;
private:
void addSome();
+61 -68
View File
@@ -17,13 +17,13 @@
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Wt/WString>
#include <Wt/WPushButton>
#include <Wt/WComboBox>
#include <Wt/WLineEdit>
#include <Wt/WString.h>
#include <Wt/WPushButton.h>
#include <Wt/WComboBox.h>
#include <Wt/WLineEdit.h>
#include <Wt/WFormModel>
#include <Wt/WStringListModel>
#include <Wt/WFormModel.h>
#include <Wt/WStringListModel.h>
#include "common/Validators.hpp"
@@ -45,8 +45,8 @@ class SettingsModel : public Wt::WFormModel
static const Field PasswordField;
static const Field PasswordConfirmField;
SettingsModel(Wt::WObject *parent = 0)
: Wt::WFormModel(parent)
SettingsModel()
: Wt::WFormModel()
{
initializeModels();
@@ -61,18 +61,18 @@ class SettingsModel : public Wt::WFormModel
loadData();
}
Wt::WAbstractItemModel *bitrateModel() { return _bitrateModel; }
Wt::WAbstractItemModel *encodingModel() { return _encodingModel; }
std::shared_ptr<Wt::WAbstractItemModel> bitrateModel() { return _bitrateModel; }
std::shared_ptr<Wt::WAbstractItemModel> encodingModel() { return _encodingModel; }
void loadData()
{
Wt::Dbo::Transaction transaction(DboSession());
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
auto bitrate = getBitrateRow(CurrentUser()->getAudioBitrate());
auto bitrate = getBitrateRow(LmsApp->getCurrentUser()->getAudioBitrate());
if (bitrate)
setValue(BitrateField, bitrateString(*bitrate));
auto encodingRow = getEncodingRow(CurrentUser()->getAudioEncoding());
auto encodingRow = getEncodingRow(LmsApp->getCurrentUser()->getAudioEncoding());
if (encodingRow)
setValue(EncodingField, encodingString(*encodingRow));
@@ -80,18 +80,18 @@ class SettingsModel : public Wt::WFormModel
void saveData()
{
Wt::Dbo::Transaction transaction(DboSession());
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
auto bitrateRow = getBitrateRow(Wt::asString(value(BitrateField)));
assert(bitrateRow);
CurrentUser().modify()->setAudioBitrate(bitrate(*bitrateRow));
LmsApp->getCurrentUser().modify()->setAudioBitrate(bitrate(*bitrateRow));
auto encodingRow = getEncodingRow(Wt::asString(value(EncodingField)));
CurrentUser().modify()->setAudioEncoding(encoding(*encodingRow));
LmsApp->getCurrentUser().modify()->setAudioEncoding(encoding(*encodingRow));
if (!valueText(PasswordField).empty())
{
Database::Handler::getPasswordService().updatePassword(CurrentAuthUser(), valueText(PasswordField));
Database::Handler::getPasswordService().updatePassword(LmsApp->getCurrentAuthUser(), valueText(PasswordField));
}
}
@@ -105,7 +105,7 @@ class SettingsModel : public Wt::WFormModel
{
// Evaluate the strength of the password
auto res = Database::Handler::getPasswordService().strengthValidator()->evaluateStrength(valueText(PasswordField),
CurrentAuthUser().identity(Wt::Auth::Identity::LoginName), "");
LmsApp->getCurrentAuthUser().identity(Wt::Auth::Identity::LoginName), "");
if (!res.isValid())
error = res.message();
@@ -115,7 +115,7 @@ class SettingsModel : public Wt::WFormModel
}
else if (field == PasswordConfirmField)
{
if (validation(PasswordField).state() == Wt::WValidator::Valid)
if (validation(PasswordField).state() == Wt::ValidationState::Valid)
{
if (valueText(PasswordField) != valueText(PasswordConfirmField))
error = Wt::WString::tr("Lms.passwords-dont-match");
@@ -126,9 +126,9 @@ class SettingsModel : public Wt::WFormModel
return Wt::WFormModel::validateField(field);
}
setValidation(field, Wt::WValidator::Result( error.empty() ? Wt::WValidator::Valid : Wt::WValidator::Invalid, error));
setValidation(field, Wt::WValidator::Result( error.empty() ? Wt::ValidationState::Valid : Wt::ValidationState::Invalid, error));
return (validation(field).state() == Wt::WValidator::Valid);
return (validation(field).state() == Wt::ValidationState::Valid);
}
boost::optional<int> getBitrateRow(Wt::WString value)
@@ -155,14 +155,14 @@ class SettingsModel : public Wt::WFormModel
std::size_t bitrate(int row)
{
return boost::any_cast<std::size_t>
(_bitrateModel->data(_bitrateModel->index(row, 0), Wt::UserRole));
return Wt::cpp17::any_cast<std::size_t>
(_bitrateModel->data(_bitrateModel->index(row, 0), Wt::ItemDataRole::User));
}
Wt::WString bitrateString(int row)
{
return boost::any_cast<Wt::WString>
(_bitrateModel->data(_bitrateModel->index(row, 0), Wt::DisplayRole));
return Wt::cpp17::any_cast<Wt::WString>
(_bitrateModel->data(_bitrateModel->index(row, 0), Wt::ItemDataRole::Display));
}
boost::optional<int> getEncodingRow(Wt::WString value)
@@ -189,14 +189,14 @@ class SettingsModel : public Wt::WFormModel
Database::AudioEncoding encoding(int row)
{
return boost::any_cast<Database::AudioEncoding>
(_encodingModel->data(_encodingModel->index(row, 0), Wt::UserRole));
return Wt::cpp17::any_cast<Database::AudioEncoding>
(_encodingModel->data(_encodingModel->index(row, 0), Wt::ItemDataRole::User));
}
Wt::WString encodingString(int row)
{
return boost::any_cast<Wt::WString>
(_encodingModel->data(_encodingModel->index(row, 0), Wt::DisplayRole));
return Wt::cpp17::any_cast<Wt::WString>
(_encodingModel->data(_encodingModel->index(row, 0), Wt::ItemDataRole::Display));
}
@@ -204,42 +204,42 @@ class SettingsModel : public Wt::WFormModel
void initializeModels()
{
_bitrateModel = new Wt::WStringListModel(this);
_bitrateModel = std::make_shared<Wt::WStringListModel>();
std::size_t maxAudioBitrate;
{
Wt::Dbo::Transaction transaction(DboSession());
maxAudioBitrate = CurrentUser()->getMaxAudioBitrate();
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
maxAudioBitrate = LmsApp->getCurrentUser()->getMaxAudioBitrate();
}
std::size_t id = 0;
for (auto bitrate : Database::User::audioBitrates)
for (std::size_t bitrate : Database::User::audioBitrates)
{
if (bitrate > maxAudioBitrate)
break;
_bitrateModel->addString( Wt::WString::fromUTF8(std::to_string(bitrate / 1000)) );
_bitrateModel->setData( id++, 0, bitrate, Wt::UserRole);
_bitrateModel->setData( id, 0, bitrate, Wt::ItemDataRole::User);
id++;
}
_encodingModel = new Wt::WStringListModel(this);
_encodingModel = std::make_shared<Wt::WStringListModel>();
_encodingModel->addString(Wt::WString::tr("Lms.Settings.auto"));
_encodingModel->setData(0, 0, Database::AudioEncoding::AUTO, Wt::UserRole);
_encodingModel->setData(0, 0, Database::AudioEncoding::AUTO, Wt::ItemDataRole::User);
_encodingModel->addString(Wt::WString::tr("Lms.Settings.mp3"));
_encodingModel->setData(1, 0, Database::AudioEncoding::MP3, Wt::UserRole);
_encodingModel->setData(1, 0, Database::AudioEncoding::MP3, Wt::ItemDataRole::User);
_encodingModel->addString(Wt::WString::tr("Lms.Settings.oga"));
_encodingModel->setData(2, 0, Database::AudioEncoding::OGA, Wt::UserRole);
_encodingModel->setData(2, 0, Database::AudioEncoding::OGA, Wt::ItemDataRole::User);
_encodingModel->addString(Wt::WString::tr("Lms.Settings.webma"));
_encodingModel->setData(3, 0, Database::AudioEncoding::WEBMA, Wt::UserRole);
_encodingModel->setData(3, 0, Database::AudioEncoding::WEBMA, Wt::ItemDataRole::User);
}
Wt::WStringListModel* _bitrateModel;
Wt::WStringListModel* _encodingModel;
std::shared_ptr<Wt::WStringListModel> _bitrateModel;
std::shared_ptr<Wt::WStringListModel> _encodingModel;
};
@@ -248,45 +248,38 @@ const Wt::WFormModel::Field SettingsModel::EncodingField = "encoding";
const Wt::WFormModel::Field SettingsModel::PasswordField = "password";
const Wt::WFormModel::Field SettingsModel::PasswordConfirmField = "password-confirm";
SettingsView::SettingsView(Wt::WContainerWidget *parent)
: Wt::WTemplateFormView(parent)
SettingsView::SettingsView()
: Wt::WTemplateFormView(Wt::WString::tr("Lms.Settings.template"))
{
auto model = new SettingsModel(this);
setTemplateText(tr("Lms.Settings.template"));
addFunction("tr", &WTemplate::Functions::tr);
addFunction("id", &WTemplate::Functions::id);
auto model = std::make_shared<SettingsModel>();
// Password
Wt::WLineEdit *password = new Wt::WLineEdit();
setFormWidget(SettingsModel::PasswordField, password);
password->setEchoMode(Wt::WLineEdit::Password);
auto password = std::make_unique<Wt::WLineEdit>();
password->setEchoMode(Wt::EchoMode::Password);
setFormWidget(SettingsModel::PasswordField, std::move(password));
// Password confirm
Wt::WLineEdit *passwordConfirm = new Wt::WLineEdit();
setFormWidget(SettingsModel::PasswordConfirmField, passwordConfirm);
passwordConfirm->setEchoMode(Wt::WLineEdit::Password);
auto passwordConfirm = std::make_unique<Wt::WLineEdit>();
passwordConfirm->setEchoMode(Wt::EchoMode::Password);
setFormWidget(SettingsModel::PasswordConfirmField, std::move(passwordConfirm));
// Bitrate
Wt::WComboBox *bitrate = new Wt::WComboBox();
setFormWidget(SettingsModel::BitrateField, bitrate);
auto bitrate = std::make_unique<Wt::WComboBox>();
bitrate->setModel(model->bitrateModel());
setFormWidget(SettingsModel::BitrateField, std::move(bitrate));
// Encoding
Wt::WComboBox *encoding = new Wt::WComboBox();
setFormWidget(SettingsModel::EncodingField, encoding);
auto encoding = std::make_unique<Wt::WComboBox>();
encoding->setModel(model->encodingModel());
setFormWidget(SettingsModel::EncodingField, std::move(encoding));
// Buttons
Wt::WPushButton *saveBtn = new Wt::WPushButton(Wt::WString::tr("Lms.apply"));
bindWidget("apply-btn", saveBtn);
Wt::WPushButton *discardBtn = new Wt::WPushButton(Wt::WString::tr("Lms.discard"));
bindWidget("discard-btn", discardBtn);
Wt::WPushButton *saveBtn = bindWidget("apply-btn", std::make_unique<Wt::WPushButton>(Wt::WString::tr("Lms.apply")));
Wt::WPushButton *discardBtn = bindWidget("discard-btn", std::make_unique<Wt::WPushButton>(Wt::WString::tr("Lms.discard")));
saveBtn->clicked().connect(std::bind([=] ()
{
updateModel(model);
updateModel(model.get());
if (model->validate())
{
@@ -295,17 +288,17 @@ SettingsView::SettingsView(Wt::WContainerWidget *parent)
}
// Udate the view: Delete any validation message in the view, etc.
updateView(model);
updateView(model.get());
}));
discardBtn->clicked().connect(std::bind([=] ()
{
model->loadData();
model->validate();
updateView(model);
updateView(model.get());
}));
updateView(model);
updateView(model.get());
}
} // namespace UserInterface
+2 -3
View File
@@ -19,15 +19,14 @@
#pragma once
#include <Wt/WContainerWidget>
#include <Wt/WTemplateFormView>
#include <Wt/WTemplateFormView.h>
namespace UserInterface {
class SettingsView : public Wt::WTemplateFormView
{
public:
SettingsView(Wt::WContainerWidget *parent = 0);
SettingsView();
};
} // namespace UserInterface
+60 -78
View File
@@ -17,13 +17,13 @@
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Wt/WString>
#include <Wt/WPushButton>
#include <Wt/WComboBox>
#include <Wt/WLineEdit>
#include <Wt/WString.h>
#include <Wt/WPushButton.h>
#include <Wt/WComboBox.h>
#include <Wt/WLineEdit.h>
#include <Wt/WFormModel>
#include <Wt/WStringListModel>
#include <Wt/WFormModel.h>
#include <Wt/WStringListModel.h>
#include "common/Validators.hpp"
#include "database/MediaDirectory.hpp"
@@ -46,8 +46,8 @@ class DatabaseSettingsModel : public Wt::WFormModel
static const Field UpdatePeriodField;
static const Field UpdateStartTimeField;
DatabaseSettingsModel(Wt::WObject *parent = 0)
: Wt::WFormModel(parent)
DatabaseSettingsModel()
: Wt::WFormModel()
{
initializeModels();
@@ -55,7 +55,7 @@ class DatabaseSettingsModel : public Wt::WFormModel
addField(UpdatePeriodField);
addField(UpdateStartTimeField);
DirectoryValidator* dirValidator = new DirectoryValidator();
auto dirValidator = std::make_shared<DirectoryValidator>();
dirValidator->setMandatory(true);
setValidator(MediaDirectoryField, dirValidator);
@@ -66,42 +66,42 @@ class DatabaseSettingsModel : public Wt::WFormModel
loadData();
}
Wt::WAbstractItemModel *updatePeriodModel() { return _updatePeriodModel; }
Wt::WAbstractItemModel *updateStartTimeModel() { return _updateStartTimeModel; }
std::shared_ptr<Wt::WAbstractItemModel> updatePeriodModel() { return _updatePeriodModel; }
std::shared_ptr<Wt::WAbstractItemModel> updateStartTimeModel() { return _updateStartTimeModel; }
void loadData()
{
using namespace Database;
Wt::Dbo::Transaction transaction(DboSession());
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
std::vector<MediaDirectory::pointer> mediaDirectories = MediaDirectory::getAll(DboSession());
std::vector<MediaDirectory::pointer> mediaDirectories = MediaDirectory::getAll(LmsApp->getDboSession());
if (!mediaDirectories.empty())
setValue(MediaDirectoryField, mediaDirectories.front()->getPath().string());
auto periodRow = getUpdatePeriodModelRow( Scanner::getUpdatePeriod(DboSession()) );
auto periodRow = getUpdatePeriodModelRow( Scanner::getUpdatePeriod(LmsApp->getDboSession()) );
if (periodRow)
setValue(UpdatePeriodField, updatePeriodString(*periodRow));
auto startTimeRow = getUpdateStartTimeModelRow( Scanner::getUpdateStartTime(DboSession()) );
auto startTimeRow = getUpdateStartTimeModelRow( Scanner::getUpdateStartTime(LmsApp->getDboSession()) );
if (startTimeRow)
setValue(UpdateStartTimeField, updateStartTimeString(*startTimeRow) );
}
void saveData()
{
Wt::Dbo::Transaction transaction(DboSession());
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
MediaDirectory::eraseAll(DboSession());
MediaDirectory::create(DboSession(), boost::any_cast<Wt::WString>(value(MediaDirectoryField)).toUTF8());
MediaDirectory::eraseAll(LmsApp->getDboSession());
MediaDirectory::create(LmsApp->getDboSession(), Wt::cpp17::any_cast<Wt::WString>(value(MediaDirectoryField)).toUTF8());
auto updatePeriodRow = getUpdatePeriodModelRow( boost::any_cast<Wt::WString>(value(UpdatePeriodField)));
auto updatePeriodRow = getUpdatePeriodModelRow( Wt::cpp17::any_cast<Wt::WString>(value(UpdatePeriodField)));
assert(updatePeriodRow);
Scanner::setUpdatePeriod(DboSession(), updatePeriod(*updatePeriodRow));
Scanner::setUpdatePeriod(LmsApp->getDboSession(), updatePeriod(*updatePeriodRow));
auto startTimeRow = getUpdateStartTimeModelRow( boost::any_cast<Wt::WString>(value(UpdateStartTimeField)));
auto startTimeRow = getUpdateStartTimeModelRow( Wt::cpp17::any_cast<Wt::WString>(value(UpdateStartTimeField)));
assert(startTimeRow);
Scanner::setUpdateStartTime(DboSession(), updateStartTime(*startTimeRow));
Scanner::setUpdateStartTime(LmsApp->getDboSession(), updateStartTime(*startTimeRow));
}
boost::optional<int> getUpdatePeriodModelRow(Wt::WString value)
@@ -128,14 +128,14 @@ class DatabaseSettingsModel : public Wt::WFormModel
Scanner::UpdatePeriod updatePeriod(int row)
{
return boost::any_cast<Scanner::UpdatePeriod>
(_updatePeriodModel->data(_updatePeriodModel->index(row, 0), Wt::UserRole));
return Wt::cpp17::any_cast<Scanner::UpdatePeriod>
(_updatePeriodModel->data(_updatePeriodModel->index(row, 0), Wt::ItemDataRole::User));
}
Wt::WString updatePeriodString(int row)
{
return boost::any_cast<Wt::WString>
(_updatePeriodModel->data(_updatePeriodModel->index(row, 0), Wt::DisplayRole));
return Wt::cpp17::any_cast<Wt::WString>
(_updatePeriodModel->data(_updatePeriodModel->index(row, 0), Wt::ItemDataRole::Display));
}
@@ -150,7 +150,7 @@ class DatabaseSettingsModel : public Wt::WFormModel
return boost::none;
}
boost::optional<int> getUpdateStartTimeModelRow(boost::posix_time::time_duration startTime)
boost::optional<int> getUpdateStartTimeModelRow(Wt::WTime startTime)
{
for (int i = 0; i < _updateStartTimeModel->rowCount(); ++i)
{
@@ -161,16 +161,16 @@ class DatabaseSettingsModel : public Wt::WFormModel
return boost::none;
}
boost::posix_time::time_duration updateStartTime(int row)
Wt::WTime updateStartTime(int row)
{
return boost::any_cast<boost::posix_time::time_duration>
(_updateStartTimeModel->data(_updateStartTimeModel->index(row, 0), Wt::UserRole));
return Wt::cpp17::any_cast<Wt::WTime>
(_updateStartTimeModel->data(_updateStartTimeModel->index(row, 0), Wt::ItemDataRole::User));
}
Wt::WString updateStartTimeString(int row)
{
return boost::any_cast<Wt::WString>
(_updateStartTimeModel->data(_updateStartTimeModel->index(row, 0), Wt::DisplayRole));
return Wt::cpp17::any_cast<Wt::WString>
(_updateStartTimeModel->data(_updateStartTimeModel->index(row, 0), Wt::ItemDataRole::Display));
}
@@ -179,43 +179,35 @@ class DatabaseSettingsModel : public Wt::WFormModel
void initializeModels()
{
_updatePeriodModel = new Wt::WStringListModel(this);
_updatePeriodModel = std::make_shared<Wt::WStringListModel>();
_updatePeriodModel->addString(Wt::WString::tr("Lms.Admin.Database.never"));
_updatePeriodModel->setData(0, 0, Scanner::UpdatePeriod::Never, Wt::UserRole);
_updatePeriodModel->setData(0, 0, Scanner::UpdatePeriod::Never, Wt::ItemDataRole::User);
_updatePeriodModel->addString(Wt::WString::tr("Lms.Admin.Database.daily"));
_updatePeriodModel->setData(1, 0, Scanner::UpdatePeriod::Daily, Wt::UserRole);
_updatePeriodModel->setData(1, 0, Scanner::UpdatePeriod::Daily, Wt::ItemDataRole::User);
_updatePeriodModel->addString(Wt::WString::tr("Lms.Admin.Database.weekly"));
_updatePeriodModel->setData(2, 0, Scanner::UpdatePeriod::Weekly, Wt::UserRole);
_updatePeriodModel->setData(2, 0, Scanner::UpdatePeriod::Weekly, Wt::ItemDataRole::User);
_updatePeriodModel->addString(Wt::WString::tr("Lms.Admin.Database.monthly"));
_updatePeriodModel->setData(3, 0, Scanner::UpdatePeriod::Monthly, Wt::UserRole);
_updatePeriodModel->setData(3, 0, Scanner::UpdatePeriod::Monthly, Wt::ItemDataRole::User);
_updateStartTimeModel = new Wt::WStringListModel(this);
_updateStartTimeModel = std::make_shared<Wt::WStringListModel>();
for (std::size_t i = 0; i < 24; ++i)
{
boost::posix_time::time_duration dur = boost::posix_time::hours(i);
Wt::WTime time(i, 0);
boost::posix_time::time_facet* facet = new boost::posix_time::time_facet("%H:%M");
facet->time_duration_format("%H:%M");
std::ostringstream oss;
oss.imbue(std::locale(oss.getloc(), facet));
oss << dur;
_updateStartTimeModel->addString( oss.str() );
_updateStartTimeModel->setData(i, 0, dur, Wt::UserRole);
_updateStartTimeModel->addString( time.toString() );
_updateStartTimeModel->setData(i, 0, time, Wt::ItemDataRole::User);
}
}
Wt::WStringListModel* _updatePeriodModel;
Wt::WStringListModel* _updateStartTimeModel;
std::shared_ptr<Wt::WStringListModel> _updatePeriodModel;
std::shared_ptr<Wt::WStringListModel> _updateStartTimeModel;
};
@@ -224,43 +216,33 @@ const Wt::WFormModel::Field DatabaseSettingsModel::UpdatePeriodField = "update-
const Wt::WFormModel::Field DatabaseSettingsModel::UpdateStartTimeField = "update-start-time";
DatabaseSettingsView::DatabaseSettingsView(Wt::WContainerWidget *parent)
: Wt::WTemplateFormView(parent)
DatabaseSettingsView::DatabaseSettingsView()
: Wt::WTemplateFormView(Wt::WString::tr("Lms.Admin.Database.template"))
{
auto model = new DatabaseSettingsModel(this);
setTemplateText(tr("Lms.Admin.Database.template"));
addFunction("tr", &WTemplate::Functions::tr);
addFunction("id", &WTemplate::Functions::id);
auto model = std::make_shared<DatabaseSettingsModel>();
// Media Directory
Wt::WLineEdit *mediaDirectoryEdit = new Wt::WLineEdit();
setFormWidget(DatabaseSettingsModel::MediaDirectoryField, mediaDirectoryEdit);
setFormWidget(DatabaseSettingsModel::MediaDirectoryField, std::make_unique<Wt::WLineEdit>());
// Update Period
Wt::WComboBox *updatePeriodCB = new Wt::WComboBox();
setFormWidget(DatabaseSettingsModel::UpdatePeriodField, updatePeriodCB);
updatePeriodCB->setModel(model->updatePeriodModel());
auto updatePeriod = std::make_unique<Wt::WComboBox>();
updatePeriod->setModel(model->updatePeriodModel());
setFormWidget(DatabaseSettingsModel::UpdatePeriodField, std::move(updatePeriod));
// Update Start Time
Wt::WComboBox *updateStartTimeCB = new Wt::WComboBox();
setFormWidget(DatabaseSettingsModel::UpdateStartTimeField, updateStartTimeCB);
updateStartTimeCB->setModel(model->updateStartTimeModel());
auto updateStartTime = std::make_unique<Wt::WComboBox>();
updateStartTime->setModel(model->updateStartTimeModel());
setFormWidget(DatabaseSettingsModel::UpdateStartTimeField, std::move(updateStartTime));
// Buttons
Wt::WPushButton *saveBtn = new Wt::WPushButton(Wt::WString::tr("Lms.apply"));
bindWidget("apply-btn", saveBtn);
Wt::WPushButton *discardBtn = new Wt::WPushButton(Wt::WString::tr("Lms.discard"));
bindWidget("discard-btn", discardBtn);
Wt::WPushButton *immScanBtn = new Wt::WPushButton(Wt::WString::tr("Lms.Admin.Database.immediate-scan"));
bindWidget("immediate-scan-btn", immScanBtn);
Wt::WPushButton *saveBtn = bindWidget("apply-btn", std::make_unique<Wt::WPushButton>(Wt::WString::tr("Lms.apply")));
Wt::WPushButton *discardBtn = bindWidget("discard-btn", std::make_unique<Wt::WPushButton>(Wt::WString::tr("Lms.discard")));
Wt::WPushButton *immScanBtn = bindWidget("immediate-scan-btn", std::make_unique<Wt::WPushButton>(Wt::WString::tr("Lms.Admin.Database.immediate-scan")));
saveBtn->clicked().connect(std::bind([=] ()
{
updateModel(model);
updateModel(model.get());
if (model->validate())
{
@@ -271,14 +253,14 @@ DatabaseSettingsView::DatabaseSettingsView(Wt::WContainerWidget *parent)
}
// Udate the view: Delete any validation message in the view, etc.
updateView(model);
updateView(model.get());
}));
discardBtn->clicked().connect(std::bind([=] ()
{
model->loadData();
model->validate();
updateView(model);
updateView(model.get());
}));
immScanBtn->clicked().connect(std::bind([=] ()
@@ -287,7 +269,7 @@ DatabaseSettingsView::DatabaseSettingsView(Wt::WContainerWidget *parent)
LmsApp->notifyMsg(Wt::WString::tr("Lms.Admin.Database.scan-launched"));
}));
updateView(model);
updateView(model.get());
}
} // namespace UserInterface
+2 -3
View File
@@ -19,15 +19,14 @@
#pragma once
#include <Wt/WContainerWidget>
#include <Wt/WTemplateFormView>
#include <Wt/WTemplateFormView.h>
namespace UserInterface {
class DatabaseSettingsView : public Wt::WTemplateFormView
{
public:
DatabaseSettingsView(Wt::WContainerWidget *parent = 0);
DatabaseSettingsView();
};
+26 -33
View File
@@ -17,10 +17,10 @@
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Wt/WFormModel>
#include <Wt/WLineEdit>
#include <Wt/WPushButton>
#include <Wt/Auth/Identity>
#include <Wt/WFormModel.h>
#include <Wt/WLineEdit.h>
#include <Wt/WPushButton.h>
#include <Wt/Auth/Identity.h>
#include "utils/Logger.hpp"
@@ -40,8 +40,7 @@ class InitWizardModel : public Wt::WFormModel
static const Field PasswordField;
static const Field PasswordConfirmField;
InitWizardModel(Wt::WObject *parent = 0)
: Wt::WFormModel(parent)
InitWizardModel() : Wt::WFormModel()
{
addField(AdminLoginField);
addField(PasswordField);
@@ -54,16 +53,16 @@ class InitWizardModel : public Wt::WFormModel
void saveData()
{
Wt::Dbo::Transaction transaction(DboSession());
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
// Check if a user already exist
// If it's the case, just do nothing
if (!Database::User::getAll(DboSession()).empty())
if (!Database::User::getAll(LmsApp->getDboSession()).empty())
throw std::runtime_error("Admin user already created");
// Create user
Wt::Auth::User authUser = DbHandler().getUserDatabase().registerNew();
Database::User::pointer user = DbHandler().getUser(authUser);
Wt::Auth::User authUser = LmsApp->getDb().getUserDatabase().registerNew();
Database::User::pointer user = LmsApp->getDb().createUser(authUser);
// Account
authUser.setIdentity(Wt::Auth::Identity::LoginName, valueText(AdminLoginField));
@@ -94,7 +93,7 @@ class InitWizardModel : public Wt::WFormModel
}
else if (field == PasswordConfirmField)
{
if (validation(PasswordField).state() == Wt::WValidator::Valid)
if (validation(PasswordField).state() == Wt::ValidationState::Valid)
{
if (valueText(PasswordField) != valueText(PasswordConfirmField))
error = Wt::WString::tr("Lms.passwords-dont-match");
@@ -105,9 +104,9 @@ class InitWizardModel : public Wt::WFormModel
return Wt::WFormModel::validateField(field);
}
setValidation(field, Wt::WValidator::Result( error.empty() ? Wt::WValidator::Valid : Wt::WValidator::Invalid, error));
setValidation(field, Wt::WValidator::Result( error.empty() ? Wt::ValidationState::Valid : Wt::ValidationState::Invalid, error));
return (validation(field).state() == Wt::WValidator::Valid);
return (validation(field).state() == Wt::ValidationState::Valid);
}
};
@@ -116,34 +115,28 @@ const Wt::WFormModel::Field InitWizardModel::AdminLoginField = "admin-login";
const Wt::WFormModel::Field InitWizardModel::PasswordField = "password";
const Wt::WFormModel::Field InitWizardModel::PasswordConfirmField = "password-confirm";
InitWizardView::InitWizardView(Wt::WContainerWidget *parent)
: Wt::WTemplateFormView(parent)
InitWizardView::InitWizardView()
: Wt::WTemplateFormView(Wt::WString::tr("Lms.Admin.InitWizard.template"))
{
auto model = new InitWizardModel(this);
setTemplateText(Wt::WString::tr("Lms.Admin.InitWizard.template"));
addFunction("tr", &WTemplate::Functions::tr);
addFunction("id", &WTemplate::Functions::id);
auto model = std::make_shared<InitWizardModel>();
// AdminLogin
Wt::WLineEdit* accountEdit = new Wt::WLineEdit();
setFormWidget(InitWizardModel::AdminLoginField, accountEdit);
setFormWidget(InitWizardModel::AdminLoginField, std::make_unique<Wt::WLineEdit>());
// Password
Wt::WLineEdit* passwordEdit = new Wt::WLineEdit();
setFormWidget(InitWizardModel::PasswordField, passwordEdit );
passwordEdit->setEchoMode(Wt::WLineEdit::Password);
auto passwordEdit = std::make_unique<Wt::WLineEdit>();
passwordEdit->setEchoMode(Wt::EchoMode::Password);
setFormWidget(InitWizardModel::PasswordField, std::move(passwordEdit) );
// Password confirmation
Wt::WLineEdit* passwordConfirmEdit = new Wt::WLineEdit();
setFormWidget(InitWizardModel::PasswordConfirmField, passwordConfirmEdit);
passwordConfirmEdit->setEchoMode(Wt::WLineEdit::Password);
auto passwordConfirmEdit = std::make_unique<Wt::WLineEdit>();
passwordConfirmEdit->setEchoMode(Wt::EchoMode::Password);
setFormWidget(InitWizardModel::PasswordConfirmField, std::move(passwordConfirmEdit));
auto saveButton = new Wt::WPushButton(Wt::WString::tr("Lms.create"));
bindWidget("create-btn", saveButton);
Wt::WPushButton* saveButton = bindNew<Wt::WPushButton>("create-btn", Wt::WString::tr("Lms.create"));
saveButton->clicked().connect(std::bind([=]
{
updateModel(model);
updateModel(model.get());
if (model->validate())
{
@@ -152,10 +145,10 @@ InitWizardView::InitWizardView(Wt::WContainerWidget *parent)
saveButton->setEnabled(false);
}
updateView(model);
updateView(model.get());
}));
updateView(model);
updateView(model.get());
}
} // namespace UserInterface
+2 -3
View File
@@ -19,15 +19,14 @@
#pragma once
#include <Wt/WContainerWidget>
#include <Wt/WTemplateFormView>
#include <Wt/WTemplateFormView.h>
namespace UserInterface {
class InitWizardView : public Wt::WTemplateFormView
{
public:
InitWizardView(Wt::WContainerWidget *parent = 0);
InitWizardView();
};
+47 -52
View File
@@ -17,15 +17,15 @@
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Wt/WApplication>
#include <Wt/WCheckBox>
#include <Wt/WComboBox>
#include <Wt/WLineEdit>
#include <Wt/WPushButton>
#include <Wt/WTemplateFormView>
#include <Wt/WApplication.h>
#include <Wt/WCheckBox.h>
#include <Wt/WComboBox.h>
#include <Wt/WLineEdit.h>
#include <Wt/WPushButton.h>
#include <Wt/WTemplateFormView.h>
#include <Wt/WFormModel>
#include <Wt/WStringListModel>
#include <Wt/WFormModel.h>
#include <Wt/WStringListModel.h>
#include "common/Validators.hpp"
#include "utils/Utils.hpp"
@@ -44,8 +44,8 @@ class UserModel : public Wt::WFormModel
static const Field PasswordField;
static const Field BitrateLimitField;
UserModel(boost::optional<Database::User::id_type> userId, Wt::WObject *parent = 0)
: Wt::WFormModel(parent),
UserModel(boost::optional<Database::User::id_type> userId)
: Wt::WFormModel(),
_userId(userId)
{
if (!_userId)
@@ -72,12 +72,12 @@ class UserModel : public Wt::WFormModel
if (!_userId)
return;
Wt::Dbo::Transaction transaction(DboSession());
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
Wt::Auth::User authUser = DbHandler().getUserDatabase().findWithId( std::to_string(*_userId) );
Database::User::pointer user = DbHandler().getUser(authUser);
Wt::Auth::User authUser = LmsApp->getDb().getUserDatabase().findWithId( std::to_string(*_userId) );
Database::User::pointer user = LmsApp->getDb().getUser(authUser);
if (user == CurrentUser())
if (user == LmsApp->getCurrentUser())
throw std::runtime_error("Cannot edit ourselves");
auto bitrate = getBitrateLimitRow(user->getMaxAudioBitrate());
@@ -87,13 +87,13 @@ class UserModel : public Wt::WFormModel
void saveData()
{
Wt::Dbo::Transaction transaction(DboSession());
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
if (_userId)
{
// Update user
Wt::Auth::User authUser = DbHandler().getUserDatabase().findWithId( std::to_string(*_userId) );
Database::User::pointer user = DbHandler().getUser( authUser );
Wt::Auth::User authUser = LmsApp->getDb().getUserDatabase().findWithId( std::to_string(*_userId) );
Database::User::pointer user = LmsApp->getDb().getUser( authUser );
// Account
if (!valueText(PasswordField).empty())
@@ -106,8 +106,8 @@ class UserModel : public Wt::WFormModel
else
{
// Create user
Wt::Auth::User authUser = DbHandler().getUserDatabase().registerNew();
Database::User::pointer user = DbHandler().createUser(authUser);
Wt::Auth::User authUser = LmsApp->getDb().getUserDatabase().registerNew();
Database::User::pointer user = LmsApp->getDb().createUser(authUser);
// Account
authUser.setIdentity(Wt::Auth::Identity::LoginName, valueText(LoginField));
@@ -142,35 +142,35 @@ class UserModel : public Wt::WFormModel
std::size_t bitrateLimit(int row)
{
return boost::any_cast<std::size_t>
(_bitrateModel->data(_bitrateModel->index(row, 0), Wt::UserRole));
return Wt::cpp17::any_cast<std::size_t>
(_bitrateModel->data(_bitrateModel->index(row, 0), Wt::ItemDataRole::User));
}
Wt::WString bitrateLimitString(int row)
{
return boost::any_cast<Wt::WString>
(_bitrateModel->data(_bitrateModel->index(row, 0), Wt::DisplayRole));
return Wt::cpp17::any_cast<Wt::WString>
(_bitrateModel->data(_bitrateModel->index(row, 0), Wt::ItemDataRole::Display));
}
Wt::WAbstractItemModel *bitrateModel() { return _bitrateModel; }
std::shared_ptr<Wt::WAbstractItemModel> bitrateModel() { return _bitrateModel; }
private:
void initializeModels()
{
_bitrateModel = new Wt::WStringListModel(this);
_bitrateModel = std::make_shared<Wt::WStringListModel>();
std::size_t id = 0;
for (auto bitrate : Database::User::audioBitrates)
{
_bitrateModel->addString( Wt::WString::fromUTF8(std::to_string(bitrate / 1000)) );
_bitrateModel->setData( id++, 0, bitrate, Wt::UserRole);
_bitrateModel->setData( id++, 0, bitrate, Wt::ItemDataRole::User);
}
}
Wt::WStringListModel* _bitrateModel;
std::shared_ptr<Wt::WStringListModel> _bitrateModel;
boost::optional<Database::User::id_type> _userId;
};
@@ -178,8 +178,7 @@ const Wt::WFormModel::Field UserModel::LoginField = "login";
const Wt::WFormModel::Field UserModel::PasswordField = "password";
const Wt::WFormModel::Field UserModel::BitrateLimitField = "audio-bitrate-limit";
UserView::UserView(Wt::WContainerWidget* parent)
: Wt::WContainerWidget(parent)
UserView::UserView()
{
wApp->internalPathChanged().connect(std::bind([=]
{
@@ -195,47 +194,44 @@ UserView::refreshView()
if (!wApp->internalPathMatches("/admin/user"))
return;
auto userId = readLong(wApp->internalPathNextPart("/admin/user/"));
auto userId = readAs<Database::User::id_type>(wApp->internalPathNextPart("/admin/user/"));
LMS_LOG(UI, DEBUG) << "userId = " << (userId ? std::to_string(*userId) : "none");
clear();
auto t = new Wt::WTemplateFormView(Wt::WString::tr("Lms.Admin.User.template"), this);
Wt::WTemplateFormView* t = addNew<Wt::WTemplateFormView>(Wt::WString::tr("Lms.Admin.User.template"));
t->addFunction("tr", &Wt::WTemplate::Functions::tr);
t->addFunction("id", &Wt::WTemplate::Functions::id);
auto model = new UserModel(userId ? boost::make_optional<Database::User::id_type>(*userId) : boost::none, this);
auto model = std::make_shared<UserModel>(userId);
if (userId)
{
auto authUser = DbHandler().getUserDatabase().findWithId( std::to_string(*userId) );
auto authUser = LmsApp->getDb().getUserDatabase().findWithId( std::to_string(*userId) );
auto name = authUser.identity(Wt::Auth::Identity::LoginName);
t->bindString("title", Wt::WString::tr("Lms.Admin.User.user-edit").arg(name), Wt::PlainText);
t->bindString("title", Wt::WString::tr("Lms.Admin.User.user-edit").arg(name), Wt::TextFormat::Plain);
}
else
{
// Login
t->setCondition("if-has-login", true);
t->setFormWidget(UserModel::LoginField, new Wt::WLineEdit());
t->setFormWidget(UserModel::LoginField, std::make_unique<Wt::WLineEdit>());
t->bindString("title", Wt::WString::tr("Lms.Admin.User.user-create"));
}
// Password
Wt::WLineEdit* passwordEdit = new Wt::WLineEdit();
t->setFormWidget(UserModel::PasswordField, passwordEdit );
passwordEdit->setEchoMode(Wt::WLineEdit::Password);
auto passwordEdit = std::make_unique<Wt::WLineEdit>();
passwordEdit->setEchoMode(Wt::EchoMode::Password);
t->setFormWidget(UserModel::PasswordField, std::move(passwordEdit));
// AudioBitrate
Wt::WComboBox *bitrateCB = new Wt::WComboBox();
t->setFormWidget(UserModel::BitrateLimitField, bitrateCB);
bitrateCB->setModel(model->bitrateModel());
// Bitrate
auto bitrate = std::make_unique<Wt::WComboBox>();
bitrate->setModel(model->bitrateModel());
t->setFormWidget(UserModel::BitrateLimitField, std::move(bitrate));
auto saveBtn = new Wt::WPushButton(Wt::WString::tr(userId ? "Lms.save" : "Lms.create"));
t->bindWidget("save-btn", saveBtn);
Wt::WPushButton* saveBtn = t->bindNew<Wt::WPushButton>("save-btn", Wt::WString::tr(userId ? "Lms.save" : "Lms.create"));
saveBtn->clicked().connect(std::bind([=]
{
t->updateModel(model);
t->updateModel(model.get());
if (model->validate())
{
@@ -245,12 +241,11 @@ UserView::refreshView()
}
else
{
t->updateView(model);
t->updateView(model.get());
}
}));
t->updateView(model);
t->updateView(model.get());
}
} // namespace UserInterface
+2 -2
View File
@@ -19,14 +19,14 @@
#pragma once
#include <Wt/WContainerWidget>
#include <Wt/WContainerWidget.h>
namespace UserInterface {
class UserView : public Wt::WContainerWidget
{
public:
UserView(Wt::WContainerWidget *parent = 0);
UserView();
private:
void refreshView();
+19 -26
View File
@@ -17,8 +17,8 @@
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Wt/WTemplate>
#include <Wt/WPushButton>
#include <Wt/WTemplate.h>
#include <Wt/WPushButton.h>
#include "database/Types.hpp"
#include "utils/Logger.hpp"
@@ -28,18 +28,14 @@
namespace UserInterface {
UsersView::UsersView(Wt::WContainerWidget *parent)
: Wt::WContainerWidget(parent)
UsersView::UsersView()
: Wt::WTemplate(Wt::WString::tr("Lms.Admin.Users.template"))
{
auto t = new Wt::WTemplate(Wt::WString::tr("Lms.Admin.Users.template"), this);
t->addFunction("tr", &Wt::WTemplate::Functions::tr);
addFunction("tr", &Wt::WTemplate::Functions::tr);
_container = new Wt::WContainerWidget();
t->bindWidget("users", _container);
auto addBtn = new Wt::WPushButton(Wt::WString::tr("Lms.Admin.Users.add"));
t->bindWidget("add-btn", addBtn);
_container = bindNew<Wt::WContainerWidget>("users");
Wt::WPushButton* addBtn = bindNew<Wt::WPushButton>("add-btn", Wt::WString::tr("Lms.Admin.Users.add"));
addBtn->clicked().connect(std::bind([=]
{
LmsApp->setInternalPath("/admin/user", true);
@@ -61,44 +57,41 @@ UsersView::refreshView()
_container->clear();
Wt::Dbo::Transaction transaction(DboSession());
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
auto users = Database::User::getAll(DboSession());
auto users = Database::User::getAll(LmsApp->getDboSession());
for (auto user : users)
{
auto userId = std::to_string(user.id());
auto entry = new Wt::WTemplate(Wt::WString::tr("Lms.Admin.Users.template.entry"), _container);
Wt::Auth::User authUser = DbHandler().getUserDatabase().findWithId(userId);
Wt::WTemplate* entry = _container->addNew<Wt::WTemplate>(Wt::WString::tr("Lms.Admin.Users.template.entry"));
Wt::Auth::User authUser = LmsApp->getDb().getUserDatabase().findWithId(userId);
if (!authUser.isValid()) {
LMS_LOG(UI, ERROR) << "Skipping invalid userId = " << user.id();
continue;
}
entry->bindString("name", authUser.identity(Wt::Auth::Identity::LoginName), Wt::PlainText);
entry->bindString("name", authUser.identity(Wt::Auth::Identity::LoginName), Wt::TextFormat::Plain);
// Don't edit ourself this way
if (CurrentUser() == user)
if (LmsApp->getCurrentUser() == user)
continue;
entry->setCondition("if-edit", true);
auto editBtn = new Wt::WPushButton(Wt::WString::tr("Lms.Admin.Users.edit"));
entry->bindWidget("edit-btn", editBtn);
Wt::WPushButton* editBtn = entry->bindNew<Wt::WPushButton>("edit-btn", Wt::WString::tr("Lms.Admin.Users.edit"));
editBtn->clicked().connect(std::bind([=]
{
LmsApp->setInternalPath("/admin/user/" + std::to_string(user.id()), true);
}));
auto delBtn = new Wt::WPushButton(Wt::WString::tr("Lms.Admin.Users.del"));
entry->bindWidget("del-btn", delBtn);
Wt::WPushButton* delBtn = entry->bindNew<Wt::WPushButton>("del-btn", Wt::WString::tr("Lms.Admin.Users.del"));
delBtn->clicked().connect(std::bind([=]
{
Wt::Dbo::Transaction transaction(DboSession());
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
auto authUser = DbHandler().getUserDatabase().findWithId(userId);
auto user = DbHandler().getUser(authUser);
DbHandler().getUserDatabase().deleteUser( authUser );
auto authUser = LmsApp->getDb().getUserDatabase().findWithId(userId);
auto user = LmsApp->getDb().getUser(authUser);
LmsApp->getDb().getUserDatabase().deleteUser( authUser );
user.remove();
_container->removeWidget(entry);
}));
+3 -3
View File
@@ -19,14 +19,14 @@
#pragma once
#include <Wt/WContainerWidget>
#include <Wt/WContainerWidget.h>
namespace UserInterface {
class UsersView : public Wt::WContainerWidget
class UsersView : public Wt::WTemplate
{
public:
UsersView(Wt::WContainerWidget *parent = 0);
UsersView();
private:
void refreshView();
-56
View File
@@ -1,56 +0,0 @@
/*
* Copyright (C) 2015 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/WConfig.h>
#if WT_VERSION < 0X03030500
#include <Wt/WTemplate>
#include <Wt/WText>
#endif
#include "InputRange.hpp"
#if WT_VERSION >= 0X03030500
InputRange::InputRange(Wt::WContainerWidget *parent)
: Wt::WWebWidget(parent)
{
setHtmlTagName("input");
setAttributeValue("type", "range");
}
std::string
InputRange::jsRef(void) const
{
return Wt::WWebWidget::jsRef();
}
#else
InputRange::InputRange(Wt::WContainerWidget *parent)
: Wt::WContainerWidget(parent)
{
addWidget(new Wt::WTemplate("<input type=\"range\"></input>"));
}
std::string
InputRange::jsRef(void) const
{
return Wt::WWebWidget::jsRef() + ".getElementsByTagName(\"input\")[0]";
}
#endif
-51
View File
@@ -1,51 +0,0 @@
/*
* Copyright (C) 2015 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 <Wt/WWebWidget>
#include <Wt/WConfig.h>
#if WT_VERSION >= 0X03030500
class InputRange : public Wt::WWebWidget
{
public:
InputRange(Wt::WContainerWidget *parent = 0);
Wt::DomElementType domElementType() const
{
return Wt::DomElement_INPUT;
}
std::string jsRef() const;
};
#else
class InputRange : public Wt::WContainerWidget
{
public:
InputRange(Wt::WContainerWidget *parent = 0);
std::string jsRef() const;
};
#endif
-55
View File
@@ -1,55 +0,0 @@
/*
* Copyright (C) 2015 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/WTimer>
#include "LineEdit.hpp"
namespace UserInterface {
LineEdit::LineEdit(std::size_t ms, Wt::WContainerWidget* parent)
: Wt::WLineEdit(parent)
{
Wt::WTimer *timer = new Wt::WTimer(this);
timer->setSingleShot(true);
timer->setInterval(ms);
this->keyWentUp().connect(std::bind([=] (Wt::WKeyEvent keyEvent)
{
if (timer->isActive())
timer->stop();
if (keyEvent.key() == Wt::Key_Enter)
_sigTimedChanged.emit(this->text());
else
timer->start();
}, std::placeholders::_1));
timer->timeout().connect(std::bind([=] ()
{
_sigTimedChanged.emit(this->text());
}));
}
} // namespace UserInterface
-44
View File
@@ -1,44 +0,0 @@
/*
* Copyright (C) 2015 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/>.
*/
#ifndef UI_LINE_EDIT_HPP
#define UI_LINE_EDIT_HPP
#include <Wt/WLineEdit>
#include <Wt/WContainerWidget>
#include <Wt/WSignal>
namespace UserInterface {
class LineEdit : public Wt::WLineEdit
{
public:
LineEdit(std::size_t ms, Wt::WContainerWidget* parent = 0);
Wt::Signal<Wt::WString>& timedChanged() { return _sigTimedChanged; }
private:
Wt::Signal<Wt::WString> _sigTimedChanged;
};
} // namespace UserInterface
#endif
+12 -9
View File
@@ -19,28 +19,31 @@
#include <boost/filesystem.hpp>
#include <Wt/WLengthValidator.h>
#include "Validators.hpp"
namespace UserInterface {
Wt::WValidator* createNameValidator()
std::shared_ptr<Wt::WValidator>
createNameValidator()
{
Wt::WLengthValidator *v = new Wt::WLengthValidator();
auto v = std::make_shared<Wt::WLengthValidator>();
v->setMandatory(true);
v->setMinimumLength(::Database::User::MinNameLength);
v->setMaximumLength(::Database::User::MaxNameLength);
return v;
}
Wt::WValidator* createMandatoryValidator()
std::shared_ptr<Wt::WValidator>
createMandatoryValidator()
{
auto v = new Wt::WValidator();
auto v = std::make_shared<Wt::WValidator>();
v->setMandatory(true);
return v;
}
DirectoryValidator::DirectoryValidator(Wt::WObject *parent)
: Wt::WValidator(parent)
DirectoryValidator::DirectoryValidator() : Wt::WValidator()
{
}
@@ -56,11 +59,11 @@ DirectoryValidator::validate(const Wt::WString& input) const
// TODO check rights
bool res = boost::filesystem::is_directory(p, ec);
if (ec)
return Wt::WValidator::Result(Wt::WValidator::Invalid, ec.message()); // TODO translate common errors
return Wt::WValidator::Result(Wt::ValidationState::Invalid, ec.message()); // TODO translate common errors
else if (res)
return Wt::WValidator::Result(Wt::WValidator::Valid);
return Wt::WValidator::Result(Wt::ValidationState::Valid);
else
return Wt::WValidator::Result(Wt::WValidator::Invalid, Wt::WString::tr("Lms.not-a-directory"));
return Wt::WValidator::Result(Wt::ValidationState::Invalid, Wt::WString::tr("Lms.not-a-directory"));
}
+4 -4
View File
@@ -19,19 +19,19 @@
#pragma once
#include <Wt/WLengthValidator>
#include <Wt/WValidator.h>
#include "database/User.hpp"
namespace UserInterface {
Wt::WValidator* createNameValidator();
Wt::WValidator* createMandatoryValidator();
std::shared_ptr<Wt::WValidator> createNameValidator();
std::shared_ptr<Wt::WValidator> createMandatoryValidator();
class DirectoryValidator : public Wt::WValidator
{
public:
DirectoryValidator(Wt::WObject *parent = 0);
DirectoryValidator();
Wt::WValidator::Result validate(const Wt::WString& input) const override;
+28 -40
View File
@@ -17,11 +17,10 @@
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Wt/WApplication>
#include <Wt/WAnchor>
#include <Wt/WImage>
#include <Wt/WTemplate>
#include <Wt/WText>
#include <Wt/WAnchor.h>
#include <Wt/WImage.h>
#include <Wt/WTemplate.h>
#include <Wt/WText.h>
#include "database/Types.hpp"
@@ -36,9 +35,8 @@
namespace UserInterface {
Artist::Artist(Filters* filters, Wt::WContainerWidget* parent)
: Wt::WContainerWidget(parent),
_filters(filters)
Artist::Artist(Filters* filters)
: _filters(filters)
{
wApp->internalPathChanged().connect(std::bind([=]
{
@@ -60,81 +58,73 @@ Artist::refresh()
clear();
Database::Artist::id_type artistId;
if (!readAs(wApp->internalPathNextPart("/artist/"), artistId))
auto artistId = readAs<Database::Artist::id_type>(wApp->internalPathNextPart("/artist/"));
if (!artistId)
return;
Wt::Dbo::Transaction transaction(DboSession());
auto artist = Database::Artist::getById(DboSession(), artistId);
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
auto artist = Database::Artist::getById(LmsApp->getDboSession(), *artistId);
if (!artist)
{
LmsApp->goHome();
return;
}
auto t = new Wt::WTemplate(Wt::WString::tr("Lms.Explore.Artist.template"), this);
Wt::WTemplate* t = addNew<Wt::WTemplate>(Wt::WString::tr("Lms.Explore.Artist.template"));
t->addFunction("tr", &Wt::WTemplate::Functions::tr);
auto clusterContainers = new Wt::WContainerWidget();
t->bindWidget("clusters", clusterContainers);
Wt::WContainerWidget* clusterContainers = t->bindNew<Wt::WContainerWidget>("clusters");
{
auto clusters = artist->getClusters(3);
for (auto cluster : clusters)
{
auto entry = new Wt::WTemplate(Wt::WString::tr("Lms.Explore.Artist.template.cluster-entry"), clusterContainers);
entry->bindString("name", Wt::WString::fromUTF8(cluster->getName()), Wt::PlainText);
Wt::WTemplate* entry = clusterContainers->addNew<Wt::WTemplate>(Wt::WString::tr("Lms.Explore.Artist.template.cluster-entry"));
entry->bindString("name", Wt::WString::fromUTF8(cluster->getName()), Wt::TextFormat::Plain);
}
}
t->bindString("name", Wt::WString::fromUTF8(artist->getName()), Wt::PlainText);
t->bindString("name", Wt::WString::fromUTF8(artist->getName()), Wt::TextFormat::Plain);
{
auto playBtn = new Wt::WText(Wt::WString::tr("Lms.Explore.Artist.play"), Wt::XHTMLText);
t->bindWidget("play-btn", playBtn);
Wt::WText* playBtn = t->bindNew<Wt::WText>("play-btn", Wt::WString::tr("Lms.Explore.Artist.play"), Wt::TextFormat::XHTML);
playBtn->clicked().connect(std::bind([=]
{
artistPlay.emit(artistId);
artistPlay.emit(*artistId);
}));
}
{
auto addBtn = new Wt::WText(Wt::WString::tr("Lms.Explore.Artist.add"), Wt::XHTMLText);
t->bindWidget("add-btn", addBtn);
Wt::WText* addBtn = t->bindNew<Wt::WText>("add-btn", Wt::WString::tr("Lms.Explore.Artist.add"), Wt::TextFormat::XHTML);
addBtn->clicked().connect(std::bind([=]
{
artistAdd.emit(artistId);
artistAdd.emit(*artistId);
}));
}
auto releasesContainer = new Wt::WContainerWidget();
t->bindWidget("releases", releasesContainer);
Wt::WContainerWidget* releasesContainer = t->bindNew<Wt::WContainerWidget>("releases");
auto releases = artist->getReleases(_filters->getClusterIds());
for (auto release : releases)
{
auto releaseId = release.id();
Wt::WTemplate* entry = new Wt::WTemplate(Wt::WString::tr("Lms.Explore.Artist.template.entry"), releasesContainer);
Wt::WTemplate* entry = releasesContainer->addNew<Wt::WTemplate>(Wt::WString::tr("Lms.Explore.Artist.template.entry"));
entry->addFunction("tr", Wt::WTemplate::Functions::tr);
{
Wt::WAnchor* coverAnchor = LmsApplication::createReleaseAnchor(release, false);
Wt::WImage* cover = new Wt::WImage(coverAnchor);
Wt::WAnchor* anchor = entry->bindWidget("cover", LmsApplication::createReleaseAnchor(release, false));
auto cover = std::make_unique<Wt::WImage>();
cover->setImageLink(LmsApp->getImageResource()->getReleaseUrl(release.id(), 128));
// Some images may not be square
cover->setWidth(128);
entry->bindWidget("cover", coverAnchor);
anchor->setImage(std::move(cover));
}
{
Wt::WAnchor* releaseAnchor = LmsApplication::createReleaseAnchor(release);
entry->bindWidget("name", releaseAnchor);
}
entry->bindWidget("name", LmsApplication::createReleaseAnchor(release));
if (release->hasVariousArtists())
entry->setCondition("if-has-various-artists", true);
@@ -153,15 +143,13 @@ Artist::refresh()
}
}
auto playBtn = new Wt::WText(Wt::WString::tr("Lms.Explore.Artist.play"), Wt::XHTMLText);
entry->bindWidget("play-btn", playBtn);
Wt::WText* playBtn = entry->bindNew<Wt::WText>("play-btn", Wt::WString::tr("Lms.Explore.Artist.play"), Wt::TextFormat::XHTML);
playBtn->clicked().connect(std::bind([=]
{
releasePlay.emit(releaseId);
}));
auto addBtn = new Wt::WText(Wt::WString::tr("Lms.Explore.Artist.add"), Wt::XHTMLText);
entry->bindWidget("add-btn", addBtn);
Wt::WText* addBtn = entry->bindNew<Wt::WText>("add-btn", Wt::WString::tr("Lms.Explore.Artist.add"), Wt::TextFormat::XHTML);
addBtn->clicked().connect(std::bind([=]
{
releaseAdd.emit(releaseId);
+3 -3
View File
@@ -19,8 +19,8 @@
#pragma once
#include <Wt/WContainerWidget>
#include <Wt/WSignal>
#include <Wt/WContainerWidget.h>
#include <Wt/WSignal.h>
namespace UserInterface {
@@ -29,7 +29,7 @@ class Filters;
class Artist : public Wt::WContainerWidget
{
public:
Artist(Filters* filters, Wt::WContainerWidget* parent = 0);
Artist(Filters* filters);
Wt::Signal<Database::id_type> artistAdd;
Wt::Signal<Database::id_type> artistPlay;
+13 -21
View File
@@ -17,9 +17,9 @@
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Wt/WAnchor>
#include <Wt/WTemplate>
#include <Wt/WLineEdit>
#include <Wt/WAnchor.h>
#include <Wt/WTemplate.h>
#include <Wt/WLineEdit.h>
#include "database/Types.hpp"
@@ -34,24 +34,20 @@ namespace UserInterface {
using namespace Database;
Artists::Artists(Filters* filters, Wt::WContainerWidget* parent)
: Wt::WContainerWidget(parent),
Artists::Artists(Filters* filters)
: Wt::WTemplate(Wt::WString::tr("Lms.Explore.Artists.template")),
_filters(filters)
{
auto container = new Wt::WTemplate(Wt::WString::tr("Lms.Explore.Artists.template"), this);
container->addFunction("tr", &Wt::WTemplate::Functions::tr);
addFunction("tr", &Wt::WTemplate::Functions::tr);
_search = new Wt::WLineEdit();
container->bindWidget("search", _search);
_search = bindNew<Wt::WLineEdit>("search");
_search->setPlaceholderText(Wt::WString::tr("Lms.Explore.search-placeholder"));
_search->textInput().connect(this, &Artists::refresh);
_artistsContainer = new Wt::WContainerWidget();
container->bindWidget("artists", _artistsContainer);
_artistsContainer = bindNew<Wt::WContainerWidget>("artists");
_showMore = new Wt::WTemplate(Wt::WString::tr("Lms.Explore.template.show-more"));
_showMore = bindNew<Wt::WTemplate>("show-more", Wt::WString::tr("Lms.Explore.template.show-more"));
_showMore->addFunction("tr", &Wt::WTemplate::Functions::tr);
container->bindWidget("show-more", _showMore);
_showMore->clicked().connect(std::bind([=]
{
@@ -77,24 +73,20 @@ Artists::addSome()
auto clusterIds = _filters->getClusterIds();
Wt::Dbo::Transaction transaction(DboSession());
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
bool moreResults;
auto artists = Artist::getByFilter(DboSession(),
auto artists = Artist::getByFilter(LmsApp->getDboSession(),
clusterIds,
searchKeywords,
_artistsContainer->count(), 20, moreResults);
for (auto artist : artists)
{
auto entry = new Wt::WTemplate(Wt::WString::tr("Lms.Explore.Artists.template.entry"), _artistsContainer);
Wt::WTemplate* entry = _artistsContainer->addNew<Wt::WTemplate>(Wt::WString::tr("Lms.Explore.Artists.template.entry"));
entry->bindInt("nb-release", artist->getReleases(clusterIds).size());
{
Wt::WAnchor *artistAnchor = LmsApplication::createArtistAnchor(artist);
entry->bindWidget("name", artistAnchor);
}
entry->bindWidget("name", LmsApplication::createArtistAnchor(artist));
}
_showMore->setHidden(!moreResults);
+6 -5
View File
@@ -19,18 +19,19 @@
#pragma once
#include <Wt/WContainerWidget>
#include <Wt/WLineEdit>
#include <Wt/WSignal>
#include <Wt/WContainerWidget.h>
#include <Wt/WTemplate.h>
#include <Wt/WLineEdit.h>
#include <Wt/WSignal.h>
namespace UserInterface {
class Filters;
class Artists : public Wt::WContainerWidget
class Artists : public Wt::WTemplate
{
public:
Artists(Filters* filters, Wt::WContainerWidget* parent = 0);
Artists(Filters* filters);
Wt::Signal<Database::id_type> artistAdd;
Wt::Signal<Database::id_type> artistPlay;
+29 -39
View File
@@ -17,9 +17,9 @@
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Wt/WStackedWidget>
#include <Wt/WTemplate>
#include <Wt/WText>
#include <Wt/WStackedWidget.h>
#include <Wt/WTemplate.h>
#include <Wt/WText.h>
#include "utils/Logger.hpp"
@@ -70,54 +70,44 @@ handlePathChange(Wt::WStackedWidget* stack)
}
}
Explore::Explore(Wt::WContainerWidget* parent)
: Wt::WContainerWidget(parent)
Explore::Explore()
: Wt::WTemplate(Wt::WString::tr("Lms.Explore.template"))
{
auto container = new Wt::WTemplate(Wt::WString::tr("Lms.Explore.template"), this);
_filters = new Filters();
container->bindWidget("filters", _filters);
_filters = bindNew<Filters>("filters");
// Contents
Wt::WStackedWidget* stack = new Wt::WStackedWidget();
container->bindWidget("contents", stack);
auto artists = new Artists(_filters);
stack->addWidget(artists);
Wt::WStackedWidget* stack = bindNew<Wt::WStackedWidget>("contents");
auto artists = std::make_unique<Artists>(_filters);
artists->artistAdd.connect(this, &Explore::handleArtistAdd);
artists->artistPlay.connect(this, &Explore::handleArtistPlay);
stack->addWidget(std::move(artists));
auto artist = new Artist(_filters);
stack->addWidget(artist);
auto artist = std::make_unique<Artist>(_filters);
artist->artistAdd.connect(this, &Explore::handleArtistAdd);
artist->artistPlay.connect(this, &Explore::handleArtistPlay);
artist->releaseAdd.connect(this, &Explore::handleReleaseAdd);
artist->releasePlay.connect(this, &Explore::handleReleasePlay);
stack->addWidget(std::move(artist));
auto releases = new Releases(_filters);
stack->addWidget(releases);
auto releases = std::make_unique<Releases>(_filters);
releases->releaseAdd.connect(this, &Explore::handleReleaseAdd);
releases->releasePlay.connect(this, &Explore::handleReleasePlay);
stack->addWidget(std::move(releases));
auto release = new Release(_filters);
stack->addWidget(release);
auto release = std::make_unique<Release>(_filters);
release->releaseAdd.connect(this, &Explore::handleReleaseAdd);
release->releasePlay.connect(this, &Explore::handleReleasePlay);
release->trackAdd.connect(this, &Explore::handleTrackAdd);
release->trackPlay.connect(this, &Explore::handleTrackPlay);
stack->addWidget(std::move(release));
auto tracks = new Tracks(_filters);
stack->addWidget(tracks);
auto tracks = std::make_unique<Tracks>(_filters);
tracks->trackAdd.connect(this, &Explore::handleTrackAdd);
tracks->trackPlay.connect(this, &Explore::handleTrackPlay);
tracks->tracksAdd.connect(this, &Explore::handleTracksAdd);
tracks->tracksPlay.connect(this, &Explore::handleTracksPlay);
stack->addWidget(std::move(tracks));
wApp->internalPathChanged().connect(std::bind([=]
{
@@ -175,49 +165,49 @@ static std::vector<Database::Track::pointer> getTrack(Wt::Dbo::Session& session,
void
Explore::handleArtistAdd(Database::id_type id)
{
Wt::Dbo::Transaction transaction(DboSession());
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
tracksAdd.emit(getArtistTracks(DboSession(), id, _filters->getClusterIds()));
tracksAdd.emit(getArtistTracks(LmsApp->getDboSession(), id, _filters->getClusterIds()));
}
void
Explore::handleArtistPlay(Database::id_type id)
{
Wt::Dbo::Transaction transaction(DboSession());
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
tracksPlay.emit(getArtistTracks(DboSession(), id, _filters->getClusterIds()));
tracksPlay.emit(getArtistTracks(LmsApp->getDboSession(), id, _filters->getClusterIds()));
}
void
Explore::handleReleaseAdd(Database::id_type id)
{
Wt::Dbo::Transaction transaction(DboSession());
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
tracksAdd.emit(getReleaseTracks(DboSession(), id, _filters->getClusterIds()));
tracksAdd.emit(getReleaseTracks(LmsApp->getDboSession(), id, _filters->getClusterIds()));
}
void
Explore::handleReleasePlay(Database::id_type id)
{
Wt::Dbo::Transaction transaction(DboSession());
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
tracksPlay.emit(getReleaseTracks(DboSession(), id, _filters->getClusterIds()));
tracksPlay.emit(getReleaseTracks(LmsApp->getDboSession(), id, _filters->getClusterIds()));
}
void
Explore::handleTrackAdd(Database::id_type id)
{
Wt::Dbo::Transaction transaction(DboSession());
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
tracksAdd.emit(getTrack(DboSession(), id));
tracksAdd.emit(getTrack(LmsApp->getDboSession(), id));
}
void
Explore::handleTrackPlay(Database::id_type id)
{
Wt::Dbo::Transaction transaction(DboSession());
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
tracksPlay.emit(getTrack(DboSession(), id));
tracksPlay.emit(getTrack(LmsApp->getDboSession(), id));
}
void
+9 -9
View File
@@ -19,7 +19,7 @@
#pragma once
#include <Wt/WContainerWidget>
#include <Wt/WTemplate.h>
#include "database/Types.hpp"
@@ -27,22 +27,22 @@ namespace UserInterface {
class Filters;
class Explore : public Wt::WContainerWidget
class Explore : public Wt::WTemplate
{
public:
Explore(Wt::WContainerWidget *parent = 0);
Explore();
Wt::Signal<std::vector<Database::Track::pointer>> tracksAdd;
Wt::Signal<std::vector<Database::Track::pointer>> 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);
void handleArtistAdd(Database::Artist::id_type id);
void handleArtistPlay(Database::Artist::id_type id);
void handleReleaseAdd(Database::Release::id_type id);
void handleReleasePlay(Database::Release::id_type id);
void handleTrackAdd(Database::Track::id_type id);
void handleTrackPlay(Database::Track::id_type id);
void handleTracksAdd(std::vector<Database::Track::pointer> tracks);
void handleTracksPlay(std::vector<Database::Track::pointer> tracks);
+25 -44
View File
@@ -17,10 +17,10 @@
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Wt/WComboBox>
#include <Wt/WDialog>
#include <Wt/WPushButton>
#include <Wt/WTemplate>
#include <Wt/WComboBox.h>
#include <Wt/WDialog.h>
#include <Wt/WPushButton.h>
#include <Wt/WTemplate.h>
#include "Filters.hpp"
@@ -31,32 +31,25 @@ namespace UserInterface {
void
Filters::showDialog()
{
auto dialog = new Wt::WDialog(Wt::WString::tr("Lms.Explore.add-filter"));
auto dialog = std::make_shared<Wt::WDialog>(Wt::WString::tr("Lms.Explore.add-filter"));
auto container = new Wt::WTemplate(Wt::WString::tr("Lms.Explore.template.add-filter"));
Wt::WTemplate* container = dialog->contents()->addNew<Wt::WTemplate>(Wt::WString::tr("Lms.Explore.template.add-filter"));
container->addFunction("tr", &Wt::WTemplate::Functions::tr);
dialog->contents()->addWidget(container);
Wt::WComboBox* typeCombo = container->bindNew<Wt::WComboBox>("type");
Wt::WComboBox* valueCombo = container->bindNew<Wt::WComboBox>("value");
auto typeCombo = new Wt::WComboBox();
container->bindWidget("type", typeCombo);
Wt::WPushButton* addBtn = container->bindNew<Wt::WPushButton>("add-btn", Wt::WString::tr("Lms.add"));
addBtn->clicked().connect(dialog.get(), &Wt::WDialog::accept);
auto valueCombo = new Wt::WComboBox();
container->bindWidget("value", valueCombo);
auto addBtn = new Wt::WPushButton(Wt::WString::tr("Lms.add"));
container->bindWidget("add-btn", addBtn);
addBtn->clicked().connect(dialog, &Wt::WDialog::accept);
auto cancelBtn = new Wt::WPushButton(Wt::WString::tr("Lms.cancel"));
container->bindWidget("cancel-btn", cancelBtn);
cancelBtn->clicked().connect(dialog, &Wt::WDialog::reject);
Wt::WPushButton* cancelBtn = container->bindNew<Wt::WPushButton>("cancel-btn", Wt::WString::tr("Lms.cancel"));
cancelBtn->clicked().connect(dialog.get(), &Wt::WDialog::reject);
// Populate data
{
Wt::Dbo::Transaction transaction(DboSession());
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
auto types = Database::ClusterType::getAll(DboSession());
auto types = Database::ClusterType::getAll(LmsApp->getDboSession());
for (auto type : types)
typeCombo->addItem(Wt::WString::fromUTF8(type->getName()));
@@ -81,9 +74,9 @@ Filters::showDialog()
valueCombo->clear();
Wt::Dbo::Transaction transaction(DboSession());
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
auto clusterType = Database::ClusterType::getByName(DboSession(), name);
auto clusterType = Database::ClusterType::getByName(LmsApp->getDboSession(), name);
auto values = clusterType->getClusters();
for (auto value : values)
@@ -94,24 +87,22 @@ Filters::showDialog()
}));
dialog->setModal(true);
#if WT_VERSION >= 0x03030700
dialog->setMovable(false);
#endif
dialog->setResizable(false);
dialog->setClosable(false);
dialog->finished().connect(std::bind([=]
{
if (dialog->result() != Wt::WDialog::Accepted)
if (dialog->result() != Wt::DialogCode::Accepted)
return;
auto type = typeCombo->valueText().toUTF8();
auto value = valueCombo->valueText().toUTF8();
Wt::Dbo::Transaction transaction(DboSession());
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
auto clusterType = Database::ClusterType::getByName(DboSession(), type);
auto clusterType = Database::ClusterType::getByName(LmsApp->getDboSession(), type);
if (!clusterType)
return;
@@ -123,8 +114,7 @@ Filters::showDialog()
_filterIds.insert(clusterId);
_sigUpdated.emit();
auto filterBtn = new Wt::WPushButton(Wt::WString::fromUTF8(value));
_filters->addWidget(filterBtn);
Wt::WPushButton* filterBtn = _filters->addNew<Wt::WPushButton>(Wt::WString::fromUTF8(value), Wt::TextFormat::Plain);
filterBtn->clicked().connect(std::bind([=]
{
@@ -137,23 +127,14 @@ Filters::showDialog()
dialog->show();
}
Filters::Filters(Wt::WContainerWidget *parent)
: Wt::WContainerWidget(parent)
Filters::Filters()
: Wt::WTemplate(Wt::WString::tr("Lms.Explore.template.filters"))
{
auto container = new Wt::WTemplate(Wt::WString::tr("Lms.Explore.template.filters"), this);
// Filters
Wt::WPushButton *addFilterBtn = new Wt::WPushButton(Wt::WText::tr("Lms.Explore.add-filter"));
container->bindWidget("add-filter", addFilterBtn);
_filters = new Wt::WContainerWidget();
container->bindWidget("filters", _filters);
addFilterBtn->clicked().connect(std::bind([this]
{
showDialog();
}));
Wt::WPushButton *addFilterBtn = bindNew<Wt::WPushButton>("add-filter", Wt::WText::tr("Lms.Explore.add-filter"));
addFilterBtn->clicked().connect(this, &Filters::showDialog);
_filters = bindNew<Wt::WContainerWidget>("filters");
}
+7 -6
View File
@@ -19,8 +19,9 @@
#pragma once
#include <Wt/WContainerWidget>
#include <Wt/WSignal>
#include <Wt/WContainerWidget.h>
#include <Wt/WSignal.h>
#include <Wt/WTemplate.h>
#include "database/Types.hpp"
@@ -28,21 +29,21 @@
namespace UserInterface {
class Filters : public Wt::WContainerWidget
class Filters : public Wt::WTemplate
{
public:
Filters(Wt::WContainerWidget *parent = 0);
Filters();
std::set<Database::Cluster::id_type> getClusterIds() const { return _filterIds; }
Wt::Signal<void>& updated() { return _sigUpdated; }
Wt::Signal<>& updated() { return _sigUpdated; }
private:
void showDialog();
Wt::WContainerWidget *_filters;
Wt::Signal<void> _sigUpdated;
Wt::Signal<> _sigUpdated;
std::set<Database::Cluster::id_type> _filterIds;
};
+28 -43
View File
@@ -17,11 +17,11 @@
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Wt/WApplication>
#include <Wt/WAnchor>
#include <Wt/WImage>
#include <Wt/WTemplate>
#include <Wt/WText>
#include <Wt/WApplication.h>
#include <Wt/WAnchor.h>
#include <Wt/WImage.h>
#include <Wt/WTemplate.h>
#include <Wt/WText.h>
#include "database/Types.hpp"
@@ -36,9 +36,8 @@
namespace UserInterface {
Release::Release(Filters* filters, Wt::WContainerWidget* parent)
: Wt::WContainerWidget(parent),
_filters(filters)
Release::Release(Filters* filters)
: _filters(filters)
{
wApp->internalPathChanged().connect(std::bind([=]
{
@@ -60,24 +59,23 @@ Release::refresh()
clear();
Database::Release::id_type releaseId;
if (!readAs(wApp->internalPathNextPart("/release/"), releaseId))
auto releaseId = readAs<Database::Release::id_type>(wApp->internalPathNextPart("/release/"));
if (!releaseId)
return;
Wt::Dbo::Transaction transaction(DboSession());
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
auto release = Database::Release::getById(DboSession(), releaseId);
auto release = Database::Release::getById(LmsApp->getDboSession(), *releaseId);
if (!release)
{
LmsApp->goHome();
return;
}
auto t = new Wt::WTemplate(Wt::WString::tr("Lms.Explore.Release.template"), this);
Wt::WTemplate* t = addNew<Wt::WTemplate>(Wt::WString::tr("Lms.Explore.Release.template"));
t->addFunction("tr", &Wt::WTemplate::Functions::tr);
t->bindString("name", Wt::WString::fromUTF8(release->getName()), Wt::PlainText);
t->bindString("name", Wt::WString::fromUTF8(release->getName()), Wt::TextFormat::Plain);
boost::optional<int> year = release->getReleaseYear();
if (year)
@@ -103,49 +101,40 @@ Release::refresh()
else if (artists.size() == 1)
{
t->setCondition("if-has-artist", true);
Wt::WAnchor *artistAnchor = LmsApplication::createArtistAnchor(artists.front());
t->bindWidget("artist-name", artistAnchor);
t->bindWidget("artist-name", LmsApplication::createArtistAnchor(artists.front()));
}
}
Wt::WImage *cover = new Wt::WImage();
cover->setImageLink(Wt::WLink(LmsApp->getImageResource()->getReleaseUrl(release.id(), 512)));
t->bindWidget("cover", cover);
auto clusterContainers = new Wt::WContainerWidget();
t->bindWidget("clusters", clusterContainers);
t->bindNew<Wt::WImage>("cover", Wt::WLink(LmsApp->getImageResource()->getReleaseUrl(release.id(), 512)));
Wt::WContainerWidget* clusterContainers = t->bindNew<Wt::WContainerWidget>("clusters");
{
auto clusters = release->getClusters(3);
for (auto cluster : clusters)
{
auto entry = new Wt::WTemplate(Wt::WString::tr("Lms.Explore.Release.template.cluster-entry"), clusterContainers);
entry->bindString("name", Wt::WString::fromUTF8(cluster->getName()), Wt::PlainText);
Wt::WTemplate* entry = clusterContainers->addNew<Wt::WTemplate>(Wt::WString::tr("Lms.Explore.Release.template.cluster-entry"));
entry->bindString("name", Wt::WString::fromUTF8(cluster->getName()), Wt::TextFormat::Plain);
}
}
{
auto playBtn = new Wt::WText(Wt::WString::tr("Lms.Explore.Release.play"), Wt::XHTMLText);
t->bindWidget("play-btn", playBtn);
Wt::WText* playBtn = t->bindNew<Wt::WText>("play-btn", Wt::WString::tr("Lms.Explore.Release.play"), Wt::TextFormat::XHTML);
playBtn->clicked().connect(std::bind([=]
{
releasePlay.emit(releaseId);
releasePlay.emit(*releaseId);
}));
}
{
auto addBtn = new Wt::WText(Wt::WString::tr("Lms.Explore.Release.add"), Wt::XHTMLText);
t->bindWidget("add-btn", addBtn);
Wt::WText* addBtn = t->bindNew<Wt::WText>("add-btn", Wt::WString::tr("Lms.Explore.Release.add"), Wt::TextFormat::XHTML);
addBtn->clicked().connect(std::bind([=]
{
releaseAdd.emit(releaseId);
releaseAdd.emit(*releaseId);
}));
}
auto tracksContainer = new Wt::WContainerWidget();
t->bindWidget("tracks", tracksContainer);
Wt::WContainerWidget* tracksContainer = t->bindNew<Wt::WContainerWidget>("tracks");
auto clusterIds = _filters->getClusterIds();
auto tracks = release->getTracks(clusterIds);
@@ -156,15 +145,13 @@ Release::refresh()
{
auto trackId = track.id();
Wt::WTemplate* entry = new Wt::WTemplate(Wt::WString::tr("Lms.Explore.Release.template.entry"), tracksContainer);
entry->bindString("name", Wt::WString::fromUTF8(track->getName()), Wt::PlainText);
Wt::WTemplate* entry = tracksContainer->addNew<Wt::WTemplate>(Wt::WString::tr("Lms.Explore.Release.template.entry"));
entry->bindString("name", Wt::WString::fromUTF8(track->getName()), Wt::TextFormat::Plain);
if (variousArtists && track->getArtist())
{
entry->setCondition("if-has-artist", true);
Wt::WAnchor *artistAnchor = LmsApplication::createArtistAnchor(track->getArtist());
entry->bindWidget("artist-name", artistAnchor);
entry->bindWidget("artist-name", LmsApplication::createArtistAnchor(track->getArtist()));
}
auto trackNumber = track->getTrackNumber();
@@ -182,15 +169,13 @@ Release::refresh()
entry->bindInt("disc-number", *discNumber);
}
auto playBtn = new Wt::WText(Wt::WString::tr("Lms.Explore.Release.play"), Wt::XHTMLText);
entry->bindWidget("play-btn", playBtn);
Wt::WText* playBtn = entry->bindNew<Wt::WText>("play-btn", Wt::WString::tr("Lms.Explore.Release.play"), Wt::TextFormat::XHTML);
playBtn->clicked().connect(std::bind([=]
{
trackPlay.emit(trackId);
}));
auto addBtn = new Wt::WText(Wt::WString::tr("Lms.Explore.Release.add"), Wt::XHTMLText);
entry->bindWidget("add-btn", addBtn);
Wt::WText* addBtn = entry->bindNew<Wt::WText>("add-btn", Wt::WString::tr("Lms.Explore.Release.add"), Wt::TextFormat::XHTML);
addBtn->clicked().connect(std::bind([=]
{
trackAdd.emit(trackId);
+2 -2
View File
@@ -19,7 +19,7 @@
#pragma once
#include <Wt/WContainerWidget>
#include <Wt/WSignal.h>
namespace UserInterface {
@@ -27,7 +27,7 @@ class Filters;
class Release : public Wt::WContainerWidget
{
public:
Release(Filters* filters, Wt::WContainerWidget* parent = 0);
Release(Filters* filters);
Wt::Signal<Database::id_type> releaseAdd;
Wt::Signal<Database::id_type> releasePlay;
+23 -36
View File
@@ -17,11 +17,11 @@
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Wt/WApplication>
#include <Wt/WAnchor>
#include <Wt/WImage>
#include <Wt/WText>
#include <Wt/WTemplate>
#include <Wt/WApplication.h>
#include <Wt/WAnchor.h>
#include <Wt/WImage.h>
#include <Wt/WText.h>
#include <Wt/WTemplate.h>
#include "database/Types.hpp"
@@ -38,25 +38,20 @@ namespace UserInterface {
using namespace Database;
Releases::Releases(Filters* filters, Wt::WContainerWidget* parent)
: Wt::WContainerWidget(parent),
_filters(filters)
Releases::Releases(Filters* filters)
: Wt::WTemplate(Wt::WString::tr("Lms.Explore.Releases.template")),
_filters(filters)
{
auto container = new Wt::WTemplate(Wt::WString::tr("Lms.Explore.Releases.template"), this);
container->addFunction("tr", &Wt::WTemplate::Functions::tr);
addFunction("tr", &Wt::WTemplate::Functions::tr);
_search = new Wt::WLineEdit();
container->bindWidget("search", _search);
_search = bindNew<Wt::WLineEdit>("search");
_search->setPlaceholderText(Wt::WString::tr("Lms.Explore.search-placeholder"));
_search->textInput().connect(this, &Releases::refresh);
_releasesContainer = new Wt::WContainerWidget();
container->bindWidget("releases", _releasesContainer);
_releasesContainer = bindNew<Wt::WContainerWidget>("releases");
_showMore = new Wt::WTemplate(Wt::WString::tr("Lms.Explore.show-more"));
_showMore = bindNew<Wt::WTemplate>("show-more", Wt::WString::tr("Lms.Explore.show-more"));
_showMore->addFunction("tr", &Wt::WTemplate::Functions::tr);
container->bindWidget("show-more", _showMore);
_showMore->clicked().connect(std::bind([=]
{
addSome();
@@ -81,29 +76,24 @@ Releases::addSome()
auto clusterIds = _filters->getClusterIds();
Wt::Dbo::Transaction transaction(DboSession());
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
bool moreResults;
auto releases = Release::getByFilter(DboSession(), clusterIds, searchKeywords, _releasesContainer->count(), 20, moreResults);
auto releases = Release::getByFilter(LmsApp->getDboSession(), clusterIds, searchKeywords, _releasesContainer->count(), 20, moreResults);
for (auto release : releases)
{
auto releaseId = release.id();
Wt::WTemplate* entry = new Wt::WTemplate(Wt::WString::tr("Lms.Explore.Releases.template.entry"), _releasesContainer);
Wt::WTemplate* entry = _releasesContainer->addNew<Wt::WTemplate>(Wt::WString::tr("Lms.Explore.Releases.template.entry"));
entry->addFunction("tr", Wt::WTemplate::Functions::tr);
Wt::WAnchor* coverAnchor = LmsApplication::createReleaseAnchor(release, false);
Wt::WImage* cover = new Wt::WImage(coverAnchor);
cover->setImageLink(LmsApp->getImageResource()->getReleaseUrl(releaseId, 128));
// Some images may not be square
cover->setWidth(128);
entry->bindWidget("cover", coverAnchor);
Wt::WAnchor* anchor = entry->bindWidget("cover", LmsApplication::createReleaseAnchor(release, false));
auto cover = std::make_unique<Wt::WImage>();
cover->setImageLink(LmsApp->getImageResource()->getReleaseUrl(release.id(), 128));
anchor->setImage(std::move(cover));
{
Wt::WAnchor* releaseAnchor = LmsApplication::createReleaseAnchor(release);
entry->bindWidget("release-name", releaseAnchor);
}
entry->bindWidget("release-name", LmsApplication::createReleaseAnchor(release));
auto artists = release->getArtists();
if (artists.size() > 1)
@@ -114,19 +104,16 @@ Releases::addSome()
else if (artists.size() == 1)
{
entry->setCondition("if-has-artist", true);
Wt::WAnchor* artistAnchor = LmsApplication::createArtistAnchor(artists.front());
entry->bindWidget("artist-name", artistAnchor);
entry->bindWidget("artist-name", LmsApplication::createArtistAnchor(artists.front()));
}
auto playBtn = new Wt::WText(Wt::WString::tr("Lms.Explore.Releases.play"), Wt::XHTMLText);
entry->bindWidget("play-btn", playBtn);
Wt::WText* playBtn = entry->bindNew<Wt::WText>("play-btn", Wt::WString::tr("Lms.Explore.Releases.play"), Wt::TextFormat::XHTML);
playBtn->clicked().connect(std::bind([=]
{
releasePlay.emit(releaseId);
}));
auto addBtn = new Wt::WText(Wt::WString::tr("Lms.Explore.Releases.add"), Wt::XHTMLText);
entry->bindWidget("add-btn", addBtn);
Wt::WText* addBtn = entry->bindNew<Wt::WText>("add-btn", Wt::WString::tr("Lms.Explore.Releases.add"), Wt::TextFormat::XHTML);
addBtn->clicked().connect(std::bind([=]
{
releaseAdd.emit(releaseId);
+6 -5
View File
@@ -19,18 +19,19 @@
#pragma once
#include <Wt/WContainerWidget>
#include <Wt/WLineEdit>
#include <Wt/WText>
#include <Wt/WContainerWidget.h>
#include <Wt/WLineEdit.h>
#include <Wt/WText.h>
#include <Wt/WTemplate.h>
namespace UserInterface {
class Filters;
class Releases : public Wt::WContainerWidget
class Releases : public Wt::WTemplate
{
public:
Releases(Filters* filters, Wt::WContainerWidget* parent = 0);
Releases(Filters* filters);
Wt::Signal<Database::id_type> releaseAdd;
Wt::Signal<Database::id_type> releasePlay;
+25 -38
View File
@@ -17,10 +17,10 @@
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Wt/WAnchor>
#include <Wt/WImage>
#include <Wt/WLineEdit>
#include <Wt/WText>
#include <Wt/WAnchor.h>
#include <Wt/WImage.h>
#include <Wt/WLineEdit.h>
#include <Wt/WText.h>
#include "database/Types.hpp"
@@ -37,41 +37,34 @@ namespace UserInterface {
using namespace Database;
Tracks::Tracks(Filters* filters, Wt::WContainerWidget* parent)
: Wt::WContainerWidget(parent),
_filters(filters)
Tracks::Tracks(Filters* filters)
: Wt::WTemplate(Wt::WString::tr("Lms.Explore.Tracks.template")),
_filters(filters)
{
auto container = new Wt::WTemplate(Wt::WString::tr("Lms.Explore.Tracks.template"), this);
container->addFunction("tr", &Wt::WTemplate::Functions::tr);
addFunction("tr", &Wt::WTemplate::Functions::tr);
_search = new Wt::WLineEdit();
container->bindWidget("search", _search);
_search = bindNew<Wt::WLineEdit>("search");
_search->setPlaceholderText(Wt::WString::tr("Lms.Explore.search-placeholder"));
_search->textInput().connect(this, &Tracks::refresh);
auto playBtn = new Wt::WText(Wt::WString::tr("Lms.Explore.Tracks.play"), Wt::XHTMLText);
container->bindWidget("play-btn", playBtn);
Wt::WText* playBtn = bindNew<Wt::WText>("play-btn", Wt::WString::tr("Lms.Explore.Tracks.play"), Wt::TextFormat::XHTML);
playBtn->clicked().connect(std::bind([=]
{
Wt::Dbo::Transaction transaction(DboSession());
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
tracksPlay.emit(getTracks());
}));
auto addBtn = new Wt::WText(Wt::WString::tr("Lms.Explore.Tracks.add"), Wt::XHTMLText);
container->bindWidget("add-btn", addBtn);
Wt::WText* addBtn = bindNew<Wt::WText>("add-btn", Wt::WString::tr("Lms.Explore.Tracks.add"), Wt::TextFormat::XHTML);
addBtn->clicked().connect(std::bind([=]
{
Wt::Dbo::Transaction transaction(DboSession());
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
tracksAdd.emit(getTracks());
}));
_tracksContainer = new Wt::WContainerWidget();
container->bindWidget("tracks", _tracksContainer);
_tracksContainer = bindNew<Wt::WContainerWidget>("tracks");
_showMore = new Wt::WTemplate(Wt::WString::tr("Lms.Explore.template.show-more"));
_showMore = bindNew<Wt::WTemplate>("show-more", Wt::WString::tr("Lms.Explore.template.show-more"));
_showMore->addFunction("tr", &Wt::WTemplate::Functions::tr);
container->bindWidget("show-more", _showMore);
_showMore->clicked().connect(std::bind([=]
{
addSome();
@@ -88,9 +81,9 @@ Tracks::getTracks(int offset, int size, bool& moreResults)
auto searchKeywords = splitString(_search->text().toUTF8(), " ");
auto clusterIds = _filters->getClusterIds();
Wt::Dbo::Transaction transaction(DboSession());
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
return Track::getByFilter(DboSession(), clusterIds, searchKeywords, offset, size, moreResults);
return Track::getByFilter(LmsApp->getDboSession(), clusterIds, searchKeywords, offset, size, moreResults);
}
std::vector<Database::Track::pointer>
@@ -110,7 +103,7 @@ Tracks::refresh()
void
Tracks::addSome()
{
Wt::Dbo::Transaction transaction(DboSession());
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
bool moreResults;
auto tracks = getTracks(_tracksContainer->count(), 20, moreResults);
@@ -118,41 +111,35 @@ Tracks::addSome()
for (auto track : tracks)
{
auto trackId = track.id();
Wt::WTemplate* entry = new Wt::WTemplate(Wt::WString::tr("Lms.Explore.Tracks.template.entry"), _tracksContainer);
Wt::WTemplate* entry = _tracksContainer->addNew<Wt::WTemplate>(Wt::WString::tr("Lms.Explore.Tracks.template.entry"));
entry->bindString("name", Wt::WString::fromUTF8(track->getName()), Wt::PlainText);
entry->bindString("name", Wt::WString::fromUTF8(track->getName()), Wt::TextFormat::Plain);
auto artist = track->getArtist();
if (artist)
{
entry->setCondition("if-has-artist", true);
Wt::WAnchor *artistAnchor = LmsApplication::createArtistAnchor(track->getArtist());
entry->bindWidget("artist-name", artistAnchor);
entry->bindWidget("artist-name", LmsApplication::createArtistAnchor(track->getArtist()));
}
auto release = track->getRelease();
if (release)
{
entry->setCondition("if-has-release", true);
Wt::WAnchor *releaseAnchor = LmsApplication::createReleaseAnchor(track->getRelease());
entry->bindWidget("release-name", releaseAnchor);
entry->bindWidget("release-name", LmsApplication::createReleaseAnchor(track->getRelease()));
}
Wt::WImage *cover = new Wt::WImage();
cover->setImageLink(LmsApp->getImageResource()->getTrackUrl(track.id(), 64));
Wt::WImage* cover = entry->bindNew<Wt::WImage>("cover", LmsApp->getImageResource()->getTrackUrl(track.id(), 64));
// Some images may not be square
cover->setWidth(64);
entry->bindWidget("cover", cover);
auto playBtn = new Wt::WText(Wt::WString::tr("Lms.Explore.Tracks.play"), Wt::XHTMLText);
entry->bindWidget("play-btn", playBtn);
Wt::WText* playBtn = entry->bindNew<Wt::WText>("play-btn", Wt::WString::tr("Lms.Explore.Tracks.play"), Wt::TextFormat::XHTML);
playBtn->clicked().connect(std::bind([=]
{
trackPlay.emit(trackId);
}));
auto addBtn = new Wt::WText(Wt::WString::tr("Lms.Explore.Tracks.add"), Wt::XHTMLText);
entry->bindWidget("add-btn", addBtn);
Wt::WText* addBtn = entry->bindNew<Wt::WText>("add-btn", Wt::WString::tr("Lms.Explore.Tracks.add"), Wt::TextFormat::XHTML);
addBtn->clicked().connect(std::bind([=]
{
trackAdd.emit(trackId);
+5 -5
View File
@@ -19,17 +19,17 @@
#pragma once
#include <Wt/WContainerWidget>
#include <Wt/WLineEdit>
#include <Wt/WTemplate>
#include <Wt/WContainerWidget.h>
#include <Wt/WLineEdit.h>
#include <Wt/WTemplate.h>
namespace UserInterface {
class Filters;
class Tracks : public Wt::WContainerWidget
class Tracks : public Wt::WTemplate
{
public:
Tracks(Filters* filters, Wt::WContainerWidget* parent = 0);
Tracks(Filters* filters);
Wt::Signal<Database::id_type> trackAdd;
Wt::Signal<Database::id_type> trackPlay;
+17 -22
View File
@@ -17,8 +17,8 @@
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Wt/WApplication>
#include <Wt/Http/Response>
#include <Wt/WApplication.h>
#include <Wt/Http/Response.h>
#include "utils/Logger.hpp"
#include "utils/Utils.hpp"
@@ -34,9 +34,8 @@ namespace UserInterface {
static const std::string unknownCoverPath = "/images/unknown-cover.jpg";
static const std::string unknownArtistImagePath = "/images/unknown-artist.jpg";
ImageResource::ImageResource(Database::Handler& db, Wt::WObject *parent)
: Wt::WResource(parent),
_db(db)
ImageResource::ImageResource(Database::Handler& db)
: _db(db)
{
}
@@ -154,14 +153,14 @@ ImageResource::handleRequest(const Wt::Http::Request& request, Wt::Http::Respons
if (!sizeStr)
return;
std::size_t size;
if (!readAs(*sizeStr, size) || size > maxSize)
auto size = readAs<std::size_t>(*sizeStr);
if (!size || *size > maxSize)
return;
if (trackIdStr)
{
Database::Track::id_type trackId;
if (!readAs(*trackIdStr, trackId))
auto trackId = readAs<Database::Track::id_type>(*trackIdStr);
if (!trackId)
return;
boost::filesystem::path path;
@@ -172,7 +171,7 @@ ImageResource::handleRequest(const Wt::Http::Request& request, Wt::Http::Respons
Wt::Dbo::Transaction transaction(_db.getSession());
Database::Track::pointer track = Database::Track::getById(_db.getSession(), trackId);
Database::Track::pointer track = Database::Track::getById(_db.getSession(), *trackId);
if (track)
{
coverType = track->getCoverType();
@@ -195,17 +194,16 @@ ImageResource::handleRequest(const Wt::Http::Request& request, Wt::Http::Respons
break;
}
putCover(response, covers, size);
putCover(response, covers, *size);
return;
}
putImage(response, getDefaultCover(size));
return;
putImage(response, getDefaultCover(*size));
}
else if (releaseIdStr)
{
Database::Release::id_type releaseId;
if (!readAs(*releaseIdStr, releaseId))
auto releaseId = readAs<Database::Release::id_type>(*releaseIdStr);
if (!releaseId)
return;
std::vector<Image::Image> covers;
@@ -213,21 +211,18 @@ ImageResource::handleRequest(const Wt::Http::Request& request, Wt::Http::Respons
// transactions are not thread safe
{
Wt::WApplication::UpdateLock lock(LmsApplication::instance());
covers = CoverArt::Grabber::instance().getFromRelease(_db.getSession(), releaseId);
covers = CoverArt::Grabber::instance().getFromRelease(_db.getSession(), *releaseId);
}
putCover(response, covers, size);
return;
putCover(response, covers, *size);
}
else if (artistIdStr)
{
putImage(response, getDefaultArtistImage(size));
return;
putImage(response, getDefaultArtistImage(*size));
}
else
{
putImage(response, getDefaultCover(size));
return;
putImage(response, getDefaultCover(*size));
}
}
+2 -2
View File
@@ -22,7 +22,7 @@
#include <mutex>
#include <Wt/WResource>
#include <Wt/WResource.h>
#include "database/DatabaseHandler.hpp"
#include "image/Image.hpp"
@@ -35,7 +35,7 @@ class ImageResource : public Wt::WResource
public:
static const std::size_t maxSize = 512;
ImageResource(Database::Handler& db, Wt::WObject *parent = 0);
ImageResource(Database::Handler& db);
~ImageResource();
std::string getReleaseUrl(Database::Release::id_type releaseId, size_t size) const;
+3 -4
View File
@@ -17,7 +17,7 @@
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Wt/Http/Response>
#include <Wt/Http/Response.h>
#include "utils/Logger.hpp"
@@ -27,9 +27,8 @@
namespace UserInterface {
TranscodeResource::TranscodeResource(Database::Handler& db, Wt::WObject *parent)
: Wt::WResource(parent),
_db(db)
TranscodeResource::TranscodeResource(Database::Handler& db)
: _db(db)
{
LMS_LOG(UI, DEBUG) << "CONSTRUCTING RESOURCE";
}
+2 -2
View File
@@ -21,7 +21,7 @@
#include <mutex>
#include <Wt/WResource>
#include <Wt/WResource.h>
#include "av/AvTranscoder.hpp"
@@ -32,7 +32,7 @@ namespace UserInterface {
class TranscodeResource : public Wt::WResource
{
public:
TranscodeResource(Database::Handler& db, Wt::WObject *parent);
TranscodeResource(Database::Handler& db);
~TranscodeResource();
std::string getUrl(Database::Track::id_type trackId, Av::Encoding encoding, boost::posix_time::time_duration offset) const;