Files
lms/src/ui/admin/DatabaseSettingsView.cpp
T

314 lines
9.4 KiB
C++

/*
* Copyright (C) 2018 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#include "DatabaseSettingsView.hpp"
#include <Wt/WString.h>
#include <Wt/WPushButton.h>
#include <Wt/WComboBox.h>
#include <Wt/WLineEdit.h>
#include <Wt/WTemplateFormView.h>
#include <Wt/WFormModel.h>
#include <Wt/WStringListModel.h>
#include "common/Validators.hpp"
#include "database/MediaDirectory.hpp"
#include "scanner/MediaScanner.hpp"
#include "utils/Logger.hpp"
#include "utils/Utils.hpp"
#include "LmsApplication.hpp"
namespace UserInterface {
using namespace Database;
class DatabaseSettingsModel : public Wt::WFormModel
{
public:
// Associate each field with a unique string literal.
static const Field MediaDirectoryField;
static const Field UpdatePeriodField;
static const Field UpdateStartTimeField;
static const Field TagsField;
DatabaseSettingsModel()
: Wt::WFormModel()
{
initializeModels();
addField(MediaDirectoryField);
addField(UpdatePeriodField);
addField(UpdateStartTimeField);
addField(TagsField);
auto dirValidator = std::make_shared<DirectoryValidator>();
dirValidator->setMandatory(true);
setValidator(MediaDirectoryField, dirValidator);
setValidator(UpdatePeriodField, createMandatoryValidator());
setValidator(UpdateStartTimeField, createMandatoryValidator());
setValidator(TagsField, createTagsValidator());
// populate the model with initial data
loadData();
}
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(LmsApp->getDboSession());
std::vector<MediaDirectory::pointer> mediaDirectories = MediaDirectory::getAll(LmsApp->getDboSession());
if (!mediaDirectories.empty())
setValue(MediaDirectoryField, mediaDirectories.front()->getPath().string());
auto periodRow = getUpdatePeriodModelRow( Scanner::getUpdatePeriod(LmsApp->getDboSession()) );
if (periodRow)
setValue(UpdatePeriodField, updatePeriodString(*periodRow));
auto startTimeRow = getUpdateStartTimeModelRow( Scanner::getUpdateStartTime(LmsApp->getDboSession()) );
if (startTimeRow)
setValue(UpdateStartTimeField, updateStartTimeString(*startTimeRow) );
auto clusterTypes = Scanner::getClusterTypes(LmsApp->getDboSession());
if (!clusterTypes.empty())
setValue(TagsField, joinStrings(std::vector<std::string>(clusterTypes.begin(), clusterTypes.end()), " "));
}
void saveData()
{
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
MediaDirectory::eraseAll(LmsApp->getDboSession());
MediaDirectory::create(LmsApp->getDboSession(), valueText(MediaDirectoryField).toUTF8());
auto updatePeriodRow = getUpdatePeriodModelRow( valueText(UpdatePeriodField));
assert(updatePeriodRow);
Scanner::setUpdatePeriod(LmsApp->getDboSession(), updatePeriod(*updatePeriodRow));
auto startTimeRow = getUpdateStartTimeModelRow( valueText(UpdateStartTimeField));
assert(startTimeRow);
Scanner::setUpdateStartTime(LmsApp->getDboSession(), updateStartTime(*startTimeRow));
auto clusterTypes = splitString(valueText(TagsField).toUTF8(), " ");
Scanner::setClusterTypes(LmsApp->getDboSession(), 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(Scanner::UpdatePeriod period)
{
for (int i = 0; i < _updatePeriodModel->rowCount(); ++i)
{
if (updatePeriod(i) == period)
return i;
}
return boost::none;
}
Scanner::UpdatePeriod updatePeriod(int row)
{
return Wt::cpp17::any_cast<Scanner::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()
{
auto v = std::make_shared<Wt::WValidator>();
return v;
}
void initializeModels()
{
_updatePeriodModel = std::make_shared<Wt::WStringListModel>();
_updatePeriodModel->addString(Wt::WString::tr("Lms.Admin.Database.never"));
_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::ItemDataRole::User);
_updatePeriodModel->addString(Wt::WString::tr("Lms.Admin.Database.weekly"));
_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::ItemDataRole::User);
_updateStartTimeModel = std::make_shared<Wt::WStringListModel>();
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);
}
}
std::shared_ptr<Wt::WStringListModel> _updatePeriodModel;
std::shared_ptr<Wt::WStringListModel> _updateStartTimeModel;
};
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::TagsField = "tags";
DatabaseSettingsView::DatabaseSettingsView()
{
wApp->internalPathChanged().connect(std::bind([=]
{
refreshView();
}));
refreshView();
}
void
DatabaseSettingsView::refreshView()
{
if (!wApp->internalPathMatches("/admin/database"))
return;
clear();
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>();
updatePeriod->setModel(model->updatePeriodModel());
t->setFormWidget(DatabaseSettingsModel::UpdatePeriodField, std::move(updatePeriod));
// Update Start Time
auto updateStartTime = std::make_unique<Wt::WComboBox>();
updateStartTime->setModel(model->updateStartTimeModel());
t->setFormWidget(DatabaseSettingsModel::UpdateStartTimeField, std::move(updateStartTime));
// Tags
t->setFormWidget(DatabaseSettingsModel::TagsField, std::make_unique<Wt::WLineEdit>());
// Buttons
Wt::WPushButton *saveBtn = t->bindWidget("apply-btn", std::make_unique<Wt::WPushButton>(Wt::WString::tr("Lms.apply")));
Wt::WPushButton *discardBtn = t->bindWidget("discard-btn", std::make_unique<Wt::WPushButton>(Wt::WString::tr("Lms.discard")));
Wt::WPushButton *immScanBtn = t->bindWidget("immediate-scan-btn", std::make_unique<Wt::WPushButton>(Wt::WString::tr("Lms.Admin.Database.immediate-scan")));
saveBtn->clicked().connect(std::bind([=] ()
{
t->updateModel(model.get());
if (model->validate())
{
model->saveData();
LmsApp->getMediaScanner().reschedule();
LmsApp->notifyMsg(Wt::WString::tr("Lms.Admin.Database.settings-saved"));
}
// Udate the view: Delete any validation message in the view, etc.
t->updateView(model.get());
}));
discardBtn->clicked().connect(std::bind([=] ()
{
model->loadData();
model->validate();
t->updateView(model.get());
}));
immScanBtn->clicked().connect(std::bind([=] ()
{
LmsApp->getMediaScanner().scheduleImmediateScan();
LmsApp->notifyMsg(Wt::WString::tr("Lms.Admin.Database.scan-launched"));
}));
t->updateView(model.get());
}
} // namespace UserInterface