Added Settings view

This commit is contained in:
emeric
2018-03-16 14:00:03 +01:00
parent bc26ddae50
commit 1e6ea42f65
11 changed files with 438 additions and 28 deletions
+9 -1
View File
@@ -35,6 +35,7 @@
#include "HomeView.hpp"
#include "MediaPlayer.hpp"
#include "PlayQueueView.hpp"
#include "SettingsView.hpp"
#include "admin/DatabaseSettingsView.hpp"
#include "admin/AdminWizardView.hpp"
@@ -93,6 +94,7 @@ LmsApplication::LmsApplication(const Wt::WEnvironment& env, Wt::Dbo::SqlConnecti
messageResourceBundle().use(appRoot() + "playqueue");
messageResourceBundle().use(appRoot() + "release");
messageResourceBundle().use(appRoot() + "releases");
messageResourceBundle().use(appRoot() + "settings");
messageResourceBundle().use(appRoot() + "tracks");
messageResourceBundle().use(appRoot() + "templates");
@@ -185,6 +187,7 @@ enum IdxRoot
IdxHome = 0,
IdxExplore,
IdxPlayQueue,
IdxSettings,
IdxAdminDatabase,
};
@@ -200,6 +203,7 @@ handlePathChange(Wt::WStackedWidget* stack)
{ "/release", IdxExplore },
{ "/tracks", IdxExplore },
{ "/playqueue", IdxPlayQueue },
{ "/settings", IdxSettings },
{ "/admin/database", IdxAdminDatabase },
};
@@ -288,7 +292,7 @@ LmsApplication::handleAuthEvent(void)
}
{
auto menuItem = rightMenu->insertItem(itemCounter++, Wt::WString::tr("Lms.settings"));
auto menuItem = rightMenu->insertItem(itemCounter++, Wt::WString::tr("Lms.Settings.settings"));
menuItem->setLink(Wt::WLink(Wt::WLink::InternalPath, "/settings"));
menuItem->setSelectable(false);
}
@@ -315,6 +319,10 @@ LmsApplication::handleAuthEvent(void)
auto playqueue = new PlayQueue();
mainStack->addWidget(playqueue);
auto settings = new SettingsView();
mainStack->addWidget(settings);
// Admin stuff
auto databaseSettings = new DatabaseSettingsView();
mainStack->addWidget(databaseSettings);
+304
View File
@@ -0,0 +1,304 @@
/*
* Copyright (C) 2018 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Wt/WString>
#include <Wt/WPushButton>
#include <Wt/WComboBox>
#include <Wt/WLineEdit>
#include <Wt/WFormModel>
#include <Wt/WStringListModel>
#include "common/Validators.hpp"
#include "utils/Logger.hpp"
#include "LmsApplication.hpp"
#include "SettingsView.hpp"
namespace UserInterface {
using namespace Database;
class SettingsModel : public Wt::WFormModel
{
public:
// Associate each field with a unique string literal.
static const Field BitrateField;
static const Field EncodingField;
static const Field PasswordField;
static const Field PasswordConfirmField;
SettingsModel(Wt::WObject *parent = 0)
: Wt::WFormModel(parent)
{
initializeModels();
addField(BitrateField);
addField(EncodingField);
addField(PasswordField);
addField(PasswordConfirmField);
setValidator(BitrateField, createMandatoryValidator());
setValidator(EncodingField, createMandatoryValidator());
loadData();
}
Wt::WAbstractItemModel *bitrateModel() { return _bitrateModel; }
Wt::WAbstractItemModel *encodingModel() { return _encodingModel; }
void loadData()
{
Wt::Dbo::Transaction transaction(DboSession());
auto bitrate = getBitrateRow(CurrentUser()->getAudioBitrate());
if (bitrate)
setValue(BitrateField, bitrateString(*bitrate));
auto encodingRow = getEncodingRow(CurrentUser()->getAudioEncoding());
if (encodingRow)
setValue(EncodingField, encodingString(*encodingRow));
}
void saveData()
{
Wt::Dbo::Transaction transaction(DboSession());
auto bitrateRow = getBitrateRow(Wt::asString(value(BitrateField)));
assert(bitrateRow);
CurrentUser().modify()->setAudioBitrate(bitrate(*bitrateRow));
auto encodingRow = getEncodingRow(Wt::asString(value(EncodingField)));
CurrentUser().modify()->setAudioEncoding(encoding(*encodingRow));
if (!valueText(PasswordField).empty())
{
Database::Handler::getPasswordService().updatePassword(CurrentAuthUser(), valueText(PasswordField));
}
}
bool validateField(Field field)
{
Wt::WString error;
if (field == PasswordField)
{
if (!valueText(PasswordField).empty())
{
// Evaluate the strength of the password
auto res = Database::Handler::getPasswordService().strengthValidator()->evaluateStrength(valueText(PasswordField),
CurrentAuthUser().identity(Wt::Auth::Identity::LoginName), "");
if (!res.isValid())
error = res.message();
}
else
return Wt::WFormModel::validateField(field);
}
else if (field == PasswordConfirmField)
{
if (validation(PasswordField).state() == Wt::WValidator::Valid)
{
if (valueText(PasswordField) != valueText(PasswordConfirmField))
error = Wt::WString::tr("Lms.passwords-dont-match");
}
}
else
{
return Wt::WFormModel::validateField(field);
}
setValidation(field, Wt::WValidator::Result( error.empty() ? Wt::WValidator::Valid : Wt::WValidator::Invalid, error));
return (validation(field).state() == Wt::WValidator::Valid);
}
boost::optional<int> getBitrateRow(Wt::WString value)
{
for (int i = 0; i < _bitrateModel->rowCount(); ++i)
{
if (bitrateString(i) == value)
return i;
}
return boost::none;
}
boost::optional<int> getBitrateRow(std::size_t value)
{
for (int i = 0; i < _bitrateModel->rowCount(); ++i)
{
if (bitrate(i) == value)
return i;
}
return boost::none;
}
std::size_t bitrate(int row)
{
return boost::any_cast<std::size_t>
(_bitrateModel->data(_encodingModel->index(row, 0), Wt::UserRole));
}
Wt::WString bitrateString(int row)
{
return boost::any_cast<Wt::WString>
(_bitrateModel->data(_encodingModel->index(row, 0), Wt::DisplayRole));
}
boost::optional<int> getEncodingRow(Wt::WString value)
{
for (int i = 0; i < _encodingModel->rowCount(); ++i)
{
if (encodingString(i) == value)
return i;
}
return boost::none;
}
boost::optional<int> getEncodingRow(Database::AudioEncoding enc)
{
for (int i = 0; i < _encodingModel->rowCount(); ++i)
{
if (encoding(i) == enc)
return i;
}
return boost::none;
}
Database::AudioEncoding encoding(int row)
{
return boost::any_cast<Database::AudioEncoding>
(_encodingModel->data(_encodingModel->index(row, 0), Wt::UserRole));
}
Wt::WString encodingString(int row)
{
return boost::any_cast<Wt::WString>
(_encodingModel->data(_encodingModel->index(row, 0), Wt::DisplayRole));
}
private:
void initializeModels()
{
_bitrateModel = new Wt::WStringListModel(this);
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);
}
_encodingModel = new Wt::WStringListModel(this);
_encodingModel->addString(Wt::WString::tr("Lms.Settings.auto"));
_encodingModel->setData(0, 0, Database::AudioEncoding::AUTO, Wt::UserRole);
_encodingModel->addString(Wt::WString::tr("Lms.Settings.mp3"));
_encodingModel->setData(1, 0, Database::AudioEncoding::MP3, Wt::UserRole);
_encodingModel->addString(Wt::WString::tr("Lms.Settings.oga"));
_encodingModel->setData(2, 0, Database::AudioEncoding::OGA, Wt::UserRole);
_encodingModel->addString(Wt::WString::tr("Lms.Settings.webma"));
_encodingModel->setData(3, 0, Database::AudioEncoding::WEBMA, Wt::UserRole);
}
Wt::WStringListModel* _bitrateModel;
Wt::WStringListModel* _encodingModel;
};
const Wt::WFormModel::Field SettingsModel::BitrateField = "bitrate";
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)
{
auto model = new SettingsModel(this);
setTemplateText(tr("Lms.Settings.template"));
addFunction("tr", &WTemplate::Functions::tr);
addFunction("id", &WTemplate::Functions::id);
// Password
Wt::WLineEdit *password = new Wt::WLineEdit();
setFormWidget(SettingsModel::PasswordField, password);
password->setEchoMode(Wt::WLineEdit::Password);
// Password confirm
Wt::WLineEdit *passwordConfirm = new Wt::WLineEdit();
setFormWidget(SettingsModel::PasswordConfirmField, passwordConfirm);
passwordConfirm->setEchoMode(Wt::WLineEdit::Password);
// Bitrate
Wt::WComboBox *bitrate = new Wt::WComboBox();
setFormWidget(SettingsModel::BitrateField, bitrate);
bitrate->setModel(model->bitrateModel());
// Encoding
Wt::WComboBox *encoding = new Wt::WComboBox();
setFormWidget(SettingsModel::EncodingField, encoding);
encoding->setModel(model->encodingModel());
// 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);
saveBtn->clicked().connect(std::bind([=] ()
{
updateModel(model);
if (model->validate())
{
model->saveData();
LmsApp->notify(Wt::WString::tr("Lms.Settings.settings-saved"));
}
// Udate the view: Delete any validation message in the view, etc.
updateView(model);
}));
discardBtn->clicked().connect(std::bind([=] ()
{
model->loadData();
model->validate();
updateView(model);
}));
updateView(model);
}
} // namespace UserInterface
+34
View File
@@ -0,0 +1,34 @@
/*
* Copyright (C) 2018 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <Wt/WContainerWidget>
#include <Wt/WTemplateFormView>
namespace UserInterface {
class SettingsView : public Wt::WTemplateFormView
{
public:
SettingsView(Wt::WContainerWidget *parent = 0);
};
} // namespace UserInterface
+1 -1
View File
@@ -97,7 +97,7 @@ class AdminWizardModel : public Wt::WFormModel
if (validation(PasswordField).state() == Wt::WValidator::Valid)
{
if (valueText(PasswordField) != valueText(PasswordConfirmField))
error = Wt::WString::tr("Wt.Auth.passwords-dont-match");
error = Wt::WString::tr("Lms.passwords-dont-match");
}
}
else
+2 -2
View File
@@ -20,7 +20,6 @@
#include <Wt/WString>
#include <Wt/WPushButton>
#include <Wt/WComboBox>
#include <Wt/WMessageBox>
#include <Wt/WLineEdit>
#include <Wt/WFormModel>
@@ -177,7 +176,8 @@ class DatabaseSettingsModel : public Wt::WFormModel
private:
void initializeModels() {
void initializeModels()
{
_updatePeriodModel = new Wt::WStringListModel(this);