Added an option for the user to choice the type of the similarity engine to use
This commit is contained in:
@@ -46,7 +46,7 @@
|
||||
|
||||
namespace Database {
|
||||
|
||||
#define LMS_DATABASE_VERSION 2
|
||||
#define LMS_DATABASE_VERSION 3
|
||||
|
||||
namespace {
|
||||
Wt::Auth::AuthService authService;
|
||||
|
||||
@@ -61,11 +61,10 @@ class SimilaritySettings : public Wt::Dbo::Dbo<SimilaritySettings>
|
||||
{
|
||||
public:
|
||||
|
||||
enum class PreferredMethod
|
||||
enum class EngineType
|
||||
{
|
||||
Auto,
|
||||
Features,
|
||||
Clusters,
|
||||
Features = 0,
|
||||
Clusters = 1,
|
||||
};
|
||||
|
||||
using pointer = Wt::Dbo::ptr<SimilaritySettings>;
|
||||
@@ -75,23 +74,25 @@ class SimilaritySettings : public Wt::Dbo::Dbo<SimilaritySettings>
|
||||
|
||||
// Accessors Read
|
||||
std::size_t getVersion() const { return _settingsVersion; }
|
||||
PreferredMethod getPreferredMethod() const { return _preferredMethod; }
|
||||
EngineType getEngineType() const { return _engineType; }
|
||||
std::vector<Wt::Dbo::ptr<SimilaritySettingsFeature>> getFeatures() const;
|
||||
|
||||
// Setters
|
||||
void setEngineType(EngineType type) { _engineType = type; }
|
||||
|
||||
template<class Action>
|
||||
void persist(Action& a)
|
||||
{
|
||||
Wt::Dbo::field(a, _settingsVersion, "settings_version");
|
||||
Wt::Dbo::field(a, _preferredMethod, "preferred_method");
|
||||
Wt::Dbo::field(a, _settingsVersion, "settings_version");
|
||||
Wt::Dbo::field(a, _engineType, "engine_type");
|
||||
|
||||
Wt::Dbo::hasMany(a, _features, Wt::Dbo::ManyToOne, "similarity_settings");
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
int _settingsVersion = 0;
|
||||
PreferredMethod _preferredMethod = PreferredMethod::Auto;
|
||||
int _settingsVersion {};
|
||||
EngineType _engineType {EngineType::Features};
|
||||
|
||||
Wt::Dbo::collection<Wt::Dbo::ptr<SimilaritySettingsFeature>> _features;
|
||||
};
|
||||
|
||||
@@ -31,23 +31,22 @@ Searcher::Searcher(FeaturesScannerAddon& somAddon)
|
||||
{}
|
||||
|
||||
static
|
||||
Database::SimilaritySettings::PreferredMethod getPreferredMethod(Wt::Dbo::Session& session)
|
||||
Database::SimilaritySettings::EngineType getEngineType(Wt::Dbo::Session& session)
|
||||
{
|
||||
Wt::Dbo::Transaction transaction(session);
|
||||
return Database::SimilaritySettings::get(session)->getPreferredMethod();
|
||||
Wt::Dbo::Transaction transaction{session};
|
||||
return Database::SimilaritySettings::get(session)->getEngineType();
|
||||
}
|
||||
|
||||
std::vector<Database::IdType>
|
||||
Searcher::getSimilarTracks(Wt::Dbo::Session& session, const std::set<Database::IdType>& trackIds, std::size_t maxCount)
|
||||
{
|
||||
|
||||
auto method = getPreferredMethod(session);
|
||||
auto somSearcher = _somAddon.getSearcher();
|
||||
auto engineType {getEngineType(session)};
|
||||
auto somSearcher {_somAddon.getSearcher()};
|
||||
|
||||
if (method == Database::SimilaritySettings::PreferredMethod::Features
|
||||
|| (method == Database::SimilaritySettings::PreferredMethod::Auto
|
||||
&& somSearcher
|
||||
&& std::any_of(std::cbegin(trackIds), std::cend(trackIds), [&](Database::IdType trackId) { return somSearcher->isTrackClassified(trackId); } )))
|
||||
if (engineType == Database::SimilaritySettings::EngineType::Features
|
||||
&& somSearcher
|
||||
&& std::any_of(std::cbegin(trackIds), std::cend(trackIds), [&](Database::IdType trackId) { return somSearcher->isTrackClassified(trackId); } ))
|
||||
{
|
||||
return somSearcher->getSimilarTracks(trackIds, maxCount);
|
||||
}
|
||||
@@ -58,13 +57,12 @@ Searcher::getSimilarTracks(Wt::Dbo::Session& session, const std::set<Database::I
|
||||
std::vector<Database::IdType>
|
||||
Searcher::getSimilarReleases(Wt::Dbo::Session& session, Database::IdType releaseId, std::size_t maxCount)
|
||||
{
|
||||
auto method = getPreferredMethod(session);
|
||||
auto somSearcher = _somAddon.getSearcher();
|
||||
auto engineType {getEngineType(session)};
|
||||
auto somSearcher {_somAddon.getSearcher()};
|
||||
|
||||
if (method == Database::SimilaritySettings::PreferredMethod::Features
|
||||
|| (method == Database::SimilaritySettings::PreferredMethod::Auto
|
||||
&& somSearcher
|
||||
&& somSearcher->isReleaseClassified(releaseId)))
|
||||
if (engineType == Database::SimilaritySettings::EngineType::Features
|
||||
&& somSearcher
|
||||
&& somSearcher->isReleaseClassified(releaseId))
|
||||
{
|
||||
return somSearcher->getSimilarReleases(releaseId, maxCount);
|
||||
}
|
||||
@@ -75,13 +73,12 @@ Searcher::getSimilarReleases(Wt::Dbo::Session& session, Database::IdType release
|
||||
std::vector<Database::IdType>
|
||||
Searcher::getSimilarArtists(Wt::Dbo::Session& session, Database::IdType artistId, std::size_t maxCount)
|
||||
{
|
||||
auto method = getPreferredMethod(session);
|
||||
auto somSearcher = _somAddon.getSearcher();
|
||||
auto engineType {getEngineType(session)};
|
||||
auto somSearcher {_somAddon.getSearcher()};
|
||||
|
||||
if (method == Database::SimilaritySettings::PreferredMethod::Features
|
||||
|| (method == Database::SimilaritySettings::PreferredMethod::Auto
|
||||
&& somSearcher
|
||||
&& somSearcher->isArtistClassified(artistId)))
|
||||
if (engineType == Database::SimilaritySettings::EngineType::Features
|
||||
&& somSearcher
|
||||
&& somSearcher->isArtistClassified(artistId))
|
||||
{
|
||||
return somSearcher->getSimilarArtists(artistId, maxCount);
|
||||
}
|
||||
|
||||
+36
-115
@@ -26,9 +26,9 @@
|
||||
#include <Wt/WLineEdit.h>
|
||||
|
||||
#include <Wt/WFormModel.h>
|
||||
#include <Wt/WStringListModel.h>
|
||||
|
||||
#include "common/Validators.hpp"
|
||||
#include "common/ValueStringModel.hpp"
|
||||
|
||||
#include "utils/Logger.hpp"
|
||||
#include "LmsApplication.hpp"
|
||||
@@ -67,6 +67,24 @@ class SettingsModel : public Wt::WFormModel
|
||||
std::shared_ptr<Wt::WAbstractItemModel> transcodeBitrateModel() { return _transcodeBitrateModel; }
|
||||
std::shared_ptr<Wt::WAbstractItemModel> transcodeFormatModel() { return _transcodeFormatModel; }
|
||||
|
||||
void saveData()
|
||||
{
|
||||
Wt::Dbo::Transaction transaction {LmsApp->getDboSession()};
|
||||
|
||||
LmsApp->getUser().modify()->setAudioTranscodeEnable(Wt::asNumber(value(TranscodeEnableField)));
|
||||
|
||||
auto transcodeBitrateRow {_transcodeBitrateModel->getRowFromString(valueText(TranscodeBitrateField))};
|
||||
if (transcodeBitrateRow)
|
||||
LmsApp->getUser().modify()->setAudioTranscodeBitrate(_transcodeBitrateModel->getValue(*transcodeBitrateRow));
|
||||
|
||||
auto transcodeFormatRow {_transcodeFormatModel->getRowFromString(valueText(TranscodeFormatField))};
|
||||
if (transcodeFormatRow)
|
||||
LmsApp->getUser().modify()->setAudioTranscodeFormat(_transcodeFormatModel->getValue(*transcodeFormatRow));
|
||||
|
||||
if (!valueText(PasswordField).empty())
|
||||
Handler::getPasswordService().updatePassword(LmsApp->getAuthUser(), valueText(PasswordField));
|
||||
}
|
||||
|
||||
void loadData()
|
||||
{
|
||||
Wt::Dbo::Transaction transaction {LmsApp->getDboSession()};
|
||||
@@ -78,32 +96,16 @@ class SettingsModel : public Wt::WFormModel
|
||||
setReadOnly(TranscodeBitrateField, true);
|
||||
}
|
||||
|
||||
auto transcodeBitrateRow {getTranscodeBitrateRow(LmsApp->getUser()->getAudioTranscodeBitrate())};
|
||||
auto transcodeBitrateRow {_transcodeBitrateModel->getRowFromValue(LmsApp->getUser()->getAudioTranscodeBitrate())};
|
||||
if (transcodeBitrateRow)
|
||||
setValue(TranscodeBitrateField, transcodeBitrateString(*transcodeBitrateRow));
|
||||
setValue(TranscodeBitrateField, _transcodeBitrateModel->getString(*transcodeBitrateRow));
|
||||
|
||||
auto transcodeFormatRow {getTranscodeFormatRow(LmsApp->getUser()->getAudioTranscodeFormat())};
|
||||
auto transcodeFormatRow {_transcodeFormatModel->getRowFromValue(LmsApp->getUser()->getAudioTranscodeFormat())};
|
||||
if (transcodeFormatRow)
|
||||
setValue(TranscodeFormatField, transcodeFormatString(*transcodeFormatRow));
|
||||
setValue(TranscodeFormatField, _transcodeFormatModel->getString(*transcodeFormatRow));
|
||||
}
|
||||
|
||||
void saveData()
|
||||
{
|
||||
Wt::Dbo::Transaction transaction {LmsApp->getDboSession()};
|
||||
|
||||
LmsApp->getUser().modify()->setAudioTranscodeEnable(Wt::asNumber(value(TranscodeEnableField)));
|
||||
|
||||
auto transcodeBitrateRow {getTranscodeBitrateRow(Wt::asString(value(TranscodeBitrateField)))};
|
||||
if (transcodeBitrateRow)
|
||||
LmsApp->getUser().modify()->setAudioTranscodeBitrate(transcodeBitrate(*transcodeBitrateRow));
|
||||
|
||||
auto transcodeFormatRow {getTranscodeFormatRow(Wt::asString(value(TranscodeFormatField)))};
|
||||
if (transcodeFormatRow)
|
||||
LmsApp->getUser().modify()->setAudioTranscodeFormat(transcodeFormat(*transcodeFormatRow));
|
||||
|
||||
if (!valueText(PasswordField).empty())
|
||||
Database::Handler::getPasswordService().updatePassword(LmsApp->getAuthUser(), valueText(PasswordField));
|
||||
}
|
||||
private:
|
||||
|
||||
bool validateField(Field field)
|
||||
{
|
||||
@@ -114,7 +116,7 @@ class SettingsModel : public Wt::WFormModel
|
||||
if (!valueText(PasswordField).empty())
|
||||
{
|
||||
// Evaluate the strength of the password
|
||||
auto res = Database::Handler::getPasswordService().strengthValidator()->evaluateStrength(valueText(PasswordField), LmsApp->getUserIdentity(), "");
|
||||
auto res = Handler::getPasswordService().strengthValidator()->evaluateStrength(valueText(PasswordField), LmsApp->getUserIdentity(), "");
|
||||
|
||||
if (!res.isValid())
|
||||
error = res.message();
|
||||
@@ -140,115 +142,34 @@ class SettingsModel : public Wt::WFormModel
|
||||
return (validation(field).state() == Wt::ValidationState::Valid);
|
||||
}
|
||||
|
||||
boost::optional<int> getTranscodeBitrateRow(Wt::WString value)
|
||||
{
|
||||
for (int i = 0; i < _transcodeBitrateModel->rowCount(); ++i)
|
||||
{
|
||||
if (transcodeBitrateString(i) == value)
|
||||
return i;
|
||||
}
|
||||
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
boost::optional<int> getTranscodeBitrateRow(std::size_t value)
|
||||
{
|
||||
for (int i = 0; i < _transcodeBitrateModel->rowCount(); ++i)
|
||||
{
|
||||
if (transcodeBitrate(i) == value)
|
||||
return i;
|
||||
}
|
||||
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
std::size_t transcodeBitrate(int row)
|
||||
{
|
||||
return Wt::cpp17::any_cast<std::size_t>
|
||||
(_transcodeBitrateModel->data(_transcodeBitrateModel->index(row, 0), Wt::ItemDataRole::User));
|
||||
}
|
||||
|
||||
Wt::WString transcodeBitrateString(int row)
|
||||
{
|
||||
return Wt::cpp17::any_cast<Wt::WString>
|
||||
(_transcodeBitrateModel->data(_transcodeBitrateModel->index(row, 0), Wt::ItemDataRole::Display));
|
||||
}
|
||||
|
||||
boost::optional<int> getTranscodeFormatRow(Wt::WString value)
|
||||
{
|
||||
for (int i = 0; i < _transcodeFormatModel->rowCount(); ++i)
|
||||
{
|
||||
if (transcodeFormatString(i) == value)
|
||||
return i;
|
||||
}
|
||||
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
boost::optional<int> getTranscodeFormatRow(Database::AudioFormat format)
|
||||
{
|
||||
for (int i = 0; i < _transcodeFormatModel->rowCount(); ++i)
|
||||
{
|
||||
if (transcodeFormat(i) == format)
|
||||
return i;
|
||||
}
|
||||
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
Database::AudioFormat transcodeFormat(int row)
|
||||
{
|
||||
return Wt::cpp17::any_cast<Database::AudioFormat>
|
||||
(_transcodeFormatModel->data(_transcodeFormatModel->index(row, 0), Wt::ItemDataRole::User));
|
||||
}
|
||||
|
||||
Wt::WString transcodeFormatString(int row)
|
||||
{
|
||||
return Wt::cpp17::any_cast<Wt::WString>
|
||||
(_transcodeFormatModel->data(_transcodeFormatModel->index(row, 0), Wt::ItemDataRole::Display));
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
void initializeModels()
|
||||
{
|
||||
_transcodeBitrateModel = std::make_shared<Wt::WStringListModel>();
|
||||
|
||||
Database::Bitrate maxAudioBitrate;
|
||||
Bitrate maxAudioBitrate;
|
||||
{
|
||||
Wt::Dbo::Transaction transaction {LmsApp->getDboSession()};
|
||||
maxAudioBitrate = LmsApp->getUser()->getMaxAudioTranscodeBitrate();
|
||||
}
|
||||
|
||||
std::size_t id = 0;
|
||||
for (Database::Bitrate bitrate : Database::User::audioTranscodeAllowedBitrates)
|
||||
_transcodeBitrateModel = std::make_shared<ValueStringModel<Bitrate>>();
|
||||
for (Bitrate bitrate : User::audioTranscodeAllowedBitrates)
|
||||
{
|
||||
if (bitrate > maxAudioBitrate)
|
||||
break;
|
||||
|
||||
_transcodeBitrateModel->addString( Wt::WString::fromUTF8(std::to_string(bitrate / 1000)) );
|
||||
_transcodeBitrateModel->setData( id, 0, bitrate, Wt::ItemDataRole::User);
|
||||
id++;
|
||||
_transcodeBitrateModel->add(Wt::WString::fromUTF8(std::to_string(bitrate / 1000)), bitrate);
|
||||
}
|
||||
|
||||
_transcodeFormatModel = std::make_shared<Wt::WStringListModel>();
|
||||
|
||||
_transcodeFormatModel->addString(Wt::WString::tr("Lms.Settings.transcoding.mp3"));
|
||||
_transcodeFormatModel->setData(0, 0, Database::AudioFormat::MP3, Wt::ItemDataRole::User);
|
||||
|
||||
_transcodeFormatModel->addString(Wt::WString::tr("Lms.Settings.transcoding.ogg_opus"));
|
||||
_transcodeFormatModel->setData(1, 0, Database::AudioFormat::OGG_OPUS, Wt::ItemDataRole::User);
|
||||
|
||||
_transcodeFormatModel->addString(Wt::WString::tr("Lms.Settings.transcoding.ogg_vorbis"));
|
||||
_transcodeFormatModel->setData(2, 0, Database::AudioFormat::OGG_VORBIS, Wt::ItemDataRole::User);
|
||||
|
||||
_transcodeFormatModel->addString(Wt::WString::tr("Lms.Settings.transcoding.webm_vorbis"));
|
||||
_transcodeFormatModel->setData(3, 0, Database::AudioFormat::WEBM_VORBIS, Wt::ItemDataRole::User);
|
||||
_transcodeFormatModel = std::make_shared<ValueStringModel<AudioFormat>>();
|
||||
_transcodeFormatModel->add(Wt::WString::tr("Lms.Settings.transcoding.mp3"), AudioFormat::MP3);
|
||||
_transcodeFormatModel->add(Wt::WString::tr("Lms.Settings.transcoding.ogg_opus"), AudioFormat::OGG_OPUS);
|
||||
_transcodeFormatModel->add(Wt::WString::tr("Lms.Settings.transcoding.ogg_vorbis"), AudioFormat::OGG_VORBIS);
|
||||
_transcodeFormatModel->add(Wt::WString::tr("Lms.Settings.transcoding.webm_vorbis"), AudioFormat::WEBM_VORBIS);
|
||||
}
|
||||
|
||||
std::shared_ptr<Wt::WStringListModel> _transcodeBitrateModel;
|
||||
std::shared_ptr<Wt::WStringListModel> _transcodeFormatModel;
|
||||
std::shared_ptr<ValueStringModel<Bitrate>> _transcodeBitrateModel;
|
||||
std::shared_ptr<ValueStringModel<AudioFormat>> _transcodeFormatModel;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -24,21 +24,23 @@
|
||||
#include <Wt/WLineEdit.h>
|
||||
#include <Wt/WPushButton.h>
|
||||
#include <Wt/WString.h>
|
||||
#include <Wt/WStringListModel.h>
|
||||
#include <Wt/WTemplateFormView.h>
|
||||
|
||||
#include "database/Cluster.hpp"
|
||||
#include "database/SimilaritySettings.hpp"
|
||||
#include "main/Service.hpp"
|
||||
#include "utils/Logger.hpp"
|
||||
#include "utils/Utils.hpp"
|
||||
|
||||
#include "common/Validators.hpp"
|
||||
#include "common/ValueStringModel.hpp"
|
||||
#include "LmsApplication.hpp"
|
||||
|
||||
namespace UserInterface {
|
||||
|
||||
using namespace Database;
|
||||
|
||||
|
||||
class DatabaseSettingsModel : public Wt::WFormModel
|
||||
{
|
||||
public:
|
||||
@@ -46,6 +48,7 @@ class DatabaseSettingsModel : public Wt::WFormModel
|
||||
static const Field MediaDirectoryField;
|
||||
static const Field UpdatePeriodField;
|
||||
static const Field UpdateStartTimeField;
|
||||
static const Field SimilarityEngineTypeField;
|
||||
static const Field TagsField;
|
||||
|
||||
DatabaseSettingsModel()
|
||||
@@ -56,6 +59,7 @@ class DatabaseSettingsModel : public Wt::WFormModel
|
||||
addField(MediaDirectoryField);
|
||||
addField(UpdatePeriodField);
|
||||
addField(UpdateStartTimeField);
|
||||
addField(SimilarityEngineTypeField);
|
||||
addField(TagsField);
|
||||
|
||||
auto dirValidator = std::make_shared<DirectoryValidator>();
|
||||
@@ -64,6 +68,7 @@ class DatabaseSettingsModel : public Wt::WFormModel
|
||||
|
||||
setValidator(UpdatePeriodField, createMandatoryValidator());
|
||||
setValidator(UpdateStartTimeField, createMandatoryValidator());
|
||||
setValidator(SimilarityEngineTypeField, createMandatoryValidator());
|
||||
setValidator(TagsField, createTagsValidator());
|
||||
|
||||
// populate the model with initial data
|
||||
@@ -72,26 +77,30 @@ class DatabaseSettingsModel : public Wt::WFormModel
|
||||
|
||||
std::shared_ptr<Wt::WAbstractItemModel> updatePeriodModel() { return _updatePeriodModel; }
|
||||
std::shared_ptr<Wt::WAbstractItemModel> updateStartTimeModel() { return _updateStartTimeModel; }
|
||||
std::shared_ptr<Wt::WAbstractItemModel> similarityEngineTypeModel() { return _similarityEngineTypeModel; }
|
||||
|
||||
void loadData()
|
||||
{
|
||||
using namespace Database;
|
||||
Wt::Dbo::Transaction transaction {LmsApp->getDboSession()};
|
||||
|
||||
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
|
||||
|
||||
auto scanSettings = ScanSettings::get(LmsApp->getDboSession());
|
||||
auto scanSettings {ScanSettings::get(LmsApp->getDboSession())};
|
||||
auto similaritySettings {SimilaritySettings::get(LmsApp->getDboSession())};
|
||||
|
||||
setValue(MediaDirectoryField, scanSettings->getMediaDirectory().string());
|
||||
|
||||
auto periodRow = getUpdatePeriodModelRow( scanSettings->getUpdatePeriod() );
|
||||
auto periodRow {_updatePeriodModel->getRowFromValue(scanSettings->getUpdatePeriod())};
|
||||
if (periodRow)
|
||||
setValue(UpdatePeriodField, updatePeriodString(*periodRow));
|
||||
setValue(UpdatePeriodField, _updatePeriodModel->getString(*periodRow));
|
||||
|
||||
auto startTimeRow = getUpdateStartTimeModelRow( scanSettings->getUpdateStartTime() );
|
||||
auto startTimeRow {_updateStartTimeModel->getRowFromValue(scanSettings->getUpdateStartTime())};
|
||||
if (startTimeRow)
|
||||
setValue(UpdateStartTimeField, updateStartTimeString(*startTimeRow) );
|
||||
setValue(UpdateStartTimeField, _updateStartTimeModel->getString(*startTimeRow));
|
||||
|
||||
auto clusterTypes = scanSettings->getClusterTypes();
|
||||
auto similarityEngineTypeRow {_similarityEngineTypeModel->getRowFromValue(similaritySettings->getEngineType())};
|
||||
if (similarityEngineTypeRow)
|
||||
setValue(SimilarityEngineTypeField, _similarityEngineTypeModel->getString(*similarityEngineTypeRow));
|
||||
|
||||
auto clusterTypes {scanSettings->getClusterTypes()};
|
||||
if (!clusterTypes.empty())
|
||||
{
|
||||
std::vector<std::string> names;
|
||||
@@ -102,94 +111,29 @@ class DatabaseSettingsModel : public Wt::WFormModel
|
||||
|
||||
void saveData()
|
||||
{
|
||||
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
|
||||
Wt::Dbo::Transaction transaction {LmsApp->getDboSession()};
|
||||
|
||||
auto scanSettings = ScanSettings::get(LmsApp->getDboSession());
|
||||
auto scanSettings {ScanSettings::get(LmsApp->getDboSession())};
|
||||
auto similaritySettings {SimilaritySettings::get(LmsApp->getDboSession())};
|
||||
|
||||
scanSettings.modify()->setMediaDirectory(valueText(MediaDirectoryField).toUTF8());
|
||||
|
||||
auto updatePeriodRow = getUpdatePeriodModelRow( valueText(UpdatePeriodField));
|
||||
assert(updatePeriodRow);
|
||||
scanSettings.modify()->setUpdatePeriod(updatePeriod(*updatePeriodRow));
|
||||
auto updatePeriodRow {_updatePeriodModel->getRowFromString(valueText(UpdatePeriodField))};
|
||||
if (updatePeriodRow)
|
||||
scanSettings.modify()->setUpdatePeriod(_updatePeriodModel->getValue(*updatePeriodRow));
|
||||
|
||||
auto startTimeRow = getUpdateStartTimeModelRow( valueText(UpdateStartTimeField));
|
||||
assert(startTimeRow);
|
||||
scanSettings.modify()->setUpdateStartTime(updateStartTime(*startTimeRow));
|
||||
auto startTimeRow {_updateStartTimeModel->getRowFromString(valueText(UpdateStartTimeField))};
|
||||
if (startTimeRow)
|
||||
scanSettings.modify()->setUpdateStartTime(_updateStartTimeModel->getValue(*startTimeRow));
|
||||
|
||||
auto clusterTypes = splitString(valueText(TagsField).toUTF8(), " ");
|
||||
auto similarityEngineTypeRow {_similarityEngineTypeModel->getRowFromString(valueText(SimilarityEngineTypeField))};
|
||||
if (similarityEngineTypeRow)
|
||||
similaritySettings.modify()->setEngineType(_similarityEngineTypeModel->getValue(*similarityEngineTypeRow));
|
||||
|
||||
auto clusterTypes {splitString(valueText(TagsField).toUTF8(), " ")};
|
||||
scanSettings.modify()->setClusterTypes(std::set<std::string>(clusterTypes.begin(), clusterTypes.end()));
|
||||
}
|
||||
|
||||
boost::optional<int> getUpdatePeriodModelRow(Wt::WString value)
|
||||
{
|
||||
for (int i = 0; i < _updatePeriodModel->rowCount(); ++i)
|
||||
{
|
||||
if (updatePeriodString(i) == value)
|
||||
return i;
|
||||
}
|
||||
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
boost::optional<int> getUpdatePeriodModelRow(ScanSettings::UpdatePeriod period)
|
||||
{
|
||||
for (int i = 0; i < _updatePeriodModel->rowCount(); ++i)
|
||||
{
|
||||
if (updatePeriod(i) == period)
|
||||
return i;
|
||||
}
|
||||
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
ScanSettings::UpdatePeriod updatePeriod(int row)
|
||||
{
|
||||
return Wt::cpp17::any_cast<ScanSettings::UpdatePeriod>
|
||||
(_updatePeriodModel->data(_updatePeriodModel->index(row, 0), Wt::ItemDataRole::User));
|
||||
}
|
||||
|
||||
Wt::WString updatePeriodString(int row)
|
||||
{
|
||||
return Wt::cpp17::any_cast<Wt::WString>
|
||||
(_updatePeriodModel->data(_updatePeriodModel->index(row, 0), Wt::ItemDataRole::Display));
|
||||
}
|
||||
|
||||
|
||||
boost::optional<int> getUpdateStartTimeModelRow(Wt::WString value)
|
||||
{
|
||||
for (int i = 0; i < _updateStartTimeModel->rowCount(); ++i)
|
||||
{
|
||||
if (updateStartTimeString(i) == value)
|
||||
return i;
|
||||
}
|
||||
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
boost::optional<int> getUpdateStartTimeModelRow(Wt::WTime startTime)
|
||||
{
|
||||
for (int i = 0; i < _updateStartTimeModel->rowCount(); ++i)
|
||||
{
|
||||
if (updateStartTime(i) == startTime)
|
||||
return i;
|
||||
}
|
||||
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
Wt::WTime updateStartTime(int row)
|
||||
{
|
||||
return Wt::cpp17::any_cast<Wt::WTime>
|
||||
(_updateStartTimeModel->data(_updateStartTimeModel->index(row, 0), Wt::ItemDataRole::User));
|
||||
}
|
||||
|
||||
Wt::WString updateStartTimeString(int row)
|
||||
{
|
||||
return Wt::cpp17::any_cast<Wt::WString>
|
||||
(_updateStartTimeModel->data(_updateStartTimeModel->index(row, 0), Wt::ItemDataRole::Display));
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
static std::shared_ptr<Wt::WValidator> createTagsValidator()
|
||||
@@ -200,42 +144,34 @@ class DatabaseSettingsModel : public Wt::WFormModel
|
||||
|
||||
void initializeModels()
|
||||
{
|
||||
_updatePeriodModel = std::make_shared<ValueStringModel<ScanSettings::UpdatePeriod>>();
|
||||
_updatePeriodModel->add(Wt::WString::tr("Lms.Admin.Database.never"), ScanSettings::UpdatePeriod::Never);
|
||||
_updatePeriodModel->add(Wt::WString::tr("Lms.Admin.Database.daily"), ScanSettings::UpdatePeriod::Daily);
|
||||
_updatePeriodModel->add(Wt::WString::tr("Lms.Admin.Database.weekly"), ScanSettings::UpdatePeriod::Weekly);
|
||||
_updatePeriodModel->add(Wt::WString::tr("Lms.Admin.Database.monthly"), ScanSettings::UpdatePeriod::Monthly);
|
||||
|
||||
_updatePeriodModel = std::make_shared<Wt::WStringListModel>();
|
||||
|
||||
_updatePeriodModel->addString(Wt::WString::tr("Lms.Admin.Database.never"));
|
||||
_updatePeriodModel->setData(0, 0, ScanSettings::UpdatePeriod::Never, Wt::ItemDataRole::User);
|
||||
|
||||
_updatePeriodModel->addString(Wt::WString::tr("Lms.Admin.Database.daily"));
|
||||
_updatePeriodModel->setData(1, 0, ScanSettings::UpdatePeriod::Daily, Wt::ItemDataRole::User);
|
||||
|
||||
_updatePeriodModel->addString(Wt::WString::tr("Lms.Admin.Database.weekly"));
|
||||
_updatePeriodModel->setData(2, 0, ScanSettings::UpdatePeriod::Weekly, Wt::ItemDataRole::User);
|
||||
|
||||
_updatePeriodModel->addString(Wt::WString::tr("Lms.Admin.Database.monthly"));
|
||||
_updatePeriodModel->setData(3, 0, ScanSettings::UpdatePeriod::Monthly, Wt::ItemDataRole::User);
|
||||
|
||||
_updateStartTimeModel = std::make_shared<Wt::WStringListModel>();
|
||||
|
||||
_updateStartTimeModel = std::make_shared<ValueStringModel<Wt::WTime>>();
|
||||
for (std::size_t i = 0; i < 24; ++i)
|
||||
{
|
||||
Wt::WTime time(i, 0);
|
||||
|
||||
_updateStartTimeModel->addString( time.toString() );
|
||||
_updateStartTimeModel->setData(i, 0, time, Wt::ItemDataRole::User);
|
||||
Wt::WTime time {static_cast<int>(i), 0};
|
||||
_updateStartTimeModel->add(time.toString(), time);
|
||||
}
|
||||
|
||||
_similarityEngineTypeModel = std::make_shared<ValueStringModel<SimilaritySettings::EngineType>>();
|
||||
_similarityEngineTypeModel->add(Wt::WString::tr("Lms.Admin.Database.similarity-engine-type.clusters"), SimilaritySettings::EngineType::Clusters);
|
||||
_similarityEngineTypeModel->add(Wt::WString::tr("Lms.Admin.Database.similarity-engine-type.features"), SimilaritySettings::EngineType::Features);
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<Wt::WStringListModel> _updatePeriodModel;
|
||||
std::shared_ptr<Wt::WStringListModel> _updateStartTimeModel;
|
||||
std::shared_ptr<ValueStringModel<ScanSettings::UpdatePeriod>> _updatePeriodModel;
|
||||
std::shared_ptr<ValueStringModel<Wt::WTime>> _updateStartTimeModel;
|
||||
std::shared_ptr<ValueStringModel<SimilaritySettings::EngineType>> _similarityEngineTypeModel;
|
||||
|
||||
};
|
||||
|
||||
const Wt::WFormModel::Field DatabaseSettingsModel::MediaDirectoryField = "media-directory";
|
||||
const Wt::WFormModel::Field DatabaseSettingsModel::UpdatePeriodField = "update-period";
|
||||
const Wt::WFormModel::Field DatabaseSettingsModel::UpdateStartTimeField = "update-start-time";
|
||||
const Wt::WFormModel::Field DatabaseSettingsModel::SimilarityEngineTypeField = "similarity-engine-type";
|
||||
const Wt::WFormModel::Field DatabaseSettingsModel::TagsField = "tags";
|
||||
|
||||
DatabaseSettingsView::DatabaseSettingsView()
|
||||
@@ -256,22 +192,27 @@ DatabaseSettingsView::refreshView()
|
||||
|
||||
clear();
|
||||
|
||||
auto t = addNew<Wt::WTemplateFormView>(Wt::WString::tr("Lms.Admin.Database.template"));
|
||||
auto model = std::make_shared<DatabaseSettingsModel>();
|
||||
auto t {addNew<Wt::WTemplateFormView>(Wt::WString::tr("Lms.Admin.Database.template"))};
|
||||
auto model {std::make_shared<DatabaseSettingsModel>()};
|
||||
|
||||
// Media Directory
|
||||
t->setFormWidget(DatabaseSettingsModel::MediaDirectoryField, std::make_unique<Wt::WLineEdit>());
|
||||
|
||||
// Update Period
|
||||
auto updatePeriod = std::make_unique<Wt::WComboBox>();
|
||||
auto updatePeriod {std::make_unique<Wt::WComboBox>()};
|
||||
updatePeriod->setModel(model->updatePeriodModel());
|
||||
t->setFormWidget(DatabaseSettingsModel::UpdatePeriodField, std::move(updatePeriod));
|
||||
|
||||
// Update Start Time
|
||||
auto updateStartTime = std::make_unique<Wt::WComboBox>();
|
||||
auto updateStartTime {std::make_unique<Wt::WComboBox>()};
|
||||
updateStartTime->setModel(model->updateStartTimeModel());
|
||||
t->setFormWidget(DatabaseSettingsModel::UpdateStartTimeField, std::move(updateStartTime));
|
||||
|
||||
// Similarity engine type
|
||||
auto similarityEngineType {std::make_unique<Wt::WComboBox>()};
|
||||
similarityEngineType->setModel(model->similarityEngineTypeModel());
|
||||
t->setFormWidget(DatabaseSettingsModel::SimilarityEngineTypeField, std::move(similarityEngineType));
|
||||
|
||||
// Tags
|
||||
t->setFormWidget(DatabaseSettingsModel::TagsField, std::make_unique<Wt::WLineEdit>());
|
||||
|
||||
|
||||
+35
-70
@@ -27,21 +27,24 @@
|
||||
#include <Wt/WTemplateFormView.h>
|
||||
|
||||
#include <Wt/WFormModel.h>
|
||||
#include <Wt/WStringListModel.h>
|
||||
|
||||
#include "common/Validators.hpp"
|
||||
#include "database/User.hpp"
|
||||
#include "utils/Config.hpp"
|
||||
#include "utils/Exception.hpp"
|
||||
#include "utils/Logger.hpp"
|
||||
#include "utils/Utils.hpp"
|
||||
|
||||
#include "common/Validators.hpp"
|
||||
#include "common/ValueStringModel.hpp"
|
||||
#include "LmsApplication.hpp"
|
||||
|
||||
namespace UserInterface {
|
||||
|
||||
using namespace Database;
|
||||
|
||||
class UserModel : public Wt::WFormModel
|
||||
{
|
||||
|
||||
public:
|
||||
static const Field LoginField;
|
||||
static const Field PasswordField;
|
||||
@@ -71,23 +74,7 @@ class UserModel : public Wt::WFormModel
|
||||
loadData();
|
||||
}
|
||||
|
||||
void loadData()
|
||||
{
|
||||
if (!_userId)
|
||||
return;
|
||||
|
||||
Wt::Dbo::Transaction transaction {LmsApp->getDboSession()};
|
||||
|
||||
auto authUser = LmsApp->getDb().getUserDatabase().findWithId( std::to_string(*_userId) );
|
||||
auto user = LmsApp->getDb().getUser(authUser);
|
||||
|
||||
if (user == LmsApp->getUser())
|
||||
throw LmsException("Cannot edit ourselves");
|
||||
|
||||
auto bitrate {getTranscodeBitrateLimitRow(user->getMaxAudioTranscodeBitrate())};
|
||||
if (bitrate)
|
||||
setValue(AudioTranscodeBitrateLimitField, transcodeBitrateLimitString(*bitrate));
|
||||
}
|
||||
std::shared_ptr<Wt::WAbstractItemModel> bitrateModel() { return _bitrateModel; }
|
||||
|
||||
void saveData()
|
||||
{
|
||||
@@ -103,9 +90,9 @@ class UserModel : public Wt::WFormModel
|
||||
if (!valueText(PasswordField).empty())
|
||||
Database::Handler::getPasswordService().updatePassword(authUser, valueText(PasswordField));
|
||||
|
||||
auto transcodeBitrateLimitRow = getTranscodeBitrateLimitRow(Wt::asString(value(AudioTranscodeBitrateLimitField)));
|
||||
user.modify()->setMaxAudioTranscodeBitrate(transcodeBitrateLimit(*transcodeBitrateLimitRow));
|
||||
LMS_LOG(UI, DEBUG) << "Max audio bitrate set to " << transcodeBitrateLimit(*transcodeBitrateLimitRow);
|
||||
auto transcodeBitrateLimitRow {_bitrateModel->getRowFromString(valueText(AudioTranscodeBitrateLimitField))};
|
||||
if (transcodeBitrateLimitRow)
|
||||
user.modify()->setMaxAudioTranscodeBitrate(_bitrateModel->getValue(*transcodeBitrateLimitRow));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -117,14 +104,35 @@ class UserModel : public Wt::WFormModel
|
||||
authUser.setIdentity(Wt::Auth::Identity::LoginName, valueText(LoginField));
|
||||
Database::Handler::getPasswordService().updatePassword(authUser, valueText(PasswordField));
|
||||
|
||||
auto transcodeBitrateLimitRow = getTranscodeBitrateLimitRow(Wt::asString(value(AudioTranscodeBitrateLimitField)));
|
||||
user.modify()->setMaxAudioTranscodeBitrate(transcodeBitrateLimit(*transcodeBitrateLimitRow));
|
||||
auto transcodeBitrateLimitRow {_bitrateModel->getRowFromString(valueText(AudioTranscodeBitrateLimitField))};
|
||||
if (transcodeBitrateLimitRow )
|
||||
user.modify()->setMaxAudioTranscodeBitrate(_bitrateModel->getValue(*transcodeBitrateLimitRow));
|
||||
|
||||
if (Wt::asNumber(value(DemoField)))
|
||||
user.modify()->setType(Database::User::Type::DEMO);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void loadData()
|
||||
{
|
||||
if (!_userId)
|
||||
return;
|
||||
|
||||
Wt::Dbo::Transaction transaction {LmsApp->getDboSession()};
|
||||
|
||||
auto authUser {LmsApp->getDb().getUserDatabase().findWithId( std::to_string(*_userId) )};
|
||||
auto user {LmsApp->getDb().getUser(authUser)};
|
||||
|
||||
if (user == LmsApp->getUser())
|
||||
throw LmsException("Cannot edit ourselves");
|
||||
|
||||
auto transcodeBitrateLimitRow {_bitrateModel->getRowFromValue(user->getMaxAudioTranscodeBitrate())};
|
||||
if (transcodeBitrateLimitRow)
|
||||
setValue(AudioTranscodeBitrateLimitField, _bitrateModel->getString(*transcodeBitrateLimitRow));
|
||||
}
|
||||
|
||||
Wt::WString getLogin() const
|
||||
{
|
||||
if (_userId)
|
||||
@@ -182,59 +190,16 @@ class UserModel : public Wt::WFormModel
|
||||
return false;
|
||||
}
|
||||
|
||||
boost::optional<int> getTranscodeBitrateLimitRow(Wt::WString value)
|
||||
{
|
||||
for (int i = 0; i < _bitrateModel->rowCount(); ++i)
|
||||
{
|
||||
if (transcodeBitrateLimitString(i) == value)
|
||||
return i;
|
||||
}
|
||||
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
boost::optional<int> getTranscodeBitrateLimitRow(std::size_t value)
|
||||
{
|
||||
for (int i = 0; i < _bitrateModel->rowCount(); ++i)
|
||||
{
|
||||
if (transcodeBitrateLimit(i) == value)
|
||||
return i;
|
||||
}
|
||||
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
std::size_t transcodeBitrateLimit(int row)
|
||||
{
|
||||
return Wt::cpp17::any_cast<std::size_t>
|
||||
(_bitrateModel->data(_bitrateModel->index(row, 0), Wt::ItemDataRole::User));
|
||||
}
|
||||
|
||||
Wt::WString transcodeBitrateLimitString(int row)
|
||||
{
|
||||
return Wt::cpp17::any_cast<Wt::WString>
|
||||
(_bitrateModel->data(_bitrateModel->index(row, 0), Wt::ItemDataRole::Display));
|
||||
}
|
||||
|
||||
std::shared_ptr<Wt::WAbstractItemModel> bitrateModel() { return _bitrateModel; }
|
||||
|
||||
private:
|
||||
|
||||
void initializeModels()
|
||||
{
|
||||
_bitrateModel = std::make_shared<Wt::WStringListModel>();
|
||||
_bitrateModel = std::make_shared<ValueStringModel<Bitrate>>();
|
||||
|
||||
std::size_t id = 0;
|
||||
for (auto bitrate : Database::User::audioTranscodeAllowedBitrates)
|
||||
{
|
||||
_bitrateModel->addString( Wt::WString::fromUTF8(std::to_string(bitrate / 1000)) );
|
||||
_bitrateModel->setData( id++, 0, bitrate, Wt::ItemDataRole::User);
|
||||
}
|
||||
|
||||
|
||||
_bitrateModel->add( Wt::WString::fromUTF8(std::to_string(bitrate / 1000)), bitrate );
|
||||
}
|
||||
|
||||
std::shared_ptr<Wt::WStringListModel> _bitrateModel;
|
||||
std::shared_ptr<ValueStringModel<Bitrate>> _bitrateModel;
|
||||
boost::optional<Database::IdType> _userId;
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 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 <boost/optional.hpp>
|
||||
#include <Wt/WStringListModel.h>
|
||||
|
||||
namespace UserInterface {
|
||||
|
||||
// Helper class
|
||||
template <typename T>
|
||||
class ValueStringModel : public Wt::WStringListModel
|
||||
{
|
||||
public:
|
||||
|
||||
T getValue(std::size_t row)
|
||||
{
|
||||
return Wt::cpp17::any_cast<T>(data(index(static_cast<int>(row), 0), Wt::ItemDataRole::User));
|
||||
}
|
||||
|
||||
Wt::WString getString(std::size_t row)
|
||||
{
|
||||
return Wt::cpp17::any_cast<Wt::WString>(data(index(static_cast<int>(row), 0), Wt::ItemDataRole::Display));
|
||||
}
|
||||
|
||||
boost::optional<std::size_t>
|
||||
getRowFromString(const Wt::WString& value)
|
||||
{
|
||||
for (std::size_t i{}; i < static_cast<std::size_t>(rowCount()); ++i)
|
||||
{
|
||||
if (getString(i) == value)
|
||||
return i;
|
||||
}
|
||||
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
boost::optional<std::size_t>
|
||||
getRowFromValue(const T& value)
|
||||
{
|
||||
for (std::size_t i{}; i < static_cast<std::size_t>(rowCount()); ++i)
|
||||
{
|
||||
if (getValue(i) == value)
|
||||
return i;
|
||||
}
|
||||
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
void
|
||||
add(const Wt::WString& str, const T& value)
|
||||
{
|
||||
insertRows(rowCount(), 1);
|
||||
setData(rowCount() - 1, 0, value, Wt::ItemDataRole::User);
|
||||
setData(rowCount() - 1, 0, str, Wt::ItemDataRole::Display);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace UserInterface
|
||||
Reference in New Issue
Block a user