WIP. Handling multiple media directories
This commit is contained in:
@@ -69,6 +69,8 @@ lms_SOURCES = \
|
|||||||
$(top_srcdir)/ui/settings/SettingsAccountFormView.cpp \
|
$(top_srcdir)/ui/settings/SettingsAccountFormView.cpp \
|
||||||
$(top_srcdir)/ui/settings/SettingsAudioFormView.cpp \
|
$(top_srcdir)/ui/settings/SettingsAudioFormView.cpp \
|
||||||
$(top_srcdir)/ui/settings/SettingsDatabaseFormView.cpp \
|
$(top_srcdir)/ui/settings/SettingsDatabaseFormView.cpp \
|
||||||
|
$(top_srcdir)/ui/settings/SettingsMediaDirectories.cpp \
|
||||||
|
$(top_srcdir)/ui/settings/SettingsMediaDirectoryFormView.cpp \
|
||||||
$(top_srcdir)/ui/settings/SettingsUserFormView.cpp \
|
$(top_srcdir)/ui/settings/SettingsUserFormView.cpp \
|
||||||
$(top_srcdir)/ui/settings/SettingsUsers.cpp
|
$(top_srcdir)/ui/settings/SettingsUsers.cpp
|
||||||
|
|
||||||
|
|||||||
@@ -89,13 +89,18 @@ Updater::process(boost::system::error_code err)
|
|||||||
removeMissingAudioFiles(_result.audioStats);
|
removeMissingAudioFiles(_result.audioStats);
|
||||||
// TODO video files
|
// TODO video files
|
||||||
|
|
||||||
|
// TODO remove files that do not belong to a root directory
|
||||||
|
|
||||||
std::vector<boost::filesystem::path> pathes;
|
std::vector<boost::filesystem::path> pathes;
|
||||||
|
|
||||||
{
|
{
|
||||||
Wt::Dbo::Transaction transaction(_db.getSession());
|
Wt::Dbo::Transaction transaction(_db.getSession());
|
||||||
std::vector<MediaDirectory::pointer> mediaDirectories = MediaDirectory::getAll(_db.getSession());
|
std::vector<MediaDirectory::pointer> mediaDirectories = MediaDirectory::getAll(_db.getSession());
|
||||||
BOOST_FOREACH(MediaDirectory::pointer directory, mediaDirectories)
|
BOOST_FOREACH(MediaDirectory::pointer directory, mediaDirectories)
|
||||||
pathes.push_back(directory->getPath());
|
{
|
||||||
|
if (directory->getType() == Database::MediaDirectory::Audio)
|
||||||
|
pathes.push_back(directory->getPath());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_FOREACH( boost::filesystem::path p, pathes)
|
BOOST_FOREACH( boost::filesystem::path p, pathes)
|
||||||
@@ -311,6 +316,7 @@ Updater::refreshAudioDirectory( const boost::filesystem::path& p, Stats& stats)
|
|||||||
|
|
||||||
typedef std::vector<boost::filesystem::path> Paths; // store paths,
|
typedef std::vector<boost::filesystem::path> Paths; // store paths,
|
||||||
|
|
||||||
|
// TODO use a recursive directory iterator instead
|
||||||
Paths files;
|
Paths files;
|
||||||
std::copy(boost::filesystem::directory_iterator(p), boost::filesystem::directory_iterator(), std::back_inserter(files));
|
std::copy(boost::filesystem::directory_iterator(p), boost::filesystem::directory_iterator(), std::back_inserter(files));
|
||||||
|
|
||||||
|
|||||||
@@ -44,5 +44,10 @@ MediaDirectory::getAll(Wt::Dbo::Session& session)
|
|||||||
|
|
||||||
return std::vector<MediaDirectory::pointer>(res.begin(), res.end());
|
return std::vector<MediaDirectory::pointer>(res.begin(), res.end());
|
||||||
}
|
}
|
||||||
|
MediaDirectory::pointer
|
||||||
|
MediaDirectory::getByPath(Wt::Dbo::Session& session, boost::filesystem::path p)
|
||||||
|
{
|
||||||
|
return session.find<MediaDirectory>().where("path = ?").bind( p.string() );
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Database
|
} // namespace Database
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ class MediaDirectory
|
|||||||
// Accessors
|
// Accessors
|
||||||
static pointer create(Wt::Dbo::Session& session, boost::filesystem::path p, Type type);
|
static pointer create(Wt::Dbo::Session& session, boost::filesystem::path p, Type type);
|
||||||
static std::vector<MediaDirectory::pointer> getAll(Wt::Dbo::Session& session);
|
static std::vector<MediaDirectory::pointer> getAll(Wt::Dbo::Session& session);
|
||||||
|
static pointer getByPath(Wt::Dbo::Session& session, boost::filesystem::path p);
|
||||||
|
|
||||||
static void eraseAll(Wt::Dbo::Session& session);
|
static void eraseAll(Wt::Dbo::Session& session);
|
||||||
|
|
||||||
|
|||||||
@@ -184,12 +184,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</message>
|
</message>
|
||||||
|
|
||||||
<message id="databaseForm-template">
|
<message id="mediaDirectoryForm-template">
|
||||||
<legend>${title}</legend>
|
<legend>${title}</legend>
|
||||||
<div class="form-horizontal">
|
<div class="form-horizontal">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="control-label col-sm-2" for="${id:path}">
|
<label class="control-label col-sm-2" for="${id:path}">
|
||||||
Media root path
|
Path
|
||||||
</label>
|
</label>
|
||||||
<div class="col-sm-5">
|
<div class="col-sm-5">
|
||||||
${path}
|
${path}
|
||||||
@@ -198,7 +198,29 @@
|
|||||||
${path-info}
|
${path-info}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="control-label col-sm-2" for="${id:type}">
|
||||||
|
Type
|
||||||
|
</label>
|
||||||
|
<div class="col-sm-5">
|
||||||
|
${type}
|
||||||
|
</div>
|
||||||
|
<div class="help-block col-sm-5">
|
||||||
|
${type-info}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-sm-offset-2 col-sm-10">
|
||||||
|
${save-button} ${cancel-button}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
${apply-info}
|
||||||
|
</div>
|
||||||
|
</message>
|
||||||
|
|
||||||
|
<message id="databaseForm-template">
|
||||||
|
<legend>${title}</legend>
|
||||||
|
<div class="form-horizontal">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="control-label col-sm-2" for="${id:update-period}">
|
<label class="control-label col-sm-2" for="${id:update-period}">
|
||||||
Update period
|
Update period
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ AudioWidget::playTrack(boost::filesystem::path p)
|
|||||||
|
|
||||||
Transcode::InputMediaFile inputFile(p);
|
Transcode::InputMediaFile inputFile(p);
|
||||||
|
|
||||||
|
// TODO get the input stream bitrate and min the result with the desired bitrate
|
||||||
Transcode::Parameters parameters(inputFile, Transcode::Format::get(Transcode::Format::OGA), bitrate);
|
Transcode::Parameters parameters(inputFile, Transcode::Format::get(Transcode::Format::OGA), bitrate);
|
||||||
|
|
||||||
_mediaPlayer->load( parameters );
|
_mediaPlayer->load( parameters );
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "SettingsUserFormView.hpp"
|
#include "SettingsUserFormView.hpp"
|
||||||
#include "SettingsAccountFormView.hpp"
|
#include "SettingsAccountFormView.hpp"
|
||||||
#include "SettingsDatabaseFormView.hpp"
|
#include "SettingsDatabaseFormView.hpp"
|
||||||
|
#include "SettingsMediaDirectories.hpp"
|
||||||
#include "SettingsUsers.hpp"
|
#include "SettingsUsers.hpp"
|
||||||
|
|
||||||
#include "Settings.hpp"
|
#include "Settings.hpp"
|
||||||
@@ -34,7 +35,8 @@ _sessionData(sessionData)
|
|||||||
menu->addItem("Audio", new AudioFormView(sessionData, Database::User::getId(user)));
|
menu->addItem("Audio", new AudioFormView(sessionData, Database::User::getId(user)));
|
||||||
if (user->isAdmin())
|
if (user->isAdmin())
|
||||||
{
|
{
|
||||||
menu->addItem("Database", new DatabaseFormView(sessionData));
|
menu->addItem("Media Folders", new MediaDirectories(sessionData));
|
||||||
|
menu->addItem("Database Update", new DatabaseFormView(sessionData));
|
||||||
menu->addItem("Users", new Users(sessionData));
|
menu->addItem("Users", new Users(sessionData));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ class DatabaseFormModel : public Wt::WFormModel
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// Associate each field with a unique string literal.
|
// Associate each field with a unique string literal.
|
||||||
static const Field PathField;
|
|
||||||
static const Field UpdatePeriodField;
|
static const Field UpdatePeriodField;
|
||||||
static const Field UpdateStartTimeField;
|
static const Field UpdateStartTimeField;
|
||||||
static const Field UpdateRequestImmediateField;
|
static const Field UpdateRequestImmediateField;
|
||||||
@@ -35,12 +34,10 @@ class DatabaseFormModel : public Wt::WFormModel
|
|||||||
{
|
{
|
||||||
initializeModels();
|
initializeModels();
|
||||||
|
|
||||||
addField(PathField);
|
|
||||||
addField(UpdatePeriodField);
|
addField(UpdatePeriodField);
|
||||||
addField(UpdateStartTimeField);
|
addField(UpdateStartTimeField);
|
||||||
addField(UpdateRequestImmediateField);
|
addField(UpdateRequestImmediateField);
|
||||||
|
|
||||||
setValidator(PathField, createPathValidator());
|
|
||||||
setValidator(UpdatePeriodField, createUpdatePeriodValidator());
|
setValidator(UpdatePeriodField, createUpdatePeriodValidator());
|
||||||
setValidator(UpdateStartTimeField, createStartTimeValidator());
|
setValidator(UpdateStartTimeField, createStartTimeValidator());
|
||||||
setValidator(UpdateRequestImmediateField, createRequestImmediateFieldValidator());
|
setValidator(UpdateRequestImmediateField, createRequestImmediateFieldValidator());
|
||||||
@@ -56,16 +53,6 @@ class DatabaseFormModel : public Wt::WFormModel
|
|||||||
{
|
{
|
||||||
Wt::Dbo::Transaction transaction(_sessionData.getDatabaseHandler().getSession());
|
Wt::Dbo::Transaction transaction(_sessionData.getDatabaseHandler().getSession());
|
||||||
|
|
||||||
// Get directories
|
|
||||||
std::vector<::Database::MediaDirectory::pointer> directories = ::Database::MediaDirectory::getAll(_sessionData.getDatabaseHandler().getSession());
|
|
||||||
|
|
||||||
BOOST_FOREACH(::Database::MediaDirectory::pointer directory, directories)
|
|
||||||
{
|
|
||||||
setValue(PathField, directory->getPath().string() );
|
|
||||||
// TODO, handle multiple directories
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get refresh settings
|
// Get refresh settings
|
||||||
::Database::MediaDirectorySettings::pointer settings = ::Database::MediaDirectorySettings::get(_sessionData.getDatabaseHandler().getSession());
|
::Database::MediaDirectorySettings::pointer settings = ::Database::MediaDirectorySettings::get(_sessionData.getDatabaseHandler().getSession());
|
||||||
|
|
||||||
@@ -77,7 +64,7 @@ class DatabaseFormModel : public Wt::WFormModel
|
|||||||
if (startTimeRow != -1)
|
if (startTimeRow != -1)
|
||||||
setValue(UpdateStartTimeField, updateStartTime( startTimeRow ) );
|
setValue(UpdateStartTimeField, updateStartTime( startTimeRow ) );
|
||||||
|
|
||||||
setValue(UpdateRequestImmediateField, settings->getManualScanRequested() );
|
setValue(UpdateRequestImmediateField, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void saveData()
|
void saveData()
|
||||||
@@ -85,9 +72,6 @@ class DatabaseFormModel : public Wt::WFormModel
|
|||||||
Wt::Dbo::Session& session( _sessionData.getDatabaseHandler().getSession());
|
Wt::Dbo::Session& session( _sessionData.getDatabaseHandler().getSession());
|
||||||
Wt::Dbo::Transaction transaction(session);
|
Wt::Dbo::Transaction transaction(session);
|
||||||
|
|
||||||
::Database::MediaDirectory::eraseAll( session );
|
|
||||||
::Database::MediaDirectory::create(session, valueText(PathField).toUTF8(), ::Database::MediaDirectory::Audio);
|
|
||||||
|
|
||||||
::Database::MediaDirectorySettings::pointer settings = ::Database::MediaDirectorySettings::get(_sessionData.getDatabaseHandler().getSession() );
|
::Database::MediaDirectorySettings::pointer settings = ::Database::MediaDirectorySettings::get(_sessionData.getDatabaseHandler().getSession() );
|
||||||
|
|
||||||
int periodRow = getUpdatePeriodModelRow( boost::any_cast<Wt::WString>(value(UpdatePeriodField)));
|
int periodRow = getUpdatePeriodModelRow( boost::any_cast<Wt::WString>(value(UpdatePeriodField)));
|
||||||
@@ -206,12 +190,6 @@ class DatabaseFormModel : public Wt::WFormModel
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Wt::WValidator *createPathValidator() {
|
|
||||||
DirectoryValidator* v = new DirectoryValidator();
|
|
||||||
v->setMandatory(true);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
Wt::WValidator *createUpdatePeriodValidator() {
|
Wt::WValidator *createUpdatePeriodValidator() {
|
||||||
Wt::WValidator* v = new Wt::WValidator();
|
Wt::WValidator* v = new Wt::WValidator();
|
||||||
v->setMandatory(true);
|
v->setMandatory(true);
|
||||||
@@ -235,7 +213,6 @@ class DatabaseFormModel : public Wt::WFormModel
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const Wt::WFormModel::Field DatabaseFormModel::PathField = "path";
|
|
||||||
const Wt::WFormModel::Field DatabaseFormModel::UpdatePeriodField = "update-period";
|
const Wt::WFormModel::Field DatabaseFormModel::UpdatePeriodField = "update-period";
|
||||||
const Wt::WFormModel::Field DatabaseFormModel::UpdateStartTimeField = "update-start-time";
|
const Wt::WFormModel::Field DatabaseFormModel::UpdateStartTimeField = "update-start-time";
|
||||||
const Wt::WFormModel::Field DatabaseFormModel::UpdateRequestImmediateField = "update-request-immediate-scan";
|
const Wt::WFormModel::Field DatabaseFormModel::UpdateRequestImmediateField = "update-request-immediate-scan";
|
||||||
@@ -255,11 +232,6 @@ DatabaseFormView::DatabaseFormView(SessionData& sessionData, Wt::WContainerWidge
|
|||||||
applyInfo->hide();
|
applyInfo->hide();
|
||||||
bindWidget("apply-info", applyInfo);
|
bindWidget("apply-info", applyInfo);
|
||||||
|
|
||||||
// Path
|
|
||||||
Wt::WLineEdit *pathEdit = new Wt::WLineEdit();
|
|
||||||
setFormWidget(DatabaseFormModel::PathField, pathEdit);
|
|
||||||
pathEdit->changed().connect(applyInfo, &Wt::WWidget::hide);
|
|
||||||
|
|
||||||
// Update Period
|
// Update Period
|
||||||
Wt::WComboBox *updatePeriodCB = new Wt::WComboBox();
|
Wt::WComboBox *updatePeriodCB = new Wt::WComboBox();
|
||||||
setFormWidget(DatabaseFormModel::UpdatePeriodField, updatePeriodCB);
|
setFormWidget(DatabaseFormModel::UpdatePeriodField, updatePeriodCB);
|
||||||
@@ -278,7 +250,7 @@ DatabaseFormView::DatabaseFormView(SessionData& sessionData, Wt::WContainerWidge
|
|||||||
immScan->changed().connect(applyInfo, &Wt::WWidget::hide);
|
immScan->changed().connect(applyInfo, &Wt::WWidget::hide);
|
||||||
|
|
||||||
// Title & Buttons
|
// Title & Buttons
|
||||||
bindString("title", "Media directories settings");
|
bindString("title", "Media folder settings");
|
||||||
|
|
||||||
Wt::WPushButton *saveButton = new Wt::WPushButton("Apply");
|
Wt::WPushButton *saveButton = new Wt::WPushButton("Apply");
|
||||||
bindWidget("apply-button", saveButton);
|
bindWidget("apply-button", saveButton);
|
||||||
@@ -328,6 +300,9 @@ DatabaseFormView::processSave()
|
|||||||
service->restart();
|
service->restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// uncheck the special button
|
||||||
|
model->setValue(DatabaseFormModel::UpdateRequestImmediateField, false);
|
||||||
|
|
||||||
applyInfo->setText( Wt::WString::fromUTF8("New parameters successfully applied!"));
|
applyInfo->setText( Wt::WString::fromUTF8("New parameters successfully applied!"));
|
||||||
applyInfo->setStyleClass("alert alert-success");
|
applyInfo->setStyleClass("alert alert-success");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,144 @@
|
|||||||
|
#include <Wt/WGroupBox>
|
||||||
|
#include <Wt/WText>
|
||||||
|
#include <Wt/WPushButton>
|
||||||
|
#include <Wt/WMessageBox>
|
||||||
|
|
||||||
|
#include "database/MediaDirectory.hpp"
|
||||||
|
|
||||||
|
#include "SettingsMediaDirectoryFormView.hpp"
|
||||||
|
|
||||||
|
#include "SettingsMediaDirectories.hpp"
|
||||||
|
|
||||||
|
namespace UserInterface {
|
||||||
|
namespace Settings {
|
||||||
|
|
||||||
|
MediaDirectories::MediaDirectories(SessionData& sessionData, Wt::WContainerWidget *parent)
|
||||||
|
: Wt::WContainerWidget(parent),
|
||||||
|
_db(sessionData.getDatabaseHandler())
|
||||||
|
{
|
||||||
|
// Stack two widgets:
|
||||||
|
_stack = new Wt::WStackedWidget(this);
|
||||||
|
|
||||||
|
// 1/ the media directory table view
|
||||||
|
{
|
||||||
|
Wt::WGroupBox *container = new Wt::WGroupBox("Media Folders", _stack);
|
||||||
|
|
||||||
|
_table = new Wt::WTable(container);
|
||||||
|
|
||||||
|
_table->addStyleClass("table form-inline");
|
||||||
|
|
||||||
|
_table->toggleStyleClass("table-hover", true);
|
||||||
|
_table->toggleStyleClass("table-striped", true);
|
||||||
|
|
||||||
|
_table->setHeaderCount(1);
|
||||||
|
|
||||||
|
_table->elementAt(0, 0)->addWidget(new Wt::WText("#"));
|
||||||
|
_table->elementAt(0, 1)->addWidget(new Wt::WText("Path"));
|
||||||
|
_table->elementAt(0, 2)->addWidget(new Wt::WText("Type"));
|
||||||
|
|
||||||
|
Wt::WPushButton* addBtn = new Wt::WPushButton("Add Folder");
|
||||||
|
addBtn->setStyleClass("btn-success");
|
||||||
|
container->addWidget( addBtn );
|
||||||
|
addBtn->clicked().connect(boost::bind(&MediaDirectories::handleCreateMediaDirectory, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MediaDirectories::refresh(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
assert(_table->rowCount() > 0);
|
||||||
|
for (int i = _table->rowCount() - 1; i > 0; --i)
|
||||||
|
_table->deleteRow(i);
|
||||||
|
|
||||||
|
Wt::Dbo::Transaction transaction(_db.getSession());
|
||||||
|
|
||||||
|
std::vector<Database::MediaDirectory::pointer> mediaDirectories = Database::MediaDirectory::getAll(_db.getSession());
|
||||||
|
|
||||||
|
std::size_t id = 1;
|
||||||
|
BOOST_FOREACH(Database::MediaDirectory::pointer mediaDirectory, mediaDirectories)
|
||||||
|
{
|
||||||
|
_table->elementAt(id, 0)->addWidget(new Wt::WText( Wt::WString::fromUTF8("{1}").arg(id)));
|
||||||
|
_table->elementAt(id, 1)->addWidget(new Wt::WText( Wt::WString::fromUTF8(mediaDirectory->getPath().string()) ));
|
||||||
|
|
||||||
|
Wt::WString dirType;
|
||||||
|
switch(mediaDirectory->getType())
|
||||||
|
{
|
||||||
|
case Database::MediaDirectory::Video: dirType = "Video"; break;
|
||||||
|
case Database::MediaDirectory::Audio: dirType = "Audio"; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
_table->elementAt(id, 2)->addWidget( new Wt::WText( dirType ));
|
||||||
|
|
||||||
|
Wt::WPushButton* delBtn = new Wt::WPushButton("Delete");
|
||||||
|
delBtn->setStyleClass("btn-danger");
|
||||||
|
_table->elementAt(id, 3)->addWidget(delBtn);
|
||||||
|
delBtn->clicked().connect(boost::bind( &MediaDirectories::handleDelMediaDirectory, this, mediaDirectory->getPath() ) );
|
||||||
|
|
||||||
|
++id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MediaDirectories::handleDelMediaDirectory(boost::filesystem::path p)
|
||||||
|
{
|
||||||
|
Wt::WMessageBox *messageBox = new Wt::WMessageBox
|
||||||
|
("Delete Folder",
|
||||||
|
Wt::WString( "Deleting folder '{1}'?").arg(p.string()),
|
||||||
|
Wt::Question, Wt::Yes | Wt::No);
|
||||||
|
|
||||||
|
messageBox->setModal(true);
|
||||||
|
|
||||||
|
messageBox->buttonClicked().connect(std::bind([=] () {
|
||||||
|
if (messageBox->buttonResult() == Wt::Yes)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
Wt::Dbo::Transaction transaction(_db.getSession());
|
||||||
|
|
||||||
|
// Delete the media diretory
|
||||||
|
Database::MediaDirectory::pointer mediaDirectory = Database::MediaDirectory::getByPath(_db.getSession(), p);
|
||||||
|
if (mediaDirectory)
|
||||||
|
mediaDirectory.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
delete messageBox;
|
||||||
|
}));
|
||||||
|
|
||||||
|
messageBox->show();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MediaDirectories::handleCreateMediaDirectory(void)
|
||||||
|
{
|
||||||
|
assert(_stack->count() == 1);
|
||||||
|
|
||||||
|
MediaDirectoryFormView* formView = new MediaDirectoryFormView(_db, _stack);
|
||||||
|
formView->completed().connect(this, &MediaDirectories::handleMediaDirectoryFormCompleted);
|
||||||
|
|
||||||
|
_stack->setCurrentIndex(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MediaDirectories::handleMediaDirectoryFormCompleted(bool changed)
|
||||||
|
{
|
||||||
|
_stack->setCurrentIndex(0);
|
||||||
|
|
||||||
|
// Refresh the user table if a change has been made
|
||||||
|
if (changed)
|
||||||
|
refresh();
|
||||||
|
|
||||||
|
// Delete the form view
|
||||||
|
delete _stack->widget(1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace UserInterface
|
||||||
|
} // namespace Settings
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
#ifndef UI_SETTINGS_MEDIA_DIRECTORIES_HPP
|
||||||
|
#define UI_SETTINGS_MEDIA_DIRECTORIES_HPP
|
||||||
|
|
||||||
|
#include <Wt/WStackedWidget>
|
||||||
|
#include <Wt/WContainerWidget>
|
||||||
|
#include <Wt/WTable>
|
||||||
|
|
||||||
|
#include "common/SessionData.hpp"
|
||||||
|
|
||||||
|
namespace UserInterface {
|
||||||
|
namespace Settings {
|
||||||
|
|
||||||
|
class MediaDirectories : public Wt::WContainerWidget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MediaDirectories(SessionData& sessioNData, Wt::WContainerWidget *parent = 0);
|
||||||
|
|
||||||
|
void refresh();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void handleMediaDirectoryFormCompleted(bool changed);
|
||||||
|
|
||||||
|
void handleDelMediaDirectory(boost::filesystem::path p);
|
||||||
|
void handleCreateMediaDirectory(void);
|
||||||
|
|
||||||
|
Database::Handler& _db;
|
||||||
|
|
||||||
|
Wt::WStackedWidget* _stack;
|
||||||
|
Wt::WTable* _table;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace UserInterface
|
||||||
|
} // namespace Settings
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,160 @@
|
|||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <Wt/WStringListModel>
|
||||||
|
#include <Wt/WLineEdit>
|
||||||
|
#include <Wt/WFormModel>
|
||||||
|
#include <Wt/WComboBox>
|
||||||
|
#include <Wt/WPushButton>
|
||||||
|
|
||||||
|
#include "database/MediaDirectory.hpp"
|
||||||
|
|
||||||
|
#include "common/DirectoryValidator.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#include "SettingsMediaDirectoryFormView.hpp"
|
||||||
|
|
||||||
|
namespace UserInterface {
|
||||||
|
namespace Settings {
|
||||||
|
|
||||||
|
// TODO validate if directory already exists
|
||||||
|
class MediaDirectoryFormModel : public Wt::WFormModel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Associate each field with a unique string literal.
|
||||||
|
static const Field PathField;
|
||||||
|
static const Field TypeField;
|
||||||
|
|
||||||
|
MediaDirectoryFormModel(Database::Handler& db, Wt::WObject *parent = 0)
|
||||||
|
: Wt::WFormModel(parent),
|
||||||
|
_db(db)
|
||||||
|
{
|
||||||
|
initializeModels();
|
||||||
|
|
||||||
|
addField(PathField);
|
||||||
|
addField(TypeField);
|
||||||
|
|
||||||
|
DirectoryValidator* dirValidator = new DirectoryValidator();
|
||||||
|
dirValidator->setMandatory(true);
|
||||||
|
setValidator(PathField, dirValidator);
|
||||||
|
setValidator(TypeField, new Wt::WValidator(true)); // mandatory
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Wt::WAbstractItemModel *typeModel() { return _typeModel; }
|
||||||
|
|
||||||
|
bool saveData(Wt::WString& error)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Wt::Dbo::Transaction transaction(_db.getSession());
|
||||||
|
|
||||||
|
Database::MediaDirectory::Type type
|
||||||
|
= (valueText(TypeField) == "Audio") ? Database::MediaDirectory::Audio : Database::MediaDirectory::Video;
|
||||||
|
|
||||||
|
Database::MediaDirectory::create(_db.getSession(), valueText(PathField).toUTF8(), type);
|
||||||
|
|
||||||
|
}
|
||||||
|
catch(Wt::Dbo::Exception& exception)
|
||||||
|
{
|
||||||
|
std::cerr << "Dbo exception: " << exception.what() << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void initializeModels()
|
||||||
|
{
|
||||||
|
_typeModel = new Wt::WStringListModel(this);
|
||||||
|
_typeModel->addString("Audio");
|
||||||
|
_typeModel->addString("Video");
|
||||||
|
}
|
||||||
|
|
||||||
|
Database::Handler& _db;
|
||||||
|
std::string _userId;
|
||||||
|
Wt::WStringListModel* _typeModel;
|
||||||
|
};
|
||||||
|
|
||||||
|
const Wt::WFormModel::Field MediaDirectoryFormModel::PathField = "path";
|
||||||
|
const Wt::WFormModel::Field MediaDirectoryFormModel::TypeField = "type";
|
||||||
|
|
||||||
|
MediaDirectoryFormView::MediaDirectoryFormView(Database::Handler& db, Wt::WContainerWidget *parent)
|
||||||
|
: Wt::WTemplateFormView(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
_model = new MediaDirectoryFormModel(db, this);
|
||||||
|
|
||||||
|
setTemplateText(tr("mediaDirectoryForm-template"));
|
||||||
|
addFunction("id", &WTemplate::Functions::id);
|
||||||
|
addFunction("block", &WTemplate::Functions::id);
|
||||||
|
|
||||||
|
_applyInfo = new Wt::WText();
|
||||||
|
_applyInfo->setInline(false);
|
||||||
|
_applyInfo->hide();
|
||||||
|
bindWidget("apply-info", _applyInfo);
|
||||||
|
|
||||||
|
// Path
|
||||||
|
Wt::WLineEdit* pathEdit = new Wt::WLineEdit();
|
||||||
|
setFormWidget(MediaDirectoryFormModel::PathField, pathEdit);
|
||||||
|
pathEdit->changed().connect(_applyInfo, &Wt::WWidget::hide);
|
||||||
|
|
||||||
|
// Type
|
||||||
|
Wt::WComboBox *typeCB = new Wt::WComboBox();
|
||||||
|
setFormWidget(MediaDirectoryFormModel::TypeField, typeCB);
|
||||||
|
typeCB->setModel(_model->typeModel());
|
||||||
|
typeCB->changed().connect(_applyInfo, &Wt::WWidget::hide);
|
||||||
|
|
||||||
|
// Title & Buttons
|
||||||
|
bindString("title", "Add Media Folder");
|
||||||
|
|
||||||
|
Wt::WPushButton *saveButton = new Wt::WPushButton("Add");
|
||||||
|
saveButton->setStyleClass("btn-primary");
|
||||||
|
bindWidget("save-button", saveButton);
|
||||||
|
saveButton->clicked().connect(this, &MediaDirectoryFormView::processSave);
|
||||||
|
|
||||||
|
Wt::WPushButton *cancelButton = new Wt::WPushButton("Cancel");
|
||||||
|
bindWidget("cancel-button", cancelButton);
|
||||||
|
cancelButton->clicked().connect(this, &MediaDirectoryFormView::processCancel);
|
||||||
|
|
||||||
|
updateView(_model);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MediaDirectoryFormView::processCancel()
|
||||||
|
{
|
||||||
|
// parent widget will delete this widget
|
||||||
|
completed().emit(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MediaDirectoryFormView::processSave()
|
||||||
|
{
|
||||||
|
updateModel(_model);
|
||||||
|
|
||||||
|
_applyInfo->show();
|
||||||
|
if (_model->validate())
|
||||||
|
{
|
||||||
|
Wt::WString error;
|
||||||
|
// commit model into DB
|
||||||
|
if (_model->saveData(error) ) {
|
||||||
|
completed().emit(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_applyInfo->setText( Wt::WString::fromUTF8("Cannot apply new parameters: ") + error);
|
||||||
|
_applyInfo->setStyleClass("alert alert-danger");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_applyInfo->setText( Wt::WString::fromUTF8("Cannot apply new parameters!"));
|
||||||
|
_applyInfo->setStyleClass("alert alert-danger");
|
||||||
|
}
|
||||||
|
|
||||||
|
updateView(_model);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Settings
|
||||||
|
} // namespace UserInterface
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
#ifndef UI_SETTINGS_MEDIA_DIR_FORM_VIEW_HPP
|
||||||
|
#define UI_SETTINGS_MEDIA_DIR_FORM_VIEW_HPP
|
||||||
|
|
||||||
|
#include <Wt/WContainerWidget>
|
||||||
|
#include <Wt/WTemplateFormView>
|
||||||
|
#include <Wt/WText>
|
||||||
|
#include <Wt/WSignal>
|
||||||
|
|
||||||
|
#include "common/SessionData.hpp"
|
||||||
|
|
||||||
|
namespace UserInterface {
|
||||||
|
namespace Settings {
|
||||||
|
|
||||||
|
class MediaDirectoryFormModel;
|
||||||
|
|
||||||
|
class MediaDirectoryFormView : public Wt::WTemplateFormView
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MediaDirectoryFormView(Database::Handler& db, Wt::WContainerWidget *parent = 0);
|
||||||
|
|
||||||
|
// Signal emitted once the form is completed
|
||||||
|
Wt::Signal<bool>& completed() { return _sigCompleted; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void processCancel(); // reload from DB
|
||||||
|
void processSave(); // commit into DB
|
||||||
|
|
||||||
|
Wt::Signal<bool> _sigCompleted;
|
||||||
|
MediaDirectoryFormModel* _model;
|
||||||
|
Wt::WText* _applyInfo;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Settings
|
||||||
|
} // namespace UserInterface
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user